diff --git a/lib/entry-points.js b/lib/entry-points.js index 62b043f7b..091132b1c 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -147730,6 +147730,8 @@ async function runInActions(action) { const actionState = { name: action.name, startedAt, + platform: process.platform, + arch: process.arch, logger, env, actions: actionsEnv @@ -163635,8 +163637,7 @@ function getCredentials(logger, registrySecrets, registriesCredentials, language } return out; } -function getProxyPackage() { - const platform2 = process.platform === "win32" ? "win64" : process.platform === "darwin" ? "osx64" : "linux64"; +function getProxyPackage(platform2) { return `${UPDATEJOB_PROXY}-${platform2}.tar.gz`; } function getFallbackUrl(proxyPackage) { @@ -163653,20 +163654,27 @@ async function getCliVersionFromFeatures(features) { const gitHubVersion = await getGitHubVersion(); return await features.getEnabledDefaultCliVersions(gitHubVersion.type); } -async function getDownloadUrl(logger, features) { - const proxyPackage = getProxyPackage(); +async function getDownloadUrl(action) { + let platform2 = getBundlePlatform(action.platform, action.arch); + if (platform2 === void 0) { + action.logger.warning( + `Unsupported platform ${action.platform} on architecture ${action.arch}, defaulting to ${"linux64" /* Linux64 */}` + ); + platform2 = "linux64" /* Linux64 */; + } + const proxyPackage = getProxyPackage(platform2); try { - const useFeaturesToDetermineCLI = await features.getValue( + const useFeaturesToDetermineCLI = await action.features.getValue( "start_proxy_use_features_release" /* StartProxyUseFeaturesRelease */ ); - const versionInfo = useFeaturesToDetermineCLI ? (await getCliVersionFromFeatures(features)).enabledVersions[0] : { + const versionInfo = useFeaturesToDetermineCLI ? (await getCliVersionFromFeatures(action.features)).enabledVersions[0] : { cliVersion, tagName: bundleVersion }; const cliRelease = await getReleaseByVersion(versionInfo.tagName); for (const asset of cliRelease.data.assets) { if (asset.name === proxyPackage) { - logger.info( + action.logger.info( `Found '${proxyPackage}' in release '${versionInfo.tagName}' at '${asset.url}'` ); return { @@ -163679,11 +163687,11 @@ async function getDownloadUrl(logger, features) { } } } catch (ex) { - logger.warning( + action.logger.warning( `Failed to retrieve information about the linked release: ${getErrorMessage(ex)}` ); } - logger.info( + action.logger.info( `Did not find '${proxyPackage}' in the linked release, falling back to hard-coded version.` ); return { @@ -163732,9 +163740,10 @@ async function cacheProxy(logger, source, filename, version) { function getProxyFilename() { return process.platform === "win32" ? `${UPDATEJOB_PROXY}.exe` : UPDATEJOB_PROXY; } -async function getProxyBinaryPath(logger, features) { +async function getProxyBinaryPath(action) { + const logger = action.logger; const proxyFileName = getProxyFilename(); - const proxyInfo = await getDownloadUrl(logger, features); + const proxyInfo = await getDownloadUrl(action); let proxyBin = toolcache4.find(proxyFileName, proxyInfo.version); if (!proxyBin) { const apiDetails = getApiDetails(); @@ -164114,7 +164123,7 @@ async function run7(action) { all_credentials: credentials, ca }; - const proxyBin = await getProxyBinaryPath(logger, features); + const proxyBin = await getProxyBinaryPath({ ...action, features }); const proxyInfo = await startProxy( proxyBin, proxyConfig, diff --git a/src/action-common.ts b/src/action-common.ts index 95323e7f2..17d4344cc 100644 --- a/src/action-common.ts +++ b/src/action-common.ts @@ -19,6 +19,10 @@ export interface BaseState { name: ActionName; /** When the Action was started. */ startedAt: Date; + /** The platform the Action is running on. */ + platform: NodeJS.Platform; + /** The architecture of the host. */ + arch: NodeJS.Architecture; } /** Describes different state features that an Action may have. */ @@ -98,6 +102,8 @@ export async function runInActions(action: Action) { const actionState = { name: action.name, startedAt, + platform: process.platform, + arch: process.arch, logger, env, actions: actionsEnv, diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index e8b89732f..d965a2dd6 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -98,7 +98,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { }; // Start the Proxy - const proxyBin = await getProxyBinaryPath(logger, features); + const proxyBin = await getProxyBinaryPath({ ...action, features }); const proxyInfo = await startProxy( proxyBin, proxyConfig, diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts index ee953798b..bd2489713 100644 --- a/src/start-proxy.test.ts +++ b/src/start-proxy.test.ts @@ -5,6 +5,7 @@ import * as toolcache from "@actions/tool-cache"; import test, { ExecutionContext } from "ava"; import sinon from "sinon"; +import { ActionState } from "./action-common"; import * as apiClient from "./api-client"; import * as defaults from "./defaults.json"; import { setUpFeatureFlagTests } from "./feature-flags/testing-util"; @@ -12,12 +13,14 @@ import { UnvalidatedObject, validateSchema } from "./json"; import { makeFromSchema } from "./json/testing-util"; import { BuiltInLanguage } from "./languages"; import { getRunnerLogger, Logger } from "./logging"; +import { BundlePlatform, getBundlePlatform } from "./platform"; import * as startProxyExports from "./start-proxy"; import * as statusReport from "./status-report"; import { assertNotLogged, checkExpectedLogMessages, createFeatures, + initAllState, makeMacro, makeTestToken, RecordingLogger, @@ -685,6 +688,12 @@ test("getCredentials always returns ALWAYS_ENABLED_REGISTRY_TYPE credentials for } }); +test("getProxyPackage - includes platform in name", (t) => { + for (const platform of Object.values(BundlePlatform)) { + t.true(startProxyExports.getProxyPackage(platform).includes(platform)); + } +}); + function mockGetApiClient(endpoints: any) { return ( sinon @@ -721,6 +730,44 @@ function mockOfflineFeatures(tempDir: string, logger: Logger) { return setUpFeatureFlagTests(tempDir, logger, gitHubVersion); } +/** Gets the `BundlePlatform` based on the `action` state, but defaults to `Linux64` if undefined. */ +function getTestPlatform(action: ActionState<["Base"]>) { + return ( + getBundlePlatform(action.platform, action.arch) ?? BundlePlatform.Linux64 + ); +} + +test.serial( + "getDownloadUrl logs unknown platforms/arch and defaults to linux64", + async (t) => { + const logger = new RecordingLogger(); + mockGetReleaseByTag(); + + await withTmpDir(async (tempDir) => { + const features = mockOfflineFeatures(tempDir, logger); + const state = initAllState({ + platform: "android", + arch: "ppc", + logger, + features, + }); + const info = await startProxyExports.getDownloadUrl(state); + + t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION); + t.is( + info.url, + startProxyExports.getFallbackUrl( + startProxyExports.getProxyPackage(BundlePlatform.Linux64), + ), + ); + + t.true( + logger.hasMessage(`Unsupported platform android on architecture ppc`), + ); + }); + }, +); + test.serial( "getDownloadUrl returns fallback when `getReleaseByVersion` rejects", async (t) => { @@ -729,15 +776,15 @@ test.serial( await withTmpDir(async (tempDir) => { const features = mockOfflineFeatures(tempDir, logger); - const info = await startProxyExports.getDownloadUrl( - getRunnerLogger(true), - features, - ); + const state = initAllState({ logger, features }); + const info = await startProxyExports.getDownloadUrl(state); t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION); t.is( info.url, - startProxyExports.getFallbackUrl(startProxyExports.getProxyPackage()), + startProxyExports.getFallbackUrl( + startProxyExports.getProxyPackage(getTestPlatform(state)), + ), ); }); }, @@ -751,18 +798,18 @@ test.serial( await withTmpDir(async (tempDir) => { const features = mockOfflineFeatures(tempDir, logger); + const state = initAllState({ logger, features }); for (const assets of testAssets) { const stub = mockGetReleaseByTag(assets); - const info = await startProxyExports.getDownloadUrl( - getRunnerLogger(true), - features, - ); + const info = await startProxyExports.getDownloadUrl(state); t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION); t.is( info.url, - startProxyExports.getFallbackUrl(startProxyExports.getProxyPackage()), + startProxyExports.getFallbackUrl( + startProxyExports.getProxyPackage(getTestPlatform(state)), + ), ); stub.restore(); @@ -773,18 +820,19 @@ test.serial( test.serial("getDownloadUrl returns matching release asset", async (t) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); const assets = [ { name: "foo", url: "other-url" }, - { name: startProxyExports.getProxyPackage(), url: "url-we-want" }, + { + name: startProxyExports.getProxyPackage(getTestPlatform(state)), + url: "url-we-want", + }, ]; mockGetReleaseByTag(assets); await withTmpDir(async (tempDir) => { const features = mockOfflineFeatures(tempDir, logger); - const info = await startProxyExports.getDownloadUrl( - getRunnerLogger(true), - features, - ); + const info = await startProxyExports.getDownloadUrl({ ...state, features }); t.is(info.version, defaults.cliVersion); t.is(info.url, "url-we-want"); @@ -918,7 +966,9 @@ test.serial( sinon.stub(toolcache, "find").returns(toolcachePath); const features = mockOfflineFeatures(tempDir, logger); - const path = await startProxyExports.getProxyBinaryPath(logger, features); + const path = await startProxyExports.getProxyBinaryPath( + initAllState({ logger, features }), + ); t.assert(path); t.is( @@ -933,9 +983,13 @@ test.serial( "getProxyBinaryPath - downloads proxy if not in cache", async (t) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); const downloadUrl = "url-we-want"; mockGetReleaseByTag([ - { name: startProxyExports.getProxyPackage(), url: downloadUrl }, + { + name: startProxyExports.getProxyPackage(getTestPlatform(state)), + url: downloadUrl, + }, ]); const toolcachePath = "/path/to/proxy/dir"; @@ -958,10 +1012,10 @@ test.serial( .resolves(extractedPath); const cacheDir = sinon.stub(toolcache, "cacheDir").resolves(toolcachePath); - const path = await startProxyExports.getProxyBinaryPath( - logger, - createFeatures([]), - ); + const path = await startProxyExports.getProxyBinaryPath({ + ...state, + features: createFeatures([]), + }); t.assert(find.calledOnce); t.assert(getApiDetails.calledOnce); @@ -976,7 +1030,7 @@ test.serial( ); checkExpectedLogMessages(t, logger.messages, [ - `Found '${startProxyExports.getProxyPackage()}' in release '${defaults.bundleVersion}' at '${downloadUrl}'`, + `Found '${startProxyExports.getProxyPackage(getTestPlatform(state))}' in release '${defaults.bundleVersion}' at '${downloadUrl}'`, ]); }, ); @@ -985,6 +1039,7 @@ test.serial( "getProxyBinaryPath - downloads proxy based on features if not in cache", async (t) => { const logger = new RecordingLogger(); + const state = initAllState({ logger }); const expectedTag = "codeql-bundle-v2.20.1"; const expectedParams = { owner: "github", @@ -994,7 +1049,7 @@ test.serial( const downloadUrl = "url-we-want"; const assets = [ { - name: startProxyExports.getProxyPackage(), + name: startProxyExports.getProxyPackage(getTestPlatform(state)), url: downloadUrl, }, ]; @@ -1045,7 +1100,10 @@ test.serial( .resolves({ enabledVersions: [{ cliVersion: "2.20.1", tagName: expectedTag }], }); - const path = await startProxyExports.getProxyBinaryPath(logger, features); + const path = await startProxyExports.getProxyBinaryPath({ + ...state, + features, + }); t.assert(getDefaultCliVersion.calledOnce); sinon.assert.calledOnceWithMatch( @@ -1067,7 +1125,7 @@ test.serial( }); checkExpectedLogMessages(t, logger.messages, [ - `Found '${startProxyExports.getProxyPackage()}' in release '${expectedTag}' at '${downloadUrl}'`, + `Found '${startProxyExports.getProxyPackage(getTestPlatform(state))}' in release '${expectedTag}' at '${downloadUrl}'`, ]); }, ); diff --git a/src/start-proxy.ts b/src/start-proxy.ts index caa1b3054..6221c9940 100644 --- a/src/start-proxy.ts +++ b/src/start-proxy.ts @@ -3,6 +3,7 @@ import * as path from "path"; import * as core from "@actions/core"; import * as toolcache from "@actions/tool-cache"; +import { ActionState } from "./action-common"; import { getApiClient, getApiDetails, @@ -20,6 +21,7 @@ import { import * as json from "./json"; import { BuiltInLanguage } from "./languages"; import { Logger } from "./logging"; +import { BundlePlatform, getBundlePlatform } from "./platform"; import { Address, Registry, @@ -370,14 +372,10 @@ export function getCredentials( /** * Gets the name of the proxy release asset for the current platform. + * + * @param platform The platform to get the asset name for. */ -export function getProxyPackage(): string { - const platform = - process.platform === "win32" - ? "win64" - : process.platform === "darwin" - ? "osx64" - : "linux64"; +export function getProxyPackage(platform: BundlePlatform): string { return `${UPDATEJOB_PROXY}-${platform}.tar.gz`; } @@ -417,25 +415,33 @@ async function getCliVersionFromFeatures( * Determines the URL of the proxy release asset that we should download if its not * already in the toolcache, and its version. * - * @param logger The logger to use. - * @param features Information about enabled features. + * @param action The action state. * @returns Returns the download URL and version of the proxy package we plan to use. */ export async function getDownloadUrl( - logger: Logger, - features: FeatureEnablement, + action: ActionState<["Base", "Logger", "FeatureFlags"]>, ): Promise<{ url: string; version: string }> { - const proxyPackage = getProxyPackage(); + // Default to linux64 if we don't recognise the platform+arch pair. + // This maintains the behaviour we had before switching to `getBundlePlatform` here. + let platform = getBundlePlatform(action.platform, action.arch); + if (platform === undefined) { + action.logger.warning( + `Unsupported platform ${action.platform} on architecture ${action.arch}, defaulting to ${BundlePlatform.Linux64}`, + ); + platform = BundlePlatform.Linux64; + } + + const proxyPackage = getProxyPackage(platform); try { - const useFeaturesToDetermineCLI = await features.getValue( + const useFeaturesToDetermineCLI = await action.features.getValue( Feature.StartProxyUseFeaturesRelease, ); // Retrieve information about the CLI version we should use. This will be either the linked // version, or the one enabled by FFs. const versionInfo = useFeaturesToDetermineCLI - ? (await getCliVersionFromFeatures(features)).enabledVersions[0] + ? (await getCliVersionFromFeatures(action.features)).enabledVersions[0] : { cliVersion: defaults.cliVersion, tagName: defaults.bundleVersion, @@ -447,7 +453,7 @@ export async function getDownloadUrl( // Search the release's assets to find the one we are looking for. for (const asset of cliRelease.data.assets) { if (asset.name === proxyPackage) { - logger.info( + action.logger.info( `Found '${proxyPackage}' in release '${versionInfo.tagName}' at '${asset.url}'`, ); return { @@ -460,13 +466,13 @@ export async function getDownloadUrl( } } } catch (ex) { - logger.warning( + action.logger.warning( `Failed to retrieve information about the linked release: ${getErrorMessage(ex)}`, ); } // Fallback to the hard-coded URL. - logger.info( + action.logger.info( `Did not find '${proxyPackage}' in the linked release, falling back to hard-coded version.`, ); return { @@ -559,15 +565,15 @@ export function getProxyFilename() { * runner's tool cache. Otherwise, it downloads and extracts the proxy binary, * and stores it in the tool cache. * - * @param logger The logger to use. + * @param action The action state. * @returns The path to the proxy binary. */ export async function getProxyBinaryPath( - logger: Logger, - features: FeatureEnablement, + action: ActionState<["Base", "Logger", "FeatureFlags"]>, ): Promise { + const logger = action.logger; const proxyFileName = getProxyFilename(); - const proxyInfo = await getDownloadUrl(logger, features); + const proxyInfo = await getDownloadUrl(action); let proxyBin = toolcache.find(proxyFileName, proxyInfo.version); if (!proxyBin) { diff --git a/src/testing-utils.ts b/src/testing-utils.ts index f15cee2e7..a5ba50554 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -234,6 +234,8 @@ export function initAllState( return { name: ActionName.Init, startedAt: new Date(), + platform: process.platform, + arch: process.arch, logger: new RecordingLogger(), env, actions: getTestActionsEnv(env),