Merge pull request #2631 from github/henrymercer/extract-direct-to-toolcache
Extract directly to the toolcache
This commit is contained in:
commit
3096afedf9
21 changed files with 484 additions and 227 deletions
101
.github/workflows/__extract-direct-to-toolcache.yml
generated
vendored
Normal file
101
.github/workflows/__extract-direct-to-toolcache.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# Warning: This file is generated automatically, and should not be modified.
|
||||
# Instead, please modify the template in the pr-checks directory and run:
|
||||
# (cd pr-checks; pip install ruamel.yaml@0.17.31 && python3 sync.py)
|
||||
# to regenerate this file.
|
||||
|
||||
name: PR Check - Extract directly to toolcache
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GO111MODULE: auto
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/v*
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
- ready_for_review
|
||||
schedule:
|
||||
- cron: '0 5 * * *'
|
||||
workflow_dispatch: {}
|
||||
jobs:
|
||||
extract-direct-to-toolcache:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-latest
|
||||
version: linked
|
||||
- os: ubuntu-latest
|
||||
version: linked
|
||||
- os: windows-latest
|
||||
version: linked
|
||||
name: Extract directly to toolcache
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
timeout-minutes: 45
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Setup Python on macOS
|
||||
uses: actions/setup-python@v5
|
||||
if: runner.os == 'macOS' && matrix.version == 'stable-v2.14.6'
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Prepare test
|
||||
id: prepare-test
|
||||
uses: ./.github/actions/prepare-test
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
use-all-platform-bundle: 'false'
|
||||
setup-kotlin: 'true'
|
||||
- name: Remove CodeQL from toolcache
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL');
|
||||
fs.rmdirSync(codeqlPath, { recursive: true });
|
||||
- name: Install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache
|
||||
- name: Check toolcache does not contain CodeQL
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const toolcache = require('@actions/tool-cache');
|
||||
const allCodeqlVersions = toolcache.findAllVersions('CodeQL');
|
||||
if (allCodeqlVersions.length !== 0) {
|
||||
throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`);
|
||||
}
|
||||
console.log('No versions of CodeQL found in the toolcache');
|
||||
- id: init
|
||||
uses: ./../action/init
|
||||
with:
|
||||
languages: javascript
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
- uses: ./../action/analyze
|
||||
with:
|
||||
output: ${{ runner.temp }}/results
|
||||
upload-database: false
|
||||
- name: Check CodeQL is installed within the toolcache
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const toolcache = require('@actions/tool-cache');
|
||||
const allCodeqlVersions = toolcache.findAllVersions('CodeQL');
|
||||
console.log(`Found CodeQL versions: ${allCodeqlVersions}`);
|
||||
if (allCodeqlVersions.length === 0) {
|
||||
throw new Error('CodeQL not found in toolcache');
|
||||
}
|
||||
if (allCodeqlVersions.length > 1) {
|
||||
throw new Error('Multiple CodeQL versions found in toolcache');
|
||||
}
|
||||
env:
|
||||
CODEQL_ACTION_EXTRACT_TOOLCACHE: true
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
|
|
@ -6,7 +6,7 @@ Note that the only difference between `v2` and `v3` of the CodeQL Action is the
|
|||
|
||||
## [UNRELEASED]
|
||||
|
||||
No user facing changes.
|
||||
- We are rolling out a change in December 2024 that will extract the CodeQL bundle directly to the toolcache to improve performance. [#2631](https://github.com/github/codeql-action/pull/2631)
|
||||
|
||||
## 3.27.6 - 03 Dec 2024
|
||||
|
||||
|
|
|
|||
2
lib/codeql.js
generated
2
lib/codeql.js
generated
|
|
@ -146,7 +146,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV
|
|||
};
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to download and extract CodeQL CLI: ${(0, util_1.getErrorMessage)(e)}`);
|
||||
throw new Error(`Unable to download and extract CodeQL CLI: ${(0, util_1.getErrorMessage)(e)}${e instanceof Error && e.stack ? `\n\nDetails: ${e.stack}` : ""}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
35
lib/codeql.test.js
generated
35
lib/codeql.test.js
generated
|
|
@ -51,7 +51,6 @@ const cli_errors_1 = require("./cli-errors");
|
|||
const codeql = __importStar(require("./codeql"));
|
||||
const defaults = __importStar(require("./defaults.json"));
|
||||
const doc_url_1 = require("./doc-url");
|
||||
const feature_flags_test_1 = require("./feature-flags.test");
|
||||
const languages_1 = require("./languages");
|
||||
const logging_1 = require("./logging");
|
||||
const setup_codeql_1 = require("./setup-codeql");
|
||||
|
|
@ -61,12 +60,7 @@ const util = __importStar(require("./util"));
|
|||
const util_1 = require("./util");
|
||||
(0, testing_utils_1.setupTests)(ava_1.default);
|
||||
let stubConfig;
|
||||
// TODO: Remove when when we no longer need to pass in features (https://github.com/github/codeql-action/issues/2600)
|
||||
const expectedFeatureEnablement = (0, feature_flags_test_1.initializeFeatures)(true);
|
||||
expectedFeatureEnablement.getValue = function (feature) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return expectedFeatureEnablement[feature];
|
||||
};
|
||||
const NO_FEATURES = (0, testing_utils_1.createFeatures)([]);
|
||||
ava_1.default.beforeEach(() => {
|
||||
(0, util_1.initializeEnvironment)("1.2.3");
|
||||
stubConfig = (0, testing_utils_1.createTestConfig)({
|
||||
|
|
@ -77,7 +71,7 @@ async function installIntoToolcache({ apiDetails = testing_utils_1.SAMPLE_DOTCOM
|
|||
const url = (0, testing_utils_1.mockBundleDownloadApi)({ apiDetails, isPinned, tagName });
|
||||
await codeql.setupCodeQL(cliVersion !== undefined ? undefined : url, apiDetails, tmpDir, util.GitHubVariant.GHES, cliVersion !== undefined
|
||||
? { cliVersion, tagName }
|
||||
: testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
: testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
}
|
||||
function mockReleaseApi({ apiDetails = testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, assetNames, tagName, }) {
|
||||
return (0, nock_1.default)(apiDetails.apiURL)
|
||||
|
|
@ -98,11 +92,8 @@ function mockApiDetails(apiDetails) {
|
|||
.stub(actionsUtil, "getRequiredInput")
|
||||
.withArgs("token")
|
||||
.returns(apiDetails.auth);
|
||||
const requiredEnvParamStub = sinon.stub(util, "getRequiredEnvParam");
|
||||
requiredEnvParamStub.withArgs("GITHUB_SERVER_URL").returns(apiDetails.url);
|
||||
requiredEnvParamStub
|
||||
.withArgs("GITHUB_API_URL")
|
||||
.returns(apiDetails.apiURL || "");
|
||||
process.env["GITHUB_SERVER_URL"] = apiDetails.url;
|
||||
process.env["GITHUB_API_URL"] = apiDetails.apiURL || "";
|
||||
}
|
||||
(0, ava_1.default)("downloads and caches explicitly requested bundles that aren't in the toolcache", async (t) => {
|
||||
await util.withTmpDir(async (tmpDir) => {
|
||||
|
|
@ -114,7 +105,7 @@ function mockApiDetails(apiDetails) {
|
|||
tagName: `codeql-bundle-${version}`,
|
||||
isPinned: false,
|
||||
});
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.assert(toolcache.find("CodeQL", `0.0.0-${version}`));
|
||||
t.is(result.toolsVersion, `0.0.0-${version}`);
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||
|
|
@ -129,7 +120,7 @@ function mockApiDetails(apiDetails) {
|
|||
tagName: `codeql-bundle-v2.15.0`,
|
||||
isPinned: false,
|
||||
});
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.is(toolcache.findAllVersions("CodeQL").length, 1);
|
||||
t.assert(toolcache.find("CodeQL", `2.15.0`));
|
||||
t.is(result.toolsVersion, `2.15.0`);
|
||||
|
|
@ -150,7 +141,7 @@ function mockApiDetails(apiDetails) {
|
|||
const url = (0, testing_utils_1.mockBundleDownloadApi)({
|
||||
tagName: "codeql-bundle-20200610",
|
||||
});
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
|
||||
t.deepEqual(result.toolsVersion, "0.0.0-20200610");
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||
|
|
@ -178,7 +169,7 @@ for (const { tagName, expectedToolcacheVersion, } of EXPLICITLY_REQUESTED_BUNDLE
|
|||
const url = (0, testing_utils_1.mockBundleDownloadApi)({
|
||||
tagName,
|
||||
});
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL(url, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
|
||||
t.deepEqual(result.toolsVersion, expectedToolcacheVersion);
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||
|
|
@ -201,7 +192,7 @@ for (const toolcacheVersion of [
|
|||
.withArgs("CodeQL", toolcacheVersion)
|
||||
.returns("path/to/cached/codeql");
|
||||
sinon.stub(toolcache, "findAllVersions").returns([toolcacheVersion]);
|
||||
const result = await codeql.setupCodeQL(undefined, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL(undefined, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.is(result.toolsVersion, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Toolcache);
|
||||
t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined);
|
||||
|
|
@ -221,7 +212,7 @@ for (const toolcacheVersion of [
|
|||
const result = await codeql.setupCodeQL(undefined, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.GHES, {
|
||||
cliVersion: defaults.cliVersion,
|
||||
tagName: defaults.bundleVersion,
|
||||
}, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
}, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.deepEqual(result.toolsVersion, "0.0.0-20200601");
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Toolcache);
|
||||
t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined);
|
||||
|
|
@ -245,7 +236,7 @@ for (const toolcacheVersion of [
|
|||
const result = await codeql.setupCodeQL(undefined, testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.GHES, {
|
||||
cliVersion: defaults.cliVersion,
|
||||
tagName: defaults.bundleVersion,
|
||||
}, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
}, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||
if (result.toolsDownloadStatusReport) {
|
||||
|
|
@ -266,7 +257,7 @@ for (const toolcacheVersion of [
|
|||
(0, testing_utils_1.mockBundleDownloadApi)({
|
||||
tagName: defaults.bundleVersion,
|
||||
});
|
||||
const result = await codeql.setupCodeQL("latest", testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL("latest", testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||
if (result.toolsDownloadStatusReport) {
|
||||
|
|
@ -290,7 +281,7 @@ for (const toolcacheVersion of [
|
|||
platformSpecific: false,
|
||||
tagName: "codeql-bundle-20230203",
|
||||
});
|
||||
const result = await codeql.setupCodeQL("https://github.com/codeql-testing/codeql-cli-nightlies/releases/download/codeql-bundle-20230203/codeql-bundle.tar.gz", testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), expectedFeatureEnablement, false);
|
||||
const result = await codeql.setupCodeQL("https://github.com/codeql-testing/codeql-cli-nightlies/releases/download/codeql-bundle-20230203/codeql-bundle.tar.gz", testing_utils_1.SAMPLE_DOTCOM_API_DETAILS, tmpDir, util.GitHubVariant.DOTCOM, testing_utils_1.SAMPLE_DEFAULT_CLI_VERSION, (0, logging_1.getRunnerLogger)(true), NO_FEATURES, false);
|
||||
t.is(result.toolsVersion, "0.0.0-20230203");
|
||||
t.is(result.toolsSource, setup_codeql_1.ToolsSource.Download);
|
||||
if (result.toolsDownloadStatusReport) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
6
lib/feature-flags.js
generated
6
lib/feature-flags.js
generated
|
|
@ -71,6 +71,7 @@ var Feature;
|
|||
Feature["DisableJavaBuildlessEnabled"] = "disable_java_buildless_enabled";
|
||||
Feature["DisableKotlinAnalysisEnabled"] = "disable_kotlin_analysis_enabled";
|
||||
Feature["ExportDiagnosticsEnabled"] = "export_diagnostics_enabled";
|
||||
Feature["ExtractToToolcache"] = "extract_to_toolcache";
|
||||
Feature["PythonDefaultIsToNotExtractStdlib"] = "python_default_is_to_not_extract_stdlib";
|
||||
Feature["QaTelemetryEnabled"] = "qa_telemetry_enabled";
|
||||
Feature["ZstdBundleStreamingExtraction"] = "zstd_bundle_streaming_extraction";
|
||||
|
|
@ -131,6 +132,11 @@ exports.featureConfig = {
|
|||
legacyApi: true,
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.ExtractToToolcache]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_EXTRACT_TOOLCACHE",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.PythonDefaultIsToNotExtractStdlib]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_DISABLE_PYTHON_STANDARD_LIBRARY_EXTRACTION",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
56
lib/setup-codeql.js
generated
56
lib/setup-codeql.js
generated
|
|
@ -51,6 +51,7 @@ const perf_hooks_1 = require("perf_hooks");
|
|||
const toolcache = __importStar(require("@actions/tool-cache"));
|
||||
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
||||
const semver = __importStar(require("semver"));
|
||||
const uuid_1 = require("uuid");
|
||||
const actions_util_1 = require("./actions-util");
|
||||
const api = __importStar(require("./api-client"));
|
||||
const defaults = __importStar(require("./defaults.json"));
|
||||
|
|
@ -411,9 +412,13 @@ const downloadCodeQL = async function (codeqlURL, maybeBundleVersion, maybeCliVe
|
|||
else {
|
||||
logger.debug("Downloading CodeQL tools without an authorization token.");
|
||||
}
|
||||
const { extractedBundlePath, statusReport } = await (0, tools_download_1.downloadAndExtract)(codeqlURL, authorization, { "User-Agent": "CodeQL Action", ...headers }, tarVersion, tempDir, features, logger);
|
||||
const bundleVersion = maybeBundleVersion ?? tryGetBundleVersionFromUrl(codeqlURL, logger);
|
||||
if (bundleVersion === undefined) {
|
||||
const toolcacheInfo = getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger);
|
||||
const extractToToolcache = !!toolcacheInfo && !!(await features.getValue(feature_flags_1.Feature.ExtractToToolcache));
|
||||
const extractedBundlePath = extractToToolcache
|
||||
? toolcacheInfo.path
|
||||
: getTempExtractionDir(tempDir);
|
||||
let statusReport = await (0, tools_download_1.downloadAndExtract)(codeqlURL, extractedBundlePath, authorization, { "User-Agent": "CodeQL Action", ...headers }, tarVersion, features, logger);
|
||||
if (!toolcacheInfo) {
|
||||
logger.debug("Could not cache CodeQL tools because we could not determine the bundle version from the " +
|
||||
`URL ${codeqlURL}.`);
|
||||
return {
|
||||
|
|
@ -422,22 +427,42 @@ const downloadCodeQL = async function (codeqlURL, maybeBundleVersion, maybeCliVe
|
|||
toolsVersion: maybeCliVersion ?? "unknown",
|
||||
};
|
||||
}
|
||||
logger.debug("Caching CodeQL bundle.");
|
||||
const toolcacheVersion = getCanonicalToolcacheVersion(maybeCliVersion, bundleVersion, logger);
|
||||
const toolcacheStart = perf_hooks_1.performance.now();
|
||||
const toolcachedBundlePath = await toolcache.cacheDir(extractedBundlePath, "CodeQL", toolcacheVersion);
|
||||
logger.info(`Added CodeQL bundle to the tool cache (${(0, logging_1.formatDuration)(perf_hooks_1.performance.now() - toolcacheStart)}).`);
|
||||
// Defensive check: we expect `cacheDir` to copy the bundle to a new location.
|
||||
if (toolcachedBundlePath !== extractedBundlePath) {
|
||||
await (0, util_1.cleanUpGlob)(extractedBundlePath, "CodeQL bundle from temporary directory", logger);
|
||||
let codeqlFolder = extractedBundlePath;
|
||||
if (extractToToolcache) {
|
||||
(0, tools_download_1.writeToolcacheMarkerFile)(toolcacheInfo.path, logger);
|
||||
}
|
||||
else {
|
||||
logger.debug("Caching CodeQL bundle.");
|
||||
const toolcacheStart = perf_hooks_1.performance.now();
|
||||
codeqlFolder = await toolcache.cacheDir(extractedBundlePath, "CodeQL", toolcacheInfo.version);
|
||||
const cacheDurationMs = perf_hooks_1.performance.now() - toolcacheStart;
|
||||
logger.info(`Added CodeQL bundle to the tool cache (${(0, logging_1.formatDuration)(cacheDurationMs)}).`);
|
||||
statusReport = {
|
||||
...statusReport,
|
||||
cacheDurationMs,
|
||||
};
|
||||
// Defensive check: we expect `cacheDir` to copy the bundle to a new location.
|
||||
if (codeqlFolder !== extractedBundlePath) {
|
||||
await (0, util_1.cleanUpGlob)(extractedBundlePath, "CodeQL bundle from temporary directory", logger);
|
||||
}
|
||||
}
|
||||
return {
|
||||
codeqlFolder: toolcachedBundlePath,
|
||||
codeqlFolder,
|
||||
statusReport,
|
||||
toolsVersion: maybeCliVersion ?? toolcacheVersion,
|
||||
toolsVersion: maybeCliVersion ?? toolcacheInfo.version,
|
||||
};
|
||||
};
|
||||
exports.downloadCodeQL = downloadCodeQL;
|
||||
function getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger) {
|
||||
if (maybeBundleVersion) {
|
||||
const version = getCanonicalToolcacheVersion(maybeCliVersion, maybeBundleVersion, logger);
|
||||
return {
|
||||
path: (0, tools_download_1.getToolcacheDirectory)(version),
|
||||
version,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function getCodeQLURLVersion(url) {
|
||||
const match = url.match(/\/codeql-bundle-(.*)\//);
|
||||
if (match === null || match.length < 2) {
|
||||
|
|
@ -485,7 +510,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, featu
|
|||
switch (source.sourceType) {
|
||||
case "local": {
|
||||
const compressionMethod = tar.inferCompressionMethod(source.codeqlTarPath);
|
||||
codeqlFolder = await tar.extract(source.codeqlTarPath, compressionMethod, zstdAvailability.version, logger);
|
||||
codeqlFolder = await tar.extract(source.codeqlTarPath, getTempExtractionDir(tempDir), compressionMethod, zstdAvailability.version, logger);
|
||||
toolsSource = ToolsSource.Local;
|
||||
break;
|
||||
}
|
||||
|
|
@ -520,4 +545,7 @@ async function useZstdBundle(cliVersion, tarSupportsZstd) {
|
|||
tarSupportsZstd &&
|
||||
semver.gte(cliVersion, feature_flags_1.CODEQL_VERSION_ZSTD_BUNDLE));
|
||||
}
|
||||
function getTempExtractionDir(tempDir) {
|
||||
return path.join(tempDir, (0, uuid_1.v4)());
|
||||
}
|
||||
//# sourceMappingURL=setup-codeql.js.map
|
||||
File diff suppressed because one or more lines are too long
64
lib/tar.js
generated
64
lib/tar.js
generated
|
|
@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isZstdAvailable = isZstdAvailable;
|
||||
exports.extract = extract;
|
||||
|
|
@ -42,12 +39,10 @@ exports.extractTarZst = extractTarZst;
|
|||
exports.inferCompressionMethod = inferCompressionMethod;
|
||||
const child_process_1 = require("child_process");
|
||||
const fs = __importStar(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const stream = __importStar(require("stream"));
|
||||
const toolrunner_1 = require("@actions/exec/lib/toolrunner");
|
||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
||||
const safe_which_1 = require("@chrisgavin/safe-which");
|
||||
const uuid_1 = require("uuid");
|
||||
const actions_util_1 = require("./actions-util");
|
||||
const util_1 = require("./util");
|
||||
const MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3";
|
||||
|
|
@ -113,28 +108,30 @@ async function isZstdAvailable(logger) {
|
|||
return { available: false, foundZstdBinary };
|
||||
}
|
||||
}
|
||||
async function extract(tarPath, compressionMethod, tarVersion, logger) {
|
||||
async function extract(tarPath, dest, compressionMethod, tarVersion, logger) {
|
||||
// Ensure destination exists
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
switch (compressionMethod) {
|
||||
case "gzip":
|
||||
// Defensively continue to call the toolcache API as requesting a gzipped
|
||||
// bundle may be a fallback option.
|
||||
return await toolcache.extractTar(tarPath);
|
||||
case "zstd":
|
||||
return await toolcache.extractTar(tarPath, dest);
|
||||
case "zstd": {
|
||||
if (!tarVersion) {
|
||||
throw new Error("Could not determine tar version, which is required to extract a Zstandard archive.");
|
||||
}
|
||||
return await extractTarZst(tarPath, tarVersion, logger);
|
||||
await extractTarZst(tarPath, dest, tarVersion, logger);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Extract a compressed tar archive
|
||||
*
|
||||
* @param tar tar stream, or path to the tar
|
||||
* @param dest destination directory. Optional.
|
||||
* @returns path to the destination directory
|
||||
* @param dest destination directory
|
||||
*/
|
||||
async function extractTarZst(tar, tarVersion, logger) {
|
||||
const dest = await createExtractFolder();
|
||||
async function extractTarZst(tar, dest, tarVersion, logger) {
|
||||
logger.debug(`Extracting to ${dest}.${tar instanceof stream.Readable
|
||||
? ` Input stream has high water mark ${tar.readableHighWaterMark}.`
|
||||
: ""}`);
|
||||
|
|
@ -148,22 +145,27 @@ async function extractTarZst(tar, tarVersion, logger) {
|
|||
}
|
||||
args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest);
|
||||
process.stdout.write(`[command]tar ${args.join(" ")}\n`);
|
||||
const tarProcess = (0, child_process_1.spawn)("tar", args, { stdio: "pipe" });
|
||||
let stdout = "";
|
||||
tarProcess.stdout?.on("data", (data) => {
|
||||
stdout += data.toString();
|
||||
process.stdout.write(data);
|
||||
});
|
||||
let stderr = "";
|
||||
tarProcess.stderr?.on("data", (data) => {
|
||||
stderr += data.toString();
|
||||
// Mimic the standard behavior of the toolrunner by writing stderr to stdout
|
||||
process.stdout.write(data);
|
||||
});
|
||||
if (tar instanceof stream.Readable) {
|
||||
tar.pipe(tarProcess.stdin);
|
||||
}
|
||||
await new Promise((resolve, reject) => {
|
||||
const tarProcess = (0, child_process_1.spawn)("tar", args, { stdio: "pipe" });
|
||||
let stdout = "";
|
||||
tarProcess.stdout?.on("data", (data) => {
|
||||
stdout += data.toString();
|
||||
process.stdout.write(data);
|
||||
});
|
||||
let stderr = "";
|
||||
tarProcess.stderr?.on("data", (data) => {
|
||||
stderr += data.toString();
|
||||
// Mimic the standard behavior of the toolrunner by writing stderr to stdout
|
||||
process.stdout.write(data);
|
||||
});
|
||||
tarProcess.on("error", (err) => {
|
||||
reject(new Error(`Error while extracting tar: ${err}`));
|
||||
});
|
||||
if (tar instanceof stream.Readable) {
|
||||
tar.pipe(tarProcess.stdin).on("error", (err) => {
|
||||
reject(new Error(`Error while downloading and extracting tar: ${err}`));
|
||||
});
|
||||
}
|
||||
tarProcess.on("exit", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new actions_util_1.CommandInvocationError("tar", args, code ?? undefined, stdout, stderr));
|
||||
|
|
@ -171,18 +173,12 @@ async function extractTarZst(tar, tarVersion, logger) {
|
|||
resolve();
|
||||
});
|
||||
});
|
||||
return dest;
|
||||
}
|
||||
catch (e) {
|
||||
await (0, util_1.cleanUpGlob)(dest, "extraction destination directory", logger);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
async function createExtractFolder() {
|
||||
const dest = path_1.default.join((0, actions_util_1.getTemporaryDirectory)(), (0, uuid_1.v4)());
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
return dest;
|
||||
}
|
||||
function inferCompressionMethod(tarPath) {
|
||||
if (tarPath.endsWith(".tar.gz")) {
|
||||
return "gzip";
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"tar.js","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"tar.js","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"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"}
|
||||
59
lib/tools-download.js
generated
59
lib/tools-download.js
generated
|
|
@ -35,11 +35,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.STREAMING_HIGH_WATERMARK_BYTES = void 0;
|
||||
exports.downloadAndExtract = downloadAndExtract;
|
||||
exports.getToolcacheDirectory = getToolcacheDirectory;
|
||||
exports.writeToolcacheMarkerFile = writeToolcacheMarkerFile;
|
||||
const fs = __importStar(require("fs"));
|
||||
const os = __importStar(require("os"));
|
||||
const path = __importStar(require("path"));
|
||||
const perf_hooks_1 = require("perf_hooks");
|
||||
const toolcache = __importStar(require("@actions/tool-cache"));
|
||||
const follow_redirects_1 = require("follow-redirects");
|
||||
const uuid_1 = require("uuid");
|
||||
const semver = __importStar(require("semver"));
|
||||
const feature_flags_1 = require("./feature-flags");
|
||||
const logging_1 = require("./logging");
|
||||
const tar = __importStar(require("./tar"));
|
||||
|
|
@ -48,6 +52,10 @@ const util_1 = require("./util");
|
|||
* High watermark to use when streaming the download and extraction of the CodeQL tools.
|
||||
*/
|
||||
exports.STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; // 4 MiB
|
||||
/**
|
||||
* The name of the tool cache directory for the CodeQL tools.
|
||||
*/
|
||||
const TOOLCACHE_TOOL_NAME = "CodeQL";
|
||||
function makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs) {
|
||||
return {
|
||||
combinedDurationMs: downloadDurationMs + extractionDurationMs,
|
||||
|
|
@ -64,7 +72,7 @@ function makeStreamedToolsDownloadDurations(combinedDurationMs) {
|
|||
streamExtraction: true,
|
||||
};
|
||||
}
|
||||
async function downloadAndExtract(codeqlURL, authorization, headers, tarVersion, tempDir, features, logger) {
|
||||
async function downloadAndExtract(codeqlURL, dest, authorization, headers, tarVersion, features, logger) {
|
||||
logger.info(`Downloading CodeQL tools from ${codeqlURL} . This may take a while.`);
|
||||
const compressionMethod = tar.inferCompressionMethod(codeqlURL);
|
||||
// TODO: Re-enable streaming when we have a more reliable way to respect proxy settings.
|
||||
|
|
@ -73,54 +81,59 @@ async function downloadAndExtract(codeqlURL, authorization, headers, tarVersion,
|
|||
process.platform === "linux") {
|
||||
logger.info(`Streaming the extraction of the CodeQL bundle.`);
|
||||
const toolsInstallStart = perf_hooks_1.performance.now();
|
||||
const extractedBundlePath = await downloadAndExtractZstdWithStreaming(codeqlURL, authorization, headers, tarVersion, logger);
|
||||
await downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger);
|
||||
const combinedDurationMs = Math.round(perf_hooks_1.performance.now() - toolsInstallStart);
|
||||
logger.info(`Finished downloading and extracting CodeQL bundle to ${extractedBundlePath} (${(0, logging_1.formatDuration)(combinedDurationMs)}).`);
|
||||
logger.info(`Finished downloading and extracting CodeQL bundle to ${dest} (${(0, logging_1.formatDuration)(combinedDurationMs)}).`);
|
||||
return {
|
||||
extractedBundlePath,
|
||||
statusReport: {
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeStreamedToolsDownloadDurations(combinedDurationMs),
|
||||
},
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeStreamedToolsDownloadDurations(combinedDurationMs),
|
||||
};
|
||||
}
|
||||
const dest = path.join(tempDir, (0, uuid_1.v4)());
|
||||
const toolsDownloadStart = perf_hooks_1.performance.now();
|
||||
const archivedBundlePath = await toolcache.downloadTool(codeqlURL, dest, authorization, headers);
|
||||
const archivedBundlePath = await toolcache.downloadTool(codeqlURL, undefined, authorization, headers);
|
||||
const downloadDurationMs = Math.round(perf_hooks_1.performance.now() - toolsDownloadStart);
|
||||
logger.info(`Finished downloading CodeQL bundle to ${archivedBundlePath} (${(0, logging_1.formatDuration)(downloadDurationMs)}).`);
|
||||
let extractedBundlePath;
|
||||
let extractionDurationMs;
|
||||
try {
|
||||
logger.info("Extracting CodeQL bundle.");
|
||||
const extractionStart = perf_hooks_1.performance.now();
|
||||
extractedBundlePath = await tar.extract(archivedBundlePath, compressionMethod, tarVersion, logger);
|
||||
await tar.extract(archivedBundlePath, dest, compressionMethod, tarVersion, logger);
|
||||
extractionDurationMs = Math.round(perf_hooks_1.performance.now() - extractionStart);
|
||||
logger.info(`Finished extracting CodeQL bundle to ${extractedBundlePath} (${(0, logging_1.formatDuration)(extractionDurationMs)}).`);
|
||||
logger.info(`Finished extracting CodeQL bundle to ${dest} (${(0, logging_1.formatDuration)(extractionDurationMs)}).`);
|
||||
}
|
||||
finally {
|
||||
await (0, util_1.cleanUpGlob)(archivedBundlePath, "CodeQL bundle archive", logger);
|
||||
}
|
||||
return {
|
||||
extractedBundlePath,
|
||||
statusReport: {
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs),
|
||||
},
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs),
|
||||
};
|
||||
}
|
||||
async function downloadAndExtractZstdWithStreaming(codeqlURL, authorization, headers, tarVersion, logger) {
|
||||
async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) {
|
||||
// Ensure destination exists
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
// Add User-Agent header and Authorization header if provided.
|
||||
headers = Object.assign({ "User-Agent": "CodeQL Action" }, authorization ? { authorization } : {}, headers);
|
||||
const response = await new Promise((resolve) => follow_redirects_1.https.get(codeqlURL, {
|
||||
headers,
|
||||
// Increase the high water mark to improve performance.
|
||||
highWaterMark: exports.STREAMING_HIGH_WATERMARK_BYTES,
|
||||
}, (r) => resolve(r)));
|
||||
if (response.statusCode !== 200) {
|
||||
throw new Error(`Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.`);
|
||||
}
|
||||
return await tar.extractTarZst(response, tarVersion, logger);
|
||||
await tar.extractTarZst(response, dest, tarVersion, logger);
|
||||
}
|
||||
/** Gets the path to the toolcache directory for the specified version of the CodeQL tools. */
|
||||
function getToolcacheDirectory(version) {
|
||||
return path.join((0, util_1.getRequiredEnvParam)("RUNNER_TOOL_CACHE"), TOOLCACHE_TOOL_NAME, semver.clean(version) || version, os.arch() || "");
|
||||
}
|
||||
function writeToolcacheMarkerFile(extractedPath, logger) {
|
||||
const markerFilePath = `${extractedPath}.complete`;
|
||||
fs.writeFileSync(markerFilePath, "");
|
||||
logger.info(`Created toolcache marker file ${markerFilePath}`);
|
||||
}
|
||||
function sanitizeUrlForStatusReport(url) {
|
||||
return ["github/codeql-action", "dsp-testing/codeql-cli-nightlies"].some((repo) => url.startsWith(`https://github.com/${repo}/releases/download/`))
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"tools-download.js","sourceRoot":"","sources":["../src/tools-download.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"tools-download.js","sourceRoot":"","sources":["../src/tools-download.ts"],"names":[],"mappings":"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"}
|
||||
53
pr-checks/checks/extract-direct-to-toolcache.yml
Normal file
53
pr-checks/checks/extract-direct-to-toolcache.yml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
name: "Extract directly to toolcache"
|
||||
description: "Extract the CodeQL bundle directly into the toolcache"
|
||||
versions:
|
||||
- linked
|
||||
operatingSystems:
|
||||
- macos
|
||||
- ubuntu
|
||||
- windows
|
||||
env:
|
||||
CODEQL_ACTION_EXTRACT_TOOLCACHE: true
|
||||
steps:
|
||||
- name: Remove CodeQL from toolcache
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL');
|
||||
fs.rmdirSync(codeqlPath, { recursive: true });
|
||||
- name: Install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache
|
||||
- name: Check toolcache does not contain CodeQL
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const toolcache = require('@actions/tool-cache');
|
||||
const allCodeqlVersions = toolcache.findAllVersions('CodeQL');
|
||||
if (allCodeqlVersions.length !== 0) {
|
||||
throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`);
|
||||
}
|
||||
console.log('No versions of CodeQL found in the toolcache');
|
||||
- id: init
|
||||
uses: ./../action/init
|
||||
with:
|
||||
languages: javascript
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
- uses: ./../action/analyze
|
||||
with:
|
||||
output: ${{ runner.temp }}/results
|
||||
upload-database: false
|
||||
- name: Check CodeQL is installed within the toolcache
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const toolcache = require('@actions/tool-cache');
|
||||
const allCodeqlVersions = toolcache.findAllVersions('CodeQL');
|
||||
console.log(`Found CodeQL versions: ${allCodeqlVersions}`);
|
||||
if (allCodeqlVersions.length === 0) {
|
||||
throw new Error('CodeQL not found in toolcache');
|
||||
}
|
||||
if (allCodeqlVersions.length > 1) {
|
||||
throw new Error('Multiple CodeQL versions found in toolcache');
|
||||
}
|
||||
|
|
@ -17,8 +17,7 @@ import * as codeql from "./codeql";
|
|||
import { AugmentationProperties, Config } from "./config-utils";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { DocUrl } from "./doc-url";
|
||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||
import { initializeFeatures } from "./feature-flags.test";
|
||||
import { FeatureEnablement } from "./feature-flags";
|
||||
import { Language } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { ToolsSource } from "./setup-codeql";
|
||||
|
|
@ -41,14 +40,7 @@ setupTests(test);
|
|||
|
||||
let stubConfig: Config;
|
||||
|
||||
// TODO: Remove when when we no longer need to pass in features (https://github.com/github/codeql-action/issues/2600)
|
||||
const expectedFeatureEnablement: FeatureEnablement = initializeFeatures(
|
||||
true,
|
||||
) as FeatureEnablement;
|
||||
expectedFeatureEnablement.getValue = function (feature: Feature) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return expectedFeatureEnablement[feature];
|
||||
};
|
||||
const NO_FEATURES: FeatureEnablement = createFeatures([]);
|
||||
|
||||
test.beforeEach(() => {
|
||||
initializeEnvironment("1.2.3");
|
||||
|
|
@ -81,7 +73,7 @@ async function installIntoToolcache({
|
|||
? { cliVersion, tagName }
|
||||
: SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
|
@ -114,11 +106,8 @@ function mockApiDetails(apiDetails: GitHubApiDetails) {
|
|||
.stub(actionsUtil, "getRequiredInput")
|
||||
.withArgs("token")
|
||||
.returns(apiDetails.auth);
|
||||
const requiredEnvParamStub = sinon.stub(util, "getRequiredEnvParam");
|
||||
requiredEnvParamStub.withArgs("GITHUB_SERVER_URL").returns(apiDetails.url);
|
||||
requiredEnvParamStub
|
||||
.withArgs("GITHUB_API_URL")
|
||||
.returns(apiDetails.apiURL || "");
|
||||
process.env["GITHUB_SERVER_URL"] = apiDetails.url;
|
||||
process.env["GITHUB_API_URL"] = apiDetails.apiURL || "";
|
||||
}
|
||||
|
||||
test("downloads and caches explicitly requested bundles that aren't in the toolcache", async (t) => {
|
||||
|
|
@ -141,7 +130,7 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
|
||||
|
|
@ -168,7 +157,7 @@ test("caches semantically versioned bundles using their semantic version number"
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
|
||||
|
|
@ -202,7 +191,7 @@ test("downloads an explicitly requested bundle even if a different version is ca
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
t.assert(toolcache.find("CodeQL", "0.0.0-20200610"));
|
||||
|
|
@ -247,7 +236,7 @@ for (const {
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
t.assert(toolcache.find("CodeQL", expectedToolcacheVersion));
|
||||
|
|
@ -286,7 +275,7 @@ for (const toolcacheVersion of [
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
|
||||
|
|
@ -319,7 +308,7 @@ test(`uses a cached bundle when no tools input is given on GHES`, async (t) => {
|
|||
tagName: defaults.bundleVersion,
|
||||
},
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
t.deepEqual(result.toolsVersion, "0.0.0-20200601");
|
||||
|
|
@ -356,7 +345,7 @@ test(`downloads bundle if only an unpinned version is cached on GHES`, async (t)
|
|||
tagName: defaults.bundleVersion,
|
||||
},
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||
|
|
@ -390,7 +379,7 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) =>
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
t.deepEqual(result.toolsVersion, defaults.cliVersion);
|
||||
|
|
@ -426,7 +415,7 @@ test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t)
|
|||
util.GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
getRunnerLogger(true),
|
||||
expectedFeatureEnablement,
|
||||
NO_FEATURES,
|
||||
false,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -395,7 +395,9 @@ export async function setupCodeQL(
|
|||
};
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Unable to download and extract CodeQL CLI: ${getErrorMessage(e)}`,
|
||||
`Unable to download and extract CodeQL CLI: ${getErrorMessage(e)}${
|
||||
e instanceof Error && e.stack ? `\n\nDetails: ${e.stack}` : ""
|
||||
}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ export enum Feature {
|
|||
DisableJavaBuildlessEnabled = "disable_java_buildless_enabled",
|
||||
DisableKotlinAnalysisEnabled = "disable_kotlin_analysis_enabled",
|
||||
ExportDiagnosticsEnabled = "export_diagnostics_enabled",
|
||||
ExtractToToolcache = "extract_to_toolcache",
|
||||
PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib",
|
||||
QaTelemetryEnabled = "qa_telemetry_enabled",
|
||||
ZstdBundleStreamingExtraction = "zstd_bundle_streaming_extraction",
|
||||
|
|
@ -148,6 +149,11 @@ export const featureConfig: Record<
|
|||
legacyApi: true,
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.ExtractToToolcache]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_EXTRACT_TOOLCACHE",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.PythonDefaultIsToNotExtractStdlib]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_DISABLE_PYTHON_STANDARD_LIBRARY_EXTRACTION",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { performance } from "perf_hooks";
|
|||
import * as toolcache from "@actions/tool-cache";
|
||||
import { default as deepEqual } from "fast-deep-equal";
|
||||
import * as semver from "semver";
|
||||
import { v4 as uuidV4 } from "uuid";
|
||||
|
||||
import { isRunningLocalAction } from "./actions-util";
|
||||
import * as api from "./api-client";
|
||||
|
|
@ -13,13 +14,16 @@ import * as defaults from "./defaults.json";
|
|||
import {
|
||||
CODEQL_VERSION_ZSTD_BUNDLE,
|
||||
CodeQLDefaultVersionInfo,
|
||||
Feature,
|
||||
FeatureEnablement,
|
||||
} from "./feature-flags";
|
||||
import { formatDuration, Logger } from "./logging";
|
||||
import * as tar from "./tar";
|
||||
import {
|
||||
downloadAndExtract,
|
||||
getToolcacheDirectory,
|
||||
ToolsDownloadStatusReport,
|
||||
writeToolcacheMarkerFile,
|
||||
} from "./tools-download";
|
||||
import * as util from "./util";
|
||||
import { cleanUpGlob, isGoodVersion } from "./util";
|
||||
|
|
@ -534,20 +538,29 @@ export const downloadCodeQL = async function (
|
|||
logger.debug("Downloading CodeQL tools without an authorization token.");
|
||||
}
|
||||
|
||||
const { extractedBundlePath, statusReport } = await downloadAndExtract(
|
||||
const toolcacheInfo = getToolcacheDestinationInfo(
|
||||
maybeBundleVersion,
|
||||
maybeCliVersion,
|
||||
logger,
|
||||
);
|
||||
const extractToToolcache =
|
||||
!!toolcacheInfo && !!(await features.getValue(Feature.ExtractToToolcache));
|
||||
|
||||
const extractedBundlePath = extractToToolcache
|
||||
? toolcacheInfo.path
|
||||
: getTempExtractionDir(tempDir);
|
||||
|
||||
let statusReport = await downloadAndExtract(
|
||||
codeqlURL,
|
||||
extractedBundlePath,
|
||||
authorization,
|
||||
{ "User-Agent": "CodeQL Action", ...headers },
|
||||
tarVersion,
|
||||
tempDir,
|
||||
features,
|
||||
logger,
|
||||
);
|
||||
|
||||
const bundleVersion =
|
||||
maybeBundleVersion ?? tryGetBundleVersionFromUrl(codeqlURL, logger);
|
||||
|
||||
if (bundleVersion === undefined) {
|
||||
if (!toolcacheInfo) {
|
||||
logger.debug(
|
||||
"Could not cache CodeQL tools because we could not determine the bundle version from the " +
|
||||
`URL ${codeqlURL}.`,
|
||||
|
|
@ -559,41 +572,68 @@ export const downloadCodeQL = async function (
|
|||
};
|
||||
}
|
||||
|
||||
logger.debug("Caching CodeQL bundle.");
|
||||
const toolcacheVersion = getCanonicalToolcacheVersion(
|
||||
maybeCliVersion,
|
||||
bundleVersion,
|
||||
logger,
|
||||
);
|
||||
const toolcacheStart = performance.now();
|
||||
const toolcachedBundlePath = await toolcache.cacheDir(
|
||||
extractedBundlePath,
|
||||
"CodeQL",
|
||||
toolcacheVersion,
|
||||
);
|
||||
let codeqlFolder = extractedBundlePath;
|
||||
|
||||
logger.info(
|
||||
`Added CodeQL bundle to the tool cache (${formatDuration(
|
||||
performance.now() - toolcacheStart,
|
||||
)}).`,
|
||||
);
|
||||
|
||||
// Defensive check: we expect `cacheDir` to copy the bundle to a new location.
|
||||
if (toolcachedBundlePath !== extractedBundlePath) {
|
||||
await cleanUpGlob(
|
||||
if (extractToToolcache) {
|
||||
writeToolcacheMarkerFile(toolcacheInfo.path, logger);
|
||||
} else {
|
||||
logger.debug("Caching CodeQL bundle.");
|
||||
const toolcacheStart = performance.now();
|
||||
codeqlFolder = await toolcache.cacheDir(
|
||||
extractedBundlePath,
|
||||
"CodeQL bundle from temporary directory",
|
||||
logger,
|
||||
"CodeQL",
|
||||
toolcacheInfo.version,
|
||||
);
|
||||
|
||||
const cacheDurationMs = performance.now() - toolcacheStart;
|
||||
logger.info(
|
||||
`Added CodeQL bundle to the tool cache (${formatDuration(
|
||||
cacheDurationMs,
|
||||
)}).`,
|
||||
);
|
||||
statusReport = {
|
||||
...statusReport,
|
||||
cacheDurationMs,
|
||||
};
|
||||
|
||||
// Defensive check: we expect `cacheDir` to copy the bundle to a new location.
|
||||
if (codeqlFolder !== extractedBundlePath) {
|
||||
await cleanUpGlob(
|
||||
extractedBundlePath,
|
||||
"CodeQL bundle from temporary directory",
|
||||
logger,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
codeqlFolder: toolcachedBundlePath,
|
||||
codeqlFolder,
|
||||
statusReport,
|
||||
toolsVersion: maybeCliVersion ?? toolcacheVersion,
|
||||
toolsVersion: maybeCliVersion ?? toolcacheInfo.version,
|
||||
};
|
||||
};
|
||||
|
||||
function getToolcacheDestinationInfo(
|
||||
maybeBundleVersion: string | undefined,
|
||||
maybeCliVersion: string | undefined,
|
||||
logger: Logger,
|
||||
): { path: string; version: string } | undefined {
|
||||
if (maybeBundleVersion) {
|
||||
const version = getCanonicalToolcacheVersion(
|
||||
maybeCliVersion,
|
||||
maybeBundleVersion,
|
||||
logger,
|
||||
);
|
||||
|
||||
return {
|
||||
path: getToolcacheDirectory(version),
|
||||
version,
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getCodeQLURLVersion(url: string): string {
|
||||
const match = url.match(/\/codeql-bundle-(.*)\//);
|
||||
if (match === null || match.length < 2) {
|
||||
|
|
@ -617,7 +657,7 @@ function getCanonicalToolcacheVersion(
|
|||
cliVersion: string | undefined,
|
||||
bundleVersion: string,
|
||||
logger: Logger,
|
||||
) {
|
||||
): string {
|
||||
// If the CLI version is a pre-release or contains build metadata, then cache the
|
||||
// bundle as `0.0.0-<bundleVersion>` to avoid the bundle being interpreted as containing a stable
|
||||
// CLI release. In principle, it should be enough to just check that the CLI version isn't a
|
||||
|
|
@ -680,6 +720,7 @@ export async function setupCodeQLBundle(
|
|||
);
|
||||
codeqlFolder = await tar.extract(
|
||||
source.codeqlTarPath,
|
||||
getTempExtractionDir(tempDir),
|
||||
compressionMethod,
|
||||
zstdAvailability.version,
|
||||
logger,
|
||||
|
|
@ -732,3 +773,7 @@ async function useZstdBundle(
|
|||
semver.gte(cliVersion, CODEQL_VERSION_ZSTD_BUNDLE)
|
||||
);
|
||||
}
|
||||
|
||||
function getTempExtractionDir(tempDir: string) {
|
||||
return path.join(tempDir, uuidV4());
|
||||
}
|
||||
|
|
|
|||
76
src/tar.ts
76
src/tar.ts
|
|
@ -1,14 +1,12 @@
|
|||
import { spawn } from "child_process";
|
||||
import * as fs from "fs";
|
||||
import path from "path";
|
||||
import * as stream from "stream";
|
||||
|
||||
import { ToolRunner } from "@actions/exec/lib/toolrunner";
|
||||
import * as toolcache from "@actions/tool-cache";
|
||||
import { safeWhich } from "@chrisgavin/safe-which";
|
||||
import { v4 as uuidV4 } from "uuid";
|
||||
|
||||
import { CommandInvocationError, getTemporaryDirectory } from "./actions-util";
|
||||
import { CommandInvocationError } from "./actions-util";
|
||||
import { Logger } from "./logging";
|
||||
import { assertNever, cleanUpGlob, isBinaryAccessible } from "./util";
|
||||
|
||||
|
|
@ -96,22 +94,28 @@ export type CompressionMethod = "gzip" | "zstd";
|
|||
|
||||
export async function extract(
|
||||
tarPath: string,
|
||||
dest: string,
|
||||
compressionMethod: CompressionMethod,
|
||||
tarVersion: TarVersion | undefined,
|
||||
logger: Logger,
|
||||
): Promise<string> {
|
||||
// Ensure destination exists
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
|
||||
switch (compressionMethod) {
|
||||
case "gzip":
|
||||
// Defensively continue to call the toolcache API as requesting a gzipped
|
||||
// bundle may be a fallback option.
|
||||
return await toolcache.extractTar(tarPath);
|
||||
case "zstd":
|
||||
return await toolcache.extractTar(tarPath, dest);
|
||||
case "zstd": {
|
||||
if (!tarVersion) {
|
||||
throw new Error(
|
||||
"Could not determine tar version, which is required to extract a Zstandard archive.",
|
||||
);
|
||||
}
|
||||
return await extractTarZst(tarPath, tarVersion, logger);
|
||||
await extractTarZst(tarPath, dest, tarVersion, logger);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,15 +123,14 @@ export async function extract(
|
|||
* Extract a compressed tar archive
|
||||
*
|
||||
* @param tar tar stream, or path to the tar
|
||||
* @param dest destination directory. Optional.
|
||||
* @returns path to the destination directory
|
||||
* @param dest destination directory
|
||||
*/
|
||||
export async function extractTarZst(
|
||||
tar: stream.Readable | string,
|
||||
dest: string,
|
||||
tarVersion: TarVersion,
|
||||
logger: Logger,
|
||||
): Promise<string> {
|
||||
const dest = await createExtractFolder();
|
||||
): Promise<void> {
|
||||
logger.debug(
|
||||
`Extracting to ${dest}.${
|
||||
tar instanceof stream.Readable
|
||||
|
|
@ -150,25 +153,34 @@ export async function extractTarZst(
|
|||
|
||||
process.stdout.write(`[command]tar ${args.join(" ")}\n`);
|
||||
|
||||
const tarProcess = spawn("tar", args, { stdio: "pipe" });
|
||||
let stdout = "";
|
||||
tarProcess.stdout?.on("data", (data: Buffer) => {
|
||||
stdout += data.toString();
|
||||
process.stdout.write(data);
|
||||
});
|
||||
|
||||
let stderr = "";
|
||||
tarProcess.stderr?.on("data", (data: Buffer) => {
|
||||
stderr += data.toString();
|
||||
// Mimic the standard behavior of the toolrunner by writing stderr to stdout
|
||||
process.stdout.write(data);
|
||||
});
|
||||
|
||||
if (tar instanceof stream.Readable) {
|
||||
tar.pipe(tarProcess.stdin);
|
||||
}
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const tarProcess = spawn("tar", args, { stdio: "pipe" });
|
||||
|
||||
let stdout = "";
|
||||
tarProcess.stdout?.on("data", (data: Buffer) => {
|
||||
stdout += data.toString();
|
||||
process.stdout.write(data);
|
||||
});
|
||||
|
||||
let stderr = "";
|
||||
tarProcess.stderr?.on("data", (data: Buffer) => {
|
||||
stderr += data.toString();
|
||||
// Mimic the standard behavior of the toolrunner by writing stderr to stdout
|
||||
process.stdout.write(data);
|
||||
});
|
||||
|
||||
tarProcess.on("error", (err) => {
|
||||
reject(new Error(`Error while extracting tar: ${err}`));
|
||||
});
|
||||
|
||||
if (tar instanceof stream.Readable) {
|
||||
tar.pipe(tarProcess.stdin).on("error", (err) => {
|
||||
reject(
|
||||
new Error(`Error while downloading and extracting tar: ${err}`),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
tarProcess.on("exit", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(
|
||||
|
|
@ -184,20 +196,12 @@ export async function extractTarZst(
|
|||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
return dest;
|
||||
} catch (e) {
|
||||
await cleanUpGlob(dest, "extraction destination directory", logger);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async function createExtractFolder(): Promise<string> {
|
||||
const dest = path.join(getTemporaryDirectory(), uuidV4());
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
return dest;
|
||||
}
|
||||
|
||||
export function inferCompressionMethod(tarPath: string): CompressionMethod {
|
||||
if (tarPath.endsWith(".tar.gz")) {
|
||||
return "gzip";
|
||||
|
|
|
|||
|
|
@ -1,21 +1,28 @@
|
|||
import * as fs from "fs";
|
||||
import { IncomingMessage, OutgoingHttpHeaders, RequestOptions } from "http";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import { performance } from "perf_hooks";
|
||||
|
||||
import * as toolcache from "@actions/tool-cache";
|
||||
import { https } from "follow-redirects";
|
||||
import { v4 as uuidV4 } from "uuid";
|
||||
import * as semver from "semver";
|
||||
|
||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||
import { formatDuration, Logger } from "./logging";
|
||||
import * as tar from "./tar";
|
||||
import { cleanUpGlob } from "./util";
|
||||
import { cleanUpGlob, getRequiredEnvParam } from "./util";
|
||||
|
||||
/**
|
||||
* High watermark to use when streaming the download and extraction of the CodeQL tools.
|
||||
*/
|
||||
export const STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; // 4 MiB
|
||||
|
||||
/**
|
||||
* The name of the tool cache directory for the CodeQL tools.
|
||||
*/
|
||||
const TOOLCACHE_TOOL_NAME = "CodeQL";
|
||||
|
||||
/**
|
||||
* Timing information for the download and extraction of the CodeQL tools when
|
||||
* we fully download the bundle before extracting.
|
||||
|
|
@ -66,6 +73,7 @@ type ToolsDownloadDurations =
|
|||
| StreamedToolsDownloadDurations;
|
||||
|
||||
export type ToolsDownloadStatusReport = {
|
||||
cacheDurationMs?: number;
|
||||
compressionMethod: tar.CompressionMethod;
|
||||
toolsUrl: string;
|
||||
zstdFailureReason?: string;
|
||||
|
|
@ -73,16 +81,13 @@ export type ToolsDownloadStatusReport = {
|
|||
|
||||
export async function downloadAndExtract(
|
||||
codeqlURL: string,
|
||||
dest: string,
|
||||
authorization: string | undefined,
|
||||
headers: OutgoingHttpHeaders,
|
||||
tarVersion: tar.TarVersion | undefined,
|
||||
tempDir: string,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
): Promise<{
|
||||
extractedBundlePath: string;
|
||||
statusReport: ToolsDownloadStatusReport;
|
||||
}> {
|
||||
): Promise<ToolsDownloadStatusReport> {
|
||||
logger.info(
|
||||
`Downloading CodeQL tools from ${codeqlURL} . This may take a while.`,
|
||||
);
|
||||
|
|
@ -99,8 +104,9 @@ export async function downloadAndExtract(
|
|||
logger.info(`Streaming the extraction of the CodeQL bundle.`);
|
||||
|
||||
const toolsInstallStart = performance.now();
|
||||
const extractedBundlePath = await downloadAndExtractZstdWithStreaming(
|
||||
await downloadAndExtractZstdWithStreaming(
|
||||
codeqlURL,
|
||||
dest,
|
||||
authorization,
|
||||
headers,
|
||||
tarVersion!,
|
||||
|
|
@ -111,27 +117,22 @@ export async function downloadAndExtract(
|
|||
performance.now() - toolsInstallStart,
|
||||
);
|
||||
logger.info(
|
||||
`Finished downloading and extracting CodeQL bundle to ${extractedBundlePath} (${formatDuration(
|
||||
`Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration(
|
||||
combinedDurationMs,
|
||||
)}).`,
|
||||
);
|
||||
|
||||
return {
|
||||
extractedBundlePath,
|
||||
statusReport: {
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeStreamedToolsDownloadDurations(combinedDurationMs),
|
||||
},
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeStreamedToolsDownloadDurations(combinedDurationMs),
|
||||
};
|
||||
}
|
||||
|
||||
const dest = path.join(tempDir, uuidV4());
|
||||
|
||||
const toolsDownloadStart = performance.now();
|
||||
const archivedBundlePath = await toolcache.downloadTool(
|
||||
codeqlURL,
|
||||
dest,
|
||||
undefined,
|
||||
authorization,
|
||||
headers,
|
||||
);
|
||||
|
|
@ -143,21 +144,21 @@ export async function downloadAndExtract(
|
|||
)}).`,
|
||||
);
|
||||
|
||||
let extractedBundlePath: string;
|
||||
let extractionDurationMs: number;
|
||||
|
||||
try {
|
||||
logger.info("Extracting CodeQL bundle.");
|
||||
const extractionStart = performance.now();
|
||||
extractedBundlePath = await tar.extract(
|
||||
await tar.extract(
|
||||
archivedBundlePath,
|
||||
dest,
|
||||
compressionMethod,
|
||||
tarVersion,
|
||||
logger,
|
||||
);
|
||||
extractionDurationMs = Math.round(performance.now() - extractionStart);
|
||||
logger.info(
|
||||
`Finished extracting CodeQL bundle to ${extractedBundlePath} (${formatDuration(
|
||||
`Finished extracting CodeQL bundle to ${dest} (${formatDuration(
|
||||
extractionDurationMs,
|
||||
)}).`,
|
||||
);
|
||||
|
|
@ -166,25 +167,27 @@ export async function downloadAndExtract(
|
|||
}
|
||||
|
||||
return {
|
||||
extractedBundlePath,
|
||||
statusReport: {
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeDownloadFirstToolsDownloadDurations(
|
||||
downloadDurationMs,
|
||||
extractionDurationMs,
|
||||
),
|
||||
},
|
||||
compressionMethod,
|
||||
toolsUrl: sanitizeUrlForStatusReport(codeqlURL),
|
||||
...makeDownloadFirstToolsDownloadDurations(
|
||||
downloadDurationMs,
|
||||
extractionDurationMs,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
async function downloadAndExtractZstdWithStreaming(
|
||||
codeqlURL: string,
|
||||
dest: string,
|
||||
authorization: string | undefined,
|
||||
headers: OutgoingHttpHeaders,
|
||||
tarVersion: tar.TarVersion,
|
||||
logger: Logger,
|
||||
): Promise<string> {
|
||||
): Promise<void> {
|
||||
// Ensure destination exists
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
|
||||
// Add User-Agent header and Authorization header if provided.
|
||||
headers = Object.assign(
|
||||
{ "User-Agent": "CodeQL Action" },
|
||||
authorization ? { authorization } : {},
|
||||
|
|
@ -195,6 +198,7 @@ async function downloadAndExtractZstdWithStreaming(
|
|||
codeqlURL,
|
||||
{
|
||||
headers,
|
||||
// Increase the high water mark to improve performance.
|
||||
highWaterMark: STREAMING_HIGH_WATERMARK_BYTES,
|
||||
} as unknown as RequestOptions,
|
||||
(r) => resolve(r),
|
||||
|
|
@ -207,7 +211,26 @@ async function downloadAndExtractZstdWithStreaming(
|
|||
);
|
||||
}
|
||||
|
||||
return await tar.extractTarZst(response, tarVersion, logger);
|
||||
await tar.extractTarZst(response, dest, tarVersion, logger);
|
||||
}
|
||||
|
||||
/** Gets the path to the toolcache directory for the specified version of the CodeQL tools. */
|
||||
export function getToolcacheDirectory(version: string): string {
|
||||
return path.join(
|
||||
getRequiredEnvParam("RUNNER_TOOL_CACHE"),
|
||||
TOOLCACHE_TOOL_NAME,
|
||||
semver.clean(version) || version,
|
||||
os.arch() || "",
|
||||
);
|
||||
}
|
||||
|
||||
export function writeToolcacheMarkerFile(
|
||||
extractedPath: string,
|
||||
logger: Logger,
|
||||
): void {
|
||||
const markerFilePath = `${extractedPath}.complete`;
|
||||
fs.writeFileSync(markerFilePath, "");
|
||||
logger.info(`Created toolcache marker file ${markerFilePath}`);
|
||||
}
|
||||
|
||||
function sanitizeUrlForStatusReport(url: string): string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue