Skip to content

Commit

Permalink
Support “nightly-latest” version (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-aws authored Feb 16, 2023
1 parent 6f0cccf commit ef97afb
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 21 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,20 @@ jobs:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
dafny: [3.0.0, 3.7.3, 3.8.1, nightly-2022-09-23-2bc0042]
dafny: [3.0.0, 3.7.3, 3.8.1, nightly-2023-02-13-14bc57f, nightly-latest]
# Windows 2.3.0 requires mono
include:
- os: macos-latest
dafny: 2.3.0
- os: ubuntu-latest
dafny: 2.3.0
steps:
# The first call to `dotnet tool` on a fresh runner sometimes takes multiple minutes,
# perhaps because it is lazily downloading and installing assets.
# It helps to hit that here so we don't hit it in a mocha test with a tight timeout.
- name: Warm up dotnet tool
run: dotnet tool search --help

- name: Checkout
uses: actions/checkout@v2

Expand Down
2 changes: 1 addition & 1 deletion __tests__/verify-dafny.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fi
echo "Expected Dafny Version: $expectedVersionString"
dafny_version="$(dafny $version)"
echo "Found $dafny_version"
if ! echo "$dafny_version" | grep -q "Dafny $expectedVersionString"; then
if ! echo "$dafny_version" | grep -qi "Dafny $expectedVersionString"; then
echo "Unexpected version" 1>&2
exit 1
fi
74 changes: 68 additions & 6 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6695,7 +6695,7 @@ const os = __nccwpck_require__(2037);
try {
const version = core.getInput("dafny-version", { required: true });
const distribution = getDistribution(os.platform(), version);
const url = dafnyURL(version, distribution);
const url = await dafnyURL(version, distribution);

core.info(`Dafny Url: ${url}`);
core.info(`Dafny Distribution: ${distribution}`);
Expand All @@ -6710,29 +6710,91 @@ const os = __nccwpck_require__(2037);
// Install related tools.
// Hopefully in the future we can install Dafny itself this way as well.
// For now the zipped releases are simpler because they include Z3.
await installDotnetTool("dafny-reportgenerator", "1.*")
await installDotnetTool("dafny-reportgenerator", "1.*");
} catch (error) {
core.setFailed(error.message);
}
})();

async function installDotnetTool(toolName, version) {
await exec.exec("dotnet", ["tool", "install", "-g", toolName, "--version", version])
await exec.exec("dotnet", [
"tool",
"install",
"-g",
toolName,
"--version",
version,
]);
}

// Export functions for testing
exports.dafnyURL = dafnyURL;
exports.getDistribution = getDistribution;
exports.latestNightlyVersionFromDotnetToolSearch = latestNightlyVersionFromDotnetToolSearch;

function dafnyURL(version, distribution) {
async function dafnyURL(version, distribution) {
const versionPath = version.startsWith("nightly") ? "nightly" : `v${version}`;
if (version == "nightly-latest") {
version = await latestNightlyVersion();
}
const root = "https://github.com/dafny-lang/dafny/releases/download";
return `${root}/${versionPath}/dafny-${version == "2.3.0" ? "2.3.0.10506" : version}-x64-${distribution}.zip`;
return `${root}/${versionPath}/dafny-${
version == "2.3.0" ? "2.3.0.10506" : version
}-x64-${distribution}.zip`;
}

async function latestNightlyVersion() {
const { exitCode, stdout, stderr } = await exec.getExecOutput(
"dotnet",
["tool", "search", "Dafny", "--detail", "--prerelease"],
{ silent: true }
);
if (exitCode != 0) {
throw new Error(
`dotnet tool command failed (exitCode ${exitCode}):\n${stderr}"`
);
}
return latestNightlyVersionFromDotnetToolSearch(stdout)
}

function latestNightlyVersionFromDotnetToolSearch(output) {
// Shamelessly copied and modified from dafny-lang/ide-vscode.
// Parsing the dotnet tool output is obviously not great,
// and we could consider using the NuGet API in the future.
// Alternatively if we move to installing Dafny using `dotnet tool install`
// we could use the `--prerelease` flag, although that assumes
// that all nightly builds use a fresh version number,
// and can't be used together with `--version` to express something like
// "install the latest 3.X version including prereleases".
const entries = output
.split("----------------")
.map((entry) => entry.split(/\r?\n/).filter((e) => e !== ""));
const dafnyEntry = entries.filter((entry) => entry[0] === "dafny")[0];
const versionsIndex = dafnyEntry.findIndex((v) => v.startsWith("Versions:"));
const versions = dafnyEntry
.slice(versionsIndex + 1)
.map((versionLine) => versionLine.trimStart().split(" ")[0]);

const nightlies = versions.filter((l) => l.includes("nightly"));
const dates = nightlies.map(nightly => {
const date = new Date(nightly.split('-').slice(2, 5).join('-'))
return { nightly, date };
});
dates.sort((a, b) => (a.date < b.date ? 1 : -1));
const toolVersion = dates[0].nightly;

// Slice off the "3.11.0.50201-" from 3.11.0.50201-nightly-2023-02-13-14bc57f, for e.g.
const version = toolVersion.slice(toolVersion.indexOf("-") + 1);

core.info(`Using latest nightly version: ${version}`);
return version;
}

function getDistribution(platform, version) {
return platform === "darwin" // Osx
? version == "2.3.0" ? "osx-10.14.1" : "osx-10.14.2"
? version == "2.3.0"
? "osx-10.14.1"
: "osx-10.14.2"
: platform === "win32" // windows
? "win"
: "ubuntu-16.04"; // Everything else is linux...
Expand Down
75 changes: 69 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const os = require("os");
try {
const version = core.getInput("dafny-version", { required: true });
const distribution = getDistribution(os.platform(), version);
const url = dafnyURL(version, distribution);
const url = await dafnyURL(version, distribution);

core.info(`Dafny Url: ${url}`);
core.info(`Dafny Distribution: ${distribution}`);
Expand All @@ -22,29 +22,92 @@ const os = require("os");
// Install related tools.
// Hopefully in the future we can install Dafny itself this way as well.
// For now the zipped releases are simpler because they include Z3.
await installDotnetTool("dafny-reportgenerator", "1.*")
await installDotnetTool("dafny-reportgenerator", "1.*");
} catch (error) {
core.setFailed(error.message);
}
})();

async function installDotnetTool(toolName, version) {
await exec.exec("dotnet", ["tool", "install", "-g", toolName, "--version", version])
await exec.exec("dotnet", [
"tool",
"install",
"-g",
toolName,
"--version",
version,
]);
}

// Export functions for testing
exports.dafnyURL = dafnyURL;
exports.getDistribution = getDistribution;
exports.latestNightlyVersionFromDotnetToolSearch =
latestNightlyVersionFromDotnetToolSearch;

function dafnyURL(version, distribution) {
async function dafnyURL(version, distribution) {
const versionPath = version.startsWith("nightly") ? "nightly" : `v${version}`;
if (version == "nightly-latest") {
version = await latestNightlyVersion();
}
const root = "https://github.com/dafny-lang/dafny/releases/download";
return `${root}/${versionPath}/dafny-${version == "2.3.0" ? "2.3.0.10506" : version}-x64-${distribution}.zip`;
return `${root}/${versionPath}/dafny-${
version == "2.3.0" ? "2.3.0.10506" : version
}-x64-${distribution}.zip`;
}

async function latestNightlyVersion() {
const { exitCode, stdout, stderr } = await exec.getExecOutput(
"dotnet",
["tool", "search", "Dafny", "--detail", "--prerelease"],
{ silent: true }
);
if (exitCode != 0) {
throw new Error(
`dotnet tool command failed (exitCode ${exitCode}):\n${stderr}"`
);
}
return latestNightlyVersionFromDotnetToolSearch(stdout);
}

function latestNightlyVersionFromDotnetToolSearch(output) {
// Shamelessly copied and modified from dafny-lang/ide-vscode.
// Parsing the dotnet tool output is obviously not great,
// and we could consider using the NuGet API in the future.
// Alternatively if we move to installing Dafny using `dotnet tool install`
// we could use the `--prerelease` flag, although that assumes
// that all nightly builds use a fresh version number,
// and can't be used together with `--version` to express something like
// "install the latest 3.X version including prereleases".
const entries = output
.split("----------------")
.map((entry) => entry.split(/\r?\n/).filter((e) => e !== ""));
const dafnyEntry = entries.filter((entry) => entry[0] === "dafny")[0];
const versionsIndex = dafnyEntry.findIndex((v) => v.startsWith("Versions:"));
const versions = dafnyEntry
.slice(versionsIndex + 1)
.map((versionLine) => versionLine.trimStart().split(" ")[0]);

const nightlies = versions.filter((l) => l.includes("nightly"));
const dates = nightlies.map((nightly) => {
const date = new Date(nightly.split("-").slice(2, 5).join("-"));
return { nightly, date };
});
dates.sort((a, b) => (a.date < b.date ? 1 : -1));
const toolVersion = dates[0].nightly;

// Slice off the "3.11.0.50201-" from 3.11.0.50201-nightly-2023-02-13-14bc57f, for e.g.
const version = toolVersion.slice(toolVersion.indexOf("-") + 1);

core.info(`Using latest nightly version: ${version}`);
return version;
}

function getDistribution(platform, version) {
return platform === "darwin" // Osx
? version == "2.3.0" ? "osx-10.14.1" : "osx-10.14.2"
? version == "2.3.0"
? "osx-10.14.1"
: "osx-10.14.2"
: platform === "win32" // windows
? "win"
: "ubuntu-16.04"; // Everything else is linux...
Expand Down
85 changes: 78 additions & 7 deletions test/setup-dafny-action.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
const { dafnyURL, getDistribution } = require("../index");
const {
dafnyURL,
getDistribution,
latestNightlyVersionFromDotnetToolSearch,
} = require("../index");
const { expect } = require("chai");

describe("dafnyURL", () => {
it("basic usage", () => {
const test = dafnyURL("3.8.1", "win");
it("basic usage", async () => {
const test = await dafnyURL("3.8.1", "win");
expect(test).to.equal(
"https://github.com/dafny-lang/dafny/releases/download/v3.8.1/dafny-3.8.1-x64-win.zip"
);
});

it("nightly usage", () => {
const test = dafnyURL("nightly-2022-09-23-2bc0042", "ubuntu-16.04");
it("nightly usage", async () => {
const test = await dafnyURL("nightly-2022-09-23-2bc0042", "ubuntu-16.04");
expect(test).to.equal(
"https://github.com/dafny-lang/dafny/releases/download/nightly/dafny-nightly-2022-09-23-2bc0042-x64-ubuntu-16.04.zip"
);
});

it("version 2.3.0", () => {
const test = dafnyURL("2.3.0", "win");
it("latest nightly parsing logic", async () => {
const test = latestNightlyVersionFromDotnetToolSearch(
sampleDotnetToolSearchOutput
);
expect(test).to.equal("nightly-2023-02-15-567a5ba");
});

it("latest nightly usage", async () => {
const test = await dafnyURL("nightly-latest", "ubuntu-16.04");
expect(test).to.match(
/^https:\/\/github.com\/dafny-lang\/dafny\/releases\/download\/nightly\/dafny-nightly-/
);
}).timeout(20_000); // Invoking and parsing the output of `dotnet tool search` can take well over 2 seconds

it("version 2.3.0", async () => {
const test = await dafnyURL("2.3.0", "win");
// https://github.com/dafny-lang/dafny/releases/download/v2.3.0/dafny-2.3.0.10506-x64-osx-10.14.1.zip
// https://github.com/dafny-lang/dafny/releases/download/v2.3.0/dafny-2.3.0.10506-x64-ubuntu-16.04.zip
// https://github.com/dafny-lang/dafny/releases/download/v2.3.0/dafny-2.3.0.10506-x64-win.zip
Expand All @@ -27,6 +45,59 @@ describe("dafnyURL", () => {
});
});

const sampleDotnetToolSearchOutput = `
----------------
dafny
Latest Version: 3.11.0.50201
Authors: Dafny
Tags:
Downloads: 16159
Verified: False
Description: Package Description
Versions:
3.10.0.41215-nightly-2023-01-24-fda11e6 Downloads: 54
3.10.0.41215-nightly-2023-01-25-07932fc Downloads: 54
3.10.0.41215-nightly-2023-01-26-97f1ced Downloads: 47
3.10.0.41215-nightly-2023-01-27-5bd9203 Downloads: 50
3.10.0.41215-nightly-2023-01-28-acb7991 Downloads: 52
3.10.0.41215-nightly-2023-01-29-acb7991 Downloads: 51
3.10.0.41215-nightly-2023-01-30-acb7991 Downloads: 53
3.10.0.41215-nightly-2023-01-31-c23b224 Downloads: 57
3.10.0.41215-nightly-2023-02-01-c5b4e15 Downloads: 46
3.10.0.41215 Downloads: 166
3.11.0.50201-nightly-2023-02-01-0cff53e Downloads: 43
3.11.0.50201-nightly-2023-02-02-4e54d04 Downloads: 49
3.11.0.50201-nightly-2023-02-03-9b97489 Downloads: 41
3.11.0.50201-nightly-2023-02-04-b8d8816 Downloads: 34
3.11.0.50201-nightly-2023-02-05-b8d8816 Downloads: 33
3.11.0.50201-nightly-2023-02-06-b8d8816 Downloads: 34
3.11.0.50201-nightly-2023-02-07-2461f1f Downloads: 30
3.11.0.50201-nightly-2023-02-08-37cfcb0 Downloads: 31
3.11.0.50201-nightly-2023-02-09-a86c579 Downloads: 31
3.11.0.50201-nightly-2023-02-10-a2a4e1b Downloads: 27
3.11.0.50201-nightly-2023-02-10-a86c579 Downloads: 26
3.11.0.50201-nightly-2023-02-11-6aeaa2b Downloads: 28
3.11.0.50201-nightly-2023-02-11-a2a4e1b Downloads: 30
3.11.0.50201-nightly-2023-02-12-6aeaa2b Downloads: 29
3.11.0.50201-nightly-2023-02-13-14bc57f Downloads: 27
3.11.0.50201-nightly-2023-02-14-7cf7164 Downloads: 27
3.11.0.50201-nightly-2023-02-15-567a5ba Downloads: 14
3.11.0.50201 Downloads: 94
----------------
dafny-reportgenerator
Latest Version: 1.2.0
Authors: dafny-reportgenerator
Tags:
Downloads: 11564
Verified: False
Description: Package Description
Versions:
1.0.0 Downloads: 248
1.0.1 Downloads: 525
1.2.0 Downloads: 10791
`;

describe("getDistribution", () => {
// https://nodejs.org/docs/latest/api/os.html#os_os_platform
[
Expand Down

0 comments on commit ef97afb

Please sign in to comment.