Merge pull request #1444 from github/henrymercer/reporting-failed-run-improvements
Improve reporting failed runs via SARIF
This commit is contained in:
commit
ff3337ee1b
15 changed files with 269 additions and 109 deletions
2
lib/analyze-action.js
generated
2
lib/analyze-action.js
generated
|
|
@ -179,7 +179,6 @@ async function run() {
|
||||||
if (runStats && actionsUtil.getRequiredInput("upload") === "true") {
|
if (runStats && actionsUtil.getRequiredInput("upload") === "true") {
|
||||||
uploadResult = await upload_lib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger);
|
uploadResult = await upload_lib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger);
|
||||||
core.setOutput("sarif-id", uploadResult.sarifID);
|
core.setOutput("sarif-id", uploadResult.sarifID);
|
||||||
core.exportVariable(shared_environment_1.CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF, "true");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logger.info("Not uploading results");
|
logger.info("Not uploading results");
|
||||||
|
|
@ -203,6 +202,7 @@ async function run() {
|
||||||
if (actionsUtil.getOptionalInput("expect-error") === "true") {
|
if (actionsUtil.getOptionalInput("expect-error") === "true") {
|
||||||
core.setFailed(`expect-error input was set to true but no error was thrown.`);
|
core.setFailed(`expect-error input was set to true but no error was thrown.`);
|
||||||
}
|
}
|
||||||
|
core.exportVariable(shared_environment_1.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY, "true");
|
||||||
}
|
}
|
||||||
catch (origError) {
|
catch (origError) {
|
||||||
const error = origError instanceof Error ? origError : new Error(String(origError));
|
const error = origError instanceof Error ? origError : new Error(String(origError));
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
46
lib/init-action-post-helper.js
generated
46
lib/init-action-post-helper.js
generated
|
|
@ -19,7 +19,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.run = exports.uploadSarifIfRunFailed = exports.uploadFailedSarif = void 0;
|
exports.run = exports.tryUploadSarifIfRunFailed = void 0;
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
const actionsUtil = __importStar(require("./actions-util"));
|
const actionsUtil = __importStar(require("./actions-util"));
|
||||||
const codeql_1 = require("./codeql");
|
const codeql_1 = require("./codeql");
|
||||||
|
|
@ -35,15 +35,17 @@ function createFailedUploadFailedSarifResult(error) {
|
||||||
upload_failed_run_stack_trace: error instanceof Error ? error.stack : undefined,
|
upload_failed_run_stack_trace: error instanceof Error ? error.stack : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function uploadFailedSarif(config, repositoryNwo, featureEnablement, logger) {
|
/**
|
||||||
|
* Upload a failed SARIF file if we can verify that SARIF upload is enabled and determine the SARIF
|
||||||
|
* category for the workflow.
|
||||||
|
*/
|
||||||
|
async function maybeUploadFailedSarif(config, repositoryNwo, featureEnablement, logger) {
|
||||||
var _a;
|
var _a;
|
||||||
if (!config.codeQLCmd) {
|
if (!config.codeQLCmd) {
|
||||||
logger.warning("CodeQL command not found. Unable to upload failed SARIF file.");
|
|
||||||
return { upload_failed_run_skipped_because: "CodeQL command not found" };
|
return { upload_failed_run_skipped_because: "CodeQL command not found" };
|
||||||
}
|
}
|
||||||
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
|
const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
|
||||||
if (!(await featureEnablement.getValue(feature_flags_1.Feature.UploadFailedSarifEnabled, codeql))) {
|
if (!(await featureEnablement.getValue(feature_flags_1.Feature.UploadFailedSarifEnabled, codeql))) {
|
||||||
logger.debug("Uploading failed SARIF is disabled.");
|
|
||||||
return { upload_failed_run_skipped_because: "Feature disabled" };
|
return { upload_failed_run_skipped_because: "Feature disabled" };
|
||||||
}
|
}
|
||||||
const workflow = await (0, workflow_1.getWorkflow)();
|
const workflow = await (0, workflow_1.getWorkflow)();
|
||||||
|
|
@ -51,7 +53,6 @@ async function uploadFailedSarif(config, repositoryNwo, featureEnablement, logge
|
||||||
const matrix = (0, util_1.parseMatrixInput)(actionsUtil.getRequiredInput("matrix"));
|
const matrix = (0, util_1.parseMatrixInput)(actionsUtil.getRequiredInput("matrix"));
|
||||||
if ((0, workflow_1.getUploadInputOrThrow)(workflow, jobName, matrix) !== "true" ||
|
if ((0, workflow_1.getUploadInputOrThrow)(workflow, jobName, matrix) !== "true" ||
|
||||||
(0, util_1.isInTestMode)()) {
|
(0, util_1.isInTestMode)()) {
|
||||||
logger.debug("Won't upload a failed SARIF file since SARIF upload is disabled.");
|
|
||||||
return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
|
return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
|
||||||
}
|
}
|
||||||
const category = (0, workflow_1.getCategoryInputOrThrow)(workflow, jobName, matrix);
|
const category = (0, workflow_1.getCategoryInputOrThrow)(workflow, jobName, matrix);
|
||||||
|
|
@ -63,40 +64,41 @@ async function uploadFailedSarif(config, repositoryNwo, featureEnablement, logge
|
||||||
await uploadLib.waitForProcessing(repositoryNwo, uploadResult.sarifID, logger, { isUnsuccessfulExecution: true });
|
await uploadLib.waitForProcessing(repositoryNwo, uploadResult.sarifID, logger, { isUnsuccessfulExecution: true });
|
||||||
return (_a = uploadResult === null || uploadResult === void 0 ? void 0 : uploadResult.statusReport) !== null && _a !== void 0 ? _a : {};
|
return (_a = uploadResult === null || uploadResult === void 0 ? void 0 : uploadResult.statusReport) !== null && _a !== void 0 ? _a : {};
|
||||||
}
|
}
|
||||||
exports.uploadFailedSarif = uploadFailedSarif;
|
async function tryUploadSarifIfRunFailed(config, repositoryNwo, featureEnablement, logger) {
|
||||||
async function uploadSarifIfRunFailed(config, repositoryNwo, featureEnablement, logger) {
|
if (process.env[shared_environment_1.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY] !== "true") {
|
||||||
// Environment variable used to integration test uploading a SARIF file for failed runs
|
|
||||||
const expectFailedSarifUpload = process.env["CODEQL_ACTION_EXPECT_UPLOAD_FAILED_SARIF"] === "true";
|
|
||||||
if (process.env[shared_environment_1.CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF] !== "true") {
|
|
||||||
try {
|
try {
|
||||||
return await uploadFailedSarif(config, repositoryNwo, featureEnablement, logger);
|
return await maybeUploadFailedSarif(config, repositoryNwo, featureEnablement, logger);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (expectFailedSarifUpload) {
|
logger.debug(`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`);
|
||||||
throw new Error("Expected to upload a SARIF file for the failed run, but encountered " +
|
|
||||||
`the following error: ${e}`);
|
|
||||||
}
|
|
||||||
logger.info(`Failed to upload a SARIF file for the failed run. Error: ${e}`);
|
|
||||||
return createFailedUploadFailedSarifResult(e);
|
return createFailedUploadFailedSarifResult(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (expectFailedSarifUpload) {
|
|
||||||
throw new Error("Expected to upload a SARIF file for the failed run, but didn't.");
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
return {
|
return {
|
||||||
upload_failed_run_skipped_because: "SARIF file already uploaded",
|
upload_failed_run_skipped_because: "Analyze Action completed successfully",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.uploadSarifIfRunFailed = uploadSarifIfRunFailed;
|
exports.tryUploadSarifIfRunFailed = tryUploadSarifIfRunFailed;
|
||||||
async function run(uploadDatabaseBundleDebugArtifact, uploadLogsDebugArtifact, printDebugLogs, repositoryNwo, featureEnablement, logger) {
|
async function run(uploadDatabaseBundleDebugArtifact, uploadLogsDebugArtifact, printDebugLogs, repositoryNwo, featureEnablement, logger) {
|
||||||
const config = await (0, config_utils_1.getConfig)(actionsUtil.getTemporaryDirectory(), logger);
|
const config = await (0, config_utils_1.getConfig)(actionsUtil.getTemporaryDirectory(), logger);
|
||||||
if (config === undefined) {
|
if (config === undefined) {
|
||||||
logger.warning("Debugging artifacts are unavailable since the 'init' Action failed before it could produce any.");
|
logger.warning("Debugging artifacts are unavailable since the 'init' Action failed before it could produce any.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const uploadFailedSarifResult = await uploadSarifIfRunFailed(config, repositoryNwo, featureEnablement, logger);
|
const uploadFailedSarifResult = await tryUploadSarifIfRunFailed(config, repositoryNwo, featureEnablement, logger);
|
||||||
|
if (uploadFailedSarifResult.upload_failed_run_skipped_because) {
|
||||||
|
logger.debug("Won't upload a failed SARIF file for this CodeQL code scanning run because: " +
|
||||||
|
`${uploadFailedSarifResult.upload_failed_run_skipped_because}.`);
|
||||||
|
}
|
||||||
|
// Throw an error if in integration tests, we expected to upload a SARIF file for a failed run
|
||||||
|
// but we didn't upload anything.
|
||||||
|
if (process.env["CODEQL_ACTION_EXPECT_UPLOAD_FAILED_SARIF"] === "true" &&
|
||||||
|
!uploadFailedSarifResult.raw_upload_size_bytes) {
|
||||||
|
throw new Error("Expected to upload a failed SARIF file for this CodeQL code scanning run, " +
|
||||||
|
`but the result was instead ${uploadFailedSarifResult}.`);
|
||||||
|
}
|
||||||
// Upload appropriate Actions artifacts for debugging
|
// Upload appropriate Actions artifacts for debugging
|
||||||
if (config.debugMode) {
|
if (config.debugMode) {
|
||||||
core.info("Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts...");
|
core.info("Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts...");
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"init-action-post-helper.js","sourceRoot":"","sources":["../src/init-action-post-helper.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"init-action-post-helper.js","sourceRoot":"","sources":["../src/init-action-post-helper.ts"],"names":[],"mappings":"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"}
|
||||||
92
lib/init-action-post-helper.test.js
generated
92
lib/init-action-post-helper.test.js
generated
|
|
@ -125,15 +125,63 @@ const workflow = __importStar(require("./workflow"));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
await testFailedSarifUpload(t, actionsWorkflow, {
|
const result = await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
expectedLogs: [
|
|
||||||
{
|
|
||||||
message: "Won't upload a failed SARIF file since SARIF upload is disabled.",
|
|
||||||
type: "debug",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
expectUpload: false,
|
expectUpload: false,
|
||||||
});
|
});
|
||||||
|
t.is(result.upload_failed_run_skipped_because, "SARIF upload is disabled");
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("uploading failed SARIF run succeeds when workflow uses an input with a matrix var", async (t) => {
|
||||||
|
const actionsWorkflow = createTestWorkflow([
|
||||||
|
{
|
||||||
|
name: "Checkout repository",
|
||||||
|
uses: "actions/checkout@v3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Initialize CodeQL",
|
||||||
|
uses: "github/codeql-action/init@v2",
|
||||||
|
with: {
|
||||||
|
languages: "javascript",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Perform CodeQL Analysis",
|
||||||
|
uses: "github/codeql-action/analyze@v2",
|
||||||
|
with: {
|
||||||
|
category: "/language:${{ matrix.language }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
|
category: "/language:csharp",
|
||||||
|
matrix: { language: "csharp" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("uploading failed SARIF run fails when workflow uses a complex upload input", async (t) => {
|
||||||
|
const actionsWorkflow = createTestWorkflow([
|
||||||
|
{
|
||||||
|
name: "Checkout repository",
|
||||||
|
uses: "actions/checkout@v3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Initialize CodeQL",
|
||||||
|
uses: "github/codeql-action/init@v2",
|
||||||
|
with: {
|
||||||
|
languages: "javascript",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Perform CodeQL Analysis",
|
||||||
|
uses: "github/codeql-action/analyze@v2",
|
||||||
|
with: {
|
||||||
|
upload: "${{ matrix.language != 'csharp' }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const result = await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
|
expectUpload: false,
|
||||||
|
});
|
||||||
|
t.is(result.upload_failed_run_error, "Could not get upload input to github/codeql-action/analyze since it contained an " +
|
||||||
|
"unrecognized dynamic value.");
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("uploading failed SARIF run fails when workflow does not reference github/codeql-action", async (t) => {
|
(0, ava_1.default)("uploading failed SARIF run fails when workflow does not reference github/codeql-action", async (t) => {
|
||||||
const actionsWorkflow = createTestWorkflow([
|
const actionsWorkflow = createTestWorkflow([
|
||||||
|
|
@ -142,7 +190,12 @@ const workflow = __importStar(require("./workflow"));
|
||||||
uses: "actions/checkout@v3",
|
uses: "actions/checkout@v3",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
await t.throwsAsync(async () => await testFailedSarifUpload(t, actionsWorkflow));
|
const result = await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
|
expectUpload: false,
|
||||||
|
});
|
||||||
|
t.is(result.upload_failed_run_error, "Could not get upload input to github/codeql-action/analyze since the analyze job does not " +
|
||||||
|
"call github/codeql-action/analyze.");
|
||||||
|
t.truthy(result.upload_failed_run_stack_trace);
|
||||||
});
|
});
|
||||||
function createTestWorkflow(steps) {
|
function createTestWorkflow(steps) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -164,28 +217,38 @@ function createTestWorkflow(steps) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function testFailedSarifUpload(t, actionsWorkflow, { category, expectedLogs = [], expectUpload = true, } = {}) {
|
async function testFailedSarifUpload(t, actionsWorkflow, { category, expectUpload = true, matrix = {}, } = {}) {
|
||||||
const config = {
|
const config = {
|
||||||
codeQLCmd: "codeql",
|
codeQLCmd: "codeql",
|
||||||
debugMode: true,
|
debugMode: true,
|
||||||
languages: [],
|
languages: [],
|
||||||
packs: [],
|
packs: [],
|
||||||
};
|
};
|
||||||
const messages = [];
|
|
||||||
process.env["GITHUB_JOB"] = "analyze";
|
process.env["GITHUB_JOB"] = "analyze";
|
||||||
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
|
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
|
||||||
process.env["GITHUB_WORKSPACE"] =
|
process.env["GITHUB_WORKSPACE"] =
|
||||||
"/home/runner/work/codeql-action/codeql-action";
|
"/home/runner/work/codeql-action/codeql-action";
|
||||||
sinon.stub(actionsUtil, "getRequiredInput").withArgs("matrix").returns("{}");
|
sinon
|
||||||
|
.stub(actionsUtil, "getRequiredInput")
|
||||||
|
.withArgs("matrix")
|
||||||
|
.returns(JSON.stringify(matrix));
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
|
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
|
||||||
const diagnosticsExportStub = sinon.stub(codeqlObject, "diagnosticsExport");
|
const diagnosticsExportStub = sinon.stub(codeqlObject, "diagnosticsExport");
|
||||||
sinon.stub(workflow, "getWorkflow").resolves(actionsWorkflow);
|
sinon.stub(workflow, "getWorkflow").resolves(actionsWorkflow);
|
||||||
const uploadFromActions = sinon.stub(uploadLib, "uploadFromActions");
|
const uploadFromActions = sinon.stub(uploadLib, "uploadFromActions");
|
||||||
uploadFromActions.resolves({ sarifID: "42" });
|
uploadFromActions.resolves({
|
||||||
|
sarifID: "42",
|
||||||
|
statusReport: { raw_upload_size_bytes: 20, zipped_upload_size_bytes: 10 },
|
||||||
|
});
|
||||||
const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing");
|
const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing");
|
||||||
await initActionPostHelper.uploadFailedSarif(config, (0, repository_1.parseRepositoryNwo)("github/codeql-action"), (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.UploadFailedSarifEnabled]), (0, testing_utils_1.getRecordingLogger)(messages));
|
const result = await initActionPostHelper.tryUploadSarifIfRunFailed(config, (0, repository_1.parseRepositoryNwo)("github/codeql-action"), (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.UploadFailedSarifEnabled]), (0, logging_1.getRunnerLogger)(true));
|
||||||
t.deepEqual(messages, expectedLogs);
|
if (expectUpload) {
|
||||||
|
t.deepEqual(result, {
|
||||||
|
raw_upload_size_bytes: 20,
|
||||||
|
zipped_upload_size_bytes: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
if (expectUpload) {
|
if (expectUpload) {
|
||||||
t.true(diagnosticsExportStub.calledOnceWith(sinon.match.string, category), `Actual args were: ${diagnosticsExportStub.args}`);
|
t.true(diagnosticsExportStub.calledOnceWith(sinon.match.string, category), `Actual args were: ${diagnosticsExportStub.args}`);
|
||||||
t.true(uploadFromActions.calledOnceWith(sinon.match.string, sinon.match.string, category, sinon.match.any), `Actual args were: ${uploadFromActions.args}`);
|
t.true(uploadFromActions.calledOnceWith(sinon.match.string, sinon.match.string, category, sinon.match.any), `Actual args were: ${uploadFromActions.args}`);
|
||||||
|
|
@ -198,5 +261,6 @@ async function testFailedSarifUpload(t, actionsWorkflow, { category, expectedLog
|
||||||
t.true(uploadFromActions.notCalled);
|
t.true(uploadFromActions.notCalled);
|
||||||
t.true(waitForProcessing.notCalled);
|
t.true(waitForProcessing.notCalled);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=init-action-post-helper.test.js.map
|
//# sourceMappingURL=init-action-post-helper.test.js.map
|
||||||
File diff suppressed because one or more lines are too long
7
lib/shared-environment.js
generated
7
lib/shared-environment.js
generated
|
|
@ -1,12 +1,11 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.ODASA_TRACER_CONFIGURATION = exports.CODEQL_WORKFLOW_STARTED_AT = exports.CODEQL_ACTION_TEST_MODE = exports.CODEQL_ACTION_TESTING_ENVIRONMENT = exports.CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF = void 0;
|
exports.ODASA_TRACER_CONFIGURATION = exports.CODEQL_WORKFLOW_STARTED_AT = exports.CODEQL_ACTION_TEST_MODE = exports.CODEQL_ACTION_TESTING_ENVIRONMENT = exports.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY = void 0;
|
||||||
/**
|
/**
|
||||||
* This environment variable is set to true when the `analyze` Action
|
* This environment variable is set to true when the `analyze` Action
|
||||||
* successfully uploads a SARIF file. It does NOT indicate whether the
|
* completes successfully.
|
||||||
* SARIF file was processed successfully.
|
|
||||||
*/
|
*/
|
||||||
exports.CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF = "CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF";
|
exports.CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY = "CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY";
|
||||||
exports.CODEQL_ACTION_TESTING_ENVIRONMENT = "CODEQL_ACTION_TESTING_ENVIRONMENT";
|
exports.CODEQL_ACTION_TESTING_ENVIRONMENT = "CODEQL_ACTION_TESTING_ENVIRONMENT";
|
||||||
/** Used to disable uploading SARIF results or status reports to the GitHub API */
|
/** Used to disable uploading SARIF results or status reports to the GitHub API */
|
||||||
exports.CODEQL_ACTION_TEST_MODE = "CODEQL_ACTION_TEST_MODE";
|
exports.CODEQL_ACTION_TEST_MODE = "CODEQL_ACTION_TEST_MODE";
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"shared-environment.js","sourceRoot":"","sources":["../src/shared-environment.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACU,QAAA,sCAAsC,GACjD,wCAAwC,CAAC;AAE9B,QAAA,iCAAiC,GAC5C,mCAAmC,CAAC;AAEtC,kFAAkF;AACrE,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AAEjE;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAE1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC"}
|
{"version":3,"file":"shared-environment.js","sourceRoot":"","sources":["../src/shared-environment.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACU,QAAA,+CAA+C,GAC1D,iDAAiD,CAAC;AAEvC,QAAA,iCAAiC,GAC5C,mCAAmC,CAAC;AAEtC,kFAAkF;AACrE,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AAEjE;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,4BAA4B,CAAC;AAE1D,QAAA,0BAA0B,GAAG,4BAA4B,CAAC"}
|
||||||
14
lib/workflow.js
generated
14
lib/workflow.js
generated
|
|
@ -213,7 +213,16 @@ exports.formatWorkflowCause = formatWorkflowCause;
|
||||||
async function getWorkflow() {
|
async function getWorkflow() {
|
||||||
const relativePath = await getWorkflowPath();
|
const relativePath = await getWorkflowPath();
|
||||||
const absolutePath = path.join((0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"), relativePath);
|
const absolutePath = path.join((0, util_1.getRequiredEnvParam)("GITHUB_WORKSPACE"), relativePath);
|
||||||
return yaml.load(fs.readFileSync(absolutePath, "utf-8"));
|
try {
|
||||||
|
return yaml.load(fs.readFileSync(absolutePath, "utf-8"));
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (e instanceof Error && e["code"] === "ENOENT") {
|
||||||
|
throw new Error(`Unable to load code scanning workflow from ${absolutePath}. This can happen if the currently ` +
|
||||||
|
"running workflow checks out a branch that doesn't contain the corresponding workflow file.");
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.getWorkflow = getWorkflow;
|
exports.getWorkflow = getWorkflow;
|
||||||
/**
|
/**
|
||||||
|
|
@ -247,6 +256,9 @@ function getWorkflowRunID() {
|
||||||
}
|
}
|
||||||
exports.getWorkflowRunID = getWorkflowRunID;
|
exports.getWorkflowRunID = getWorkflowRunID;
|
||||||
function getStepsCallingAction(job, actionName) {
|
function getStepsCallingAction(job, actionName) {
|
||||||
|
if (job.uses) {
|
||||||
|
throw new Error(`Could not get steps calling ${actionName} since the job calls a reusable workflow.`);
|
||||||
|
}
|
||||||
const steps = job.steps;
|
const steps = job.steps;
|
||||||
if (!Array.isArray(steps)) {
|
if (!Array.isArray(steps)) {
|
||||||
throw new Error(`Could not get steps calling ${actionName} since job.steps was not an array.`);
|
throw new Error(`Could not get steps calling ${actionName} since job.steps was not an array.`);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -24,7 +24,7 @@ import { Features } from "./feature-flags";
|
||||||
import { Language } from "./languages";
|
import { Language } from "./languages";
|
||||||
import { getActionsLogger, Logger } from "./logging";
|
import { getActionsLogger, Logger } from "./logging";
|
||||||
import { parseRepositoryNwo } from "./repository";
|
import { parseRepositoryNwo } from "./repository";
|
||||||
import { CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF } from "./shared-environment";
|
import { CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY } from "./shared-environment";
|
||||||
import { getTotalCacheSize, uploadTrapCaches } from "./trap-caching";
|
import { getTotalCacheSize, uploadTrapCaches } from "./trap-caching";
|
||||||
import * as upload_lib from "./upload-lib";
|
import * as upload_lib from "./upload-lib";
|
||||||
import { UploadResult } from "./upload-lib";
|
import { UploadResult } from "./upload-lib";
|
||||||
|
|
@ -279,7 +279,6 @@ async function run() {
|
||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
core.setOutput("sarif-id", uploadResult.sarifID);
|
core.setOutput("sarif-id", uploadResult.sarifID);
|
||||||
core.exportVariable(CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF, "true");
|
|
||||||
} else {
|
} else {
|
||||||
logger.info("Not uploading results");
|
logger.info("Not uploading results");
|
||||||
}
|
}
|
||||||
|
|
@ -312,6 +311,10 @@ async function run() {
|
||||||
`expect-error input was set to true but no error was thrown.`
|
`expect-error input was set to true but no error was thrown.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
core.exportVariable(
|
||||||
|
CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY,
|
||||||
|
"true"
|
||||||
|
);
|
||||||
} catch (origError) {
|
} catch (origError) {
|
||||||
const error =
|
const error =
|
||||||
origError instanceof Error ? origError : new Error(String(origError));
|
origError instanceof Error ? origError : new Error(String(origError));
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,7 @@ import { Feature } from "./feature-flags";
|
||||||
import * as initActionPostHelper from "./init-action-post-helper";
|
import * as initActionPostHelper from "./init-action-post-helper";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { parseRepositoryNwo } from "./repository";
|
import { parseRepositoryNwo } from "./repository";
|
||||||
import {
|
import { createFeatures, setupTests } from "./testing-utils";
|
||||||
createFeatures,
|
|
||||||
getRecordingLogger,
|
|
||||||
LoggedMessage,
|
|
||||||
setupTests,
|
|
||||||
} from "./testing-utils";
|
|
||||||
import * as uploadLib from "./upload-lib";
|
import * as uploadLib from "./upload-lib";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
import * as workflow from "./workflow";
|
import * as workflow from "./workflow";
|
||||||
|
|
@ -134,16 +129,68 @@ test("doesn't upload failed SARIF for workflow with upload: false", async (t) =>
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
await testFailedSarifUpload(t, actionsWorkflow, {
|
const result = await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
expectedLogs: [
|
|
||||||
{
|
|
||||||
message:
|
|
||||||
"Won't upload a failed SARIF file since SARIF upload is disabled.",
|
|
||||||
type: "debug",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
expectUpload: false,
|
expectUpload: false,
|
||||||
});
|
});
|
||||||
|
t.is(result.upload_failed_run_skipped_because, "SARIF upload is disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("uploading failed SARIF run succeeds when workflow uses an input with a matrix var", async (t) => {
|
||||||
|
const actionsWorkflow = createTestWorkflow([
|
||||||
|
{
|
||||||
|
name: "Checkout repository",
|
||||||
|
uses: "actions/checkout@v3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Initialize CodeQL",
|
||||||
|
uses: "github/codeql-action/init@v2",
|
||||||
|
with: {
|
||||||
|
languages: "javascript",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Perform CodeQL Analysis",
|
||||||
|
uses: "github/codeql-action/analyze@v2",
|
||||||
|
with: {
|
||||||
|
category: "/language:${{ matrix.language }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
|
category: "/language:csharp",
|
||||||
|
matrix: { language: "csharp" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("uploading failed SARIF run fails when workflow uses a complex upload input", async (t) => {
|
||||||
|
const actionsWorkflow = createTestWorkflow([
|
||||||
|
{
|
||||||
|
name: "Checkout repository",
|
||||||
|
uses: "actions/checkout@v3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Initialize CodeQL",
|
||||||
|
uses: "github/codeql-action/init@v2",
|
||||||
|
with: {
|
||||||
|
languages: "javascript",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Perform CodeQL Analysis",
|
||||||
|
uses: "github/codeql-action/analyze@v2",
|
||||||
|
with: {
|
||||||
|
upload: "${{ matrix.language != 'csharp' }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const result = await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
|
expectUpload: false,
|
||||||
|
});
|
||||||
|
t.is(
|
||||||
|
result.upload_failed_run_error,
|
||||||
|
"Could not get upload input to github/codeql-action/analyze since it contained an " +
|
||||||
|
"unrecognized dynamic value."
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uploading failed SARIF run fails when workflow does not reference github/codeql-action", async (t) => {
|
test("uploading failed SARIF run fails when workflow does not reference github/codeql-action", async (t) => {
|
||||||
|
|
@ -153,9 +200,15 @@ test("uploading failed SARIF run fails when workflow does not reference github/c
|
||||||
uses: "actions/checkout@v3",
|
uses: "actions/checkout@v3",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
await t.throwsAsync(
|
const result = await testFailedSarifUpload(t, actionsWorkflow, {
|
||||||
async () => await testFailedSarifUpload(t, actionsWorkflow)
|
expectUpload: false,
|
||||||
|
});
|
||||||
|
t.is(
|
||||||
|
result.upload_failed_run_error,
|
||||||
|
"Could not get upload input to github/codeql-action/analyze since the analyze job does not " +
|
||||||
|
"call github/codeql-action/analyze."
|
||||||
);
|
);
|
||||||
|
t.truthy(result.upload_failed_run_stack_trace);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createTestWorkflow(
|
function createTestWorkflow(
|
||||||
|
|
@ -186,26 +239,28 @@ async function testFailedSarifUpload(
|
||||||
actionsWorkflow: workflow.Workflow,
|
actionsWorkflow: workflow.Workflow,
|
||||||
{
|
{
|
||||||
category,
|
category,
|
||||||
expectedLogs = [],
|
|
||||||
expectUpload = true,
|
expectUpload = true,
|
||||||
|
matrix = {},
|
||||||
}: {
|
}: {
|
||||||
category?: string;
|
category?: string;
|
||||||
expectedLogs?: LoggedMessage[];
|
|
||||||
expectUpload?: boolean;
|
expectUpload?: boolean;
|
||||||
|
matrix?: { [key: string]: string };
|
||||||
} = {}
|
} = {}
|
||||||
): Promise<void> {
|
): Promise<initActionPostHelper.UploadFailedSarifResult> {
|
||||||
const config = {
|
const config = {
|
||||||
codeQLCmd: "codeql",
|
codeQLCmd: "codeql",
|
||||||
debugMode: true,
|
debugMode: true,
|
||||||
languages: [],
|
languages: [],
|
||||||
packs: [],
|
packs: [],
|
||||||
} as unknown as configUtils.Config;
|
} as unknown as configUtils.Config;
|
||||||
const messages = [];
|
|
||||||
process.env["GITHUB_JOB"] = "analyze";
|
process.env["GITHUB_JOB"] = "analyze";
|
||||||
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
|
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
|
||||||
process.env["GITHUB_WORKSPACE"] =
|
process.env["GITHUB_WORKSPACE"] =
|
||||||
"/home/runner/work/codeql-action/codeql-action";
|
"/home/runner/work/codeql-action/codeql-action";
|
||||||
sinon.stub(actionsUtil, "getRequiredInput").withArgs("matrix").returns("{}");
|
sinon
|
||||||
|
.stub(actionsUtil, "getRequiredInput")
|
||||||
|
.withArgs("matrix")
|
||||||
|
.returns(JSON.stringify(matrix));
|
||||||
|
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
|
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
|
||||||
|
|
@ -214,16 +269,24 @@ async function testFailedSarifUpload(
|
||||||
sinon.stub(workflow, "getWorkflow").resolves(actionsWorkflow);
|
sinon.stub(workflow, "getWorkflow").resolves(actionsWorkflow);
|
||||||
|
|
||||||
const uploadFromActions = sinon.stub(uploadLib, "uploadFromActions");
|
const uploadFromActions = sinon.stub(uploadLib, "uploadFromActions");
|
||||||
uploadFromActions.resolves({ sarifID: "42" } as uploadLib.UploadResult);
|
uploadFromActions.resolves({
|
||||||
|
sarifID: "42",
|
||||||
|
statusReport: { raw_upload_size_bytes: 20, zipped_upload_size_bytes: 10 },
|
||||||
|
} as uploadLib.UploadResult);
|
||||||
const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing");
|
const waitForProcessing = sinon.stub(uploadLib, "waitForProcessing");
|
||||||
|
|
||||||
await initActionPostHelper.uploadFailedSarif(
|
const result = await initActionPostHelper.tryUploadSarifIfRunFailed(
|
||||||
config,
|
config,
|
||||||
parseRepositoryNwo("github/codeql-action"),
|
parseRepositoryNwo("github/codeql-action"),
|
||||||
createFeatures([Feature.UploadFailedSarifEnabled]),
|
createFeatures([Feature.UploadFailedSarifEnabled]),
|
||||||
getRecordingLogger(messages)
|
getRunnerLogger(true)
|
||||||
);
|
);
|
||||||
t.deepEqual(messages, expectedLogs);
|
if (expectUpload) {
|
||||||
|
t.deepEqual(result, {
|
||||||
|
raw_upload_size_bytes: 20,
|
||||||
|
zipped_upload_size_bytes: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
if (expectUpload) {
|
if (expectUpload) {
|
||||||
t.true(
|
t.true(
|
||||||
diagnosticsExportStub.calledOnceWith(sinon.match.string, category),
|
diagnosticsExportStub.calledOnceWith(sinon.match.string, category),
|
||||||
|
|
@ -248,4 +311,5 @@ async function testFailedSarifUpload(
|
||||||
t.true(uploadFromActions.notCalled);
|
t.true(uploadFromActions.notCalled);
|
||||||
t.true(waitForProcessing.notCalled);
|
t.true(waitForProcessing.notCalled);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { Config, getConfig } from "./config-utils";
|
||||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { RepositoryNwo } from "./repository";
|
import { RepositoryNwo } from "./repository";
|
||||||
import { CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF } from "./shared-environment";
|
import { CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY } from "./shared-environment";
|
||||||
import * as uploadLib from "./upload-lib";
|
import * as uploadLib from "./upload-lib";
|
||||||
import { getRequiredEnvParam, isInTestMode, parseMatrixInput } from "./util";
|
import { getRequiredEnvParam, isInTestMode, parseMatrixInput } from "./util";
|
||||||
import {
|
import {
|
||||||
|
|
@ -36,16 +36,17 @@ function createFailedUploadFailedSarifResult(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function uploadFailedSarif(
|
/**
|
||||||
|
* Upload a failed SARIF file if we can verify that SARIF upload is enabled and determine the SARIF
|
||||||
|
* category for the workflow.
|
||||||
|
*/
|
||||||
|
async function maybeUploadFailedSarif(
|
||||||
config: Config,
|
config: Config,
|
||||||
repositoryNwo: RepositoryNwo,
|
repositoryNwo: RepositoryNwo,
|
||||||
featureEnablement: FeatureEnablement,
|
featureEnablement: FeatureEnablement,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<UploadFailedSarifResult> {
|
): Promise<UploadFailedSarifResult> {
|
||||||
if (!config.codeQLCmd) {
|
if (!config.codeQLCmd) {
|
||||||
logger.warning(
|
|
||||||
"CodeQL command not found. Unable to upload failed SARIF file."
|
|
||||||
);
|
|
||||||
return { upload_failed_run_skipped_because: "CodeQL command not found" };
|
return { upload_failed_run_skipped_because: "CodeQL command not found" };
|
||||||
}
|
}
|
||||||
const codeql = await getCodeQL(config.codeQLCmd);
|
const codeql = await getCodeQL(config.codeQLCmd);
|
||||||
|
|
@ -55,7 +56,6 @@ export async function uploadFailedSarif(
|
||||||
codeql
|
codeql
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
logger.debug("Uploading failed SARIF is disabled.");
|
|
||||||
return { upload_failed_run_skipped_because: "Feature disabled" };
|
return { upload_failed_run_skipped_because: "Feature disabled" };
|
||||||
}
|
}
|
||||||
const workflow = await getWorkflow();
|
const workflow = await getWorkflow();
|
||||||
|
|
@ -65,9 +65,6 @@ export async function uploadFailedSarif(
|
||||||
getUploadInputOrThrow(workflow, jobName, matrix) !== "true" ||
|
getUploadInputOrThrow(workflow, jobName, matrix) !== "true" ||
|
||||||
isInTestMode()
|
isInTestMode()
|
||||||
) {
|
) {
|
||||||
logger.debug(
|
|
||||||
"Won't upload a failed SARIF file since SARIF upload is disabled."
|
|
||||||
);
|
|
||||||
return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
|
return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
|
||||||
}
|
}
|
||||||
const category = getCategoryInputOrThrow(workflow, jobName, matrix);
|
const category = getCategoryInputOrThrow(workflow, jobName, matrix);
|
||||||
|
|
@ -92,43 +89,30 @@ export async function uploadFailedSarif(
|
||||||
return uploadResult?.statusReport ?? {};
|
return uploadResult?.statusReport ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function uploadSarifIfRunFailed(
|
export async function tryUploadSarifIfRunFailed(
|
||||||
config: Config,
|
config: Config,
|
||||||
repositoryNwo: RepositoryNwo,
|
repositoryNwo: RepositoryNwo,
|
||||||
featureEnablement: FeatureEnablement,
|
featureEnablement: FeatureEnablement,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<UploadFailedSarifResult> {
|
): Promise<UploadFailedSarifResult> {
|
||||||
// Environment variable used to integration test uploading a SARIF file for failed runs
|
if (process.env[CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY] !== "true") {
|
||||||
const expectFailedSarifUpload =
|
|
||||||
process.env["CODEQL_ACTION_EXPECT_UPLOAD_FAILED_SARIF"] === "true";
|
|
||||||
|
|
||||||
if (process.env[CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF] !== "true") {
|
|
||||||
try {
|
try {
|
||||||
return await uploadFailedSarif(
|
return await maybeUploadFailedSarif(
|
||||||
config,
|
config,
|
||||||
repositoryNwo,
|
repositoryNwo,
|
||||||
featureEnablement,
|
featureEnablement,
|
||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (expectFailedSarifUpload) {
|
logger.debug(
|
||||||
throw new Error(
|
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`
|
||||||
"Expected to upload a SARIF file for the failed run, but encountered " +
|
|
||||||
`the following error: ${e}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
logger.info(
|
|
||||||
`Failed to upload a SARIF file for the failed run. Error: ${e}`
|
|
||||||
);
|
);
|
||||||
return createFailedUploadFailedSarifResult(e);
|
return createFailedUploadFailedSarifResult(e);
|
||||||
}
|
}
|
||||||
} else if (expectFailedSarifUpload) {
|
|
||||||
throw new Error(
|
|
||||||
"Expected to upload a SARIF file for the failed run, but didn't."
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
upload_failed_run_skipped_because: "SARIF file already uploaded",
|
upload_failed_run_skipped_because:
|
||||||
|
"Analyze Action completed successfully",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,12 +133,29 @@ export async function run(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadFailedSarifResult = await uploadSarifIfRunFailed(
|
const uploadFailedSarifResult = await tryUploadSarifIfRunFailed(
|
||||||
config,
|
config,
|
||||||
repositoryNwo,
|
repositoryNwo,
|
||||||
featureEnablement,
|
featureEnablement,
|
||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
|
if (uploadFailedSarifResult.upload_failed_run_skipped_because) {
|
||||||
|
logger.debug(
|
||||||
|
"Won't upload a failed SARIF file for this CodeQL code scanning run because: " +
|
||||||
|
`${uploadFailedSarifResult.upload_failed_run_skipped_because}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Throw an error if in integration tests, we expected to upload a SARIF file for a failed run
|
||||||
|
// but we didn't upload anything.
|
||||||
|
if (
|
||||||
|
process.env["CODEQL_ACTION_EXPECT_UPLOAD_FAILED_SARIF"] === "true" &&
|
||||||
|
!uploadFailedSarifResult.raw_upload_size_bytes
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
"Expected to upload a failed SARIF file for this CodeQL code scanning run, " +
|
||||||
|
`but the result was instead ${uploadFailedSarifResult}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Upload appropriate Actions artifacts for debugging
|
// Upload appropriate Actions artifacts for debugging
|
||||||
if (config.debugMode) {
|
if (config.debugMode) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* This environment variable is set to true when the `analyze` Action
|
* This environment variable is set to true when the `analyze` Action
|
||||||
* successfully uploads a SARIF file. It does NOT indicate whether the
|
* completes successfully.
|
||||||
* SARIF file was processed successfully.
|
|
||||||
*/
|
*/
|
||||||
export const CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF =
|
export const CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY =
|
||||||
"CODEQL_ACTION_ANALYZE_DID_UPLOAD_SARIF";
|
"CODEQL_ACTION_ANALYZE_DID_COMPLETE_SUCCESSFULLY";
|
||||||
|
|
||||||
export const CODEQL_ACTION_TESTING_ENVIRONMENT =
|
export const CODEQL_ACTION_TESTING_ENVIRONMENT =
|
||||||
"CODEQL_ACTION_TESTING_ENVIRONMENT";
|
"CODEQL_ACTION_TESTING_ENVIRONMENT";
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ interface WorkflowJob {
|
||||||
name?: string;
|
name?: string;
|
||||||
"runs-on"?: string;
|
"runs-on"?: string;
|
||||||
steps?: WorkflowJobStep[];
|
steps?: WorkflowJobStep[];
|
||||||
|
uses?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WorkflowTrigger {
|
interface WorkflowTrigger {
|
||||||
|
|
@ -258,7 +259,17 @@ export async function getWorkflow(): Promise<Workflow> {
|
||||||
relativePath
|
relativePath
|
||||||
);
|
);
|
||||||
|
|
||||||
return yaml.load(fs.readFileSync(absolutePath, "utf-8")) as Workflow;
|
try {
|
||||||
|
return yaml.load(fs.readFileSync(absolutePath, "utf-8")) as Workflow;
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error && e["code"] === "ENOENT") {
|
||||||
|
throw new Error(
|
||||||
|
`Unable to load code scanning workflow from ${absolutePath}. This can happen if the currently ` +
|
||||||
|
"running workflow checks out a branch that doesn't contain the corresponding workflow file."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -301,6 +312,11 @@ function getStepsCallingAction(
|
||||||
job: WorkflowJob,
|
job: WorkflowJob,
|
||||||
actionName: string
|
actionName: string
|
||||||
): WorkflowJobStep[] {
|
): WorkflowJobStep[] {
|
||||||
|
if (job.uses) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not get steps calling ${actionName} since the job calls a reusable workflow.`
|
||||||
|
);
|
||||||
|
}
|
||||||
const steps = job.steps;
|
const steps = job.steps;
|
||||||
if (!Array.isArray(steps)) {
|
if (!Array.isArray(steps)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue