mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 17:41:28 +00:00
Merge branch 'main' into sam-robson/overlay-per-lang-min-bundle-version
This commit is contained in:
1184
lib/init-action-post.js
generated
1184
lib/init-action-post.js
generated
File diff suppressed because it is too large
Load Diff
@@ -1554,6 +1554,13 @@ export function isCodeQualityEnabled(config: Config): boolean {
|
|||||||
return config.analysisKinds.includes(AnalysisKind.CodeQuality);
|
return config.analysisKinds.includes(AnalysisKind.CodeQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns `true` if Code Scanning Risk Assessment analysis is enabled, or `false` if not.
|
||||||
|
*/
|
||||||
|
export function isRiskAssessmentEnabled(config: Config): boolean {
|
||||||
|
return config.analysisKinds.includes(AnalysisKind.RiskAssessment);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the primary analysis kind that the Action is initialised with. If there is only
|
* Returns the primary analysis kind that the Action is initialised with. If there is only
|
||||||
* one analysis kind, then that is returned.
|
* one analysis kind, then that is returned.
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
import * as core from "@actions/core";
|
||||||
import test, { ExecutionContext } from "ava";
|
import test, { ExecutionContext } from "ava";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import { AnalysisKind } from "./analyses";
|
import { AnalysisKind } from "./analyses";
|
||||||
|
import * as apiClient from "./api-client";
|
||||||
import * as codeql from "./codeql";
|
import * as codeql from "./codeql";
|
||||||
import * as configUtils from "./config-utils";
|
import * as configUtils from "./config-utils";
|
||||||
|
import * as debugArtifacts from "./debug-artifacts";
|
||||||
import { EnvVar } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { Feature } from "./feature-flags";
|
import { Feature } from "./feature-flags";
|
||||||
import * as initActionPostHelper from "./init-action-post-helper";
|
import * as initActionPostHelper from "./init-action-post-helper";
|
||||||
@@ -17,6 +20,7 @@ import {
|
|||||||
createTestConfig,
|
createTestConfig,
|
||||||
DEFAULT_ACTIONS_VARS,
|
DEFAULT_ACTIONS_VARS,
|
||||||
makeVersionInfo,
|
makeVersionInfo,
|
||||||
|
RecordingLogger,
|
||||||
setupActionsVars,
|
setupActionsVars,
|
||||||
setupTests,
|
setupTests,
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
@@ -46,7 +50,7 @@ test.serial("init-post action with debug mode off", async (t) => {
|
|||||||
const uploadAllAvailableDebugArtifactsSpy = sinon.spy();
|
const uploadAllAvailableDebugArtifactsSpy = sinon.spy();
|
||||||
const printDebugLogsSpy = sinon.spy();
|
const printDebugLogsSpy = sinon.spy();
|
||||||
|
|
||||||
await initActionPostHelper.run(
|
await initActionPostHelper.uploadFailureInfo(
|
||||||
uploadAllAvailableDebugArtifactsSpy,
|
uploadAllAvailableDebugArtifactsSpy,
|
||||||
printDebugLogsSpy,
|
printDebugLogsSpy,
|
||||||
codeql.createStubCodeQL({}),
|
codeql.createStubCodeQL({}),
|
||||||
@@ -68,7 +72,7 @@ test.serial("init-post action with debug mode on", async (t) => {
|
|||||||
const uploadAllAvailableDebugArtifactsSpy = sinon.spy();
|
const uploadAllAvailableDebugArtifactsSpy = sinon.spy();
|
||||||
const printDebugLogsSpy = sinon.spy();
|
const printDebugLogsSpy = sinon.spy();
|
||||||
|
|
||||||
await initActionPostHelper.run(
|
await initActionPostHelper.uploadFailureInfo(
|
||||||
uploadAllAvailableDebugArtifactsSpy,
|
uploadAllAvailableDebugArtifactsSpy,
|
||||||
printDebugLogsSpy,
|
printDebugLogsSpy,
|
||||||
codeql.createStubCodeQL({}),
|
codeql.createStubCodeQL({}),
|
||||||
@@ -334,7 +338,7 @@ test.serial(
|
|||||||
});
|
});
|
||||||
t.is(
|
t.is(
|
||||||
result.upload_failed_run_skipped_because,
|
result.upload_failed_run_skipped_because,
|
||||||
"Code Scanning is not enabled.",
|
"No analysis kind that supports failed SARIF uploads is enabled.",
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -359,7 +363,7 @@ test.serial(
|
|||||||
|
|
||||||
const stubCodeQL = codeql.createStubCodeQL({});
|
const stubCodeQL = codeql.createStubCodeQL({});
|
||||||
|
|
||||||
await initActionPostHelper.run(
|
await initActionPostHelper.uploadFailureInfo(
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
stubCodeQL,
|
stubCodeQL,
|
||||||
@@ -427,7 +431,7 @@ test.serial(
|
|||||||
.stub(overlayStatus, "saveOverlayStatus")
|
.stub(overlayStatus, "saveOverlayStatus")
|
||||||
.resolves(true);
|
.resolves(true);
|
||||||
|
|
||||||
await initActionPostHelper.run(
|
await initActionPostHelper.uploadFailureInfo(
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
codeql.createStubCodeQL({}),
|
codeql.createStubCodeQL({}),
|
||||||
@@ -464,7 +468,7 @@ test.serial("does not save overlay status when build successful", async (t) => {
|
|||||||
.stub(overlayStatus, "saveOverlayStatus")
|
.stub(overlayStatus, "saveOverlayStatus")
|
||||||
.resolves(true);
|
.resolves(true);
|
||||||
|
|
||||||
await initActionPostHelper.run(
|
await initActionPostHelper.uploadFailureInfo(
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
codeql.createStubCodeQL({}),
|
codeql.createStubCodeQL({}),
|
||||||
@@ -501,7 +505,7 @@ test.serial(
|
|||||||
.stub(overlayStatus, "saveOverlayStatus")
|
.stub(overlayStatus, "saveOverlayStatus")
|
||||||
.resolves(true);
|
.resolves(true);
|
||||||
|
|
||||||
await initActionPostHelper.run(
|
await initActionPostHelper.uploadFailureInfo(
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
sinon.spy(),
|
sinon.spy(),
|
||||||
codeql.createStubCodeQL({}),
|
codeql.createStubCodeQL({}),
|
||||||
@@ -658,3 +662,197 @@ async function testFailedSarifUpload(
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const singleLanguageMatrix = JSON.stringify({
|
||||||
|
language: "javascript",
|
||||||
|
category: "/language:javascript",
|
||||||
|
"build-mode": "none",
|
||||||
|
runner: "ubuntu-latest",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function mockRiskAssessmentEnv(matrix: string) {
|
||||||
|
process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] = "false";
|
||||||
|
process.env["GITHUB_JOB"] = "analyze";
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
|
||||||
|
process.env["GITHUB_WORKSPACE"] =
|
||||||
|
"/home/runner/work/codeql-action-fake-repository/codeql-action-fake-repository";
|
||||||
|
|
||||||
|
sinon
|
||||||
|
.stub(apiClient, "getGitHubVersion")
|
||||||
|
.resolves({ type: util.GitHubVariant.GHES, version: "3.0.0" });
|
||||||
|
|
||||||
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
|
const databaseExportDiagnostics = sinon
|
||||||
|
.stub(codeqlObject, "databaseExportDiagnostics")
|
||||||
|
.resolves();
|
||||||
|
const diagnosticsExport = sinon
|
||||||
|
.stub(codeqlObject, "diagnosticsExport")
|
||||||
|
.resolves();
|
||||||
|
|
||||||
|
sinon.stub(codeql, "getCodeQL").resolves(codeqlObject);
|
||||||
|
|
||||||
|
sinon.stub(core, "getInput").withArgs("matrix").returns(matrix);
|
||||||
|
|
||||||
|
const uploadArtifact = sinon.stub().resolves();
|
||||||
|
const artifactClient = { uploadArtifact };
|
||||||
|
sinon
|
||||||
|
.stub(debugArtifacts, "getArtifactUploaderClient")
|
||||||
|
.value(() => artifactClient);
|
||||||
|
|
||||||
|
return { uploadArtifact, databaseExportDiagnostics, diagnosticsExport };
|
||||||
|
}
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"tryUploadSarifIfRunFailed - uploads as artifact for risk assessments (diagnosticsExport)",
|
||||||
|
async (t) => {
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
const { uploadArtifact, databaseExportDiagnostics, diagnosticsExport } =
|
||||||
|
await mockRiskAssessmentEnv(singleLanguageMatrix);
|
||||||
|
|
||||||
|
const config = createTestConfig({
|
||||||
|
analysisKinds: [AnalysisKind.RiskAssessment],
|
||||||
|
codeQLCmd: "codeql-for-testing",
|
||||||
|
languages: ["javascript"],
|
||||||
|
});
|
||||||
|
const features = createFeatures([]);
|
||||||
|
|
||||||
|
const result = await initActionPostHelper.tryUploadSarifIfRunFailed(
|
||||||
|
config,
|
||||||
|
parseRepositoryNwo("github/codeql-action-fake-repository"),
|
||||||
|
features,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
|
|
||||||
|
const expectedName = debugArtifacts.sanitizeArtifactName(
|
||||||
|
`sarif-artifact-${debugArtifacts.getArtifactSuffix(singleLanguageMatrix)}`,
|
||||||
|
);
|
||||||
|
const expectedFilePattern = /codeql-failed-sarif-javascript\.csra\.sarif$/;
|
||||||
|
t.is(result.upload_failed_run_skipped_because, undefined);
|
||||||
|
t.is(result.upload_failed_run_error, undefined);
|
||||||
|
t.is(result.sarifID, expectedName);
|
||||||
|
t.assert(
|
||||||
|
uploadArtifact.calledOnceWith(
|
||||||
|
expectedName,
|
||||||
|
[sinon.match(expectedFilePattern)],
|
||||||
|
sinon.match.string,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
t.assert(databaseExportDiagnostics.notCalled);
|
||||||
|
t.assert(
|
||||||
|
diagnosticsExport.calledOnceWith(
|
||||||
|
sinon.match(expectedFilePattern),
|
||||||
|
"/language:javascript",
|
||||||
|
config,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"tryUploadSarifIfRunFailed - uploads as artifact for risk assessments (databaseExportDiagnostics)",
|
||||||
|
async (t) => {
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
const { uploadArtifact, databaseExportDiagnostics, diagnosticsExport } =
|
||||||
|
await mockRiskAssessmentEnv(singleLanguageMatrix);
|
||||||
|
|
||||||
|
const dbLocation = "/some/path";
|
||||||
|
const config = createTestConfig({
|
||||||
|
analysisKinds: [AnalysisKind.RiskAssessment],
|
||||||
|
codeQLCmd: "codeql-for-testing",
|
||||||
|
languages: ["javascript"],
|
||||||
|
dbLocation: "/some/path",
|
||||||
|
});
|
||||||
|
const features = createFeatures([Feature.ExportDiagnosticsEnabled]);
|
||||||
|
|
||||||
|
const result = await initActionPostHelper.tryUploadSarifIfRunFailed(
|
||||||
|
config,
|
||||||
|
parseRepositoryNwo("github/codeql-action-fake-repository"),
|
||||||
|
features,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
|
|
||||||
|
const expectedName = debugArtifacts.sanitizeArtifactName(
|
||||||
|
`sarif-artifact-${debugArtifacts.getArtifactSuffix(singleLanguageMatrix)}`,
|
||||||
|
);
|
||||||
|
const expectedFilePattern = /codeql-failed-sarif-javascript\.csra\.sarif$/;
|
||||||
|
t.is(result.upload_failed_run_skipped_because, undefined);
|
||||||
|
t.is(result.upload_failed_run_error, undefined);
|
||||||
|
t.is(result.sarifID, expectedName);
|
||||||
|
t.assert(
|
||||||
|
uploadArtifact.calledOnceWith(
|
||||||
|
expectedName,
|
||||||
|
[sinon.match(expectedFilePattern)],
|
||||||
|
sinon.match.string,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
t.assert(diagnosticsExport.notCalled);
|
||||||
|
t.assert(
|
||||||
|
databaseExportDiagnostics.calledOnceWith(
|
||||||
|
dbLocation,
|
||||||
|
sinon.match(expectedFilePattern),
|
||||||
|
"/language:javascript",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const skippedUploadTest = test.macro({
|
||||||
|
exec: async (
|
||||||
|
t: ExecutionContext<unknown>,
|
||||||
|
config: Partial<configUtils.Config>,
|
||||||
|
expectedSkippedReason: string,
|
||||||
|
) => {
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
const { uploadArtifact, diagnosticsExport } =
|
||||||
|
await mockRiskAssessmentEnv(singleLanguageMatrix);
|
||||||
|
const features = createFeatures([]);
|
||||||
|
|
||||||
|
const result = await initActionPostHelper.tryUploadSarifIfRunFailed(
|
||||||
|
createTestConfig(config),
|
||||||
|
parseRepositoryNwo("github/codeql-action-fake-repository"),
|
||||||
|
features,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(result.upload_failed_run_skipped_because, expectedSkippedReason);
|
||||||
|
t.assert(uploadArtifact.notCalled);
|
||||||
|
t.assert(diagnosticsExport.notCalled);
|
||||||
|
},
|
||||||
|
|
||||||
|
title: (providedTitle: string = "") =>
|
||||||
|
`tryUploadSarifIfRunFailed - skips upload ${providedTitle}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"without CodeQL command",
|
||||||
|
skippedUploadTest,
|
||||||
|
// No codeQLCmd
|
||||||
|
{
|
||||||
|
analysisKinds: [AnalysisKind.RiskAssessment],
|
||||||
|
languages: ["javascript"],
|
||||||
|
} satisfies Partial<configUtils.Config>,
|
||||||
|
"CodeQL command not found",
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"if no language is configured",
|
||||||
|
skippedUploadTest,
|
||||||
|
// No explicit language configuration
|
||||||
|
{
|
||||||
|
analysisKinds: [AnalysisKind.RiskAssessment],
|
||||||
|
codeQLCmd: "codeql-for-testing",
|
||||||
|
} satisfies Partial<configUtils.Config>,
|
||||||
|
"Unexpectedly, the configuration is not for a single language.",
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"if multiple languages is configured",
|
||||||
|
skippedUploadTest,
|
||||||
|
// Multiple explicit languages configured
|
||||||
|
{
|
||||||
|
analysisKinds: [AnalysisKind.RiskAssessment],
|
||||||
|
codeQLCmd: "codeql-for-testing",
|
||||||
|
languages: ["javascript", "python"],
|
||||||
|
} satisfies Partial<configUtils.Config>,
|
||||||
|
"Unexpectedly, the configuration is not for a single language.",
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
import * as github from "@actions/github";
|
import * as github from "@actions/github";
|
||||||
|
|
||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import { CodeScanning } from "./analyses";
|
import { CodeScanning, RiskAssessment } from "./analyses";
|
||||||
import { getApiClient } from "./api-client";
|
import { getApiClient, getGitHubVersion } from "./api-client";
|
||||||
import { CodeQL, getCodeQL } from "./codeql";
|
import { CodeQL, getCodeQL } from "./codeql";
|
||||||
import { Config, isCodeScanningEnabled } from "./config-utils";
|
import {
|
||||||
|
Config,
|
||||||
|
isCodeScanningEnabled,
|
||||||
|
isRiskAssessmentEnabled,
|
||||||
|
} from "./config-utils";
|
||||||
|
import {
|
||||||
|
getArtifactSuffix,
|
||||||
|
getArtifactUploaderClient,
|
||||||
|
sanitizeArtifactName,
|
||||||
|
} from "./debug-artifacts";
|
||||||
import * as dependencyCaching from "./dependency-caching";
|
import * as dependencyCaching from "./dependency-caching";
|
||||||
import { EnvVar } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||||
@@ -23,10 +33,13 @@ import * as uploadLib from "./upload-lib";
|
|||||||
import {
|
import {
|
||||||
checkDiskUsage,
|
checkDiskUsage,
|
||||||
delay,
|
delay,
|
||||||
|
Failure,
|
||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
getRequiredEnvParam,
|
getRequiredEnvParam,
|
||||||
parseMatrixInput,
|
parseMatrixInput,
|
||||||
|
Result,
|
||||||
shouldSkipSarifUpload,
|
shouldSkipSarifUpload,
|
||||||
|
Success,
|
||||||
wrapError,
|
wrapError,
|
||||||
} from "./util";
|
} from "./util";
|
||||||
import {
|
import {
|
||||||
@@ -66,37 +79,96 @@ function createFailedUploadFailedSarifResult(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Records details about a SARIF file that contains information about a failed analysis. */
|
||||||
|
interface FailedSarifInfo {
|
||||||
|
sarifFile: string;
|
||||||
|
category: string | undefined;
|
||||||
|
checkoutPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload a failed SARIF file if we can verify that SARIF upload is enabled and determine the SARIF
|
* Tries to prepare a SARIF file that contains information about a failed analysis.
|
||||||
* category for the workflow.
|
*
|
||||||
|
* @returns Either information about the SARIF file that was produced, or a reason why it couldn't be produced.
|
||||||
*/
|
*/
|
||||||
async function maybeUploadFailedSarif(
|
async function prepareFailedSarif(
|
||||||
config: Config,
|
|
||||||
repositoryNwo: RepositoryNwo,
|
|
||||||
features: FeatureEnablement,
|
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
): Promise<UploadFailedSarifResult> {
|
features: FeatureEnablement,
|
||||||
|
config: Config,
|
||||||
|
): Promise<Result<FailedSarifInfo, UploadFailedSarifResult>> {
|
||||||
if (!config.codeQLCmd) {
|
if (!config.codeQLCmd) {
|
||||||
return { upload_failed_run_skipped_because: "CodeQL command not found" };
|
return new Failure({
|
||||||
|
upload_failed_run_skipped_because: "CodeQL command not found",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const workflow = await getWorkflow(logger);
|
|
||||||
const jobName = getRequiredEnvParam("GITHUB_JOB");
|
const jobName = getRequiredEnvParam("GITHUB_JOB");
|
||||||
const matrix = parseMatrixInput(actionsUtil.getRequiredInput("matrix"));
|
const matrix = parseMatrixInput(actionsUtil.getRequiredInput("matrix"));
|
||||||
const shouldUpload = getUploadInputOrThrow(workflow, jobName, matrix);
|
|
||||||
if (
|
|
||||||
!["always", "failure-only"].includes(
|
|
||||||
actionsUtil.getUploadValue(shouldUpload),
|
|
||||||
) ||
|
|
||||||
shouldSkipSarifUpload()
|
|
||||||
) {
|
|
||||||
return { upload_failed_run_skipped_because: "SARIF upload is disabled" };
|
|
||||||
}
|
|
||||||
const category = getCategoryInputOrThrow(workflow, jobName, matrix);
|
|
||||||
const checkoutPath = getCheckoutPathInputOrThrow(workflow, jobName, matrix);
|
|
||||||
const databasePath = config.dbLocation;
|
|
||||||
|
|
||||||
|
if (shouldSkipSarifUpload()) {
|
||||||
|
return new Failure({
|
||||||
|
upload_failed_run_skipped_because: "SARIF upload is disabled",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRiskAssessmentEnabled(config)) {
|
||||||
|
if (config.languages.length !== 1) {
|
||||||
|
return new Failure({
|
||||||
|
upload_failed_run_skipped_because:
|
||||||
|
"Unexpectedly, the configuration is not for a single language.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can make these assumptions for risk assessments.
|
||||||
|
const language = config.languages[0];
|
||||||
|
const category = `/language:${language}`;
|
||||||
|
const checkoutPath = ".";
|
||||||
|
const result = await generateFailedSarif(
|
||||||
|
features,
|
||||||
|
config,
|
||||||
|
category,
|
||||||
|
checkoutPath,
|
||||||
|
`../codeql-failed-sarif-${language}${RiskAssessment.sarifExtension}`,
|
||||||
|
);
|
||||||
|
return new Success(result);
|
||||||
|
} else {
|
||||||
|
const workflow = await getWorkflow(logger);
|
||||||
|
const shouldUpload = getUploadInputOrThrow(workflow, jobName, matrix);
|
||||||
|
if (
|
||||||
|
!["always", "failure-only"].includes(
|
||||||
|
actionsUtil.getUploadValue(shouldUpload),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return new Failure({
|
||||||
|
upload_failed_run_skipped_because: "SARIF upload is disabled",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const category = getCategoryInputOrThrow(workflow, jobName, matrix);
|
||||||
|
const checkoutPath = getCheckoutPathInputOrThrow(workflow, jobName, matrix);
|
||||||
|
|
||||||
|
const result = await generateFailedSarif(
|
||||||
|
features,
|
||||||
|
config,
|
||||||
|
category,
|
||||||
|
checkoutPath,
|
||||||
|
);
|
||||||
|
return new Success(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateFailedSarif(
|
||||||
|
features: FeatureEnablement,
|
||||||
|
config: Config,
|
||||||
|
category: string | undefined,
|
||||||
|
checkoutPath: string,
|
||||||
|
sarifFile?: string,
|
||||||
|
) {
|
||||||
|
const databasePath = config.dbLocation;
|
||||||
const codeql = await getCodeQL(config.codeQLCmd);
|
const codeql = await getCodeQL(config.codeQLCmd);
|
||||||
const sarifFile = "../codeql-failed-run.sarif";
|
|
||||||
|
// Set the filename for the SARIF file if not already set.
|
||||||
|
if (sarifFile === undefined) {
|
||||||
|
sarifFile = "../codeql-failed-run.sarif";
|
||||||
|
}
|
||||||
|
|
||||||
// If there is no database or the feature flag is off, we run 'export diagnostics'
|
// If there is no database or the feature flag is off, we run 'export diagnostics'
|
||||||
if (
|
if (
|
||||||
@@ -109,11 +181,32 @@ async function maybeUploadFailedSarif(
|
|||||||
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category);
|
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`Uploading failed SARIF file ${sarifFile}`);
|
return { sarifFile, category, checkoutPath };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
repositoryNwo: RepositoryNwo,
|
||||||
|
features: FeatureEnablement,
|
||||||
|
logger: Logger,
|
||||||
|
): Promise<UploadFailedSarifResult> {
|
||||||
|
const failedSarifResult = await prepareFailedSarif(logger, features, config);
|
||||||
|
|
||||||
|
if (failedSarifResult.isFailure()) {
|
||||||
|
return failedSarifResult.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const failedSarif = failedSarifResult.value;
|
||||||
|
|
||||||
|
logger.info(`Uploading failed SARIF file ${failedSarif.sarifFile}`);
|
||||||
const uploadResult = await uploadLib.uploadFiles(
|
const uploadResult = await uploadLib.uploadFiles(
|
||||||
sarifFile,
|
failedSarif.sarifFile,
|
||||||
checkoutPath,
|
failedSarif.checkoutPath,
|
||||||
category,
|
failedSarif.category,
|
||||||
features,
|
features,
|
||||||
logger,
|
logger,
|
||||||
CodeScanning,
|
CodeScanning,
|
||||||
@@ -129,31 +222,78 @@ async function maybeUploadFailedSarif(
|
|||||||
: {};
|
: {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Uploads a failed SARIF file as workflow artifact, if it can be generated. */
|
||||||
|
async function maybeUploadFailedSarifArtifact(
|
||||||
|
config: Config,
|
||||||
|
features: FeatureEnablement,
|
||||||
|
logger: Logger,
|
||||||
|
): Promise<UploadFailedSarifResult> {
|
||||||
|
const failedSarifResult = await prepareFailedSarif(logger, features, config);
|
||||||
|
|
||||||
|
if (failedSarifResult.isFailure()) {
|
||||||
|
return failedSarifResult.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const failedSarif = failedSarifResult.value;
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
`Uploading failed SARIF file ${failedSarif.sarifFile} as artifact`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const gitHubVersion = await getGitHubVersion();
|
||||||
|
const client = await getArtifactUploaderClient(logger, gitHubVersion.type);
|
||||||
|
|
||||||
|
const suffix = getArtifactSuffix(actionsUtil.getOptionalInput("matrix"));
|
||||||
|
const name = sanitizeArtifactName(`sarif-artifact-${suffix}`);
|
||||||
|
await client.uploadArtifact(
|
||||||
|
name,
|
||||||
|
[path.normalize(failedSarif.sarifFile)],
|
||||||
|
path.normalize(".."),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { sarifID: name };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to upload a SARIF file with information about the run, if it failed.
|
||||||
|
*
|
||||||
|
* @param config The CodeQL Action configuration.
|
||||||
|
* @param repositoryNwo The name and owner of the repository.
|
||||||
|
* @param features Information about enabled features.
|
||||||
|
* @param logger The logger to use.
|
||||||
|
* @returns The results of uploading the SARIF file for the failure.
|
||||||
|
*/
|
||||||
export async function tryUploadSarifIfRunFailed(
|
export async function tryUploadSarifIfRunFailed(
|
||||||
config: Config,
|
config: Config,
|
||||||
repositoryNwo: RepositoryNwo,
|
repositoryNwo: RepositoryNwo,
|
||||||
features: FeatureEnablement,
|
features: FeatureEnablement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
): Promise<UploadFailedSarifResult> {
|
): Promise<UploadFailedSarifResult> {
|
||||||
// Only upload the failed SARIF to Code scanning if Code scanning is enabled.
|
// There's nothing to do here if the analysis succeeded.
|
||||||
if (!isCodeScanningEnabled(config)) {
|
|
||||||
return {
|
|
||||||
upload_failed_run_skipped_because: "Code Scanning is not enabled.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true") {
|
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true") {
|
||||||
return {
|
return {
|
||||||
upload_failed_run_skipped_because:
|
upload_failed_run_skipped_because:
|
||||||
"Analyze Action completed successfully",
|
"Analyze Action completed successfully",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await maybeUploadFailedSarif(
|
// Only upload the failed SARIF to Code scanning if Code scanning is enabled.
|
||||||
config,
|
if (isCodeScanningEnabled(config)) {
|
||||||
repositoryNwo,
|
return await maybeUploadFailedSarif(
|
||||||
features,
|
config,
|
||||||
logger,
|
repositoryNwo,
|
||||||
);
|
features,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
|
} else if (isRiskAssessmentEnabled(config)) {
|
||||||
|
return await maybeUploadFailedSarifArtifact(config, features, logger);
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
upload_failed_run_skipped_because:
|
||||||
|
"No analysis kind that supports failed SARIF uploads is enabled.",
|
||||||
|
};
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`,
|
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`,
|
||||||
@@ -162,7 +302,21 @@ export async function tryUploadSarifIfRunFailed(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run(
|
/**
|
||||||
|
* Handles the majority of the `post-init` step logic which, depending on the configuration,
|
||||||
|
* mainly involves uploading a SARIF file with information about the failed run, debug
|
||||||
|
* artifacts, and performing clean-up operations.
|
||||||
|
*
|
||||||
|
* @param uploadAllAvailableDebugArtifacts A function with which to upload debug artifacts.
|
||||||
|
* @param printDebugLogs A function with which to print debug logs.
|
||||||
|
* @param codeql The CodeQL CLI instance.
|
||||||
|
* @param config The CodeQL Action configuration.
|
||||||
|
* @param repositoryNwo The name and owner of the repository.
|
||||||
|
* @param features Information about enabled features.
|
||||||
|
* @param logger The logger to use.
|
||||||
|
* @returns The results of uploading the SARIF file for the failure.
|
||||||
|
*/
|
||||||
|
export async function uploadFailureInfo(
|
||||||
uploadAllAvailableDebugArtifacts: (
|
uploadAllAvailableDebugArtifacts: (
|
||||||
codeql: CodeQL,
|
codeql: CodeQL,
|
||||||
config: Config,
|
config: Config,
|
||||||
@@ -175,7 +329,7 @@ export async function run(
|
|||||||
repositoryNwo: RepositoryNwo,
|
repositoryNwo: RepositoryNwo,
|
||||||
features: FeatureEnablement,
|
features: FeatureEnablement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
) {
|
): Promise<UploadFailedSarifResult> {
|
||||||
await recordOverlayStatus(codeql, config, features, logger);
|
await recordOverlayStatus(codeql, config, features, logger);
|
||||||
|
|
||||||
const uploadFailedSarifResult = await tryUploadSarifIfRunFailed(
|
const uploadFailedSarifResult = await tryUploadSarifIfRunFailed(
|
||||||
@@ -187,7 +341,7 @@ export async function run(
|
|||||||
|
|
||||||
if (uploadFailedSarifResult.upload_failed_run_skipped_because) {
|
if (uploadFailedSarifResult.upload_failed_run_skipped_because) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Won't upload a failed SARIF file for this CodeQL code scanning run because: " +
|
"Won't upload a failed SARIF file for this CodeQL analysis because: " +
|
||||||
`${uploadFailedSarifResult.upload_failed_run_skipped_because}.`,
|
`${uploadFailedSarifResult.upload_failed_run_skipped_because}.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ async function run(startedAt: Date) {
|
|||||||
} else {
|
} else {
|
||||||
const codeql = await getCodeQL(config.codeQLCmd);
|
const codeql = await getCodeQL(config.codeQLCmd);
|
||||||
|
|
||||||
uploadFailedSarifResult = await initActionPostHelper.run(
|
uploadFailedSarifResult = await initActionPostHelper.uploadFailureInfo(
|
||||||
debugArtifacts.tryUploadAllAvailableDebugArtifacts,
|
debugArtifacts.tryUploadAllAvailableDebugArtifacts,
|
||||||
printDebugLogs,
|
printDebugLogs,
|
||||||
codeql,
|
codeql,
|
||||||
|
|||||||
Reference in New Issue
Block a user