From 4bf13c505bef935428f9ed5332aded26635e5a77 Mon Sep 17 00:00:00 2001 From: Felix P Date: Fri, 17 Feb 2023 16:07:00 +0100 Subject: [PATCH 1/5] Verify this is a stable version --- src/install.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/install.js b/src/install.js index 9e1ebb6..875f72b 100644 --- a/src/install.js +++ b/src/install.js @@ -22,6 +22,14 @@ function getPlatform() { return osName && arch && `${osName}_${arch}`; } +function needsDefaultVersion(versionSpec) { + return versionSpec === undefined && versionSpec === "latest"; +} + +function isStableVersion(version) { + return !version.prerelease && !version.draft; +} + async function selectCompatibleVersion(versionSpec) { // NOTE: authStrategy is set conditionnaly. Docs specifies that GITHUB_TOKEN needs to be set explicitely. // To avoid breaking every pipeline that has no GITHUB_TOKEN set, this strategy is not passed until @@ -41,8 +49,14 @@ async function selectCompatibleVersion(versionSpec) { const versions = response.data; for (let i = 0; i < versions.length; i++) { - if (versionSpec === undefined || versionSpec === "latest" - || semver.satisfies(versions[i].tag_name, versionSpec)) { + // Ensure that assets are available + if (versions[i].assets?.length === 0) { + continue; + } + if (needsDefaultVersion(versionSpec) && isStableVersion(versions[i])) { + return versions[i]; + } + if (semver.satisfies(versions[i].tag_name, versionSpec)) { return versions[i]; } } From 7a6b8217dcde25e8459085733b1c606412530be6 Mon Sep 17 00:00:00 2001 From: Felix P Date: Fri, 17 Feb 2023 16:46:46 +0100 Subject: [PATCH 2/5] Update func + tests --- dist/main/index.js | 17 ++++++++-- src/install.js | 3 +- tests/fixtures/github-releases-mock.json | 39 +++++++++++++++++++++ tests/install.spec.js | 43 +++++++++++++----------- 4 files changed, 78 insertions(+), 24 deletions(-) diff --git a/dist/main/index.js b/dist/main/index.js index 8a85724..0d8e667 100644 --- a/dist/main/index.js +++ b/dist/main/index.js @@ -16357,6 +16357,14 @@ function getPlatform() { return osName && arch && `${osName}_${arch}`; } +function needsDefaultVersion(versionSpec) { + return versionSpec === undefined || versionSpec === "latest"; +} + +function isStableVersion(version) { + return !version.prerelease && !version.draft; +} + async function selectCompatibleVersion(versionSpec) { // NOTE: authStrategy is set conditionnaly. Docs specifies that GITHUB_TOKEN needs to be set explicitely. // To avoid breaking every pipeline that has no GITHUB_TOKEN set, this strategy is not passed until @@ -16376,8 +16384,13 @@ async function selectCompatibleVersion(versionSpec) { const versions = response.data; for (let i = 0; i < versions.length; i++) { - if (versionSpec === undefined || versionSpec === "latest" - || semver.satisfies(versions[i].tag_name, versionSpec)) { + if (versions[i].assets?.length === 0) { + continue; + } + if (needsDefaultVersion(versionSpec) && isStableVersion(versions[i])) { + return versions[i]; + } + if (semver.satisfies(versions[i].tag_name, versionSpec)) { return versions[i]; } } diff --git a/src/install.js b/src/install.js index 875f72b..5d4dfab 100644 --- a/src/install.js +++ b/src/install.js @@ -23,7 +23,7 @@ function getPlatform() { } function needsDefaultVersion(versionSpec) { - return versionSpec === undefined && versionSpec === "latest"; + return versionSpec === undefined || versionSpec === "latest"; } function isStableVersion(version) { @@ -49,7 +49,6 @@ async function selectCompatibleVersion(versionSpec) { const versions = response.data; for (let i = 0; i < versions.length; i++) { - // Ensure that assets are available if (versions[i].assets?.length === 0) { continue; } diff --git a/tests/fixtures/github-releases-mock.json b/tests/fixtures/github-releases-mock.json index 235e9a8..fc92e99 100644 --- a/tests/fixtures/github-releases-mock.json +++ b/tests/fixtures/github-releases-mock.json @@ -1,7 +1,43 @@ [ + { + "tag_name": "v0.26.0-alpha1", + "name": "v0.26.0-alpha1", + "prerelease": true, + "assets": [ + { + "name": "checksums.txt", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/checksums.txt" + }, + { + "name": "saucectl_0.26.0-alpha1_linux_32-bit.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/saucectl_0.26.0-alpha1_linux_32-bit.tar.gz" + }, + { + "name": "saucectl_0.26.0-alpha1_linux_64-bit.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/saucectl_0.26.0-alpha1_linux_64-bit.tar.gz" + }, + { + "name": "saucectl_0.26.0-alpha1_linux_arm64.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/saucectl_0.26.0-alpha1_linux_arm64.tar.gz" + }, + { + "name": "saucectl_0.26.0-alpha1_mac_64-bit.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/saucectl_0.26.0-alpha1_mac_64-bit.tar.gz" + }, + { + "name": "saucectl_0.26.0-alpha1_win_32-bit.zip", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/saucectl_0.26.0-alpha1_win_32-bit.zip" + }, + { + "name": "saucectl_0.26.0-alpha1_win_64-bit.zip", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.26.0-alpha1/saucectl_0.26.0-alpha1_win_64-bit.zip" + } + ] + }, { "tag_name": "v0.25.1", "name": "v0.25.1", + "prerelease": false, "assets": [ { "name": "checksums.txt", @@ -36,6 +72,7 @@ { "tag_name": "v0.25.0", "name": "v0.25.0", + "prerelease": false, "assets": [ { "name": "checksums.txt", @@ -70,6 +107,7 @@ { "tag_name": "v0.24.1", "name": "v0.24.1", + "prerelease": false, "assets": [ { "name": "checksums.txt", @@ -104,6 +142,7 @@ { "tag_name": "v0.24.0", "name": "v0.24.0", + "prerelease": false, "assets": [ { "name": "checksums.txt", diff --git a/tests/install.spec.js b/tests/install.spec.js index bbf3f8d..86d741c 100644 --- a/tests/install.spec.js +++ b/tests/install.spec.js @@ -9,28 +9,42 @@ const core = require("@actions/core"); jest.mock("@actions/tool-cache"); const tc = require("@actions/tool-cache"); - -const nock = require('nock'); +jest.mock('@octokit/rest') +const { Octokit } = require("@octokit/rest"); const install = require("../src/install.js"); +const requestMock = jest.fn(); +requestMock.mockImplementation((target) => new Promise((resolve, reject) => { + if (target === "GET /repos/:org/:repo/releases") { + resolve({ + status: 200, + headers: { location: 'mock-url' }, + data: JSON.parse(fs.readFileSync("./tests/fixtures/github-releases-mock.json")), + }); + } + reject('Unexpected Endpoint'); +})); +Octokit.mockImplementation(() => ({ request: requestMock })) + beforeAll(() => { process.env.GITHUB_ACTION = "FAKE_IN_ACTION"; }); +beforeEach(() => { + jest.clearAllMocks(); +}); + it("Version matching", async () => { // rewire wrapping const selectCompatibleVersion = install.selectCompatibleVersion; const testCases = [["latest", "v0.25.1"], ["0.25.1", "v0.25.1"], ["0.25.0", "v0.25.0"], ["^0.25.0", "v0.25.1"], [">=0.24.0", "v0.25.1"], ["0.24.x", "v0.24.1"]]; for (let i = 0; i < testCases.length; i++) { - const scope = nock('https://api.github.com') - .get('/repos/saucelabs/saucectl/releases') - .reply(200, JSON.parse(fs.readFileSync("./tests/fixtures/github-releases-mock.json"))); let [input, expected] = testCases[i]; let version = await selectCompatibleVersion(input); expect(version.tag_name).toBe(expected); - expect(scope.isDone()).toBe(true); + expect(requestMock).toHaveBeenCalled() } }); @@ -52,13 +66,10 @@ describe("Installation", () => { it("Invalid version", async () => { os.platform.mockReturnValue('linux'); os.arch.mockReturnValue('x64'); - const scope = nock('https://api.github.com') - .get('/repos/saucelabs/saucectl/releases') - .reply(200, JSON.parse(fs.readFileSync("./tests/fixtures/github-releases-mock.json"))); const ret = await install.saucectlInstall({ versionSpec: '0.29.5' }); expect(ret).toBe(false); - expect(scope.isDone()).toBe(true); + expect(requestMock).toHaveBeenCalled(); }); it("Install version - linux", async () => { @@ -68,14 +79,10 @@ describe("Installation", () => { const extractFn = tc.extractTar.mockReturnValue('/tmp/install-dir-extracted'); const addPathFn = core.addPath.mockReturnValue('/bin/saucectl'); - const scope = nock('https://api.github.com') - .get('/repos/saucelabs/saucectl/releases') - .reply(200, JSON.parse(fs.readFileSync("./tests/fixtures/github-releases-mock.json"))); - const ret = await install.saucectlInstall({ versionSpec: '0.25.1' }); expect(ret).toBe(true); - expect(scope.isDone()).toBe(true); + expect(requestMock).toHaveBeenCalled(); expect(downloadFn).toHaveBeenCalled(); expect(extractFn).toHaveBeenCalled(); expect(addPathFn).toHaveBeenCalled(); @@ -88,14 +95,10 @@ describe("Installation", () => { const extractFn = tc.extractZip.mockReturnValue('/tmp/install-dir-extracted'); const addPathFn = core.addPath.mockReturnValue('/bin/saucectl'); - const scope = nock('https://api.github.com') - .get('/repos/saucelabs/saucectl/releases') - .reply(200, JSON.parse(fs.readFileSync("./tests/fixtures/github-releases-mock.json"))); - const ret = await install.saucectlInstall({ versionSpec: '0.25.1' }); expect(ret).toBe(true); - expect(scope.isDone()).toBe(true); + expect(requestMock).toHaveBeenCalled(); expect(downloadFn).toHaveBeenCalled(); expect(extractFn).toHaveBeenCalled(); expect(addPathFn).toHaveBeenCalled(); From 3cb5c5fc22a9dd432b55ba723dbc1a9c35bb1bea Mon Sep 17 00:00:00 2001 From: Felix P Date: Fri, 17 Feb 2023 16:48:11 +0100 Subject: [PATCH 3/5] Add test for alpha --- tests/install.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/install.spec.js b/tests/install.spec.js index 86d741c..611e0ef 100644 --- a/tests/install.spec.js +++ b/tests/install.spec.js @@ -38,7 +38,7 @@ beforeEach(() => { it("Version matching", async () => { // rewire wrapping const selectCompatibleVersion = install.selectCompatibleVersion; - const testCases = [["latest", "v0.25.1"], ["0.25.1", "v0.25.1"], ["0.25.0", "v0.25.0"], ["^0.25.0", "v0.25.1"], [">=0.24.0", "v0.25.1"], ["0.24.x", "v0.24.1"]]; + const testCases = [["latest", "v0.25.1"], ["0.25.1", "v0.25.1"], ["0.25.0", "v0.25.0"], ["^0.25.0", "v0.25.1"], [">=0.24.0", "v0.25.1"], ["0.24.x", "v0.24.1"], ["v0.26.0-alpha1", "v0.26.0-alpha1"]]; for (let i = 0; i < testCases.length; i++) { let [input, expected] = testCases[i]; From b102e5e85f43348b89e38fda34cf9c7b347afa88 Mon Sep 17 00:00:00 2001 From: Felix P Date: Fri, 17 Feb 2023 16:51:10 +0100 Subject: [PATCH 4/5] Add test for draft --- dist/main/index.js | 2 +- src/install.js | 2 +- tests/fixtures/github-releases-mock.json | 37 ++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/dist/main/index.js b/dist/main/index.js index 0d8e667..0df1e22 100644 --- a/dist/main/index.js +++ b/dist/main/index.js @@ -16384,7 +16384,7 @@ async function selectCompatibleVersion(versionSpec) { const versions = response.data; for (let i = 0; i < versions.length; i++) { - if (versions[i].assets?.length === 0) { + if (versions[i].draft || versions[i].assets?.length === 0) { continue; } if (needsDefaultVersion(versionSpec) && isStableVersion(versions[i])) { diff --git a/src/install.js b/src/install.js index 5d4dfab..c3478a5 100644 --- a/src/install.js +++ b/src/install.js @@ -49,7 +49,7 @@ async function selectCompatibleVersion(versionSpec) { const versions = response.data; for (let i = 0; i < versions.length; i++) { - if (versions[i].assets?.length === 0) { + if (versions[i].draft || versions[i].assets?.length === 0) { continue; } if (needsDefaultVersion(versionSpec) && isStableVersion(versions[i])) { diff --git a/tests/fixtures/github-releases-mock.json b/tests/fixtures/github-releases-mock.json index fc92e99..12e0f4f 100644 --- a/tests/fixtures/github-releases-mock.json +++ b/tests/fixtures/github-releases-mock.json @@ -1,4 +1,41 @@ [ + + { + "tag_name": "v0.27.0", + "name": "v0.27.0", + "prerelease": false, + "draft": true, + "assets": [ + { + "name": "checksums.txt", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/checksums.txt" + }, + { + "name": "saucectl_0.27.0_linux_32-bit.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/saucectl_0.27.0_linux_32-bit.tar.gz" + }, + { + "name": "saucectl_0.27.0_linux_64-bit.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/saucectl_0.27.0_linux_64-bit.tar.gz" + }, + { + "name": "saucectl_0.27.0_linux_arm64.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/saucectl_0.27.0_linux_arm64.tar.gz" + }, + { + "name": "saucectl_0.27.0_mac_64-bit.tar.gz", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/saucectl_0.27.0_mac_64-bit.tar.gz" + }, + { + "name": "saucectl_0.27.0_win_32-bit.zip", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/saucectl_0.27.0_win_32-bit.zip" + }, + { + "name": "saucectl_0.27.0_win_64-bit.zip", + "browser_download_url": "https://github.com/saucelabs/saucectl/releases/download/v0.27.0/saucectl_0.27.0_win_64-bit.zip" + } + ] + }, { "tag_name": "v0.26.0-alpha1", "name": "v0.26.0-alpha1", From 6a3e74d65212bce42174ba47de9fbf168f5d1f2a Mon Sep 17 00:00:00 2001 From: Felix P Date: Fri, 17 Feb 2023 17:37:52 +0100 Subject: [PATCH 5/5] Rename check for latest --- dist/main/index.js | 4 ++-- src/install.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/main/index.js b/dist/main/index.js index 0df1e22..972fd8b 100644 --- a/dist/main/index.js +++ b/dist/main/index.js @@ -16357,7 +16357,7 @@ function getPlatform() { return osName && arch && `${osName}_${arch}`; } -function needsDefaultVersion(versionSpec) { +function isLatestRequested(versionSpec) { return versionSpec === undefined || versionSpec === "latest"; } @@ -16387,7 +16387,7 @@ async function selectCompatibleVersion(versionSpec) { if (versions[i].draft || versions[i].assets?.length === 0) { continue; } - if (needsDefaultVersion(versionSpec) && isStableVersion(versions[i])) { + if (isLatestRequested(versionSpec) && isStableVersion(versions[i])) { return versions[i]; } if (semver.satisfies(versions[i].tag_name, versionSpec)) { diff --git a/src/install.js b/src/install.js index c3478a5..1aeff48 100644 --- a/src/install.js +++ b/src/install.js @@ -22,7 +22,7 @@ function getPlatform() { return osName && arch && `${osName}_${arch}`; } -function needsDefaultVersion(versionSpec) { +function isLatestRequested(versionSpec) { return versionSpec === undefined || versionSpec === "latest"; } @@ -52,7 +52,7 @@ async function selectCompatibleVersion(versionSpec) { if (versions[i].draft || versions[i].assets?.length === 0) { continue; } - if (needsDefaultVersion(versionSpec) && isStableVersion(versions[i])) { + if (isLatestRequested(versionSpec) && isStableVersion(versions[i])) { return versions[i]; } if (semver.satisfies(versions[i].tag_name, versionSpec)) {