Skip to content
Permalink
Newer
Older
100644 224 lines (224 sloc) 10.4 KB
1
"use strict";
2
var __importStar = (this && this.__importStar) || function (mod) {
3
if (mod && mod.__esModule) return mod;
4
var result = {};
5
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
6
result["default"] = mod;
7
return result;
8
};
August 12, 2020 17:42
9
var __importDefault = (this && this.__importDefault) || function (mod) {
10
return (mod && mod.__esModule) ? mod : { "default": mod };
11
};
12
Object.defineProperty(exports, "__esModule", { value: true });
13
const fs = __importStar(require("fs"));
14
const path = __importStar(require("path"));
15
const zlib_1 = __importDefault(require("zlib"));
16
const core = __importStar(require("@actions/core"));
17
const file_url_1 = __importDefault(require("file-url"));
18
const jsonschema = __importStar(require("jsonschema"));
19
const semver = __importStar(require("semver"));
20
const actionsUtil = __importStar(require("./actions-util"));
21
const api = __importStar(require("./api-client"));
22
const fingerprints = __importStar(require("./fingerprints"));
23
const repository_1 = require("./repository");
August 12, 2020 17:42
24
const sharedEnv = __importStar(require("./shared-environment"));
25
const util = __importStar(require("./util"));
26
// Takes a list of paths to sarif files and combines them together,
27
// returning the contents of the combined sarif file.
28
function combineSarifFiles(sarifFiles) {
September 14, 2020 10:44
29
const combinedSarif = {
September 14, 2020 10:44
31
runs: [],
September 14, 2020 10:44
33
for (const sarifFile of sarifFiles) {
34
const sarifObject = JSON.parse(fs.readFileSync(sarifFile, "utf8"));
35
// Check SARIF version
36
if (combinedSarif.version === null) {
37
combinedSarif.version = sarifObject.version;
38
}
39
else if (combinedSarif.version !== sarifObject.version) {
40
throw new Error(`Different SARIF versions encountered: ${combinedSarif.version} and ${sarifObject.version}`);
41
}
42
combinedSarif.runs.push(...sarifObject.runs);
43
}
44
return JSON.stringify(combinedSarif);
45
}
46
exports.combineSarifFiles = combineSarifFiles;
May 1, 2020 10:39
47
// Upload the given payload.
May 1, 2020 11:19
48
// If the request fails then this will retry a small number of times.
49
async function uploadPayload(payload, repositoryNwo, apiDetails, mode, logger) {
September 14, 2020 10:44
50
logger.info("Uploading results");
May 8, 2020 16:06
51
// If in test mode we don't want to upload the results
September 14, 2020 10:44
52
const testMode = process.env["TEST_MODE"] === "true" || false;
May 8, 2020 16:06
53
if (testMode) {
54
return;
May 8, 2020 16:06
55
}
56
const client = api.getApiClient(apiDetails);
57
const reqURL = mode === "actions"
58
? "PUT /repos/:owner/:repo/code-scanning/analysis"
59
: "POST /repos/:owner/:repo/code-scanning/sarifs";
60
const response = await client.request(reqURL, {
61
owner: repositoryNwo.owner,
62
repo: repositoryNwo.repo,
63
data: payload,
64
});
65
logger.debug(`response status: ${response.status}`);
66
logger.info("Successfully uploaded results");
May 1, 2020 10:39
67
}
68
// Recursively walks a directory and returns all SARIF files it finds.
69
// Does not follow symlinks.
70
function findSarifFilesInDir(sarifPath) {
71
const sarifFiles = [];
72
const walkSarifFiles = (dir) => {
73
const entries = fs.readdirSync(dir, { withFileTypes: true });
74
for (const entry of entries) {
75
if (entry.isFile() && entry.name.endsWith(".sarif")) {
76
sarifFiles.push(path.resolve(dir, entry.name));
77
}
78
else if (entry.isDirectory()) {
79
walkSarifFiles(path.resolve(dir, entry.name));
80
}
81
}
82
};
83
walkSarifFiles(sarifPath);
84
return sarifFiles;
85
}
86
exports.findSarifFilesInDir = findSarifFilesInDir;
87
// Uploads a single sarif file or a directory of sarif files
88
// depending on what the path happens to refer to.
89
// Returns true iff the upload occurred and succeeded
90
async function uploadFromActions(sarifPath, gitHubVersion, apiDetails, logger) {
January 28, 2021 15:40
91
return await uploadFiles(getSarifFilePaths(sarifPath), repository_1.parseRepositoryNwo(actionsUtil.getRequiredEnvParam("GITHUB_REPOSITORY")), await actionsUtil.getCommitOid(), await actionsUtil.getRef(), await actionsUtil.getAnalysisKey(), actionsUtil.getRequiredEnvParam("GITHUB_WORKFLOW"), actionsUtil.getWorkflowRunID(), actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getRequiredInput("matrix"), gitHubVersion, apiDetails, "actions", logger);
92
}
93
exports.uploadFromActions = uploadFromActions;
94
// Uploads a single sarif file or a directory of sarif files
95
// depending on what the path happens to refer to.
96
// Returns true iff the upload occurred and succeeded
97
async function uploadFromRunner(sarifPath, repositoryNwo, commitOid, ref, checkoutPath, gitHubVersion, apiDetails, logger) {
98
return await uploadFiles(getSarifFilePaths(sarifPath), repositoryNwo, commitOid, ref, undefined, undefined, undefined, checkoutPath, undefined, gitHubVersion, apiDetails, "runner", logger);
99
}
100
exports.uploadFromRunner = uploadFromRunner;
101
function getSarifFilePaths(sarifPath) {
August 12, 2020 18:00
102
if (!fs.existsSync(sarifPath)) {
103
throw new Error(`Path does not exist: ${sarifPath}`);
104
}
105
let sarifFiles;
August 12, 2020 17:42
106
if (fs.lstatSync(sarifPath).isDirectory()) {
107
sarifFiles = findSarifFilesInDir(sarifPath);
108
if (sarifFiles.length === 0) {
September 14, 2020 10:44
109
throw new Error(`No SARIF files found to upload in "${sarifPath}".`);
110
}
113
sarifFiles = [sarifPath];
115
return sarifFiles;
May 15, 2020 17:25
117
// Counts the number of results in the given SARIF file
118
function countResultsInSarif(sarif) {
119
let numResults = 0;
120
for (const run of JSON.parse(sarif).runs) {
121
numResults += run.results.length;
122
}
123
return numResults;
124
}
125
exports.countResultsInSarif = countResultsInSarif;
126
// Validates that the given file path refers to a valid SARIF file.
127
// Throws an error if the file is invalid.
128
function validateSarifFileSchema(sarifFilePath, logger) {
September 14, 2020 10:44
129
const sarif = JSON.parse(fs.readFileSync(sarifFilePath, "utf8"));
130
const schema = require("../src/sarif_v2.1.0_schema.json");
131
const result = new jsonschema.Validator().validate(sarif, schema);
132
if (!result.valid) {
133
// Output the more verbose error messages in groups as these may be very large.
May 22, 2020 14:56
134
for (const error of result.errors) {
September 14, 2020 10:44
135
logger.startGroup(`Error details: ${error.stack}`);
136
logger.info(JSON.stringify(error, null, 2));
137
logger.endGroup();
May 22, 2020 14:56
138
}
139
// Set the main error message to the stacks of all the errors.
140
// This should be of a manageable size and may even give enough to fix the error.
September 14, 2020 10:44
141
const sarifErrors = result.errors.map((e) => `- ${e.stack}`);
142
throw new Error(`Unable to upload "${sarifFilePath}" as it is not valid SARIF:\n${sarifErrors.join("\n")}`);
143
}
144
}
145
exports.validateSarifFileSchema = validateSarifFileSchema;
146
// buildPayload constructs a map ready to be uploaded to the API from the given
147
// parameters, respecting the current mode and target GitHub instance version.
148
function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, workflowRunID, checkoutURI, environment, toolNames, gitHubVersion, mode) {
September 14, 2020 10:44
149
if (mode === "actions") {
150
const payloadObj = {
September 14, 2020 10:44
151
commit_oid: commitOid,
152
ref,
153
analysis_key: analysisKey,
154
analysis_name: analysisName,
155
sarif: zippedSarif,
September 14, 2020 10:44
156
workflow_run_id: workflowRunID,
157
checkout_uri: checkoutURI,
158
environment,
159
started_at: process.env[sharedEnv.CODEQL_WORKFLOW_STARTED_AT],
160
tool_names: toolNames,
161
base_ref: undefined,
162
base_sha: undefined,
163
};
164
// This behaviour can be made the default when support for GHES 3.0 is discontinued.
February 15, 2021 09:29
165
if (gitHubVersion.type !== util.GitHubVariant.GHES ||
166
semver.satisfies(gitHubVersion.version, `>=3.1`)) {
167
if (process.env.GITHUB_EVENT_NAME === "pull_request" &&
168
process.env.GITHUB_EVENT_PATH) {
169
const githubEvent = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"));
January 13, 2021 12:16
170
payloadObj.base_ref = `refs/heads/${githubEvent.pull_request.base.ref}`;
171
payloadObj.base_sha = githubEvent.pull_request.base.sha;
172
}
173
}
174
return payloadObj;
176
else {
177
return {
September 14, 2020 10:44
178
commit_sha: commitOid,
179
ref,
180
sarif: zippedSarif,
September 14, 2020 10:44
181
checkout_uri: checkoutURI,
182
tool_name: toolNames[0],
183
};
185
}
186
exports.buildPayload = buildPayload;
187
// Uploads the given set of sarif files.
188
// Returns true iff the upload occurred and succeeded
189
async function uploadFiles(sarifFiles, repositoryNwo, commitOid, ref, analysisKey, analysisName, workflowRunID, checkoutPath, environment, gitHubVersion, apiDetails, mode, logger) {
September 14, 2020 10:44
190
logger.info(`Uploading sarif files: ${JSON.stringify(sarifFiles)}`);
191
if (mode === "actions") {
August 24, 2020 14:21
192
// This check only works on actions as env vars don't persist between calls to the runner
August 12, 2020 17:42
193
const sentinelEnvVar = "CODEQL_UPLOAD_SARIF";
194
if (process.env[sentinelEnvVar]) {
195
throw new Error("Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job");
196
}
197
core.exportVariable(sentinelEnvVar, sentinelEnvVar);
198
}
199
// Validate that the files we were asked to upload are all valid SARIF files
200
for (const file of sarifFiles) {
201
validateSarifFileSchema(file, logger);
May 28, 2020 10:40
203
let sarifPayload = combineSarifFiles(sarifFiles);
August 25, 2020 16:19
204
sarifPayload = fingerprints.addFingerprints(sarifPayload, checkoutPath, logger);
205
const zippedSarif = zlib_1.default.gzipSync(sarifPayload).toString("base64");
September 14, 2020 10:44
206
const checkoutURI = file_url_1.default(checkoutPath);
207
const toolNames = util.getToolNames(sarifPayload);
208
const payload = buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, workflowRunID, checkoutURI, environment, toolNames, gitHubVersion, mode);
May 28, 2020 10:40
209
// Log some useful debug info about the info
210
const rawUploadSizeBytes = sarifPayload.length;
September 14, 2020 10:44
211
logger.debug(`Raw upload size: ${rawUploadSizeBytes} bytes`);
212
const zippedUploadSizeBytes = zippedSarif.length;
September 14, 2020 10:44
213
logger.debug(`Base64 zipped upload size: ${zippedUploadSizeBytes} bytes`);
214
const numResultInSarif = countResultsInSarif(sarifPayload);
September 14, 2020 10:44
215
logger.debug(`Number of results in upload: ${numResultInSarif}`);
216
// Make the upload
217
await uploadPayload(payload, repositoryNwo, apiDetails, mode, logger);
218
return {
219
raw_upload_size_bytes: rawUploadSizeBytes,
220
zipped_upload_size_bytes: zippedUploadSizeBytes,
221
num_results_in_sarif: numResultInSarif,
222
};
May 13, 2020 16:31
224
//# sourceMappingURL=upload-lib.js.map