mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 09:14:58 +00:00
Merge remote-tracking branch 'origin/main' into mbg/status/registries
This commit is contained in:
4
.github/workflows/__job-run-uuid-sarif.yml
generated
vendored
4
.github/workflows/__job-run-uuid-sarif.yml
generated
vendored
@@ -71,8 +71,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd "$RUNNER_TEMP/results"
|
cd "$RUNNER_TEMP/results"
|
||||||
actual=$(jq -r '.runs[0].properties.jobRunUuid' javascript.sarif)
|
actual=$(jq -r '.runs[0].properties.jobRunUuid' javascript.sarif)
|
||||||
if [[ "$actual" != "$JOB_RUN_UUID" ]]; then
|
if [[ "$actual" != "$CODEQL_ACTION_JOB_RUN_UUID" ]]; then
|
||||||
echo "Expected SARIF output to contain job run UUID '$JOB_RUN_UUID', but found '$actual'."
|
echo "Expected SARIF output to contain job run UUID '$CODEQL_ACTION_JOB_RUN_UUID', but found '$actual'."
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
echo "Found job run UUID '$actual'."
|
echo "Found job run UUID '$actual'."
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
|
|||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
- This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037)
|
- This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037)
|
||||||
|
- Update default CodeQL bundle version to [2.26.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.2). [#4051](https://github.com/github/codeql-action/pull/4051)
|
||||||
|
|
||||||
## 4.37.3 - 22 Jul 2026
|
## 4.37.3 - 22 Jul 2026
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-v2.26.1",
|
"bundleVersion": "codeql-bundle-v2.26.2",
|
||||||
"cliVersion": "2.26.1",
|
"cliVersion": "2.26.2",
|
||||||
"priorBundleVersion": "codeql-bundle-v2.26.0",
|
"priorBundleVersion": "codeql-bundle-v2.26.1",
|
||||||
"priorCliVersion": "2.26.0"
|
"priorCliVersion": "2.26.1"
|
||||||
}
|
}
|
||||||
|
|||||||
202
lib/entry-points.js
generated
202
lib/entry-points.js
generated
@@ -21559,7 +21559,7 @@ var require_core = __commonJS({
|
|||||||
};
|
};
|
||||||
Object.defineProperty(exports2, "__esModule", { value: true });
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
||||||
exports2.platform = exports2.toPlatformPath = exports2.toWin32Path = exports2.toPosixPath = exports2.markdownSummary = exports2.summary = exports2.ExitCode = void 0;
|
exports2.platform = exports2.toPlatformPath = exports2.toWin32Path = exports2.toPosixPath = exports2.markdownSummary = exports2.summary = exports2.ExitCode = void 0;
|
||||||
exports2.exportVariable = exportVariable15;
|
exports2.exportVariable = exportVariable16;
|
||||||
exports2.setSecret = setSecret2;
|
exports2.setSecret = setSecret2;
|
||||||
exports2.addPath = addPath2;
|
exports2.addPath = addPath2;
|
||||||
exports2.getInput = getInput2;
|
exports2.getInput = getInput2;
|
||||||
@@ -21567,7 +21567,7 @@ var require_core = __commonJS({
|
|||||||
exports2.getBooleanInput = getBooleanInput;
|
exports2.getBooleanInput = getBooleanInput;
|
||||||
exports2.setOutput = setOutput7;
|
exports2.setOutput = setOutput7;
|
||||||
exports2.setCommandEcho = setCommandEcho;
|
exports2.setCommandEcho = setCommandEcho;
|
||||||
exports2.setFailed = setFailed13;
|
exports2.setFailed = setFailed12;
|
||||||
exports2.isDebug = isDebug5;
|
exports2.isDebug = isDebug5;
|
||||||
exports2.debug = debug6;
|
exports2.debug = debug6;
|
||||||
exports2.error = error3;
|
exports2.error = error3;
|
||||||
@@ -21591,7 +21591,7 @@ var require_core = __commonJS({
|
|||||||
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
||||||
ExitCode2[ExitCode2["Failure"] = 1] = "Failure";
|
ExitCode2[ExitCode2["Failure"] = 1] = "Failure";
|
||||||
})(ExitCode || (exports2.ExitCode = ExitCode = {}));
|
})(ExitCode || (exports2.ExitCode = ExitCode = {}));
|
||||||
function exportVariable15(name, val) {
|
function exportVariable16(name, val) {
|
||||||
const convertedVal = (0, utils_1.toCommandValue)(val);
|
const convertedVal = (0, utils_1.toCommandValue)(val);
|
||||||
process.env[name] = convertedVal;
|
process.env[name] = convertedVal;
|
||||||
const filePath = process.env["GITHUB_ENV"] || "";
|
const filePath = process.env["GITHUB_ENV"] || "";
|
||||||
@@ -21651,7 +21651,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
|||||||
function setCommandEcho(enabled) {
|
function setCommandEcho(enabled) {
|
||||||
(0, command_1.issue)("echo", enabled ? "on" : "off");
|
(0, command_1.issue)("echo", enabled ? "on" : "off");
|
||||||
}
|
}
|
||||||
function setFailed13(message) {
|
function setFailed12(message) {
|
||||||
process.exitCode = ExitCode.Failure;
|
process.exitCode = ExitCode.Failure;
|
||||||
error3(message);
|
error3(message);
|
||||||
}
|
}
|
||||||
@@ -30477,7 +30477,7 @@ var require_validator = __commonJS({
|
|||||||
Validator3.prototype.getSchema = function getSchema(urn) {
|
Validator3.prototype.getSchema = function getSchema(urn) {
|
||||||
return this.schemas[urn];
|
return this.schemas[urn];
|
||||||
};
|
};
|
||||||
Validator3.prototype.validate = function validate(instance, schema, options, ctx) {
|
Validator3.prototype.validate = function validate2(instance, schema, options, ctx) {
|
||||||
if (typeof schema !== "boolean" && typeof schema !== "object" || schema === null) {
|
if (typeof schema !== "boolean" && typeof schema !== "object" || schema === null) {
|
||||||
throw new SchemaError("Expected `schema` to be an object or boolean");
|
throw new SchemaError("Expected `schema` to be an object or boolean");
|
||||||
}
|
}
|
||||||
@@ -121026,7 +121026,7 @@ var require_core3 = __commonJS({
|
|||||||
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
||||||
ExitCode2[ExitCode2["Failure"] = 1] = "Failure";
|
ExitCode2[ExitCode2["Failure"] = 1] = "Failure";
|
||||||
})(ExitCode || (exports2.ExitCode = ExitCode = {}));
|
})(ExitCode || (exports2.ExitCode = ExitCode = {}));
|
||||||
function exportVariable15(name, val) {
|
function exportVariable16(name, val) {
|
||||||
const convertedVal = (0, utils_1.toCommandValue)(val);
|
const convertedVal = (0, utils_1.toCommandValue)(val);
|
||||||
process.env[name] = convertedVal;
|
process.env[name] = convertedVal;
|
||||||
const filePath = process.env["GITHUB_ENV"] || "";
|
const filePath = process.env["GITHUB_ENV"] || "";
|
||||||
@@ -121035,7 +121035,7 @@ var require_core3 = __commonJS({
|
|||||||
}
|
}
|
||||||
(0, command_1.issueCommand)("set-env", { name }, convertedVal);
|
(0, command_1.issueCommand)("set-env", { name }, convertedVal);
|
||||||
}
|
}
|
||||||
exports2.exportVariable = exportVariable15;
|
exports2.exportVariable = exportVariable16;
|
||||||
function setSecret2(secret) {
|
function setSecret2(secret) {
|
||||||
(0, command_1.issueCommand)("add-mask", {}, secret);
|
(0, command_1.issueCommand)("add-mask", {}, secret);
|
||||||
}
|
}
|
||||||
@@ -121094,11 +121094,11 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
|||||||
(0, command_1.issue)("echo", enabled ? "on" : "off");
|
(0, command_1.issue)("echo", enabled ? "on" : "off");
|
||||||
}
|
}
|
||||||
exports2.setCommandEcho = setCommandEcho;
|
exports2.setCommandEcho = setCommandEcho;
|
||||||
function setFailed13(message) {
|
function setFailed12(message) {
|
||||||
process.exitCode = ExitCode.Failure;
|
process.exitCode = ExitCode.Failure;
|
||||||
error3(message);
|
error3(message);
|
||||||
}
|
}
|
||||||
exports2.setFailed = setFailed13;
|
exports2.setFailed = setFailed12;
|
||||||
function isDebug5() {
|
function isDebug5() {
|
||||||
return process.env["RUNNER_DEBUG"] === "1";
|
return process.env["RUNNER_DEBUG"] === "1";
|
||||||
}
|
}
|
||||||
@@ -141565,6 +141565,10 @@ var ReadOnlyEnv = class {
|
|||||||
clone() {
|
clone() {
|
||||||
return Object.create(this, { vars: { value: { ...this.vars } } });
|
return Object.create(this, { vars: { value: { ...this.vars } } });
|
||||||
}
|
}
|
||||||
|
/** Gets a copy of the underlying environment. */
|
||||||
|
get() {
|
||||||
|
return { ...this.vars };
|
||||||
|
}
|
||||||
/** Tries to get the value for `name` and throws if there isn't one. */
|
/** Tries to get the value for `name` and throws if there isn't one. */
|
||||||
getRequired(name) {
|
getRequired(name) {
|
||||||
return getRequiredEnvVar(this.vars, name);
|
return getRequiredEnvVar(this.vars, name);
|
||||||
@@ -144598,13 +144602,13 @@ function isBoolean(value) {
|
|||||||
function isStringOrUndefined(value) {
|
function isStringOrUndefined(value) {
|
||||||
return value === void 0 || isString(value);
|
return value === void 0 || isString(value);
|
||||||
}
|
}
|
||||||
function defaultCheck(validate) {
|
function defaultCheck(validate2) {
|
||||||
return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate(arg) });
|
return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate2(arg) });
|
||||||
}
|
}
|
||||||
function makeValidator(validate) {
|
function makeValidator(validate2) {
|
||||||
return {
|
return {
|
||||||
validate,
|
validate: validate2,
|
||||||
check: defaultCheck(validate),
|
check: defaultCheck(validate2),
|
||||||
required: true
|
required: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -144612,11 +144616,11 @@ var string = makeValidator(isString);
|
|||||||
var number = makeValidator(isNumber);
|
var number = makeValidator(isNumber);
|
||||||
var boolean = makeValidator(isBoolean);
|
var boolean = makeValidator(isBoolean);
|
||||||
function array(validator) {
|
function array(validator) {
|
||||||
const validate = (val) => {
|
const validate2 = (val) => {
|
||||||
return isArray(val) && val.every((e) => validator.validate(e));
|
return isArray(val) && val.every((e) => validator.validate(e));
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
validate,
|
validate: validate2,
|
||||||
check: (val, opts, path29) => {
|
check: (val, opts, path29) => {
|
||||||
const result = successfulCheckSchema();
|
const result = successfulCheckSchema();
|
||||||
if (!isArray(val)) {
|
if (!isArray(val)) {
|
||||||
@@ -145391,7 +145395,11 @@ var Failure = class {
|
|||||||
|
|
||||||
// src/actions-util.ts
|
// src/actions-util.ts
|
||||||
function getActionsEnv() {
|
function getActionsEnv() {
|
||||||
return { getOptionalInput };
|
return {
|
||||||
|
getRequiredInput,
|
||||||
|
getOptionalInput,
|
||||||
|
exportVariable: core3.exportVariable
|
||||||
|
};
|
||||||
}
|
}
|
||||||
var getRequiredInput = function(name) {
|
var getRequiredInput = function(name) {
|
||||||
const value = core3.getInput(name);
|
const value = core3.getInput(name);
|
||||||
@@ -145736,6 +145744,59 @@ function formatDuration(durationMs) {
|
|||||||
var os3 = __toESM(require("os"));
|
var os3 = __toESM(require("os"));
|
||||||
var core7 = __toESM(require_core());
|
var core7 = __toESM(require_core());
|
||||||
|
|
||||||
|
// node_modules/uuid/dist-node/regex.js
|
||||||
|
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
||||||
|
|
||||||
|
// node_modules/uuid/dist-node/validate.js
|
||||||
|
function validate(uuid) {
|
||||||
|
return typeof uuid === "string" && regex_default.test(uuid);
|
||||||
|
}
|
||||||
|
var validate_default = validate;
|
||||||
|
|
||||||
|
// node_modules/uuid/dist-node/stringify.js
|
||||||
|
var byteToHex = [];
|
||||||
|
for (let i = 0; i < 256; ++i) {
|
||||||
|
byteToHex.push((i + 256).toString(16).slice(1));
|
||||||
|
}
|
||||||
|
function unsafeStringify(arr, offset = 0) {
|
||||||
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/uuid/dist-node/rng.js
|
||||||
|
var rnds8 = new Uint8Array(16);
|
||||||
|
function rng() {
|
||||||
|
return crypto.getRandomValues(rnds8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/uuid/dist-node/v4.js
|
||||||
|
function v4(options, buf, offset) {
|
||||||
|
if (!buf && !options && crypto.randomUUID) {
|
||||||
|
return crypto.randomUUID();
|
||||||
|
}
|
||||||
|
return _v4(options, buf, offset);
|
||||||
|
}
|
||||||
|
function _v4(options, buf, offset) {
|
||||||
|
options = options || {};
|
||||||
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
||||||
|
if (rnds.length < 16) {
|
||||||
|
throw new Error("Random bytes length must be >= 16");
|
||||||
|
}
|
||||||
|
rnds[6] = rnds[6] & 15 | 64;
|
||||||
|
rnds[8] = rnds[8] & 63 | 128;
|
||||||
|
if (buf) {
|
||||||
|
offset = offset || 0;
|
||||||
|
if (offset < 0 || offset + 16 > buf.length) {
|
||||||
|
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 16; ++i) {
|
||||||
|
buf[offset + i] = rnds[i];
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
return unsafeStringify(rnds);
|
||||||
|
}
|
||||||
|
var v4_default = v4;
|
||||||
|
|
||||||
// src/api-client.ts
|
// src/api-client.ts
|
||||||
var core5 = __toESM(require_core());
|
var core5 = __toESM(require_core());
|
||||||
var githubUtils = __toESM(require_utils4());
|
var githubUtils = __toESM(require_utils4());
|
||||||
@@ -146496,6 +146557,17 @@ function getDisplayActionName(actionName) {
|
|||||||
}
|
}
|
||||||
return actionName;
|
return actionName;
|
||||||
}
|
}
|
||||||
|
function getJobUUID(action) {
|
||||||
|
const existingJobRunUuid = action.env.getOptional("CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */);
|
||||||
|
if (existingJobRunUuid !== void 0 && validate_default(existingJobRunUuid)) {
|
||||||
|
action.logger.info(`Existing job run UUID is ${existingJobRunUuid}.`);
|
||||||
|
return existingJobRunUuid;
|
||||||
|
}
|
||||||
|
const jobRunUuid = v4_default();
|
||||||
|
action.logger.info(`Job run UUID is ${jobRunUuid}.`);
|
||||||
|
action.actions.exportVariable("CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid);
|
||||||
|
return jobRunUuid;
|
||||||
|
}
|
||||||
function isFirstPartyAnalysis(actionName) {
|
function isFirstPartyAnalysis(actionName) {
|
||||||
if (actionName !== "upload-sarif" /* UploadSarif */) {
|
if (actionName !== "upload-sarif" /* UploadSarif */) {
|
||||||
return true;
|
return true;
|
||||||
@@ -146578,7 +146650,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi
|
|||||||
try {
|
try {
|
||||||
const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || "";
|
const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || "";
|
||||||
const ref = await getRef();
|
const ref = await getRef();
|
||||||
const jobRunUUID = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */] || "";
|
const jobRunUUID = process.env["CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */] || "";
|
||||||
const workflowRunID = getWorkflowRunID();
|
const workflowRunID = getWorkflowRunID();
|
||||||
const workflowRunAttempt = getWorkflowRunAttempt();
|
const workflowRunAttempt = getWorkflowRunAttempt();
|
||||||
const workflowName = process.env["GITHUB_WORKFLOW"] || "";
|
const workflowName = process.env["GITHUB_WORKFLOW"] || "";
|
||||||
@@ -146807,18 +146879,26 @@ async function runInActions(action) {
|
|||||||
const env = getEnv();
|
const env = getEnv();
|
||||||
const actionsEnv = getActionsEnv();
|
const actionsEnv = getActionsEnv();
|
||||||
try {
|
try {
|
||||||
await action.run({
|
const actionState = {
|
||||||
name: action.name,
|
name: action.name,
|
||||||
startedAt,
|
startedAt,
|
||||||
logger,
|
logger,
|
||||||
env,
|
env,
|
||||||
actions: actionsEnv
|
actions: actionsEnv
|
||||||
});
|
};
|
||||||
|
getJobUUID(actionState);
|
||||||
|
await action.run(actionState);
|
||||||
} catch (error3) {
|
} catch (error3) {
|
||||||
core8.setFailed(
|
core8.setFailed(
|
||||||
`${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error3)}`
|
`${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error3)}`
|
||||||
);
|
);
|
||||||
await sendUnhandledErrorStatusReport(action.name, startedAt, error3, logger);
|
const statusReportError = action.transformTelemetryError !== void 0 ? action.transformTelemetryError(wrapError(error3)) : error3;
|
||||||
|
await sendUnhandledErrorStatusReport(
|
||||||
|
action.name,
|
||||||
|
startedAt,
|
||||||
|
statusReportError,
|
||||||
|
logger
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146828,8 +146908,8 @@ var path5 = __toESM(require("path"));
|
|||||||
var semver4 = __toESM(require_semver2());
|
var semver4 = __toESM(require_semver2());
|
||||||
|
|
||||||
// src/defaults.json
|
// src/defaults.json
|
||||||
var bundleVersion = "codeql-bundle-v2.26.1";
|
var bundleVersion = "codeql-bundle-v2.26.2";
|
||||||
var cliVersion = "2.26.1";
|
var cliVersion = "2.26.2";
|
||||||
|
|
||||||
// src/overlay/index.ts
|
// src/overlay/index.ts
|
||||||
var fs4 = __toESM(require("fs"));
|
var fs4 = __toESM(require("fs"));
|
||||||
@@ -150247,50 +150327,6 @@ var toolcache3 = __toESM(require_tool_cache());
|
|||||||
var import_fast_deep_equal = __toESM(require_fast_deep_equal());
|
var import_fast_deep_equal = __toESM(require_fast_deep_equal());
|
||||||
var semver9 = __toESM(require_semver2());
|
var semver9 = __toESM(require_semver2());
|
||||||
|
|
||||||
// node_modules/uuid/dist-node/stringify.js
|
|
||||||
var byteToHex = [];
|
|
||||||
for (let i = 0; i < 256; ++i) {
|
|
||||||
byteToHex.push((i + 256).toString(16).slice(1));
|
|
||||||
}
|
|
||||||
function unsafeStringify(arr, offset = 0) {
|
|
||||||
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/uuid/dist-node/rng.js
|
|
||||||
var rnds8 = new Uint8Array(16);
|
|
||||||
function rng() {
|
|
||||||
return crypto.getRandomValues(rnds8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/uuid/dist-node/v4.js
|
|
||||||
function v4(options, buf, offset) {
|
|
||||||
if (!buf && !options && crypto.randomUUID) {
|
|
||||||
return crypto.randomUUID();
|
|
||||||
}
|
|
||||||
return _v4(options, buf, offset);
|
|
||||||
}
|
|
||||||
function _v4(options, buf, offset) {
|
|
||||||
options = options || {};
|
|
||||||
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
||||||
if (rnds.length < 16) {
|
|
||||||
throw new Error("Random bytes length must be >= 16");
|
|
||||||
}
|
|
||||||
rnds[6] = rnds[6] & 15 | 64;
|
|
||||||
rnds[8] = rnds[8] & 63 | 128;
|
|
||||||
if (buf) {
|
|
||||||
offset = offset || 0;
|
|
||||||
if (offset < 0 || offset + 16 > buf.length) {
|
|
||||||
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
||||||
}
|
|
||||||
for (let i = 0; i < 16; ++i) {
|
|
||||||
buf[offset + i] = rnds[i];
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return unsafeStringify(rnds);
|
|
||||||
}
|
|
||||||
var v4_default = v4;
|
|
||||||
|
|
||||||
// src/overlay/caching.ts
|
// src/overlay/caching.ts
|
||||||
var fs10 = __toESM(require("fs"));
|
var fs10 = __toESM(require("fs"));
|
||||||
var actionsCache3 = __toESM(require_cache4());
|
var actionsCache3 = __toESM(require_cache4());
|
||||||
@@ -152163,7 +152199,7 @@ function applyAutobuildAzurePipelinesTimeoutFix() {
|
|||||||
].join(" ");
|
].join(" ");
|
||||||
}
|
}
|
||||||
async function getJobRunUuidSarifOptions() {
|
async function getJobRunUuidSarifOptions() {
|
||||||
const jobRunUuid = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */];
|
const jobRunUuid = process.env["CODEQL_ACTION_JOB_RUN_UUID" /* JOB_RUN_UUID */];
|
||||||
return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : [];
|
return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160930,9 +160966,6 @@ async function run3(actionState) {
|
|||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
const repositoryProperties = repositoryPropertiesResult.orElse({});
|
const repositoryProperties = repositoryPropertiesResult.orElse({});
|
||||||
const jobRunUuid = v4_default();
|
|
||||||
logger.info(`Job run UUID is ${jobRunUuid}.`);
|
|
||||||
core21.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid);
|
|
||||||
core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true");
|
core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true");
|
||||||
sourceRoot = path24.resolve(
|
sourceRoot = path24.resolve(
|
||||||
getRequiredEnvParam("GITHUB_WORKSPACE"),
|
getRequiredEnvParam("GITHUB_WORKSPACE"),
|
||||||
@@ -161930,9 +161963,6 @@ async function run6(actionState) {
|
|||||||
);
|
);
|
||||||
const repositoryProperties = repositoryPropertiesResult.orElse({});
|
const repositoryProperties = repositoryPropertiesResult.orElse({});
|
||||||
const actionStateWithFeatures = { ...actionState, features };
|
const actionStateWithFeatures = { ...actionState, features };
|
||||||
const jobRunUuid = v4_default();
|
|
||||||
logger.info(`Job run UUID is ${jobRunUuid}.`);
|
|
||||||
core24.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid);
|
|
||||||
const statusReportBase = await createStatusReportBase(
|
const statusReportBase = await createStatusReportBase(
|
||||||
"setup-codeql" /* SetupCodeQL */,
|
"setup-codeql" /* SetupCodeQL */,
|
||||||
"starting",
|
"starting",
|
||||||
@@ -162667,8 +162697,9 @@ async function checkConnections(logger, proxy, backend) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// src/start-proxy-action.ts
|
// src/start-proxy-action.ts
|
||||||
async function run7(startedAt) {
|
async function run7(action) {
|
||||||
const logger = getActionsLogger();
|
const startedAt = action.startedAt;
|
||||||
|
const logger = action.logger;
|
||||||
let features;
|
let features;
|
||||||
let language;
|
let language;
|
||||||
try {
|
try {
|
||||||
@@ -162734,20 +162765,13 @@ async function run7(startedAt) {
|
|||||||
await sendFailedStatusReport(logger, startedAt, language, unwrappedError);
|
await sendFailedStatusReport(logger, startedAt, language, unwrappedError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var startProxyAction = {
|
||||||
|
name: "start-proxy" /* StartProxy */,
|
||||||
|
run: run7,
|
||||||
|
transformTelemetryError: getSafeErrorMessage
|
||||||
|
};
|
||||||
async function runWrapper8() {
|
async function runWrapper8() {
|
||||||
const startedAt = /* @__PURE__ */ new Date();
|
await runInActions(startProxyAction);
|
||||||
const logger = getActionsLogger();
|
|
||||||
try {
|
|
||||||
await run7(startedAt);
|
|
||||||
} catch (error3) {
|
|
||||||
core27.setFailed(`start-proxy action failed: ${getErrorMessage(error3)}`);
|
|
||||||
await sendUnhandledErrorStatusReport(
|
|
||||||
"start-proxy" /* StartProxy */,
|
|
||||||
startedAt,
|
|
||||||
getSafeErrorMessage(wrapError(error3)),
|
|
||||||
logger
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async function startProxy(binPath, config, logFilePath, logger) {
|
async function startProxy(binPath, config, logFilePath, logger) {
|
||||||
const host = "127.0.0.1";
|
const host = "127.0.0.1";
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ steps:
|
|||||||
run: |
|
run: |
|
||||||
cd "$RUNNER_TEMP/results"
|
cd "$RUNNER_TEMP/results"
|
||||||
actual=$(jq -r '.runs[0].properties.jobRunUuid' javascript.sarif)
|
actual=$(jq -r '.runs[0].properties.jobRunUuid' javascript.sarif)
|
||||||
if [[ "$actual" != "$JOB_RUN_UUID" ]]; then
|
if [[ "$actual" != "$CODEQL_ACTION_JOB_RUN_UUID" ]]; then
|
||||||
echo "Expected SARIF output to contain job run UUID '$JOB_RUN_UUID', but found '$actual'."
|
echo "Expected SARIF output to contain job run UUID '$CODEQL_ACTION_JOB_RUN_UUID', but found '$actual'."
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
echo "Found job run UUID '$actual'."
|
echo "Found job run UUID '$actual'."
|
||||||
|
|||||||
123
src/action-common.test.ts
Normal file
123
src/action-common.test.ts
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import * as core from "@actions/core";
|
||||||
|
import test from "ava";
|
||||||
|
import sinon from "sinon";
|
||||||
|
|
||||||
|
import * as common from "./action-common";
|
||||||
|
import * as actionsUtil from "./actions-util";
|
||||||
|
import * as environment from "./environment";
|
||||||
|
import * as logging from "./logging";
|
||||||
|
import { ActionName } from "./status-report";
|
||||||
|
import * as statusReport from "./status-report";
|
||||||
|
import {
|
||||||
|
getTestActionsEnv,
|
||||||
|
getTestEnv,
|
||||||
|
makeMacro,
|
||||||
|
RecordingLogger,
|
||||||
|
setupTests,
|
||||||
|
} from "./testing-utils";
|
||||||
|
import { getErrorMessage } from "./util";
|
||||||
|
|
||||||
|
setupTests(test);
|
||||||
|
|
||||||
|
interface RunInActionsTestOpts {
|
||||||
|
runFn?: () => Promise<any>;
|
||||||
|
expectedErrorMessage?: string;
|
||||||
|
expectedTelemetryError?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const runInActionsMacro = makeMacro({
|
||||||
|
exec: async (t, opts: RunInActionsTestOpts) => {
|
||||||
|
const expectFailure = opts?.expectedErrorMessage !== undefined;
|
||||||
|
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
const getActionsLogger = sinon
|
||||||
|
.stub(logging, "getActionsLogger")
|
||||||
|
.returns(logger);
|
||||||
|
|
||||||
|
const env = getTestEnv();
|
||||||
|
const getEnv = sinon.stub(environment, "getEnv").returns(env);
|
||||||
|
|
||||||
|
const actionsEnv = getTestActionsEnv(env);
|
||||||
|
const getActionsEnv = sinon
|
||||||
|
.stub(actionsUtil, "getActionsEnv")
|
||||||
|
.returns(actionsEnv);
|
||||||
|
|
||||||
|
const getJobUUID = sinon
|
||||||
|
.stub(statusReport, "getJobUUID")
|
||||||
|
.returns("test-job-uuid");
|
||||||
|
|
||||||
|
const setFailed = sinon.stub(core, "setFailed");
|
||||||
|
const sendUnhandledErrorStatusReport = sinon.stub(
|
||||||
|
statusReport,
|
||||||
|
"sendUnhandledErrorStatusReport",
|
||||||
|
);
|
||||||
|
|
||||||
|
const name = ActionName.Init;
|
||||||
|
const run = sinon.stub();
|
||||||
|
|
||||||
|
if (opts?.runFn) {
|
||||||
|
run.callsFake(opts.runFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
const transformTelemetryError = sinon
|
||||||
|
.stub()
|
||||||
|
.callsFake((err) => opts?.expectedTelemetryError ?? getErrorMessage(err));
|
||||||
|
const testAction: common.Action = {
|
||||||
|
name,
|
||||||
|
run,
|
||||||
|
transformTelemetryError,
|
||||||
|
};
|
||||||
|
|
||||||
|
await common.runInActions(testAction);
|
||||||
|
|
||||||
|
// These always should have been called once.
|
||||||
|
t.true(getActionsLogger.calledOnce);
|
||||||
|
t.true(getEnv.calledOnce);
|
||||||
|
t.true(getActionsEnv.calledOnce);
|
||||||
|
|
||||||
|
const expectedActionState = {
|
||||||
|
actions: actionsEnv,
|
||||||
|
env,
|
||||||
|
logger,
|
||||||
|
name: ActionName.Init,
|
||||||
|
};
|
||||||
|
|
||||||
|
t.true(getJobUUID.calledOnceWithExactly(sinon.match(expectedActionState)));
|
||||||
|
t.true(run.calledOnceWithExactly(sinon.match(expectedActionState)));
|
||||||
|
|
||||||
|
t.is(setFailed.calledOnce, expectFailure ?? false);
|
||||||
|
t.is(sendUnhandledErrorStatusReport.calledOnce, expectFailure ?? false);
|
||||||
|
|
||||||
|
if (expectFailure) {
|
||||||
|
t.true(
|
||||||
|
setFailed.calledOnceWithExactly(
|
||||||
|
`${statusReport.getDisplayActionName(name)} action failed: ${opts?.expectedErrorMessage}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
t.true(
|
||||||
|
sendUnhandledErrorStatusReport.calledOnceWithExactly(
|
||||||
|
name,
|
||||||
|
sinon.match.any,
|
||||||
|
opts?.expectedTelemetryError ?? opts?.expectedErrorMessage,
|
||||||
|
logger,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: (providedTitle) => `runInActions - ${providedTitle}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
runInActionsMacro.serial("calls run", {});
|
||||||
|
runInActionsMacro.serial("handles run exceptions", {
|
||||||
|
runFn: () => {
|
||||||
|
throw new Error("Test failure");
|
||||||
|
},
|
||||||
|
expectedErrorMessage: "Test failure",
|
||||||
|
});
|
||||||
|
runInActionsMacro.serial("transforms run exceptions", {
|
||||||
|
runFn: () => {
|
||||||
|
throw new Error("Test failure");
|
||||||
|
},
|
||||||
|
expectedErrorMessage: "Test failure",
|
||||||
|
expectedTelemetryError: "Transformed failure message",
|
||||||
|
});
|
||||||
@@ -8,9 +8,10 @@ import { getActionsLogger, Logger } from "./logging";
|
|||||||
import {
|
import {
|
||||||
ActionName,
|
ActionName,
|
||||||
getDisplayActionName,
|
getDisplayActionName,
|
||||||
|
getJobUUID,
|
||||||
sendUnhandledErrorStatusReport,
|
sendUnhandledErrorStatusReport,
|
||||||
} from "./status-report";
|
} from "./status-report";
|
||||||
import { getEnv, getErrorMessage } from "./util";
|
import { getEnv, getErrorMessage, wrapError } from "./util";
|
||||||
|
|
||||||
/** Base state that is available to an Action on startup. */
|
/** Base state that is available to an Action on startup. */
|
||||||
export interface BaseState {
|
export interface BaseState {
|
||||||
@@ -78,6 +79,12 @@ export interface Action {
|
|||||||
name: ActionName;
|
name: ActionName;
|
||||||
/** The entry point for the Action. */
|
/** The entry point for the Action. */
|
||||||
run: ActionMain;
|
run: ActionMain;
|
||||||
|
/**
|
||||||
|
* An optional function that transforms a caught error into a message suitable for
|
||||||
|
* inclusion in a status report. This is primarily intended for the `start-proxy`
|
||||||
|
* action to replace the thrown `Error`'s message with a safe one.
|
||||||
|
*/
|
||||||
|
transformTelemetryError?: (error: Error) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A generic entry point that sets up the basic environment for the `action` and runs it. */
|
/** A generic entry point that sets up the basic environment for the `action` and runs it. */
|
||||||
@@ -88,17 +95,32 @@ export async function runInActions(action: Action) {
|
|||||||
const actionsEnv = getActionsEnv();
|
const actionsEnv = getActionsEnv();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await action.run({
|
const actionState = {
|
||||||
name: action.name,
|
name: action.name,
|
||||||
startedAt,
|
startedAt,
|
||||||
logger,
|
logger,
|
||||||
env,
|
env,
|
||||||
actions: actionsEnv,
|
actions: actionsEnv,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Create a unique identifier for this run.
|
||||||
|
getJobUUID(actionState);
|
||||||
|
|
||||||
|
await action.run(actionState);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(
|
core.setFailed(
|
||||||
`${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error)}`,
|
`${getDisplayActionName(action.name)} action failed: ${getErrorMessage(error)}`,
|
||||||
);
|
);
|
||||||
await sendUnhandledErrorStatusReport(action.name, startedAt, error, logger);
|
|
||||||
|
const statusReportError =
|
||||||
|
action.transformTelemetryError !== undefined
|
||||||
|
? action.transformTelemetryError(wrapError(error))
|
||||||
|
: error;
|
||||||
|
await sendUnhandledErrorStatusReport(
|
||||||
|
action.name,
|
||||||
|
startedAt,
|
||||||
|
statusReportError,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,14 +27,20 @@ declare const __CODEQL_ACTION_VERSION__: string;
|
|||||||
* global functions in tests.
|
* global functions in tests.
|
||||||
*/
|
*/
|
||||||
export interface ActionsEnv {
|
export interface ActionsEnv {
|
||||||
|
getRequiredInput: (name: string) => string;
|
||||||
getOptionalInput: (name: string) => string | undefined;
|
getOptionalInput: (name: string) => string | undefined;
|
||||||
|
exportVariable: (name: string, value: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the real `ActionsEnv` used by production code.
|
* Gets the real `ActionsEnv` used by production code.
|
||||||
*/
|
*/
|
||||||
export function getActionsEnv(): ActionsEnv {
|
export function getActionsEnv(): ActionsEnv {
|
||||||
return { getOptionalInput };
|
return {
|
||||||
|
getRequiredInput,
|
||||||
|
getOptionalInput,
|
||||||
|
exportVariable: core.exportVariable,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import test from "ava";
|
import test from "ava";
|
||||||
import sinon from "sinon";
|
import sinon from "sinon";
|
||||||
|
|
||||||
import { getActionsEnv } from "../actions-util";
|
import { ActionsEnv } from "../actions-util";
|
||||||
import { Feature } from "../feature-flags";
|
import { Feature } from "../feature-flags";
|
||||||
import { RepositoryPropertyName } from "../feature-flags/properties";
|
import { RepositoryPropertyName } from "../feature-flags/properties";
|
||||||
import { callee } from "../testing-utils";
|
import { callee } from "../testing-utils";
|
||||||
@@ -22,32 +22,26 @@ const expectedRepositoryPropertyResult: ComputedInput = {
|
|||||||
value: "repo-property-input-value",
|
value: "repo-property-input-value",
|
||||||
};
|
};
|
||||||
|
|
||||||
function stubGetToolsInput() {
|
function stubGetToolsInput(actions: ActionsEnv) {
|
||||||
const actions = getActionsEnv();
|
|
||||||
sinon
|
sinon
|
||||||
.stub(actions, "getOptionalInput")
|
.stub(actions, "getOptionalInput")
|
||||||
.withArgs(InputName.Tools)
|
.withArgs(InputName.Tools)
|
||||||
.returns(expectedWorkflowResult.value);
|
.returns(expectedWorkflowResult.value);
|
||||||
return actions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowLogMessage = `Using ${InputName.Tools} input from workflow:`;
|
const workflowLogMessage = `Using ${InputName.Tools} input from workflow:`;
|
||||||
|
|
||||||
test("getToolsInput - returns workflow input if available", async (t) => {
|
test("getToolsInput - returns workflow input if available", async (t) => {
|
||||||
const actions = stubGetToolsInput();
|
|
||||||
|
|
||||||
await callee(getToolsInput)
|
await callee(getToolsInput)
|
||||||
.withActions(actions)
|
.withActions(stubGetToolsInput)
|
||||||
.withArgs({})
|
.withArgs({})
|
||||||
.logs(t, workflowLogMessage)
|
.logs(t, workflowLogMessage)
|
||||||
.passes(t.deepEqual, expectedWorkflowResult);
|
.passes(t.deepEqual, expectedWorkflowResult);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getToolsInput - returns repository property value if enforced", async (t) => {
|
test("getToolsInput - returns repository property value if enforced", async (t) => {
|
||||||
const actions = stubGetToolsInput();
|
|
||||||
|
|
||||||
const target = callee(getToolsInput)
|
const target = callee(getToolsInput)
|
||||||
.withActions(actions)
|
.withActions(stubGetToolsInput)
|
||||||
.withArgs({
|
.withArgs({
|
||||||
[RepositoryPropertyName.TOOLS]: `!${expectedRepositoryPropertyResult.value}`,
|
[RepositoryPropertyName.TOOLS]: `!${expectedRepositoryPropertyResult.value}`,
|
||||||
});
|
});
|
||||||
@@ -65,10 +59,8 @@ test("getToolsInput - returns repository property value if enforced", async (t)
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("getToolsInput - prefers workflow input", async (t) => {
|
test("getToolsInput - prefers workflow input", async (t) => {
|
||||||
const actions = stubGetToolsInput();
|
|
||||||
|
|
||||||
const target = callee(getToolsInput)
|
const target = callee(getToolsInput)
|
||||||
.withActions(actions)
|
.withActions(stubGetToolsInput)
|
||||||
.withArgs({
|
.withArgs({
|
||||||
[RepositoryPropertyName.TOOLS]: expectedRepositoryPropertyResult.value,
|
[RepositoryPropertyName.TOOLS]: expectedRepositoryPropertyResult.value,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-v2.26.1",
|
"bundleVersion": "codeql-bundle-v2.26.2",
|
||||||
"cliVersion": "2.26.1",
|
"cliVersion": "2.26.2",
|
||||||
"priorBundleVersion": "codeql-bundle-v2.26.0",
|
"priorBundleVersion": "codeql-bundle-v2.26.1",
|
||||||
"priorCliVersion": "2.26.0"
|
"priorCliVersion": "2.26.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export enum EnvVar {
|
|||||||
LOG_VERSION_DEPRECATION = "CODEQL_ACTION_DID_LOG_VERSION_DEPRECATION",
|
LOG_VERSION_DEPRECATION = "CODEQL_ACTION_DID_LOG_VERSION_DEPRECATION",
|
||||||
|
|
||||||
/** UUID representing the current job run. */
|
/** UUID representing the current job run. */
|
||||||
JOB_RUN_UUID = "JOB_RUN_UUID",
|
JOB_RUN_UUID = "CODEQL_ACTION_JOB_RUN_UUID",
|
||||||
|
|
||||||
/** Status for the entire job, submitted to the status report in `init-post` */
|
/** Status for the entire job, submitted to the status report in `init-post` */
|
||||||
JOB_STATUS = "CODEQL_ACTION_JOB_STATUS",
|
JOB_STATUS = "CODEQL_ACTION_JOB_STATUS",
|
||||||
@@ -270,6 +270,11 @@ export class ReadOnlyEnv<T extends string | undefined = string | undefined> {
|
|||||||
return Object.create(this, { vars: { value: { ...this.vars } } }) as this;
|
return Object.create(this, { vars: { value: { ...this.vars } } }) as this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets a copy of the underlying environment. */
|
||||||
|
public get(): Record<string, T> {
|
||||||
|
return { ...this.vars };
|
||||||
|
}
|
||||||
|
|
||||||
/** Tries to get the value for `name` and throws if there isn't one. */
|
/** Tries to get the value for `name` and throws if there isn't one. */
|
||||||
public getRequired(name: string): string {
|
public getRequired(name: string): string {
|
||||||
return getRequiredEnvVar(this.vars, name);
|
return getRequiredEnvVar(this.vars, name);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import * as path from "path";
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as io from "@actions/io";
|
import * as io from "@actions/io";
|
||||||
import * as semver from "semver";
|
import * as semver from "semver";
|
||||||
import { v4 as uuidV4 } from "uuid";
|
|
||||||
|
|
||||||
import { Action, ActionState, runInActions } from "./action-common";
|
import { Action, ActionState, runInActions } from "./action-common";
|
||||||
import {
|
import {
|
||||||
@@ -255,11 +254,6 @@ async function run(
|
|||||||
);
|
);
|
||||||
const repositoryProperties = repositoryPropertiesResult.orElse({});
|
const repositoryProperties = repositoryPropertiesResult.orElse({});
|
||||||
|
|
||||||
// Create a unique identifier for this run.
|
|
||||||
const jobRunUuid = uuidV4();
|
|
||||||
logger.info(`Job run UUID is ${jobRunUuid}.`);
|
|
||||||
core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid);
|
|
||||||
|
|
||||||
core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true");
|
core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true");
|
||||||
|
|
||||||
// path.resolve() respects the intended semantics of source-root. If
|
// path.resolve() respects the intended semantics of source-root. If
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { v4 as uuidV4 } from "uuid";
|
|
||||||
|
|
||||||
import { Action, ActionState, runInActions } from "./action-common";
|
import { Action, ActionState, runInActions } from "./action-common";
|
||||||
import {
|
import {
|
||||||
@@ -95,7 +94,7 @@ async function sendCompletedStatusReport(
|
|||||||
|
|
||||||
/** The main behaviour of this action. */
|
/** The main behaviour of this action. */
|
||||||
async function run(
|
async function run(
|
||||||
actionState: ActionState<["Base", "Logger", "Actions"]>,
|
actionState: ActionState<["Base", "Logger", "Env", "Actions"]>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// To capture errors appropriately, keep as much code within the try-catch as
|
// To capture errors appropriately, keep as much code within the try-catch as
|
||||||
// possible, and only use safe functions outside.
|
// possible, and only use safe functions outside.
|
||||||
@@ -140,10 +139,6 @@ async function run(
|
|||||||
|
|
||||||
const actionStateWithFeatures = { ...actionState, features };
|
const actionStateWithFeatures = { ...actionState, features };
|
||||||
|
|
||||||
const jobRunUuid = uuidV4();
|
|
||||||
logger.info(`Job run UUID is ${jobRunUuid}.`);
|
|
||||||
core.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid);
|
|
||||||
|
|
||||||
const statusReportBase = await createStatusReportBase(
|
const statusReportBase = await createStatusReportBase(
|
||||||
ActionName.SetupCodeQL,
|
ActionName.SetupCodeQL,
|
||||||
"starting",
|
"starting",
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import * as path from "path";
|
|||||||
|
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
|
||||||
|
import { Action, ActionState, runInActions } from "./action-common";
|
||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import { getGitHubVersion } from "./api-client";
|
import { getGitHubVersion } from "./api-client";
|
||||||
import { FeatureEnablement, initFeatures } from "./feature-flags";
|
import { FeatureEnablement, initFeatures } from "./feature-flags";
|
||||||
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
|
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
|
||||||
import { getActionsLogger, Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { getRepositoryNwo } from "./repository";
|
import { getRepositoryNwo } from "./repository";
|
||||||
import {
|
import {
|
||||||
credentialToStr,
|
credentialToStr,
|
||||||
@@ -23,14 +24,14 @@ import {
|
|||||||
import { generateCertificateAuthority } from "./start-proxy/ca";
|
import { generateCertificateAuthority } from "./start-proxy/ca";
|
||||||
import { checkProxyEnvironment } from "./start-proxy/environment";
|
import { checkProxyEnvironment } from "./start-proxy/environment";
|
||||||
import { checkConnections } from "./start-proxy/reachability";
|
import { checkConnections } from "./start-proxy/reachability";
|
||||||
import { ActionName, sendUnhandledErrorStatusReport } from "./status-report";
|
import { ActionName } from "./status-report";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
|
||||||
async function run(startedAt: Date) {
|
async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) {
|
||||||
// To capture errors appropriately, keep as much code within the try-catch as
|
// To capture errors appropriately, keep as much code within the try-catch as
|
||||||
// possible, and only use safe functions outside.
|
// possible, and only use safe functions outside.
|
||||||
|
const startedAt = action.startedAt;
|
||||||
const logger = getActionsLogger();
|
const logger = action.logger;
|
||||||
let features: FeatureEnablement | undefined;
|
let features: FeatureEnablement | undefined;
|
||||||
let language: BuiltInLanguage | undefined;
|
let language: BuiltInLanguage | undefined;
|
||||||
|
|
||||||
@@ -122,21 +123,15 @@ async function run(startedAt: Date) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runWrapper() {
|
/** Defines the `start-proxy` Action. */
|
||||||
const startedAt = new Date();
|
const startProxyAction: Action = {
|
||||||
const logger = getActionsLogger();
|
name: ActionName.StartProxy,
|
||||||
|
run,
|
||||||
|
transformTelemetryError: getSafeErrorMessage,
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
export async function runWrapper() {
|
||||||
await run(startedAt);
|
await runInActions(startProxyAction);
|
||||||
} catch (error) {
|
|
||||||
core.setFailed(`start-proxy action failed: ${util.getErrorMessage(error)}`);
|
|
||||||
await sendUnhandledErrorStatusReport(
|
|
||||||
ActionName.StartProxy,
|
|
||||||
startedAt,
|
|
||||||
getSafeErrorMessage(util.wrapError(error)),
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startProxy(
|
async function startProxy(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import test from "ava";
|
import test from "ava";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
|
import * as uuid from "uuid";
|
||||||
|
|
||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import { Config } from "./config-utils";
|
import { Config } from "./config-utils";
|
||||||
@@ -14,6 +15,7 @@ import {
|
|||||||
createStatusReportBase,
|
createStatusReportBase,
|
||||||
getActionsStatus,
|
getActionsStatus,
|
||||||
getRegistryTypesFromEnv,
|
getRegistryTypesFromEnv,
|
||||||
|
getJobUUID,
|
||||||
InitStatusReport,
|
InitStatusReport,
|
||||||
InitWithConfigStatusReport,
|
InitWithConfigStatusReport,
|
||||||
} from "./status-report";
|
} from "./status-report";
|
||||||
@@ -24,6 +26,7 @@ import {
|
|||||||
makeMacro,
|
makeMacro,
|
||||||
getTestEnv,
|
getTestEnv,
|
||||||
RecordingLogger,
|
RecordingLogger,
|
||||||
|
callee,
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util";
|
import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util";
|
||||||
|
|
||||||
@@ -84,6 +87,43 @@ test("getRegistryTypesFromEnv - returns undefined if the env var is unexpected J
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("getJobUUID - generates valid UUIDs", async (t) => {
|
||||||
|
await callee(getJobUUID)
|
||||||
|
.withArgs()
|
||||||
|
.logs(t, "Job run UUID is ")
|
||||||
|
.hasEnv(t, (val) => {
|
||||||
|
return {
|
||||||
|
[EnvVar.JOB_RUN_UUID]: val,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.passes((val) => {
|
||||||
|
t.true(uuid.validate(val));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getJobUUID - retrieves existing job UUIDs", async (t) => {
|
||||||
|
const existingJobUuid = uuid.v4();
|
||||||
|
await callee(getJobUUID)
|
||||||
|
.withArgs()
|
||||||
|
.withEnv((env) => {
|
||||||
|
env.set(EnvVar.JOB_RUN_UUID, existingJobUuid);
|
||||||
|
})
|
||||||
|
.logs(t, `Existing job run UUID is ${existingJobUuid}.`)
|
||||||
|
.passes(t.deepEqual, existingJobUuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getJobUUID - doesn't retrieve invalid UUIDs", async (t) => {
|
||||||
|
const existingJobUuid = "not-a-uuid";
|
||||||
|
await callee(getJobUUID)
|
||||||
|
.withArgs()
|
||||||
|
.withEnv((env) => {
|
||||||
|
env.set(EnvVar.JOB_RUN_UUID, existingJobUuid);
|
||||||
|
})
|
||||||
|
.logs(t, `Job run UUID is `)
|
||||||
|
.notLogs(t, `Existing job run UUID is ${existingJobUuid}.`)
|
||||||
|
.passes(t.notDeepEqual, existingJobUuid);
|
||||||
|
});
|
||||||
|
|
||||||
function setupEnvironmentAndStub(tmpDir: string) {
|
function setupEnvironmentAndStub(tmpDir: string) {
|
||||||
setupActionsVars(tmpDir, tmpDir, {
|
setupActionsVars(tmpDir, tmpDir, {
|
||||||
GITHUB_EVENT_NAME: "dynamic",
|
GITHUB_EVENT_NAME: "dynamic",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
|
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import * as uuid from "uuid";
|
||||||
|
|
||||||
|
import type { ActionState } from "./action-common";
|
||||||
import {
|
import {
|
||||||
getWorkflowEventName,
|
getWorkflowEventName,
|
||||||
getOptionalInput,
|
getOptionalInput,
|
||||||
@@ -61,6 +63,30 @@ export function getDisplayActionName(actionName: ActionName): string {
|
|||||||
return actionName;
|
return actionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Either creates a UUIDv4 for the analysis or retrieves an existing one from the
|
||||||
|
* environment and returns it.
|
||||||
|
* If a new UUID is generated, it is also exported as an environment variable.
|
||||||
|
*/
|
||||||
|
export function getJobUUID(
|
||||||
|
action: ActionState<["Logger", "ReadOnlyEnv", "Actions"]>,
|
||||||
|
) {
|
||||||
|
// Check if we already have a UUID for the analysis and return it if so.
|
||||||
|
const existingJobRunUuid = action.env.getOptional(EnvVar.JOB_RUN_UUID);
|
||||||
|
|
||||||
|
if (existingJobRunUuid !== undefined && uuid.validate(existingJobRunUuid)) {
|
||||||
|
action.logger.info(`Existing job run UUID is ${existingJobRunUuid}.`);
|
||||||
|
return existingJobRunUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise generate a new UUID.
|
||||||
|
const jobRunUuid = uuid.v4();
|
||||||
|
action.logger.info(`Job run UUID is ${jobRunUuid}.`);
|
||||||
|
|
||||||
|
action.actions.exportVariable(EnvVar.JOB_RUN_UUID, jobRunUuid);
|
||||||
|
return jobRunUuid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns a boolean indicating whether the analysis is considered to be first party.
|
* @returns a boolean indicating whether the analysis is considered to be first party.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -34,11 +34,14 @@ import { ActionName } from "./status-report";
|
|||||||
import {
|
import {
|
||||||
DEFAULT_DEBUG_ARTIFACT_NAME,
|
DEFAULT_DEBUG_ARTIFACT_NAME,
|
||||||
DEFAULT_DEBUG_DATABASE_NAME,
|
DEFAULT_DEBUG_DATABASE_NAME,
|
||||||
|
Failure,
|
||||||
getEnv,
|
getEnv,
|
||||||
GitHubVariant,
|
GitHubVariant,
|
||||||
GitHubVersion,
|
GitHubVersion,
|
||||||
HTTPError,
|
HTTPError,
|
||||||
resetCachedCodeQlVersion,
|
resetCachedCodeQlVersion,
|
||||||
|
Result,
|
||||||
|
Success,
|
||||||
} from "./util";
|
} from "./util";
|
||||||
|
|
||||||
export const SAMPLE_DOTCOM_API_DETAILS = {
|
export const SAMPLE_DOTCOM_API_DETAILS = {
|
||||||
@@ -182,13 +185,32 @@ export function getTestEnv(testEnv: NodeJS.ProcessEnv = {}): Env {
|
|||||||
return getEnv(testEnv);
|
return getEnv(testEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** An implementation of `ActionsEnv` for use in tests. */
|
||||||
|
class TestActionsEnv implements ActionsEnv {
|
||||||
|
constructor(private readonly env: Env) {}
|
||||||
|
|
||||||
|
public clone(env: Env): this {
|
||||||
|
return Object.create(this, { env: { value: env } }) as this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRequiredInput(name: string): string {
|
||||||
|
throw new Error(`Input required and not supplied: ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOptionalInput(_name: string): string | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public exportVariable(name: string, value: string): void {
|
||||||
|
this.env.set(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an `ActionsEnv` instance for use in tests.
|
* Gets an `ActionsEnv` instance for use in tests.
|
||||||
*/
|
*/
|
||||||
export function getTestActionsEnv(): ActionsEnv {
|
export function getTestActionsEnv(env: Env): TestActionsEnv {
|
||||||
return {
|
return new TestActionsEnv(env);
|
||||||
getOptionalInput: () => undefined,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For testing purposes, we make all available state features accessible in `TestEnv`. */
|
/** For testing purposes, we make all available state features accessible in `TestEnv`. */
|
||||||
@@ -206,12 +228,13 @@ type AllState = [
|
|||||||
export function initAllState(
|
export function initAllState(
|
||||||
overrides?: Partial<ActionState<AllState>>,
|
overrides?: Partial<ActionState<AllState>>,
|
||||||
): ActionState<AllState> {
|
): ActionState<AllState> {
|
||||||
|
const env = getTestEnv();
|
||||||
return {
|
return {
|
||||||
name: ActionName.Init,
|
name: ActionName.Init,
|
||||||
startedAt: new Date(),
|
startedAt: new Date(),
|
||||||
logger: new RecordingLogger(),
|
logger: new RecordingLogger(),
|
||||||
env: getTestEnv(),
|
env,
|
||||||
actions: getTestActionsEnv(),
|
actions: getTestActionsEnv(env),
|
||||||
apiClient: github.getOctokit("123"),
|
apiClient: github.getOctokit("123"),
|
||||||
features: createFeatures([]),
|
features: createFeatures([]),
|
||||||
...overrides,
|
...overrides,
|
||||||
@@ -222,9 +245,13 @@ type DelayedCheck<
|
|||||||
Args extends readonly any[],
|
Args extends readonly any[],
|
||||||
R,
|
R,
|
||||||
Fs extends ReadonlyArray<AllState[number]>,
|
Fs extends ReadonlyArray<AllState[number]>,
|
||||||
> = (env: Readonly<BaseEnvBuilder<Args, R, Fs>>) => Promise<any>;
|
> = (
|
||||||
|
env: Readonly<BaseEnvBuilder<Args, R, Fs>>,
|
||||||
|
result: Result<Awaited<R>, ThrownError<ErrorConstructor | Error>>,
|
||||||
|
) => Promise<any>;
|
||||||
|
|
||||||
export type ValueOrMutation<T> = T | ((val: T) => void);
|
export type Mutation<T> = (val: T) => void;
|
||||||
|
export type ValueOrMutation<T> = T | Mutation<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a function that accepts an `ActionState` for testing in different environments.
|
* Wraps a function that accepts an `ActionState` for testing in different environments.
|
||||||
@@ -236,6 +263,7 @@ abstract class BaseEnvBuilder<
|
|||||||
> {
|
> {
|
||||||
protected readonly fn: (state: ActionState<Fs>, ...args: Args) => R;
|
protected readonly fn: (state: ActionState<Fs>, ...args: Args) => R;
|
||||||
private logger: RecordingLogger;
|
private logger: RecordingLogger;
|
||||||
|
private actions: TestActionsEnv;
|
||||||
protected state: ActionState<AllState>;
|
protected state: ActionState<AllState>;
|
||||||
protected checks: Array<DelayedCheck<Args, R, Fs>>;
|
protected checks: Array<DelayedCheck<Args, R, Fs>>;
|
||||||
|
|
||||||
@@ -245,15 +273,26 @@ abstract class BaseEnvBuilder<
|
|||||||
) {
|
) {
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.logger = new RecordingLogger();
|
this.logger = new RecordingLogger();
|
||||||
this.state =
|
|
||||||
cloneFrom !== undefined
|
if (cloneFrom !== undefined) {
|
||||||
? ({
|
const env = cloneFrom.state.env.clone();
|
||||||
...cloneFrom.state,
|
this.actions = cloneFrom.actions.clone(env);
|
||||||
env: cloneFrom.state.env.clone(),
|
this.state = {
|
||||||
actions: Object.create(cloneFrom.state.actions),
|
...cloneFrom.state,
|
||||||
logger: this.logger,
|
env,
|
||||||
} satisfies ActionState<AllState>)
|
actions: this.actions,
|
||||||
: initAllState({ logger: this.logger });
|
logger: this.logger,
|
||||||
|
} satisfies ActionState<AllState>;
|
||||||
|
} else {
|
||||||
|
const env = getTestEnv();
|
||||||
|
this.actions = getTestActionsEnv(env);
|
||||||
|
this.state = initAllState({
|
||||||
|
logger: this.logger,
|
||||||
|
env,
|
||||||
|
actions: this.actions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.checks = [...(cloneFrom?.checks ?? [])];
|
this.checks = [...(cloneFrom?.checks ?? [])];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,13 +359,10 @@ abstract class BaseEnvBuilder<
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withActions(arg: ValueOrMutation<ActionsEnv>): this {
|
/** Applies `fn` to the `ActionsEnv`. */
|
||||||
|
public withActions(fn: Mutation<ActionsEnv>): this {
|
||||||
const result = this.clone();
|
const result = this.clone();
|
||||||
if (typeof arg === "function") {
|
fn(result.state.actions);
|
||||||
arg(result.state.actions);
|
|
||||||
} else {
|
|
||||||
result.state.actions = arg;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +378,28 @@ abstract class BaseEnvBuilder<
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a delayed check that the environment variables returned by `fn`
|
||||||
|
* are present in the environment after the main assertion passes.
|
||||||
|
*/
|
||||||
|
public hasEnv(
|
||||||
|
t: ExecutionContext<unknown>,
|
||||||
|
fn: (
|
||||||
|
value: Awaited<R> | undefined,
|
||||||
|
error: ThrownError<ErrorConstructor | Error> | undefined,
|
||||||
|
) => Record<string, string | undefined>,
|
||||||
|
): this {
|
||||||
|
const result = this.clone();
|
||||||
|
result.checks.push(async (env, r) => {
|
||||||
|
const value = r.orElse(undefined);
|
||||||
|
const error = r.isFailure() ? r.value : undefined;
|
||||||
|
const expected = fn(value, error);
|
||||||
|
|
||||||
|
t.like(env.getState().env.get(), expected);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a delayed check that `messages` are not logged. The check will be
|
* Adds a delayed check that `messages` are not logged. The check will be
|
||||||
* performed after the main assertion passes.
|
* performed after the main assertion passes.
|
||||||
@@ -439,7 +497,7 @@ class CallableEnvBuilder<
|
|||||||
|
|
||||||
// Run other delayed checks.
|
// Run other delayed checks.
|
||||||
for (const delayedCheck of this.checks) {
|
for (const delayedCheck of this.checks) {
|
||||||
await delayedCheck(this);
|
await delayedCheck(this, new Success(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the results of the function call and the main assertion.
|
// Return the results of the function call and the main assertion.
|
||||||
@@ -465,7 +523,7 @@ class CallableEnvBuilder<
|
|||||||
|
|
||||||
// Run other delayed checks.
|
// Run other delayed checks.
|
||||||
for (const delayedCheck of this.checks) {
|
for (const delayedCheck of this.checks) {
|
||||||
await delayedCheck(this);
|
await delayedCheck(this, new Failure(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the error.
|
// Return the error.
|
||||||
|
|||||||
Reference in New Issue
Block a user