Compare commits

...

14 Commits

Author SHA1 Message Date
Andrew Eisenberg a589d4087e Merge pull request #1527 from github/aeisenberg/qlconfig-in-cli
Ensure qlconfig file is created when config parsing in cli is on
2023-02-27 10:26:08 -08:00
Andrew Eisenberg 98d24e5629 Address comments from PR 2023-02-27 09:59:16 -08:00
Henry Mercer 903be79953 Merge pull request #1548 from github/mergeback/v2.2.5-to-main-32dc4993
Mergeback v2.2.5 refs/heads/releases/v2 into main
2023-02-27 11:02:00 +00:00
github-actions[bot] 18ff14b615 Update checked-in dependencies 2023-02-27 09:35:51 +00:00
Henry Mercer 36a249f5ae Merge branch 'main' into mergeback/v2.2.5-to-main-32dc4993 2023-02-27 09:33:05 +00:00
Henry Mercer 041757fc59 Merge pull request #1549 from github/henrymercer/fix-update-dependencies
Fix workflow to update dependencies
2023-02-27 09:11:46 +00:00
Andrew Eisenberg 8f19113f88 Merge branch 'main' into aeisenberg/qlconfig-in-cli 2023-02-26 18:35:21 -08:00
Henry Mercer cf1855ae37 Fix workflow to update dependencies
Port over the fix from
https://github.com/github/codeql-action/pull/1544
and share code so these scripts don't get out of sync again.
2023-02-24 20:25:21 +00:00
github-actions[bot] 652709d1b9 Update changelog and version after v2.2.5 2023-02-24 19:28:26 +00:00
Andrew Eisenberg 736263f8fe Update src/codeql.ts 2023-02-17 13:22:25 -08:00
Andrew Eisenberg 5492b7d104 Add tests for generateRegistries with an existing CODEQL_REGISTRIES_AUTH 2023-02-09 13:37:08 -08:00
Andrew Eisenberg 3c81243bb1 Apply suggestions from code review
Co-authored-by: Henry Mercer <henry.mercer@me.com>
2023-02-09 12:25:33 -08:00
Andrew Eisenberg e2f72f11e4 Merge remote-tracking branch 'upstream/main' into aeisenberg/qlconfig-in-cli 2023-02-09 09:47:43 -08:00
Andrew Eisenberg bbe8d375fd Ensure qlconfig file is created when config parsing in cli is on
Previously, with the config parsing in the cli feature flag turned on,
the CLI was not able to download packs from other registries. This PR
adds the codeql-action changes required for this. The CLI changes will
be in a separate, internal PR.
2023-02-07 10:40:56 -08:00
27 changed files with 626 additions and 178 deletions
+42
View File
@@ -25,6 +25,18 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- os: ubuntu-latest
version: cached
- os: macos-latest
version: cached
- os: windows-latest
version: cached
- os: ubuntu-latest
version: latest
- os: macos-latest
version: latest
- os: windows-latest
version: latest
- os: ubuntu-latest - os: ubuntu-latest
version: nightly-latest version: nightly-latest
- os: macos-latest - os: macos-latest
@@ -75,5 +87,35 @@ jobs:
echo "::error $CODEQL_PACK1 pack was not installed." echo "::error $CODEQL_PACK1 pack was not installed."
exit 1 exit 1
fi fi
- name: Verify qlconfig.yml file was created
shell: bash
run: |
QLCONFIG_PATH=$RUNNER_TEMP/qlconfig.yml
echo "Expected qlconfig.yml file to be created at $QLCONFIG_PATH"
if [[ -f $QLCONFIG_PATH ]]
then
echo "qlconfig.yml file was created."
else
echo "::error qlconfig.yml file was not created."
exit 1
fi
- name: Verify contents of qlconfig.yml
# yq is not available on windows
if: runner.os != 'Windows'
shell: bash
run: |
QLCONFIG_PATH=$RUNNER_TEMP/qlconfig.yml
cat $QLCONFIG_PATH | yq -e '.registries[] | select(.url == "https://ghcr.io/v2/") | select(.packages == "*/*")'
if [[ $? -eq 0 ]]
then
echo "Registry was added to qlconfig.yml file."
else
echo "::error Registry was not added to qlconfig.yml file."
echo "Contents of qlconfig.yml file:"
cat $QLCONFIG_PATH
exit 1
fi
env: env:
CODEQL_ACTION_TEST_MODE: true CODEQL_ACTION_TEST_MODE: true
@@ -7,17 +7,9 @@ if [ ! -z "$(git status --porcelain)" ]; then
>&2 echo "Failed: Repo should be clean before testing!" >&2 echo "Failed: Repo should be clean before testing!"
exit 1 exit 1
fi fi
# When updating this, make sure to update the npm version in
# `.github/workflows/update-dependencies.yml` too.
sudo npm install --force -g npm@9.2.0
# clean the npm cache to ensure we don't have any files owned by root "$(dirname "$0")/update-node-modules.sh" check-only
sudo npm cache clean --force
# Reinstall modules and then clean to remove absolute paths
# Use 'npm ci' instead of 'npm install' as this is intended to be reproducible
npm ci
npm run removeNPMAbsolutePaths
# Check that repo is still clean # Check that repo is still clean
if [ ! -z "$(git status --porcelain)" ]; then if [ ! -z "$(git status --porcelain)" ]; then
# If we get a fail here then the PR needs attention # If we get a fail here then the PR needs attention
+18
View File
@@ -0,0 +1,18 @@
if [ "$1" != "update" && "$1" != "check-only" ]; then
>&2 echo "Failed: Invalid argument. Must be 'update' or 'check-only'"
exit 1
fi
sudo npm install --force -g npm@9.2.0
# clean the npm cache to ensure we don't have any files owned by root
sudo npm cache clean --force
if [ "$1" = "update" ]; then
npm install
fi
# Reinstall modules and then clean to remove absolute paths
# Use 'npm ci' instead of 'npm install' as this is intended to be reproducible
npm ci
npm run removeNPMAbsolutePaths
+1 -6
View File
@@ -27,12 +27,7 @@ jobs:
run: | run: |
git fetch origin "$BRANCH" --depth=1 git fetch origin "$BRANCH" --depth=1
git checkout "origin/$BRANCH" git checkout "origin/$BRANCH"
# When updating this, make sure to update the npm version in .github/workflows/script/update-node-modules.sh update
# `.github/workflows/script/check-node-modules.sh` too.
sudo npm install --force -g npm@9.2.0
npm install
npm ci
npm run removeNPMAbsolutePaths
if [ ! -z "$(git status --porcelain)" ]; then if [ ! -z "$(git status --porcelain)" ]; then
git config --global user.email "github-actions@github.com" git config --global user.email "github-actions@github.com"
git config --global user.name "github-actions[bot]" git config --global user.name "github-actions[bot]"
+4
View File
@@ -1,5 +1,9 @@
# CodeQL Action Changelog # CodeQL Action Changelog
## [UNRELEASED]
No user facing changes.
## 2.2.5 - 24 Feb 2023 ## 2.2.5 - 24 Feb 2023
- Update default CodeQL bundle version to 2.12.3. [#1543](https://github.com/github/codeql-action/pull/1543) - Update default CodeQL bundle version to 2.12.3. [#1543](https://github.com/github/codeql-action/pull/1543)
Generated
+17 -10
View File
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_TRACING_GLIBC_2_34 = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0; exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_TRACING_GLIBC_2_34 = exports.CODEQL_VERSION_NEW_TRACING = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner")); const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
@@ -98,6 +98,10 @@ exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3";
* Versions 2.11.1+ of the CodeQL Bundle include a `security-experimental` built-in query suite for each language. * Versions 2.11.1+ of the CodeQL Bundle include a `security-experimental` built-in query suite for each language.
*/ */
exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1"; exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1";
/**
* Versions 2.12.4+ of the CodeQL CLI support the `--qlconfig` flag in calls to `database init`.
*/
exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
/** /**
* Set up CodeQL CLI access. * Set up CodeQL CLI access.
* *
@@ -302,7 +306,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
...getExtraOptionsFromEnv(["database", "init"]), ...getExtraOptionsFromEnv(["database", "init"]),
]); ]);
}, },
async databaseInitCluster(config, sourceRoot, processName, featureEnablement, logger) { async databaseInitCluster(config, sourceRoot, processName, featureEnablement, qlconfigFile, logger) {
const extraArgs = config.languages.map((language) => `--language=${language}`); const extraArgs = config.languages.map((language) => `--language=${language}`);
if (config.languages.filter((l) => (0, languages_1.isTracedLanguage)(l)).length > 0) { if (config.languages.filter((l) => (0, languages_1.isTracedLanguage)(l)).length > 0) {
extraArgs.push("--begin-tracing"); extraArgs.push("--begin-tracing");
@@ -320,17 +324,20 @@ async function getCodeQLForCmd(cmd, checkVersion) {
extraArgs.push("--no-internal-use-lua-tracing"); extraArgs.push("--no-internal-use-lua-tracing");
} }
} }
// A config file is only generated if the CliConfigFileEnabled feature flag is enabled. // A code scanning config file is only generated if the CliConfigFileEnabled feature flag is enabled.
const configLocation = await generateCodeScanningConfig(codeql, config, featureEnablement, logger); const codeScanningConfigFile = await generateCodeScanningConfig(codeql, config, featureEnablement, logger);
// Only pass external repository token if a config file is going to be parsed by the CLI. // Only pass external repository token if a config file is going to be parsed by the CLI.
let externalRepositoryToken; let externalRepositoryToken;
if (configLocation) { if (codeScanningConfigFile) {
extraArgs.push(`--codescanning-config=${configLocation}`);
externalRepositoryToken = (0, actions_util_1.getOptionalInput)("external-repository-token"); externalRepositoryToken = (0, actions_util_1.getOptionalInput)("external-repository-token");
extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`);
if (externalRepositoryToken) { if (externalRepositoryToken) {
extraArgs.push("--external-repository-token-stdin"); extraArgs.push("--external-repository-token-stdin");
} }
} }
if (await util.codeQlVersionAbove(this, exports.CODEQL_VERSION_INIT_WITH_QLCONFIG)) {
extraArgs.push(`--qlconfig=${qlconfigFile}`);
}
await runTool(cmd, [ await runTool(cmd, [
"database", "database",
"init", "init",
@@ -718,7 +725,7 @@ async function generateCodeScanningConfig(codeql, config, featureEnablement, log
if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) { if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) {
return; return;
} }
const configLocation = path.resolve(config.tempDir, "user-config.yaml"); const codeScanningConfigFile = path.resolve(config.tempDir, "user-config.yaml");
// make a copy so we can modify it // make a copy so we can modify it
const augmentedConfig = cloneObject(config.originalUserInput); const augmentedConfig = cloneObject(config.originalUserInput);
// Inject the queries from the input // Inject the queries from the input
@@ -772,12 +779,12 @@ async function generateCodeScanningConfig(codeql, config, featureEnablement, log
augmentedConfig.packs["javascript"].push(packString); augmentedConfig.packs["javascript"].push(packString);
} }
} }
logger.info(`Writing augmented user configuration file to ${configLocation}`); logger.info(`Writing augmented user configuration file to ${codeScanningConfigFile}`);
logger.startGroup("Augmented user configuration file contents"); logger.startGroup("Augmented user configuration file contents");
logger.info(yaml.dump(augmentedConfig)); logger.info(yaml.dump(augmentedConfig));
logger.endGroup(); logger.endGroup();
fs.writeFileSync(configLocation, yaml.dump(augmentedConfig)); fs.writeFileSync(codeScanningConfigFile, yaml.dump(augmentedConfig));
return configLocation; return codeScanningConfigFile;
} }
function cloneObject(obj) { function cloneObject(obj) {
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
+1 -1
View File
File diff suppressed because one or more lines are too long
+44 -21
View File
@@ -452,11 +452,11 @@ for (const isBundleVersionInUrl of [true, false]) {
packsInputCombines: false, packsInputCombines: false,
}, },
}; };
await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true)); await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, (0, testing_utils_1.createFeatures)([]), "/path/to/qlconfig.yml", (0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1]; const args = runnerConstructorStub.firstCall.args[1];
// should NOT have used an config file // should NOT have used an config file
const configArg = args.find((arg) => arg.startsWith("--codescanning-config=")); const configArg = args.find((arg) => arg.startsWith("--codescanning-config="));
t.falsy(configArg, "Should have injected a codescanning config"); t.falsy(configArg, "Should NOT have injected a codescanning config");
}); });
}); });
// Test macro for ensuring different variants of injected augmented configurations // Test macro for ensuring different variants of injected augmented configurations
@@ -474,7 +474,7 @@ const injectedConfigMacro = ava_1.default.macro({
tempDir, tempDir,
augmentationProperties, augmentationProperties,
}; };
await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.CliConfigFileEnabled]), (0, logging_1.getRunnerLogger)(true)); await codeqlObject.databaseInitCluster(thisStubConfig, "", undefined, (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.CliConfigFileEnabled]), undefined, (0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1]; const args = runnerConstructorStub.firstCall.args[1];
// should have used an config file // should have used an config file
const configArg = args.find((arg) => arg.startsWith("--codescanning-config=")); const configArg = args.find((arg) => arg.startsWith("--codescanning-config="));
@@ -665,24 +665,47 @@ const injectedConfigMacro = ava_1.default.macro({
queries: [], queries: [],
}, },
}, {}); }, {});
(0, ava_1.default)("does not use injected config", async (t) => { (0, ava_1.default)("does not pass a code scanning config or qlconfig file to the CLI when CLI config passing is disabled", async (t) => {
const origCODEQL_PASS_CONFIG_TO_CLI = process.env.CODEQL_PASS_CONFIG_TO_CLI; const runnerConstructorStub = stubToolRunnerConstructor();
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = "false"; const codeqlObject = await codeql.getCodeQLForTesting();
try { // stubbed version doesn't matter. It just needs to be valid semver.
const runnerConstructorStub = stubToolRunnerConstructor(); sinon.stub(codeqlObject, "getVersion").resolves("0.0.0");
const codeqlObject = await codeql.getCodeQLForTesting(); await codeqlObject.databaseInitCluster(stubConfig, "", undefined, (0, testing_utils_1.createFeatures)([]), "/path/to/qlconfig.yml", (0, logging_1.getRunnerLogger)(true));
sinon const args = runnerConstructorStub.firstCall.args[1];
.stub(codeqlObject, "getVersion") // should not have used a config file
.resolves(feature_flags_1.featureConfig[feature_flags_1.Feature.CliConfigFileEnabled].minimumVersion); const hasConfigArg = args.some((arg) => arg.startsWith("--codescanning-config="));
await codeqlObject.databaseInitCluster(stubConfig, "", undefined, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true)); t.false(hasConfigArg, "Should NOT have injected a codescanning config");
const args = runnerConstructorStub.firstCall.args[1]; // should not have passed a qlconfig file
// should have used an config file const hasQlconfigArg = args.some((arg) => arg.startsWith("--qlconfig="));
const configArg = args.find((arg) => arg.startsWith("--codescanning-config=")); t.false(hasQlconfigArg, "Should NOT have passed a qlconfig file");
t.falsy(configArg, "Should NOT have injected a codescanning config"); });
} (0, ava_1.default)("passes a code scanning config AND qlconfig to the CLI when CLI config passing is enabled", async (t) => {
finally { const runnerConstructorStub = stubToolRunnerConstructor();
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = origCODEQL_PASS_CONFIG_TO_CLI; const codeqlObject = await codeql.getCodeQLForTesting();
} sinon
.stub(codeqlObject, "getVersion")
.resolves(codeql.CODEQL_VERSION_INIT_WITH_QLCONFIG);
await codeqlObject.databaseInitCluster(stubConfig, "", undefined, (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.CliConfigFileEnabled]), "/path/to/qlconfig.yml", (0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1];
// should have used a config file
const hasCodeScanningConfigArg = args.some((arg) => arg.startsWith("--codescanning-config="));
t.true(hasCodeScanningConfigArg, "Should have injected a qlconfig");
// should have passed a qlconfig file
const hasQlconfigArg = args.some((arg) => arg.startsWith("--qlconfig="));
t.truthy(hasQlconfigArg, "Should have injected a codescanning config");
});
(0, ava_1.default)("passes a code scanning config BUT NOT a qlconfig to the CLI when CLI config passing is enabled", async (t) => {
const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves("2.12.2");
await codeqlObject.databaseInitCluster(stubConfig, "", undefined, (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.CliConfigFileEnabled]), "/path/to/qlconfig.yml", (0, logging_1.getRunnerLogger)(true));
const args = runnerConstructorStub.firstCall.args[1];
// should have used a config file
const hasCodeScanningConfigArg = args.some((arg) => arg.startsWith("--codescanning-config="));
t.true(hasCodeScanningConfigArg, "Should NOT have injected a qlconfig");
// should have passed a qlconfig file
const hasQlconfigArg = args.some((arg) => arg.startsWith("--qlconfig="));
t.false(hasQlconfigArg, "Should have injected a codescanning config");
}); });
(0, ava_1.default)("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3", async (t) => { (0, ava_1.default)("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3", async (t) => {
const runnerConstructorStub = stubToolRunnerConstructor(); const runnerConstructorStub = stubToolRunnerConstructor();
File diff suppressed because one or more lines are too long
+50 -20
View File
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.downloadPacks = exports.getConfig = exports.getPathToParsedConfigFile = exports.initConfig = exports.parsePacks = exports.validatePackSpecification = exports.prettyPrintPack = exports.parsePacksSpecification = exports.parsePacksFromConfig = exports.calculateAugmentation = exports.getDefaultConfig = exports.getRawLanguages = exports.getLanguages = exports.getLanguagesInRepo = exports.getUnknownLanguagesError = exports.getNoLanguagesError = exports.getConfigFileDirectoryGivenMessage = exports.getConfigFileFormatInvalidMessage = exports.getConfigFileRepoFormatInvalidMessage = exports.getConfigFileDoesNotExistErrorMessage = exports.getConfigFileOutsideWorkspaceErrorMessage = exports.getLocalPathDoesNotExist = exports.getLocalPathOutsideOfRepository = exports.getPacksStrInvalid = exports.getPacksInvalid = exports.getPacksInvalidSplit = exports.getPathsInvalid = exports.getPathsIgnoreInvalid = exports.getQueryUsesInvalid = exports.getQueriesMissingUses = exports.getQueriesInvalid = exports.getDisableDefaultQueriesInvalid = exports.getNameInvalid = exports.validateAndSanitisePath = exports.defaultAugmentationProperties = void 0; exports.wrapEnvironment = exports.generateRegistries = exports.downloadPacks = exports.getConfig = exports.getPathToParsedConfigFile = exports.initConfig = exports.parsePacks = exports.validatePackSpecification = exports.prettyPrintPack = exports.parsePacksSpecification = exports.parsePacksFromConfig = exports.calculateAugmentation = exports.getDefaultConfig = exports.getRawLanguages = exports.getLanguages = exports.getLanguagesInRepo = exports.getUnknownLanguagesError = exports.getNoLanguagesError = exports.getConfigFileDirectoryGivenMessage = exports.getConfigFileFormatInvalidMessage = exports.getConfigFileRepoFormatInvalidMessage = exports.getConfigFileDoesNotExistErrorMessage = exports.getConfigFileOutsideWorkspaceErrorMessage = exports.getLocalPathDoesNotExist = exports.getLocalPathOutsideOfRepository = exports.getPacksStrInvalid = exports.getPacksInvalid = exports.getPacksInvalidSplit = exports.getPathsInvalid = exports.getPathsIgnoreInvalid = exports.getQueryUsesInvalid = exports.getQueriesMissingUses = exports.getQueriesInvalid = exports.getDisableDefaultQueriesInvalid = exports.getNameInvalid = exports.validateAndSanitisePath = exports.defaultAugmentationProperties = void 0;
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const path = __importStar(require("path")); const path = __importStar(require("path"));
const perf_hooks_1 = require("perf_hooks"); const perf_hooks_1 = require("perf_hooks");
@@ -149,7 +149,7 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
} }
if (suiteName === "security-experimental" && if (suiteName === "security-experimental" &&
!(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE))) { !(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE))) {
throw new Error(`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than throw new Error(`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version ${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version
${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`); ${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`);
} }
@@ -725,7 +725,7 @@ function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
} }
const trimmedInput = queriesInputCombines const trimmedInput = queriesInputCombines
? rawQueriesInput.trim().slice(1).trim() ? rawQueriesInput.trim().slice(1).trim()
: rawQueriesInput?.trim(); : rawQueriesInput?.trim() ?? "";
if (queriesInputCombines && trimmedInput.length === 0) { if (queriesInputCombines && trimmedInput.length === 0) {
throw new Error(getConfigFilePropertyError(undefined, "queries", "A '+' was used in the 'queries' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs.")); throw new Error(getConfigFilePropertyError(undefined, "queries", "A '+' was used in the 'queries' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs."));
} }
@@ -959,8 +959,7 @@ async function initConfig(languagesInput, queriesInput, packsInput, registriesIn
"Please make sure that the default queries are enabled, or you are specifying queries to run."); "Please make sure that the default queries are enabled, or you are specifying queries to run.");
} }
} }
const registries = parseRegistries(registriesInput); await downloadPacks(codeQL, config.languages, config.packs, apiDetails, registriesInput, config.tempDir, logger);
await downloadPacks(codeQL, config.languages, config.packs, registries, apiDetails, config.tempDir, logger);
} }
// Save the config so we can easily access it again in the future // Save the config so we can easily access it again in the future
await saveConfig(config, logger); await saveConfig(config, logger);
@@ -1056,21 +1055,9 @@ async function getConfig(tempDir, logger) {
return JSON.parse(configString); return JSON.parse(configString);
} }
exports.getConfig = getConfig; exports.getConfig = getConfig;
async function downloadPacks(codeQL, languages, packs, registries, apiDetails, tmpDir, logger) { async function downloadPacks(codeQL, languages, packs, apiDetails, registriesInput, tempDir, logger) {
let qlconfigFile; // This code path is only used when config parsing occurs in the Action.
let registriesAuthTokens; const { registriesAuthTokens, qlconfigFile } = await generateRegistries(registriesInput, codeQL, tempDir, logger);
if (registries) {
if (!(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD))) {
throw new Error(`'registries' input is not supported on CodeQL versions less than ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD}.`);
}
// generate a qlconfig.yml file to hold the registry configs.
const qlconfig = createRegistriesBlock(registries);
qlconfigFile = path.join(tmpDir, "qlconfig.yml");
fs.writeFileSync(qlconfigFile, yaml.dump(qlconfig), "utf8");
registriesAuthTokens = registries
.map((registry) => `${registry.url}=${registry.token}`)
.join(",");
}
await wrapEnvironment({ await wrapEnvironment({
GITHUB_TOKEN: apiDetails.auth, GITHUB_TOKEN: apiDetails.auth,
CODEQL_REGISTRIES_AUTH: registriesAuthTokens, CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
@@ -1098,6 +1085,48 @@ async function downloadPacks(codeQL, languages, packs, registries, apiDetails, t
}); });
} }
exports.downloadPacks = downloadPacks; exports.downloadPacks = downloadPacks;
/**
* Generate a `qlconfig.yml` file from the `registries` input.
* This file is used by the CodeQL CLI to list the registries to use for each
* pack.
*
* @param registriesInput The value of the `registries` input.
* @param codeQL a codeQL object, used only for checking the version of CodeQL.
* @param tempDir a temporary directory to store the generated qlconfig.yml file.
* @param logger a logger object.
* @returns The path to the generated `qlconfig.yml` file and the auth tokens to
* use for each registry.
*/
async function generateRegistries(registriesInput, codeQL, tempDir, logger) {
const registries = parseRegistries(registriesInput);
let registriesAuthTokens;
let qlconfigFile;
if (registries) {
if (!(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD))) {
throw new Error(`The 'registries' input is not supported on CodeQL CLI versions earlier than ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD}. Please upgrade to CodeQL CLI version ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD} or later.`);
}
// generate a qlconfig.yml file to hold the registry configs.
const qlconfig = createRegistriesBlock(registries);
qlconfigFile = path.join(tempDir, "qlconfig.yml");
const qlconfigContents = yaml.dump(qlconfig);
fs.writeFileSync(qlconfigFile, qlconfigContents, "utf8");
logger.debug("Generated qlconfig.yml:");
logger.debug(qlconfigContents);
registriesAuthTokens = registries
.map((registry) => `${registry.url}=${registry.token}`)
.join(",");
}
if (typeof process.env.CODEQL_REGISTRIES_AUTH === "string") {
logger.debug("Using CODEQL_REGISTRIES_AUTH environment variable to authenticate with registries.");
}
return {
registriesAuthTokens:
// if the user has explicitly set the CODEQL_REGISTRIES_AUTH env var then use that
process.env.CODEQL_REGISTRIES_AUTH ?? registriesAuthTokens,
qlconfigFile,
};
}
exports.generateRegistries = generateRegistries;
function createRegistriesBlock(registries) { function createRegistriesBlock(registries) {
if (!Array.isArray(registries) || if (!Array.isArray(registries) ||
registries.some((r) => !r.url || !r.packages)) { registries.some((r) => !r.url || !r.packages)) {
@@ -1147,4 +1176,5 @@ async function wrapEnvironment(env, operation) {
} }
} }
} }
exports.wrapEnvironment = wrapEnvironment;
//# sourceMappingURL=config-utils.js.map //# sourceMappingURL=config-utils.js.map
File diff suppressed because one or more lines are too long
+67 -13
View File
@@ -1114,8 +1114,8 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
java: ["a", "b"], java: ["a", "b"],
go: ["c", "d"], go: ["c", "d"],
python: ["e", "f"], python: ["e", "f"],
}, undefined, // registries }, sampleApiDetails, undefined, // registriesAuthTokens
sampleApiDetails, tmpDir, logger); tmpDir, logger);
// Expecting packs to be downloaded once for java and once for python // Expecting packs to be downloaded once for java and once for python
t.deepEqual(packDownloadStub.callCount, 2); t.deepEqual(packDownloadStub.callCount, 2);
// no config file was created, so pass `undefined` as the config file path // no config file was created, so pass `undefined` as the config file path
@@ -1128,9 +1128,9 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
// associated env vars // associated env vars
return await util.withTmpDir(async (tmpDir) => { return await util.withTmpDir(async (tmpDir) => {
process.env.GITHUB_TOKEN = "not-a-token"; process.env.GITHUB_TOKEN = "not-a-token";
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth"; process.env.CODEQL_REGISTRIES_AUTH = undefined;
const logger = (0, logging_1.getRunnerLogger)(true); const logger = (0, logging_1.getRunnerLogger)(true);
const registries = [ const registriesInput = yaml.dump([
{ {
// no slash // no slash
url: "http://ghcr.io", url: "http://ghcr.io",
@@ -1143,8 +1143,9 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
packages: "semmle/*", packages: "semmle/*",
token: "still-not-a-token", token: "still-not-a-token",
}, },
]; ]);
// append a slash to the first url // append a slash to the first url
const registries = yaml.load(registriesInput);
const expectedRegistries = registries.map((r, i) => ({ const expectedRegistries = registries.map((r, i) => ({
packages: r.packages, packages: r.packages,
url: i === 0 ? `${r.url}/` : r.url, url: i === 0 ? `${r.url}/` : r.url,
@@ -1173,7 +1174,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
java: ["a", "b"], java: ["a", "b"],
go: ["c", "d"], go: ["c", "d"],
python: ["e", "f"], python: ["e", "f"],
}, registries, sampleApiDetails, tmpDir, logger); }, sampleApiDetails, registriesInput, tmpDir, logger);
// Same packs are downloaded as in previous test // Same packs are downloaded as in previous test
t.deepEqual(packDownloadStub.callCount, 2); t.deepEqual(packDownloadStub.callCount, 2);
t.deepEqual(packDownloadStub.firstCall.args, [ t.deepEqual(packDownloadStub.firstCall.args, [
@@ -1186,7 +1187,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
]); ]);
// Verify that the env vars were unset. // Verify that the env vars were unset.
t.deepEqual(process.env.GITHUB_TOKEN, "not-a-token"); t.deepEqual(process.env.GITHUB_TOKEN, "not-a-token");
t.deepEqual(process.env.CODEQL_REGISTRIES_AUTH, "not-a-registries-auth"); t.deepEqual(process.env.CODEQL_REGISTRIES_AUTH, undefined);
}); });
}); });
(0, ava_1.default)("downloadPacks-with-registries fails on 2.10.3", async (t) => { (0, ava_1.default)("downloadPacks-with-registries fails on 2.10.3", async (t) => {
@@ -1196,7 +1197,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
process.env.GITHUB_TOKEN = "not-a-token"; process.env.GITHUB_TOKEN = "not-a-token";
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth"; process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
const logger = (0, logging_1.getRunnerLogger)(true); const logger = (0, logging_1.getRunnerLogger)(true);
const registries = [ const registriesInput = yaml.dump([
{ {
url: "http://ghcr.io", url: "http://ghcr.io",
packages: ["codeql/*", "dsp-testing/*"], packages: ["codeql/*", "dsp-testing/*"],
@@ -1207,12 +1208,12 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
packages: "semmle/*", packages: "semmle/*",
token: "still-not-a-token", token: "still-not-a-token",
}, },
]; ]);
const codeQL = (0, codeql_1.setCodeQL)({ const codeQL = (0, codeql_1.setCodeQL)({
getVersion: () => Promise.resolve("2.10.3"), getVersion: () => Promise.resolve("2.10.3"),
}); });
await t.throwsAsync(async () => { await t.throwsAsync(async () => {
return await configUtils.downloadPacks(codeQL, [languages_1.Language.javascript, languages_1.Language.java, languages_1.Language.python], {}, registries, sampleApiDetails, tmpDir, logger); return await configUtils.downloadPacks(codeQL, [languages_1.Language.javascript, languages_1.Language.java, languages_1.Language.python], {}, sampleApiDetails, registriesInput, tmpDir, logger);
}, { instanceOf: Error }, "'registries' input is not supported on CodeQL versions less than 2.10.4."); }, { instanceOf: Error }, "'registries' input is not supported on CodeQL versions less than 2.10.4.");
}); });
}); });
@@ -1223,7 +1224,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
process.env.GITHUB_TOKEN = "not-a-token"; process.env.GITHUB_TOKEN = "not-a-token";
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth"; process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
const logger = (0, logging_1.getRunnerLogger)(true); const logger = (0, logging_1.getRunnerLogger)(true);
const registries = [ const registriesInput = yaml.dump([
{ {
// missing url property // missing url property
packages: ["codeql/*", "dsp-testing/*"], packages: ["codeql/*", "dsp-testing/*"],
@@ -1234,15 +1235,68 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
packages: "semmle/*", packages: "semmle/*",
token: "still-not-a-token", token: "still-not-a-token",
}, },
]; ]);
const codeQL = (0, codeql_1.setCodeQL)({ const codeQL = (0, codeql_1.setCodeQL)({
getVersion: () => Promise.resolve("2.10.4"), getVersion: () => Promise.resolve("2.10.4"),
}); });
await t.throwsAsync(async () => { await t.throwsAsync(async () => {
return await configUtils.downloadPacks(codeQL, [languages_1.Language.javascript, languages_1.Language.java, languages_1.Language.python], {}, registries, sampleApiDetails, tmpDir, logger); return await configUtils.downloadPacks(codeQL, [languages_1.Language.javascript, languages_1.Language.java, languages_1.Language.python], {}, sampleApiDetails, registriesInput, tmpDir, logger);
}, { instanceOf: Error }, "Invalid 'registries' input. Must be an array of objects with 'url' and 'packages' properties."); }, { instanceOf: Error }, "Invalid 'registries' input. Must be an array of objects with 'url' and 'packages' properties.");
}); });
}); });
// the happy path for generateRegistries is already tested in downloadPacks.
// these following tests are for the error cases and when nothing is generated.
(0, ava_1.default)("no generateRegistries when CLI is too old", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
const registriesInput = yaml.dump([
{
// no slash
url: "http://ghcr.io",
packages: ["codeql/*", "dsp-testing/*"],
token: "not-a-token",
},
]);
const codeQL = (0, codeql_1.setCodeQL)({
// Accepted CLI versions are 2.10.4 or higher
getVersion: () => Promise.resolve("2.10.3"),
});
const logger = (0, logging_1.getRunnerLogger)(true);
await t.throwsAsync(async () => await configUtils.generateRegistries(registriesInput, codeQL, tmpDir, logger), undefined, "'registries' input is not supported on CodeQL versions less than 2.10.4.");
});
});
(0, ava_1.default)("no generateRegistries when registries is undefined", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
const registriesInput = undefined;
const codeQL = (0, codeql_1.setCodeQL)({
// Accepted CLI versions are 2.10.4 or higher
getVersion: () => Promise.resolve(codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD),
});
const logger = (0, logging_1.getRunnerLogger)(true);
const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, codeQL, tmpDir, logger);
t.is(registriesAuthTokens, undefined);
t.is(qlconfigFile, undefined);
});
});
(0, ava_1.default)("generateRegistries prefers original CODEQL_REGISTRIES_AUTH", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env.CODEQL_REGISTRIES_AUTH = "original";
const registriesInput = yaml.dump([
{
url: "http://ghcr.io",
packages: ["codeql/*", "dsp-testing/*"],
token: "not-a-token",
},
]);
const codeQL = (0, codeql_1.setCodeQL)({
// Accepted CLI versions are 2.10.4 or higher
getVersion: () => Promise.resolve(codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD),
});
const logger = (0, logging_1.getRunnerLogger)(true);
const { registriesAuthTokens, qlconfigFile } = await configUtils.generateRegistries(registriesInput, codeQL, tmpDir, logger);
t.is(registriesAuthTokens, "original");
t.is(qlconfigFile, path.join(tmpDir, "qlconfig.yml"));
});
});
// getLanguages // getLanguages
const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo"); const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo");
// eslint-disable-next-line github/array-foreach // eslint-disable-next-line github/array-foreach
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -113,6 +113,7 @@ async function run() {
const gitHubVersion = await (0, api_client_1.getGitHubVersion)(); const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
(0, util_1.checkGitHubVersionInRange)(gitHubVersion, logger); (0, util_1.checkGitHubVersionInRange)(gitHubVersion, logger);
const repositoryNwo = (0, repository_1.parseRepositoryNwo)((0, util_1.getRequiredEnvParam)("GITHUB_REPOSITORY")); const repositoryNwo = (0, repository_1.parseRepositoryNwo)((0, util_1.getRequiredEnvParam)("GITHUB_REPOSITORY"));
const registriesInput = (0, actions_util_1.getOptionalInput)("registries");
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, (0, actions_util_1.getTemporaryDirectory)(), logger); const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, (0, actions_util_1.getTemporaryDirectory)(), logger);
try { try {
const workflowErrors = await (0, workflow_1.validateWorkflow)(); const workflowErrors = await (0, workflow_1.validateWorkflow)();
@@ -129,7 +130,7 @@ async function run() {
toolsVersion = initCodeQLResult.toolsVersion; toolsVersion = initCodeQLResult.toolsVersion;
toolsSource = initCodeQLResult.toolsSource; toolsSource = initCodeQLResult.toolsSource;
await (0, util_1.enrichEnvironment)(codeql); await (0, util_1.enrichEnvironment)(codeql);
config = await (0, init_1.initConfig)((0, actions_util_1.getOptionalInput)("languages"), (0, actions_util_1.getOptionalInput)("queries"), (0, actions_util_1.getOptionalInput)("packs"), (0, actions_util_1.getOptionalInput)("registries"), (0, actions_util_1.getOptionalInput)("config-file"), (0, actions_util_1.getOptionalInput)("db-location"), getTrapCachingEnabled(), config = await (0, init_1.initConfig)((0, actions_util_1.getOptionalInput)("languages"), (0, actions_util_1.getOptionalInput)("queries"), (0, actions_util_1.getOptionalInput)("packs"), registriesInput, (0, actions_util_1.getOptionalInput)("config-file"), (0, actions_util_1.getOptionalInput)("db-location"), getTrapCachingEnabled(),
// Debug mode is enabled if: // Debug mode is enabled if:
// - The `init` Action is passed `debug: true`. // - The `init` Action is passed `debug: true`.
// - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow), // - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow),
@@ -173,7 +174,7 @@ async function run() {
core.exportVariable("CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN", "true"); core.exportVariable("CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN", "true");
} }
const sourceRoot = path.resolve((0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"), (0, actions_util_1.getOptionalInput)("source-root") || ""); const sourceRoot = path.resolve((0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"), (0, actions_util_1.getOptionalInput)("source-root") || "");
const tracerConfig = await (0, init_1.runInit)(codeql, config, sourceRoot, "Runner.Worker.exe", features, logger); const tracerConfig = await (0, init_1.runInit)(codeql, config, sourceRoot, "Runner.Worker.exe", registriesInput, features, apiDetails, logger);
if (tracerConfig !== undefined) { if (tracerConfig !== undefined) {
for (const [key, value] of Object.entries(tracerConfig.env)) { for (const [key, value] of Object.entries(tracerConfig.env)) {
core.exportVariable(key, value); core.exportVariable(key, value);
File diff suppressed because one or more lines are too long
Generated
+16 -2
View File
@@ -57,12 +57,26 @@ async function initConfig(languagesInput, queriesInput, packsInput, registriesIn
return config; return config;
} }
exports.initConfig = initConfig; exports.initConfig = initConfig;
async function runInit(codeql, config, sourceRoot, processName, featureEnablement, logger) { async function runInit(codeql, config, sourceRoot, processName, registriesInput, featureEnablement, apiDetails, logger) {
fs.mkdirSync(config.dbLocation, { recursive: true }); fs.mkdirSync(config.dbLocation, { recursive: true });
try { try {
if (await (0, util_1.codeQlVersionAbove)(codeql, codeql_1.CODEQL_VERSION_NEW_TRACING)) { if (await (0, util_1.codeQlVersionAbove)(codeql, codeql_1.CODEQL_VERSION_NEW_TRACING)) {
// When parsing the codeql config in the CLI, we have not yet created the qlconfig file.
// So, create it now.
// If we are parsing the config file in the Action, then the qlconfig file was already created
// before the `pack download` command was invoked. It is not required for the init command.
let registriesAuthTokens;
let qlconfigFile;
if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) {
({ registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries(registriesInput, codeql, config.tempDir, logger));
}
await configUtils.wrapEnvironment({
GITHUB_TOKEN: apiDetails.auth,
CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
},
// Init a database cluster // Init a database cluster
await codeql.databaseInitCluster(config, sourceRoot, processName, featureEnablement, logger); async () => await codeql.databaseInitCluster(config, sourceRoot, processName, featureEnablement, qlconfigFile, logger));
} }
else { else {
for (const language of config.languages) { for (const language of config.languages) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "codeql", "name": "codeql",
"version": "2.2.5", "version": "2.2.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "codeql", "name": "codeql",
"version": "2.2.5", "version": "2.2.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "codeql", "name": "codeql",
"version": "2.2.5", "version": "2.2.6",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/artifact": "^1.1.0", "@actions/artifact": "^1.1.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "codeql", "name": "codeql",
"version": "2.2.5", "version": "2.2.6",
"private": true, "private": true,
"description": "CodeQL action", "description": "CodeQL action",
"scripts": { "scripts": {
+36 -1
View File
@@ -4,7 +4,12 @@
# basic mechanics of multi-registry auth is working. # basic mechanics of multi-registry auth is working.
name: "Packaging: Download using registries" name: "Packaging: Download using registries"
description: "Checks that specifying a registries block and associated auth works as expected" description: "Checks that specifying a registries block and associated auth works as expected"
versions: ["nightly-latest"] # This feature is not compatible with old CLIs versions: [
# This feature is not compatible with older CLIs
"cached",
"latest",
"nightly-latest",
]
steps: steps:
- name: Init with registries - name: Init with registries
@@ -40,3 +45,33 @@ steps:
echo "::error $CODEQL_PACK1 pack was not installed." echo "::error $CODEQL_PACK1 pack was not installed."
exit 1 exit 1
fi fi
- name: Verify qlconfig.yml file was created
shell: bash
run: |
QLCONFIG_PATH=$RUNNER_TEMP/qlconfig.yml
echo "Expected qlconfig.yml file to be created at $QLCONFIG_PATH"
if [[ -f $QLCONFIG_PATH ]]
then
echo "qlconfig.yml file was created."
else
echo "::error qlconfig.yml file was not created."
exit 1
fi
- name: Verify contents of qlconfig.yml
# yq is not available on windows
if: runner.os != 'Windows'
shell: bash
run: |
QLCONFIG_PATH=$RUNNER_TEMP/qlconfig.yml
cat $QLCONFIG_PATH | yq -e '.registries[] | select(.url == "https://ghcr.io/v2/") | select(.packages == "*/*")'
if [[ $? -eq 0 ]]
then
echo "Registry was added to qlconfig.yml file."
else
echo "::error Registry was not added to qlconfig.yml file."
echo "Contents of qlconfig.yml file:"
cat $QLCONFIG_PATH
exit 1
fi
+84 -26
View File
@@ -671,6 +671,7 @@ test("databaseInitCluster() without injected codescanning config", async (t) =>
"", "",
undefined, undefined,
createFeatures([]), createFeatures([]),
"/path/to/qlconfig.yml",
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -679,7 +680,7 @@ test("databaseInitCluster() without injected codescanning config", async (t) =>
const configArg = args.find((arg: string) => const configArg = args.find((arg: string) =>
arg.startsWith("--codescanning-config=") arg.startsWith("--codescanning-config=")
); );
t.falsy(configArg, "Should have injected a codescanning config"); t.falsy(configArg, "Should NOT have injected a codescanning config");
}); });
}); });
@@ -710,6 +711,7 @@ const injectedConfigMacro = test.macro({
"", "",
undefined, undefined,
createFeatures([Feature.CliConfigFileEnabled]), createFeatures([Feature.CliConfigFileEnabled]),
undefined,
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -1000,34 +1002,90 @@ test(
{} {}
); );
test("does not use injected config", async (t: ExecutionContext<unknown>) => { test("does not pass a code scanning config or qlconfig file to the CLI when CLI config passing is disabled", async (t: ExecutionContext<unknown>) => {
const origCODEQL_PASS_CONFIG_TO_CLI = process.env.CODEQL_PASS_CONFIG_TO_CLI; const runnerConstructorStub = stubToolRunnerConstructor();
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = "false"; const codeqlObject = await codeql.getCodeQLForTesting();
// stubbed version doesn't matter. It just needs to be valid semver.
sinon.stub(codeqlObject, "getVersion").resolves("0.0.0");
try { await codeqlObject.databaseInitCluster(
const runnerConstructorStub = stubToolRunnerConstructor(); stubConfig,
const codeqlObject = await codeql.getCodeQLForTesting(); "",
sinon undefined,
.stub(codeqlObject, "getVersion") createFeatures([]),
.resolves(featureConfig[Feature.CliConfigFileEnabled].minimumVersion); "/path/to/qlconfig.yml",
getRunnerLogger(true)
);
await codeqlObject.databaseInitCluster( const args = runnerConstructorStub.firstCall.args[1];
stubConfig, // should not have used a config file
"", const hasConfigArg = args.some((arg: string) =>
undefined, arg.startsWith("--codescanning-config=")
createFeatures([]), );
getRunnerLogger(true) t.false(hasConfigArg, "Should NOT have injected a codescanning config");
);
const args = runnerConstructorStub.firstCall.args[1]; // should not have passed a qlconfig file
// should have used an config file const hasQlconfigArg = args.some((arg: string) =>
const configArg = args.find((arg: string) => arg.startsWith("--qlconfig=")
arg.startsWith("--codescanning-config=") );
); t.false(hasQlconfigArg, "Should NOT have passed a qlconfig file");
t.falsy(configArg, "Should NOT have injected a codescanning config"); });
} finally {
process.env["CODEQL_PASS_CONFIG_TO_CLI"] = origCODEQL_PASS_CONFIG_TO_CLI; test("passes a code scanning config AND qlconfig to the CLI when CLI config passing is enabled", async (t: ExecutionContext<unknown>) => {
} const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon
.stub(codeqlObject, "getVersion")
.resolves(codeql.CODEQL_VERSION_INIT_WITH_QLCONFIG);
await codeqlObject.databaseInitCluster(
stubConfig,
"",
undefined,
createFeatures([Feature.CliConfigFileEnabled]),
"/path/to/qlconfig.yml",
getRunnerLogger(true)
);
const args = runnerConstructorStub.firstCall.args[1];
// should have used a config file
const hasCodeScanningConfigArg = args.some((arg: string) =>
arg.startsWith("--codescanning-config=")
);
t.true(hasCodeScanningConfigArg, "Should have injected a qlconfig");
// should have passed a qlconfig file
const hasQlconfigArg = args.some((arg: string) =>
arg.startsWith("--qlconfig=")
);
t.truthy(hasQlconfigArg, "Should have injected a codescanning config");
});
test("passes a code scanning config BUT NOT a qlconfig to the CLI when CLI config passing is enabled", async (t: ExecutionContext<unknown>) => {
const runnerConstructorStub = stubToolRunnerConstructor();
const codeqlObject = await codeql.getCodeQLForTesting();
sinon.stub(codeqlObject, "getVersion").resolves("2.12.2");
await codeqlObject.databaseInitCluster(
stubConfig,
"",
undefined,
createFeatures([Feature.CliConfigFileEnabled]),
"/path/to/qlconfig.yml",
getRunnerLogger(true)
);
const args = runnerConstructorStub.firstCall.args[1] as any[];
// should have used a config file
const hasCodeScanningConfigArg = args.some((arg: string) =>
arg.startsWith("--codescanning-config=")
);
t.true(hasCodeScanningConfigArg, "Should NOT have injected a qlconfig");
// should have passed a qlconfig file
const hasQlconfigArg = args.some((arg: string) =>
arg.startsWith("--qlconfig=")
);
t.false(hasQlconfigArg, "Should have injected a codescanning config");
}); });
test("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3", async (t) => { test("databaseInterpretResults() sets --sarif-add-baseline-file-info for 2.11.3", async (t) => {
+25 -8
View File
@@ -91,6 +91,7 @@ export interface CodeQL {
sourceRoot: string, sourceRoot: string,
processName: string | undefined, processName: string | undefined,
featureEnablement: FeatureEnablement, featureEnablement: FeatureEnablement,
qlconfigFile: string | undefined,
logger: Logger logger: Logger
): Promise<void>; ): Promise<void>;
/** /**
@@ -289,6 +290,11 @@ export const CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = "2.10.3";
*/ */
export const CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1"; export const CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1";
/**
* Versions 2.12.4+ of the CodeQL CLI support the `--qlconfig` flag in calls to `database init`.
*/
export const CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
/** /**
* Set up CodeQL CLI access. * Set up CodeQL CLI access.
* *
@@ -565,6 +571,7 @@ export async function getCodeQLForCmd(
sourceRoot: string, sourceRoot: string,
processName: string | undefined, processName: string | undefined,
featureEnablement: FeatureEnablement, featureEnablement: FeatureEnablement,
qlconfigFile: string | undefined,
logger: Logger logger: Logger
) { ) {
const extraArgs = config.languages.map( const extraArgs = config.languages.map(
@@ -594,8 +601,8 @@ export async function getCodeQLForCmd(
} }
} }
// A config file is only generated if the CliConfigFileEnabled feature flag is enabled. // A code scanning config file is only generated if the CliConfigFileEnabled feature flag is enabled.
const configLocation = await generateCodeScanningConfig( const codeScanningConfigFile = await generateCodeScanningConfig(
codeql, codeql,
config, config,
featureEnablement, featureEnablement,
@@ -603,14 +610,19 @@ export async function getCodeQLForCmd(
); );
// Only pass external repository token if a config file is going to be parsed by the CLI. // Only pass external repository token if a config file is going to be parsed by the CLI.
let externalRepositoryToken: string | undefined; let externalRepositoryToken: string | undefined;
if (configLocation) { if (codeScanningConfigFile) {
extraArgs.push(`--codescanning-config=${configLocation}`);
externalRepositoryToken = getOptionalInput("external-repository-token"); externalRepositoryToken = getOptionalInput("external-repository-token");
extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`);
if (externalRepositoryToken) { if (externalRepositoryToken) {
extraArgs.push("--external-repository-token-stdin"); extraArgs.push("--external-repository-token-stdin");
} }
} }
if (
await util.codeQlVersionAbove(this, CODEQL_VERSION_INIT_WITH_QLCONFIG)
) {
extraArgs.push(`--qlconfig=${qlconfigFile}`);
}
await runTool( await runTool(
cmd, cmd,
[ [
@@ -1111,7 +1123,10 @@ async function generateCodeScanningConfig(
if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) { if (!(await util.useCodeScanningConfigInCli(codeql, featureEnablement))) {
return; return;
} }
const configLocation = path.resolve(config.tempDir, "user-config.yaml"); const codeScanningConfigFile = path.resolve(
config.tempDir,
"user-config.yaml"
);
// make a copy so we can modify it // make a copy so we can modify it
const augmentedConfig = cloneObject(config.originalUserInput); const augmentedConfig = cloneObject(config.originalUserInput);
@@ -1168,13 +1183,15 @@ async function generateCodeScanningConfig(
augmentedConfig.packs["javascript"].push(packString); augmentedConfig.packs["javascript"].push(packString);
} }
} }
logger.info(`Writing augmented user configuration file to ${configLocation}`); logger.info(
`Writing augmented user configuration file to ${codeScanningConfigFile}`
);
logger.startGroup("Augmented user configuration file contents"); logger.startGroup("Augmented user configuration file contents");
logger.info(yaml.dump(augmentedConfig)); logger.info(yaml.dump(augmentedConfig));
logger.endGroup(); logger.endGroup();
fs.writeFileSync(configLocation, yaml.dump(augmentedConfig)); fs.writeFileSync(codeScanningConfigFile, yaml.dump(augmentedConfig));
return configLocation; return codeScanningConfigFile;
} }
function cloneObject<T>(obj: T): T { function cloneObject<T>(obj: T): T {
+100 -14
View File
@@ -7,9 +7,13 @@ import * as yaml from "js-yaml";
import * as sinon from "sinon"; import * as sinon from "sinon";
import * as api from "./api-client"; import * as api from "./api-client";
import { getCachedCodeQL, PackDownloadOutput, setCodeQL } from "./codeql"; import {
CODEQL_VERSION_GHES_PACK_DOWNLOAD,
getCachedCodeQL,
PackDownloadOutput,
setCodeQL,
} from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { RegistryConfigWithCredentials } from "./config-utils";
import { Feature } from "./feature-flags"; import { Feature } from "./feature-flags";
import { Language } from "./languages"; import { Language } from "./languages";
import { getRunnerLogger, Logger } from "./logging"; import { getRunnerLogger, Logger } from "./logging";
@@ -2277,8 +2281,8 @@ test("downloadPacks-no-registries", async (t) => {
go: ["c", "d"], go: ["c", "d"],
python: ["e", "f"], python: ["e", "f"],
}, },
undefined, // registries
sampleApiDetails, sampleApiDetails,
undefined, // registriesAuthTokens
tmpDir, tmpDir,
logger logger
); );
@@ -2296,10 +2300,10 @@ test("downloadPacks-with-registries", async (t) => {
// associated env vars // associated env vars
return await util.withTmpDir(async (tmpDir) => { return await util.withTmpDir(async (tmpDir) => {
process.env.GITHUB_TOKEN = "not-a-token"; process.env.GITHUB_TOKEN = "not-a-token";
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth"; process.env.CODEQL_REGISTRIES_AUTH = undefined;
const logger = getRunnerLogger(true); const logger = getRunnerLogger(true);
const registries = [ const registriesInput = yaml.dump([
{ {
// no slash // no slash
url: "http://ghcr.io", url: "http://ghcr.io",
@@ -2312,9 +2316,12 @@ test("downloadPacks-with-registries", async (t) => {
packages: "semmle/*", packages: "semmle/*",
token: "still-not-a-token", token: "still-not-a-token",
}, },
]; ]);
// append a slash to the first url // append a slash to the first url
const registries = yaml.load(
registriesInput
) as configUtils.RegistryConfigWithCredentials[];
const expectedRegistries = registries.map((r, i) => ({ const expectedRegistries = registries.map((r, i) => ({
packages: r.packages, packages: r.packages,
url: i === 0 ? `${r.url}/` : r.url, url: i === 0 ? `${r.url}/` : r.url,
@@ -2356,8 +2363,8 @@ test("downloadPacks-with-registries", async (t) => {
go: ["c", "d"], go: ["c", "d"],
python: ["e", "f"], python: ["e", "f"],
}, },
registries,
sampleApiDetails, sampleApiDetails,
registriesInput,
tmpDir, tmpDir,
logger logger
); );
@@ -2375,7 +2382,7 @@ test("downloadPacks-with-registries", async (t) => {
// Verify that the env vars were unset. // Verify that the env vars were unset.
t.deepEqual(process.env.GITHUB_TOKEN, "not-a-token"); t.deepEqual(process.env.GITHUB_TOKEN, "not-a-token");
t.deepEqual(process.env.CODEQL_REGISTRIES_AUTH, "not-a-registries-auth"); t.deepEqual(process.env.CODEQL_REGISTRIES_AUTH, undefined);
}); });
}); });
@@ -2387,7 +2394,7 @@ test("downloadPacks-with-registries fails on 2.10.3", async (t) => {
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth"; process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
const logger = getRunnerLogger(true); const logger = getRunnerLogger(true);
const registries = [ const registriesInput = yaml.dump([
{ {
url: "http://ghcr.io", url: "http://ghcr.io",
packages: ["codeql/*", "dsp-testing/*"], packages: ["codeql/*", "dsp-testing/*"],
@@ -2398,7 +2405,7 @@ test("downloadPacks-with-registries fails on 2.10.3", async (t) => {
packages: "semmle/*", packages: "semmle/*",
token: "still-not-a-token", token: "still-not-a-token",
}, },
]; ]);
const codeQL = setCodeQL({ const codeQL = setCodeQL({
getVersion: () => Promise.resolve("2.10.3"), getVersion: () => Promise.resolve("2.10.3"),
@@ -2409,8 +2416,8 @@ test("downloadPacks-with-registries fails on 2.10.3", async (t) => {
codeQL, codeQL,
[Language.javascript, Language.java, Language.python], [Language.javascript, Language.java, Language.python],
{}, {},
registries,
sampleApiDetails, sampleApiDetails,
registriesInput,
tmpDir, tmpDir,
logger logger
); );
@@ -2429,7 +2436,7 @@ test("downloadPacks-with-registries fails with invalid registries block", async
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth"; process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
const logger = getRunnerLogger(true); const logger = getRunnerLogger(true);
const registries = [ const registriesInput = yaml.dump([
{ {
// missing url property // missing url property
packages: ["codeql/*", "dsp-testing/*"], packages: ["codeql/*", "dsp-testing/*"],
@@ -2440,7 +2447,7 @@ test("downloadPacks-with-registries fails with invalid registries block", async
packages: "semmle/*", packages: "semmle/*",
token: "still-not-a-token", token: "still-not-a-token",
}, },
]; ]);
const codeQL = setCodeQL({ const codeQL = setCodeQL({
getVersion: () => Promise.resolve("2.10.4"), getVersion: () => Promise.resolve("2.10.4"),
@@ -2451,8 +2458,8 @@ test("downloadPacks-with-registries fails with invalid registries block", async
codeQL, codeQL,
[Language.javascript, Language.java, Language.python], [Language.javascript, Language.java, Language.python],
{}, {},
registries as RegistryConfigWithCredentials[] | undefined,
sampleApiDetails, sampleApiDetails,
registriesInput,
tmpDir, tmpDir,
logger logger
); );
@@ -2463,6 +2470,85 @@ test("downloadPacks-with-registries fails with invalid registries block", async
}); });
}); });
// the happy path for generateRegistries is already tested in downloadPacks.
// these following tests are for the error cases and when nothing is generated.
test("no generateRegistries when CLI is too old", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
const registriesInput = yaml.dump([
{
// no slash
url: "http://ghcr.io",
packages: ["codeql/*", "dsp-testing/*"],
token: "not-a-token",
},
]);
const codeQL = setCodeQL({
// Accepted CLI versions are 2.10.4 or higher
getVersion: () => Promise.resolve("2.10.3"),
});
const logger = getRunnerLogger(true);
await t.throwsAsync(
async () =>
await configUtils.generateRegistries(
registriesInput,
codeQL,
tmpDir,
logger
),
undefined,
"'registries' input is not supported on CodeQL versions less than 2.10.4."
);
});
});
test("no generateRegistries when registries is undefined", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
const registriesInput = undefined;
const codeQL = setCodeQL({
// Accepted CLI versions are 2.10.4 or higher
getVersion: () => Promise.resolve(CODEQL_VERSION_GHES_PACK_DOWNLOAD),
});
const logger = getRunnerLogger(true);
const { registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries(
registriesInput,
codeQL,
tmpDir,
logger
);
t.is(registriesAuthTokens, undefined);
t.is(qlconfigFile, undefined);
});
});
test("generateRegistries prefers original CODEQL_REGISTRIES_AUTH", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env.CODEQL_REGISTRIES_AUTH = "original";
const registriesInput = yaml.dump([
{
url: "http://ghcr.io",
packages: ["codeql/*", "dsp-testing/*"],
token: "not-a-token",
},
]);
const codeQL = setCodeQL({
// Accepted CLI versions are 2.10.4 or higher
getVersion: () => Promise.resolve(CODEQL_VERSION_GHES_PACK_DOWNLOAD),
});
const logger = getRunnerLogger(true);
const { registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries(
registriesInput,
codeQL,
tmpDir,
logger
);
t.is(registriesAuthTokens, "original");
t.is(qlconfigFile, path.join(tmpDir, "qlconfig.yml"));
});
});
// getLanguages // getLanguages
const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
+70 -28
View File
@@ -414,7 +414,7 @@ async function addBuiltinSuiteQueries(
)) ))
) { ) {
throw new Error( throw new Error(
`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than `The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version ${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version
${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.` ${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`
); );
@@ -1403,7 +1403,7 @@ function parseQueriesFromInput(
const trimmedInput = queriesInputCombines const trimmedInput = queriesInputCombines
? rawQueriesInput.trim().slice(1).trim() ? rawQueriesInput.trim().slice(1).trim()
: rawQueriesInput?.trim(); : rawQueriesInput?.trim() ?? "";
if (queriesInputCombines && trimmedInput.length === 0) { if (queriesInputCombines && trimmedInput.length === 0) {
throw new Error( throw new Error(
getConfigFilePropertyError( getConfigFilePropertyError(
@@ -1769,13 +1769,12 @@ export async function initConfig(
} }
} }
const registries = parseRegistries(registriesInput);
await downloadPacks( await downloadPacks(
codeQL, codeQL,
config.languages, config.languages,
config.packs, config.packs,
registries,
apiDetails, apiDetails,
registriesInput,
config.tempDir, config.tempDir,
logger logger
); );
@@ -1899,32 +1898,18 @@ export async function downloadPacks(
codeQL: CodeQL, codeQL: CodeQL,
languages: Language[], languages: Language[],
packs: Packs, packs: Packs,
registries: RegistryConfigWithCredentials[] | undefined,
apiDetails: api.GitHubApiDetails, apiDetails: api.GitHubApiDetails,
tmpDir: string, registriesInput: string | undefined,
tempDir: string,
logger: Logger logger: Logger
) { ) {
let qlconfigFile: string | undefined; // This code path is only used when config parsing occurs in the Action.
let registriesAuthTokens: string | undefined; const { registriesAuthTokens, qlconfigFile } = await generateRegistries(
if (registries) { registriesInput,
if ( codeQL,
!(await codeQlVersionAbove(codeQL, CODEQL_VERSION_GHES_PACK_DOWNLOAD)) tempDir,
) { logger
throw new Error( );
`'registries' input is not supported on CodeQL versions less than ${CODEQL_VERSION_GHES_PACK_DOWNLOAD}.`
);
}
// generate a qlconfig.yml file to hold the registry configs.
const qlconfig = createRegistriesBlock(registries);
qlconfigFile = path.join(tmpDir, "qlconfig.yml");
fs.writeFileSync(qlconfigFile, yaml.dump(qlconfig), "utf8");
registriesAuthTokens = registries
.map((registry) => `${registry.url}=${registry.token}`)
.join(",");
}
await wrapEnvironment( await wrapEnvironment(
{ {
GITHUB_TOKEN: apiDetails.auth, GITHUB_TOKEN: apiDetails.auth,
@@ -1963,6 +1948,63 @@ export async function downloadPacks(
); );
} }
/**
* Generate a `qlconfig.yml` file from the `registries` input.
* This file is used by the CodeQL CLI to list the registries to use for each
* pack.
*
* @param registriesInput The value of the `registries` input.
* @param codeQL a codeQL object, used only for checking the version of CodeQL.
* @param tempDir a temporary directory to store the generated qlconfig.yml file.
* @param logger a logger object.
* @returns The path to the generated `qlconfig.yml` file and the auth tokens to
* use for each registry.
*/
export async function generateRegistries(
registriesInput: string | undefined,
codeQL: CodeQL,
tempDir: string,
logger: Logger
) {
const registries = parseRegistries(registriesInput);
let registriesAuthTokens: string | undefined;
let qlconfigFile: string | undefined;
if (registries) {
if (
!(await codeQlVersionAbove(codeQL, CODEQL_VERSION_GHES_PACK_DOWNLOAD))
) {
throw new Error(
`The 'registries' input is not supported on CodeQL CLI versions earlier than ${CODEQL_VERSION_GHES_PACK_DOWNLOAD}. Please upgrade to CodeQL CLI version ${CODEQL_VERSION_GHES_PACK_DOWNLOAD} or later.`
);
}
// generate a qlconfig.yml file to hold the registry configs.
const qlconfig = createRegistriesBlock(registries);
qlconfigFile = path.join(tempDir, "qlconfig.yml");
const qlconfigContents = yaml.dump(qlconfig);
fs.writeFileSync(qlconfigFile, qlconfigContents, "utf8");
logger.debug("Generated qlconfig.yml:");
logger.debug(qlconfigContents);
registriesAuthTokens = registries
.map((registry) => `${registry.url}=${registry.token}`)
.join(",");
}
if (typeof process.env.CODEQL_REGISTRIES_AUTH === "string") {
logger.debug(
"Using CODEQL_REGISTRIES_AUTH environment variable to authenticate with registries."
);
}
return {
registriesAuthTokens:
// if the user has explicitly set the CODEQL_REGISTRIES_AUTH env var then use that
process.env.CODEQL_REGISTRIES_AUTH ?? registriesAuthTokens,
qlconfigFile,
};
}
function createRegistriesBlock(registries: RegistryConfigWithCredentials[]): { function createRegistriesBlock(registries: RegistryConfigWithCredentials[]): {
registries: RegistryConfigNoCredentials[]; registries: RegistryConfigNoCredentials[];
} { } {
@@ -1999,7 +2041,7 @@ function createRegistriesBlock(registries: RegistryConfigWithCredentials[]): {
* @param env * @param env
* @param operation * @param operation
*/ */
async function wrapEnvironment( export async function wrapEnvironment(
env: Record<string, string | undefined>, env: Record<string, string | undefined>,
operation: Function operation: Function
) { ) {
+5 -1
View File
@@ -204,6 +204,8 @@ async function run() {
getRequiredEnvParam("GITHUB_REPOSITORY") getRequiredEnvParam("GITHUB_REPOSITORY")
); );
const registriesInput = getOptionalInput("registries");
const features = new Features( const features = new Features(
gitHubVersion, gitHubVersion,
repositoryNwo, repositoryNwo,
@@ -251,7 +253,7 @@ async function run() {
getOptionalInput("languages"), getOptionalInput("languages"),
getOptionalInput("queries"), getOptionalInput("queries"),
getOptionalInput("packs"), getOptionalInput("packs"),
getOptionalInput("registries"), registriesInput,
getOptionalInput("config-file"), getOptionalInput("config-file"),
getOptionalInput("db-location"), getOptionalInput("db-location"),
getTrapCachingEnabled(), getTrapCachingEnabled(),
@@ -335,7 +337,9 @@ async function run() {
config, config,
sourceRoot, sourceRoot,
"Runner.Worker.exe", "Runner.Worker.exe",
registriesInput,
features, features,
apiDetails,
logger logger
); );
if (tracerConfig !== undefined) { if (tracerConfig !== undefined) {
+33 -7
View File
@@ -102,20 +102,46 @@ export async function runInit(
config: configUtils.Config, config: configUtils.Config,
sourceRoot: string, sourceRoot: string,
processName: string | undefined, processName: string | undefined,
registriesInput: string | undefined,
featureEnablement: FeatureEnablement, featureEnablement: FeatureEnablement,
apiDetails: GitHubApiCombinedDetails,
logger: Logger logger: Logger
): Promise<TracerConfig | undefined> { ): Promise<TracerConfig | undefined> {
fs.mkdirSync(config.dbLocation, { recursive: true }); fs.mkdirSync(config.dbLocation, { recursive: true });
try { try {
if (await codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) { if (await codeQlVersionAbove(codeql, CODEQL_VERSION_NEW_TRACING)) {
// Init a database cluster // When parsing the codeql config in the CLI, we have not yet created the qlconfig file.
await codeql.databaseInitCluster( // So, create it now.
config, // If we are parsing the config file in the Action, then the qlconfig file was already created
sourceRoot, // before the `pack download` command was invoked. It is not required for the init command.
processName, let registriesAuthTokens: string | undefined;
featureEnablement, let qlconfigFile: string | undefined;
logger if (await util.useCodeScanningConfigInCli(codeql, featureEnablement)) {
({ registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries(
registriesInput,
codeql,
config.tempDir,
logger
));
}
await configUtils.wrapEnvironment(
{
GITHUB_TOKEN: apiDetails.auth,
CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
},
// Init a database cluster
async () =>
await codeql.databaseInitCluster(
config,
sourceRoot,
processName,
featureEnablement,
qlconfigFile,
logger
)
); );
} else { } else {
for (const language of config.languages) { for (const language of config.languages) {