mirror of
https://github.com/github/codeql-action.git
synced 2026-01-04 21:50:17 +08:00
Merge pull request #3110 from github/mbg/proxy/fetch-from-release
Fetch proxy binaries from `defaults.json` release
This commit is contained in:
@@ -7,13 +7,14 @@ import { pki } from "node-forge";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { getActionsLogger, Logger } from "./logging";
|
||||
import { Credential, getCredentials } from "./start-proxy";
|
||||
import {
|
||||
Credential,
|
||||
getCredentials,
|
||||
getDownloadUrl,
|
||||
UPDATEJOB_PROXY,
|
||||
} from "./start-proxy";
|
||||
import * as util from "./util";
|
||||
|
||||
const UPDATEJOB_PROXY = "update-job-proxy";
|
||||
const UPDATEJOB_PROXY_VERSION = "v2.0.20250624110901";
|
||||
const UPDATEJOB_PROXY_URL_PREFIX =
|
||||
"https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.22.0/";
|
||||
const KEY_SIZE = 2048;
|
||||
const KEY_EXPIRY_YEARS = 2;
|
||||
|
||||
@@ -119,7 +120,7 @@ async function runWrapper() {
|
||||
};
|
||||
|
||||
// Start the Proxy
|
||||
const proxyBin = await getProxyBinaryPath();
|
||||
const proxyBin = await getProxyBinaryPath(logger);
|
||||
await startProxy(proxyBin, proxyConfig, proxyLogFilePath, logger);
|
||||
}
|
||||
|
||||
@@ -184,26 +185,19 @@ async function startProxy(
|
||||
}
|
||||
}
|
||||
|
||||
async function getProxyBinaryPath(): Promise<string> {
|
||||
async function getProxyBinaryPath(logger: Logger): Promise<string> {
|
||||
const proxyFileName =
|
||||
process.platform === "win32" ? `${UPDATEJOB_PROXY}.exe` : UPDATEJOB_PROXY;
|
||||
const platform =
|
||||
process.platform === "win32"
|
||||
? "win64"
|
||||
: process.platform === "darwin"
|
||||
? "osx64"
|
||||
: "linux64";
|
||||
const proxyPackage = `${UPDATEJOB_PROXY}-${platform}.tar.gz`;
|
||||
const proxyURL = `${UPDATEJOB_PROXY_URL_PREFIX}${proxyPackage}`;
|
||||
const proxyInfo = await getDownloadUrl(logger);
|
||||
|
||||
let proxyBin = toolcache.find(proxyFileName, UPDATEJOB_PROXY_VERSION);
|
||||
let proxyBin = toolcache.find(proxyFileName, proxyInfo.version);
|
||||
if (!proxyBin) {
|
||||
const temp = await toolcache.downloadTool(proxyURL);
|
||||
const temp = await toolcache.downloadTool(proxyInfo.url);
|
||||
const extracted = await toolcache.extractTar(temp);
|
||||
proxyBin = await toolcache.cacheDir(
|
||||
extracted,
|
||||
proxyFileName,
|
||||
UPDATEJOB_PROXY_VERSION,
|
||||
proxyInfo.version,
|
||||
);
|
||||
}
|
||||
proxyBin = path.join(proxyBin, proxyFileName);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import test from "ava";
|
||||
import sinon from "sinon";
|
||||
|
||||
import * as apiClient from "./api-client";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import * as startProxyExports from "./start-proxy";
|
||||
@@ -197,3 +200,68 @@ test("parseLanguage", async (t) => {
|
||||
t.deepEqual(parseLanguage(" "), undefined);
|
||||
t.deepEqual(parseLanguage(""), undefined);
|
||||
});
|
||||
|
||||
function mockGetReleaseByTag(assets?: Array<{ name: string; url?: string }>) {
|
||||
const mockClient = sinon.stub(apiClient, "getApiClient");
|
||||
const getReleaseByTag =
|
||||
assets === undefined
|
||||
? sinon.stub().rejects()
|
||||
: sinon.stub().resolves({
|
||||
status: 200,
|
||||
data: { assets },
|
||||
headers: {},
|
||||
url: "GET /repos/:owner/:repo/releases/tags/:tag",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
mockClient.returns({
|
||||
rest: {
|
||||
repos: {
|
||||
getReleaseByTag,
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
return mockClient;
|
||||
}
|
||||
|
||||
test("getDownloadUrl returns fallback when `getLinkedRelease` rejects", async (t) => {
|
||||
mockGetReleaseByTag();
|
||||
|
||||
const info = await startProxyExports.getDownloadUrl(getRunnerLogger(true));
|
||||
|
||||
t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION);
|
||||
t.is(
|
||||
info.url,
|
||||
startProxyExports.getFallbackUrl(startProxyExports.getProxyPackage()),
|
||||
);
|
||||
});
|
||||
|
||||
test("getDownloadUrl returns fallback when there's no matching release asset", async (t) => {
|
||||
const testAssets = [[], [{ name: "foo" }]];
|
||||
|
||||
for (const assets of testAssets) {
|
||||
const stub = mockGetReleaseByTag(assets);
|
||||
const info = await startProxyExports.getDownloadUrl(getRunnerLogger(true));
|
||||
|
||||
t.is(info.version, startProxyExports.UPDATEJOB_PROXY_VERSION);
|
||||
t.is(
|
||||
info.url,
|
||||
startProxyExports.getFallbackUrl(startProxyExports.getProxyPackage()),
|
||||
);
|
||||
|
||||
stub.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test("getDownloadUrl returns matching release asset", async (t) => {
|
||||
const assets = [
|
||||
{ name: "foo", url: "other-url" },
|
||||
{ name: startProxyExports.getProxyPackage(), url: "url-we-want" },
|
||||
];
|
||||
mockGetReleaseByTag(assets);
|
||||
|
||||
const info = await startProxyExports.getDownloadUrl(getRunnerLogger(true));
|
||||
|
||||
t.is(info.version, defaults.cliVersion);
|
||||
t.is(info.url, "url-we-want");
|
||||
});
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { getApiClient } from "./api-client";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { Logger } from "./logging";
|
||||
import { ConfigurationError, isDefined } from "./util";
|
||||
import { ConfigurationError, getErrorMessage, isDefined } from "./util";
|
||||
|
||||
export const UPDATEJOB_PROXY = "update-job-proxy";
|
||||
export const UPDATEJOB_PROXY_VERSION = "v2.0.20250624110901";
|
||||
export const UPDATEJOB_PROXY_URL_PREFIX =
|
||||
"https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.22.0/";
|
||||
|
||||
export type Credential = {
|
||||
type: string;
|
||||
@@ -166,3 +173,87 @@ export function getCredentials(
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the proxy release asset for the current platform.
|
||||
*/
|
||||
export function getProxyPackage(): string {
|
||||
const platform =
|
||||
process.platform === "win32"
|
||||
? "win64"
|
||||
: process.platform === "darwin"
|
||||
? "osx64"
|
||||
: "linux64";
|
||||
return `${UPDATEJOB_PROXY}-${platform}.tar.gz`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fallback URL for downloading the proxy release asset.
|
||||
*
|
||||
* @param proxyPackage The asset name.
|
||||
* @returns The full URL to download the specified asset from the fallback release.
|
||||
*/
|
||||
export function getFallbackUrl(proxyPackage: string): string {
|
||||
return `${UPDATEJOB_PROXY_URL_PREFIX}${proxyPackage}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the GitHub API to obtain information about the CodeQL CLI bundle release
|
||||
* that is pointed at by `defaults.json`.
|
||||
*
|
||||
* @returns The response from the GitHub API.
|
||||
*/
|
||||
export async function getLinkedRelease() {
|
||||
return getApiClient().rest.repos.getReleaseByTag({
|
||||
owner: "github",
|
||||
repo: "codeql-action",
|
||||
tag: defaults.bundleVersion,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @returns Returns the download URL and version of the proxy package we plan to use.
|
||||
*/
|
||||
export async function getDownloadUrl(
|
||||
logger: Logger,
|
||||
): Promise<{ url: string; version: string }> {
|
||||
const proxyPackage = getProxyPackage();
|
||||
|
||||
try {
|
||||
// Try to retrieve information about the CLI bundle release pointed at by `defaults.json`.
|
||||
const cliRelease = await getLinkedRelease();
|
||||
|
||||
// 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(
|
||||
`Found '${proxyPackage}' in release '${defaults.bundleVersion}' at '${asset.url}'`,
|
||||
);
|
||||
return {
|
||||
url: asset.url,
|
||||
// The `update-job-proxy` doesn't have a version as such. Since we now bundle it
|
||||
// with CodeQL CLI bundle releases, we use the corresponding CLI version to
|
||||
// differentiate between (potentially) different versions of `update-job-proxy`.
|
||||
version: defaults.cliVersion,
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
logger.warning(
|
||||
`Failed to retrieve information about the linked release: ${getErrorMessage(ex)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback to the hard-coded URL.
|
||||
logger.info(
|
||||
`Did not find '${proxyPackage}' in the linked release, falling back to hard-coded version.`,
|
||||
);
|
||||
return {
|
||||
url: getFallbackUrl(proxyPackage),
|
||||
version: UPDATEJOB_PROXY_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user