Merge pull request #1746 from github/update-v2.20.2-7dfbc0e0d
Merge main into releases/v2
This commit is contained in:
commit
004c5de30b
39 changed files with 549 additions and 209 deletions
|
|
@ -1,5 +1,9 @@
|
|||
# CodeQL Action Changelog
|
||||
|
||||
## 2.20.2 - 03 Jul 2023
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 2.20.1 - 21 Jun 2023
|
||||
|
||||
- Update default CodeQL bundle version to 2.13.4. [#1721](https://github.com/github/codeql-action/pull/1721)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
6
lib/analyze-action.js
generated
6
lib/analyze-action.js
generated
|
|
@ -44,7 +44,7 @@ const logging_1 = require("./logging");
|
|||
const repository_1 = require("./repository");
|
||||
const shared_environment_1 = require("./shared-environment");
|
||||
const trap_caching_1 = require("./trap-caching");
|
||||
const upload_lib = __importStar(require("./upload-lib"));
|
||||
const uploadLib = __importStar(require("./upload-lib"));
|
||||
const util = __importStar(require("./util"));
|
||||
const util_1 = require("./util");
|
||||
async function sendStatusReport(startedAt, config, stats, error, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, logger) {
|
||||
|
|
@ -177,7 +177,7 @@ async function run() {
|
|||
core.setOutput("db-locations", dbLocations);
|
||||
const uploadInput = actionsUtil.getOptionalInput("upload");
|
||||
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
|
||||
uploadResult = await upload_lib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger);
|
||||
uploadResult = await uploadLib.uploadFromActions(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), logger);
|
||||
core.setOutput("sarif-id", uploadResult.sarifID);
|
||||
}
|
||||
else {
|
||||
|
|
@ -196,7 +196,7 @@ async function run() {
|
|||
}
|
||||
else if (uploadResult !== undefined &&
|
||||
actionsUtil.getRequiredInput("wait-for-processing") === "true") {
|
||||
await upload_lib.waitForProcessing((0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY")), uploadResult.sarifID, (0, logging_1.getActionsLogger)());
|
||||
await uploadLib.waitForProcessing((0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY")), uploadResult.sarifID, (0, logging_1.getActionsLogger)());
|
||||
}
|
||||
// If we did not throw an error yet here, but we expect one, throw it.
|
||||
if (actionsUtil.getOptionalInput("expect-error") === "true") {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
51
lib/analyze.js
generated
51
lib/analyze.js
generated
|
|
@ -39,6 +39,7 @@ const configUtils = __importStar(require("./config-utils"));
|
|||
const feature_flags_1 = require("./feature-flags");
|
||||
const languages_1 = require("./languages");
|
||||
const tracer_config_1 = require("./tracer-config");
|
||||
const upload_lib_1 = require("./upload-lib");
|
||||
const util = __importStar(require("./util"));
|
||||
class CodeQLAnalysisError extends Error {
|
||||
constructor(queriesStatusReport, message) {
|
||||
|
|
@ -138,6 +139,9 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||
const queryFilters = validateQueryFilters(config.originalUserInput["query-filters"]);
|
||||
const packsWithVersion = config.packs[language] || [];
|
||||
try {
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
let startTimeInterpretResults;
|
||||
let endTimeInterpretResults;
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
// If we are using the code scanning config in the CLI,
|
||||
// much of the work needed to generate the query suites
|
||||
|
|
@ -152,11 +156,11 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||
statusReport[`analyze_builtin_queries_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeBuiltIn;
|
||||
logger.startGroup(`Interpreting results for ${language}`);
|
||||
const startTimeInterpretResults = new Date().getTime();
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
startTimeInterpretResults = new Date().getTime();
|
||||
const analysisSummary = await runInterpretResults(language, undefined, sarifFile, config.debugMode);
|
||||
endTimeInterpretResults = new Date().getTime();
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
endTimeInterpretResults - startTimeInterpretResults;
|
||||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
}
|
||||
|
|
@ -201,14 +205,29 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||
}
|
||||
logger.endGroup();
|
||||
logger.startGroup(`Interpreting results for ${language}`);
|
||||
const startTimeInterpretResults = new Date().getTime();
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
startTimeInterpretResults = new Date().getTime();
|
||||
const analysisSummary = await runInterpretResults(language, querySuitePaths, sarifFile, config.debugMode);
|
||||
endTimeInterpretResults = new Date().getTime();
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
endTimeInterpretResults - startTimeInterpretResults;
|
||||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
}
|
||||
if (await features.getValue(feature_flags_1.Feature.QaTelemetryEnabled)) {
|
||||
const perQueryAlertCounts = getPerQueryAlertCounts(sarifFile, logger);
|
||||
const perQueryAlertCountEventReport = {
|
||||
event: "codeql database interpret-results",
|
||||
started_at: startTimeInterpretResults.toString(),
|
||||
completed_at: endTimeInterpretResults.toString(),
|
||||
exit_status: "success",
|
||||
language,
|
||||
properties: perQueryAlertCounts,
|
||||
};
|
||||
if (statusReport["event_reports"] === undefined) {
|
||||
statusReport["event_reports"] = [];
|
||||
}
|
||||
statusReport["event_reports"].push(perQueryAlertCountEventReport);
|
||||
}
|
||||
await runPrintLinesOfCode(language);
|
||||
}
|
||||
catch (e) {
|
||||
|
|
@ -225,6 +244,26 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag,
|
|||
const databasePath = util.getCodeQLDatabasePath(config, language);
|
||||
return await codeql.databaseInterpretResults(databasePath, queries, sarifFile, addSnippetsFlag, threadsFlag, enableDebugLogging ? "-vv" : "-v", automationDetailsId, config, features, logger);
|
||||
}
|
||||
/** Get an object with all queries and their counts parsed from a SARIF file path. */
|
||||
function getPerQueryAlertCounts(sarifPath, log) {
|
||||
(0, upload_lib_1.validateSarifFileSchema)(sarifPath, log);
|
||||
const sarifObject = JSON.parse(fs.readFileSync(sarifPath, "utf8"));
|
||||
// We do not need to compute fingerprints because we are not sending data based off of locations.
|
||||
// Generate the query: alert count object
|
||||
const perQueryAlertCounts = {};
|
||||
// All rules (queries), from all results, from all runs
|
||||
for (const sarifRun of sarifObject.runs) {
|
||||
if (sarifRun.results) {
|
||||
for (const result of sarifRun.results) {
|
||||
const query = result.rule?.id || result.ruleId;
|
||||
if (query) {
|
||||
perQueryAlertCounts[query] = (perQueryAlertCounts[query] || 0) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return perQueryAlertCounts;
|
||||
}
|
||||
async function runPrintLinesOfCode(language) {
|
||||
const databasePath = util.getCodeQLDatabasePath(config, language);
|
||||
return await codeql.databasePrintBaseline(databasePath);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
37
lib/analyze.test.js
generated
37
lib/analyze.test.js
generated
|
|
@ -37,11 +37,16 @@ const feature_flags_1 = require("./feature-flags");
|
|||
const languages_1 = require("./languages");
|
||||
const logging_1 = require("./logging");
|
||||
const testing_utils_1 = require("./testing-utils");
|
||||
const uploadLib = __importStar(require("./upload-lib"));
|
||||
const util = __importStar(require("./util"));
|
||||
(0, testing_utils_1.setupTests)(ava_1.default);
|
||||
// Checks that the duration fields are populated for the correct language
|
||||
// and correct case of builtin or custom. Also checks the correct search
|
||||
// paths are set in the database analyze invocation.
|
||||
/** Checks that the duration fields are populated for the correct language
|
||||
* and correct case of builtin or custom. Also checks the correct search
|
||||
* paths are set in the database analyze invocation.
|
||||
*
|
||||
* Mocks the QA telemetry feature flag and checks the appropriate status report
|
||||
* fields.
|
||||
*/
|
||||
(0, ava_1.default)("status report fields and search path setting", async (t) => {
|
||||
let searchPathsUsed = [];
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
|
|
@ -53,6 +58,7 @@ const util = __importStar(require("./util"));
|
|||
[languages_1.Language.cpp]: ["a/b@1.0.0"],
|
||||
[languages_1.Language.java]: ["c/d@2.0.0"],
|
||||
};
|
||||
sinon.stub(uploadLib, "validateSarifFileSchema");
|
||||
for (const language of Object.values(languages_1.Language)) {
|
||||
(0, codeql_1.setCodeQL)({
|
||||
packDownload: async () => ({ packs: [] }),
|
||||
|
|
@ -130,18 +136,25 @@ const util = __importStar(require("./util"));
|
|||
builtin: ["foo.ql"],
|
||||
custom: [],
|
||||
};
|
||||
const builtinStatusReport = await (0, analyze_1.runQueries)(tmpDir, memoryFlag, addSnippetsFlag, threadsFlag, undefined, config, (0, logging_1.getRunnerLogger)(true), (0, testing_utils_1.createFeatures)([]));
|
||||
const builtinStatusReport = await (0, analyze_1.runQueries)(tmpDir, memoryFlag, addSnippetsFlag, threadsFlag, undefined, config, (0, logging_1.getRunnerLogger)(true), (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.QaTelemetryEnabled]));
|
||||
const hasPacks = language in packs;
|
||||
const statusReportKeys = Object.keys(builtinStatusReport).sort();
|
||||
if (hasPacks) {
|
||||
t.deepEqual(statusReportKeys.length, 3, statusReportKeys.toString());
|
||||
t.deepEqual(statusReportKeys.length, 4, statusReportKeys.toString());
|
||||
t.deepEqual(statusReportKeys[0], `analyze_builtin_queries_${language}_duration_ms`);
|
||||
t.deepEqual(statusReportKeys[1], `analyze_custom_queries_${language}_duration_ms`);
|
||||
t.deepEqual(statusReportKeys[2], `interpret_results_${language}_duration_ms`);
|
||||
t.deepEqual(statusReportKeys[2], "event_reports");
|
||||
t.deepEqual(statusReportKeys[3], `interpret_results_${language}_duration_ms`);
|
||||
}
|
||||
else {
|
||||
t.deepEqual(statusReportKeys[0], `analyze_builtin_queries_${language}_duration_ms`);
|
||||
t.deepEqual(statusReportKeys[1], `interpret_results_${language}_duration_ms`);
|
||||
t.deepEqual(statusReportKeys[1], "event_reports");
|
||||
t.deepEqual(statusReportKeys[2], `interpret_results_${language}_duration_ms`);
|
||||
}
|
||||
if (builtinStatusReport.event_reports) {
|
||||
for (const eventReport of builtinStatusReport.event_reports) {
|
||||
t.deepEqual(eventReport.event, "codeql database interpret-results");
|
||||
}
|
||||
}
|
||||
config.queries[language] = {
|
||||
builtin: [],
|
||||
|
|
@ -156,14 +169,20 @@ const util = __importStar(require("./util"));
|
|||
},
|
||||
],
|
||||
};
|
||||
const customStatusReport = await (0, analyze_1.runQueries)(tmpDir, memoryFlag, addSnippetsFlag, threadsFlag, undefined, config, (0, logging_1.getRunnerLogger)(true), (0, testing_utils_1.createFeatures)([]));
|
||||
t.deepEqual(Object.keys(customStatusReport).length, 2);
|
||||
const customStatusReport = await (0, analyze_1.runQueries)(tmpDir, memoryFlag, addSnippetsFlag, threadsFlag, undefined, config, (0, logging_1.getRunnerLogger)(true), (0, testing_utils_1.createFeatures)([feature_flags_1.Feature.QaTelemetryEnabled]));
|
||||
t.deepEqual(Object.keys(customStatusReport).length, 3);
|
||||
t.true(`analyze_custom_queries_${language}_duration_ms` in customStatusReport);
|
||||
const expectedSearchPathsUsed = hasPacks
|
||||
? [undefined, undefined, "/1", "/2", undefined]
|
||||
: [undefined, "/1", "/2"];
|
||||
t.deepEqual(searchPathsUsed, expectedSearchPathsUsed);
|
||||
t.true(`interpret_results_${language}_duration_ms` in customStatusReport);
|
||||
t.true("event_reports" in customStatusReport);
|
||||
if (customStatusReport.event_reports) {
|
||||
for (const eventReport of customStatusReport.event_reports) {
|
||||
t.deepEqual(eventReport.event, "codeql database interpret-results");
|
||||
}
|
||||
}
|
||||
}
|
||||
verifyQuerySuites(tmpDir);
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
6
lib/feature-flags.js
generated
6
lib/feature-flags.js
generated
|
|
@ -40,6 +40,7 @@ var Feature;
|
|||
Feature["ExportCodeScanningConfigEnabled"] = "export_code_scanning_config_enabled";
|
||||
Feature["ExportDiagnosticsEnabled"] = "export_diagnostics_enabled";
|
||||
Feature["MlPoweredQueriesEnabled"] = "ml_powered_queries_enabled";
|
||||
Feature["QaTelemetryEnabled"] = "qa_telemetry_enabled";
|
||||
Feature["UploadFailedSarifEnabled"] = "upload_failed_sarif_enabled";
|
||||
})(Feature = exports.Feature || (exports.Feature = {}));
|
||||
exports.featureConfig = {
|
||||
|
|
@ -68,6 +69,11 @@ exports.featureConfig = {
|
|||
minimumVersion: "2.7.5",
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.QaTelemetryEnabled]: {
|
||||
envVar: "CODEQL_ACTION_QA_TELEMETRY",
|
||||
minimumVersion: undefined,
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.UploadFailedSarifEnabled]: {
|
||||
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
|
||||
minimumVersion: "2.11.3",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
4
lib/upload-lib.js
generated
4
lib/upload-lib.js
generated
|
|
@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.pruneInvalidResults = exports.validateUniqueCategory = exports.waitForProcessing = exports.buildPayload = exports.validateSarifFileSchema = exports.countResultsInSarif = exports.uploadFromActions = exports.findSarifFilesInDir = exports.populateRunAutomationDetails = exports.combineSarifFiles = void 0;
|
||||
exports.pruneInvalidResults = exports.validateUniqueCategory = exports.waitForProcessing = exports.buildPayload = exports.validateSarifFileSchema = exports.uploadFromActions = exports.findSarifFilesInDir = exports.populateRunAutomationDetails = void 0;
|
||||
const fs = __importStar(require("fs"));
|
||||
const path = __importStar(require("path"));
|
||||
const process_1 = require("process");
|
||||
|
|
@ -62,7 +62,6 @@ function combineSarifFiles(sarifFiles) {
|
|||
}
|
||||
return combinedSarif;
|
||||
}
|
||||
exports.combineSarifFiles = combineSarifFiles;
|
||||
// Populates the run.automationDetails.id field using the analysis_key and environment
|
||||
// and return an updated sarif file contents.
|
||||
function populateRunAutomationDetails(sarif, category, analysis_key, environment) {
|
||||
|
|
@ -174,7 +173,6 @@ function countResultsInSarif(sarif) {
|
|||
}
|
||||
return numResults;
|
||||
}
|
||||
exports.countResultsInSarif = countResultsInSarif;
|
||||
// Validates that the given file path refers to a valid SARIF file.
|
||||
// Throws an error if the file is invalid.
|
||||
function validateSarifFileSchema(sarifFilePath, logger) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
node_modules/.package-lock.json
generated
vendored
8
node_modules/.package-lock.json
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "codeql",
|
||||
"version": "2.20.1",
|
||||
"version": "2.20.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
@ -5221,9 +5221,9 @@
|
|||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.3.8",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
||||
"version": "7.5.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
|
||||
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
|
|
|
|||
67
node_modules/semver/README.md
generated
vendored
67
node_modules/semver/README.md
generated
vendored
|
|
@ -110,6 +110,9 @@ Options:
|
|||
-l --loose
|
||||
Interpret versions and ranges loosely
|
||||
|
||||
-n <0|1>
|
||||
This is the base to be used for the prerelease identifier.
|
||||
|
||||
-p --include-prerelease
|
||||
Always include prerelease versions in range matching
|
||||
|
||||
|
|
@ -232,6 +235,35 @@ $ semver 1.2.4-beta.0 -i prerelease
|
|||
1.2.4-beta.1
|
||||
```
|
||||
|
||||
#### Prerelease Identifier Base
|
||||
|
||||
The method `.inc` takes an optional parameter 'identifierBase' string
|
||||
that will let you let your prerelease number as zero-based or one-based.
|
||||
Set to `false` to omit the prerelease number altogether.
|
||||
If you do not specify this parameter, it will default to zero-based.
|
||||
|
||||
```javascript
|
||||
semver.inc('1.2.3', 'prerelease', 'beta', '1')
|
||||
// '1.2.4-beta.1'
|
||||
```
|
||||
|
||||
```javascript
|
||||
semver.inc('1.2.3', 'prerelease', 'beta', false)
|
||||
// '1.2.4-beta'
|
||||
```
|
||||
|
||||
command-line example:
|
||||
|
||||
```bash
|
||||
$ semver 1.2.3 -i prerelease --preid beta -n 1
|
||||
1.2.4-beta.1
|
||||
```
|
||||
|
||||
```bash
|
||||
$ semver 1.2.3 -i prerelease --preid beta -n false
|
||||
1.2.4-beta
|
||||
```
|
||||
|
||||
### Advanced Range Syntax
|
||||
|
||||
Advanced range syntax desugars to primitive comparators in
|
||||
|
|
@ -513,6 +545,40 @@ ex.
|
|||
* `s.clean(' 2.1.5 ')`: `'2.1.5'`
|
||||
* `s.clean('~1.0.0')`: `null`
|
||||
|
||||
## Constants
|
||||
|
||||
As a convenience, helper constants are exported to provide information about what `node-semver` supports:
|
||||
|
||||
### `RELEASE_TYPES`
|
||||
|
||||
- major
|
||||
- premajor
|
||||
- minor
|
||||
- preminor
|
||||
- patch
|
||||
- prepatch
|
||||
- prerelease
|
||||
|
||||
```
|
||||
const semver = require('semver');
|
||||
|
||||
if (semver.RELEASE_TYPES.includes(arbitraryUserInput)) {
|
||||
console.log('This is a valid release type!');
|
||||
} else {
|
||||
console.warn('This is NOT a valid release type!');
|
||||
}
|
||||
```
|
||||
|
||||
### `SEMVER_SPEC_VERSION`
|
||||
|
||||
2.0.0
|
||||
|
||||
```
|
||||
const semver = require('semver');
|
||||
|
||||
console.log('We are currently using the semver specification version:', semver.SEMVER_SPEC_VERSION);
|
||||
```
|
||||
|
||||
## Exported Modules
|
||||
|
||||
<!--
|
||||
|
|
@ -566,3 +632,4 @@ The following modules are available:
|
|||
* `require('semver/ranges/outside')`
|
||||
* `require('semver/ranges/to-comparators')`
|
||||
* `require('semver/ranges/valid')`
|
||||
|
||||
|
|
|
|||
18
node_modules/semver/bin/semver.js
generated
vendored
18
node_modules/semver/bin/semver.js
generated
vendored
|
|
@ -23,7 +23,10 @@ let rtl = false
|
|||
|
||||
let identifier
|
||||
|
||||
let identifierBase
|
||||
|
||||
const semver = require('../')
|
||||
const parseOptions = require('../internal/parse-options')
|
||||
|
||||
let reverse = false
|
||||
|
||||
|
|
@ -71,6 +74,12 @@ const main = () => {
|
|||
case '-r': case '--range':
|
||||
range.push(argv.shift())
|
||||
break
|
||||
case '-n':
|
||||
identifierBase = argv.shift()
|
||||
if (identifierBase === 'false') {
|
||||
identifierBase = false
|
||||
}
|
||||
break
|
||||
case '-c': case '--coerce':
|
||||
coerce = true
|
||||
break
|
||||
|
|
@ -88,7 +97,7 @@ const main = () => {
|
|||
}
|
||||
}
|
||||
|
||||
options = { loose: loose, includePrerelease: includePrerelease, rtl: rtl }
|
||||
options = parseOptions({ loose, includePrerelease, rtl })
|
||||
|
||||
versions = versions.map((v) => {
|
||||
return coerce ? (semver.coerce(v, options) || { version: v }).version : v
|
||||
|
|
@ -127,7 +136,7 @@ const success = () => {
|
|||
}).map((v) => {
|
||||
return semver.clean(v, options)
|
||||
}).map((v) => {
|
||||
return inc ? semver.inc(v, inc, options, identifier) : v
|
||||
return inc ? semver.inc(v, inc, options, identifier, identifierBase) : v
|
||||
}).forEach((v, i, _) => {
|
||||
console.log(v)
|
||||
})
|
||||
|
|
@ -172,6 +181,11 @@ Options:
|
|||
--ltr
|
||||
Coerce version strings left to right (default)
|
||||
|
||||
-n <base>
|
||||
Base number to be used for the prerelease identifier.
|
||||
Can be either 0 or 1, or false to omit the number altogether.
|
||||
Defaults to 0.
|
||||
|
||||
Program exits successfully if any valid version satisfies
|
||||
all supplied ranges, and prints all satisfying versions.
|
||||
|
||||
|
|
|
|||
71
node_modules/semver/classes/comparator.js
generated
vendored
71
node_modules/semver/classes/comparator.js
generated
vendored
|
|
@ -16,6 +16,7 @@ class Comparator {
|
|||
}
|
||||
}
|
||||
|
||||
comp = comp.trim().split(/\s+/).join(' ')
|
||||
debug('comparator', comp, options)
|
||||
this.options = options
|
||||
this.loose = !!options.loose
|
||||
|
|
@ -78,13 +79,6 @@ class Comparator {
|
|||
throw new TypeError('a Comparator is required')
|
||||
}
|
||||
|
||||
if (!options || typeof options !== 'object') {
|
||||
options = {
|
||||
loose: !!options,
|
||||
includePrerelease: false,
|
||||
}
|
||||
}
|
||||
|
||||
if (this.operator === '') {
|
||||
if (this.value === '') {
|
||||
return true
|
||||
|
|
@ -97,39 +91,50 @@ class Comparator {
|
|||
return new Range(this.value, options).test(comp.semver)
|
||||
}
|
||||
|
||||
const sameDirectionIncreasing =
|
||||
(this.operator === '>=' || this.operator === '>') &&
|
||||
(comp.operator === '>=' || comp.operator === '>')
|
||||
const sameDirectionDecreasing =
|
||||
(this.operator === '<=' || this.operator === '<') &&
|
||||
(comp.operator === '<=' || comp.operator === '<')
|
||||
const sameSemVer = this.semver.version === comp.semver.version
|
||||
const differentDirectionsInclusive =
|
||||
(this.operator === '>=' || this.operator === '<=') &&
|
||||
(comp.operator === '>=' || comp.operator === '<=')
|
||||
const oppositeDirectionsLessThan =
|
||||
cmp(this.semver, '<', comp.semver, options) &&
|
||||
(this.operator === '>=' || this.operator === '>') &&
|
||||
(comp.operator === '<=' || comp.operator === '<')
|
||||
const oppositeDirectionsGreaterThan =
|
||||
cmp(this.semver, '>', comp.semver, options) &&
|
||||
(this.operator === '<=' || this.operator === '<') &&
|
||||
(comp.operator === '>=' || comp.operator === '>')
|
||||
options = parseOptions(options)
|
||||
|
||||
return (
|
||||
sameDirectionIncreasing ||
|
||||
sameDirectionDecreasing ||
|
||||
(sameSemVer && differentDirectionsInclusive) ||
|
||||
oppositeDirectionsLessThan ||
|
||||
oppositeDirectionsGreaterThan
|
||||
)
|
||||
// Special cases where nothing can possibly be lower
|
||||
if (options.includePrerelease &&
|
||||
(this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
|
||||
return false
|
||||
}
|
||||
if (!options.includePrerelease &&
|
||||
(this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Same direction increasing (> or >=)
|
||||
if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
|
||||
return true
|
||||
}
|
||||
// Same direction decreasing (< or <=)
|
||||
if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
|
||||
return true
|
||||
}
|
||||
// same SemVer and both sides are inclusive (<= or >=)
|
||||
if (
|
||||
(this.semver.version === comp.semver.version) &&
|
||||
this.operator.includes('=') && comp.operator.includes('=')) {
|
||||
return true
|
||||
}
|
||||
// opposite directions less than
|
||||
if (cmp(this.semver, '<', comp.semver, options) &&
|
||||
this.operator.startsWith('>') && comp.operator.startsWith('<')) {
|
||||
return true
|
||||
}
|
||||
// opposite directions greater than
|
||||
if (cmp(this.semver, '>', comp.semver, options) &&
|
||||
this.operator.startsWith('<') && comp.operator.startsWith('>')) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Comparator
|
||||
|
||||
const parseOptions = require('../internal/parse-options')
|
||||
const { re, t } = require('../internal/re')
|
||||
const { safeRe: re, t } = require('../internal/re')
|
||||
const cmp = require('../functions/cmp')
|
||||
const debug = require('../internal/debug')
|
||||
const SemVer = require('./semver')
|
||||
|
|
|
|||
72
node_modules/semver/classes/range.js
generated
vendored
72
node_modules/semver/classes/range.js
generated
vendored
|
|
@ -26,19 +26,26 @@ class Range {
|
|||
this.loose = !!options.loose
|
||||
this.includePrerelease = !!options.includePrerelease
|
||||
|
||||
// First, split based on boolean or ||
|
||||
// First reduce all whitespace as much as possible so we do not have to rely
|
||||
// on potentially slow regexes like \s*. This is then stored and used for
|
||||
// future error messages as well.
|
||||
this.raw = range
|
||||
this.set = range
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.join(' ')
|
||||
|
||||
// First, split on ||
|
||||
this.set = this.raw
|
||||
.split('||')
|
||||
// map the range to a 2d array of comparators
|
||||
.map(r => this.parseRange(r.trim()))
|
||||
.map(r => this.parseRange(r))
|
||||
// throw out any comparator lists that are empty
|
||||
// this generally means that it was not a valid range, which is allowed
|
||||
// in loose mode, but will still throw if the WHOLE range is invalid.
|
||||
.filter(c => c.length)
|
||||
|
||||
if (!this.set.length) {
|
||||
throw new TypeError(`Invalid SemVer Range: ${range}`)
|
||||
throw new TypeError(`Invalid SemVer Range: ${this.raw}`)
|
||||
}
|
||||
|
||||
// if we have any that are not the null set, throw out null sets.
|
||||
|
|
@ -64,9 +71,7 @@ class Range {
|
|||
|
||||
format () {
|
||||
this.range = this.set
|
||||
.map((comps) => {
|
||||
return comps.join(' ').trim()
|
||||
})
|
||||
.map((comps) => comps.join(' ').trim())
|
||||
.join('||')
|
||||
.trim()
|
||||
return this.range
|
||||
|
|
@ -77,12 +82,12 @@ class Range {
|
|||
}
|
||||
|
||||
parseRange (range) {
|
||||
range = range.trim()
|
||||
|
||||
// memoize range parsing for performance.
|
||||
// this is a very hot path, and fully deterministic.
|
||||
const memoOpts = Object.keys(this.options).join(',')
|
||||
const memoKey = `parseRange:${memoOpts}:${range}`
|
||||
const memoOpts =
|
||||
(this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) |
|
||||
(this.options.loose && FLAG_LOOSE)
|
||||
const memoKey = memoOpts + ':' + range
|
||||
const cached = cache.get(memoKey)
|
||||
if (cached) {
|
||||
return cached
|
||||
|
|
@ -103,9 +108,6 @@ class Range {
|
|||
// `^ 1.2.3` => `^1.2.3`
|
||||
range = range.replace(re[t.CARETTRIM], caretTrimReplace)
|
||||
|
||||
// normalize spaces
|
||||
range = range.split(/\s+/).join(' ')
|
||||
|
||||
// At this point, the range is completely trimmed and
|
||||
// ready to be split into comparators.
|
||||
|
||||
|
|
@ -190,6 +192,7 @@ class Range {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Range
|
||||
|
||||
const LRU = require('lru-cache')
|
||||
|
|
@ -200,12 +203,13 @@ const Comparator = require('./comparator')
|
|||
const debug = require('../internal/debug')
|
||||
const SemVer = require('./semver')
|
||||
const {
|
||||
re,
|
||||
safeRe: re,
|
||||
t,
|
||||
comparatorTrimReplace,
|
||||
tildeTrimReplace,
|
||||
caretTrimReplace,
|
||||
} = require('../internal/re')
|
||||
const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require('../internal/constants')
|
||||
|
||||
const isNullSet = c => c.value === '<0.0.0-0'
|
||||
const isAny = c => c.value === ''
|
||||
|
|
@ -253,10 +257,13 @@ const isX = id => !id || id.toLowerCase() === 'x' || id === '*'
|
|||
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
|
||||
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
|
||||
// ~0.0.1 --> >=0.0.1 <0.1.0-0
|
||||
const replaceTildes = (comp, options) =>
|
||||
comp.trim().split(/\s+/).map((c) => {
|
||||
return replaceTilde(c, options)
|
||||
}).join(' ')
|
||||
const replaceTildes = (comp, options) => {
|
||||
return comp
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.map((c) => replaceTilde(c, options))
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const replaceTilde = (comp, options) => {
|
||||
const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]
|
||||
|
|
@ -294,10 +301,13 @@ const replaceTilde = (comp, options) => {
|
|||
// ^1.2.0 --> >=1.2.0 <2.0.0-0
|
||||
// ^0.0.1 --> >=0.0.1 <0.0.2-0
|
||||
// ^0.1.0 --> >=0.1.0 <0.2.0-0
|
||||
const replaceCarets = (comp, options) =>
|
||||
comp.trim().split(/\s+/).map((c) => {
|
||||
return replaceCaret(c, options)
|
||||
}).join(' ')
|
||||
const replaceCarets = (comp, options) => {
|
||||
return comp
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.map((c) => replaceCaret(c, options))
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const replaceCaret = (comp, options) => {
|
||||
debug('caret', comp, options)
|
||||
|
|
@ -354,9 +364,10 @@ const replaceCaret = (comp, options) => {
|
|||
|
||||
const replaceXRanges = (comp, options) => {
|
||||
debug('replaceXRanges', comp, options)
|
||||
return comp.split(/\s+/).map((c) => {
|
||||
return replaceXRange(c, options)
|
||||
}).join(' ')
|
||||
return comp
|
||||
.split(/\s+/)
|
||||
.map((c) => replaceXRange(c, options))
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const replaceXRange = (comp, options) => {
|
||||
|
|
@ -439,12 +450,15 @@ const replaceXRange = (comp, options) => {
|
|||
const replaceStars = (comp, options) => {
|
||||
debug('replaceStars', comp, options)
|
||||
// Looseness is ignored here. star is always as loose as it gets!
|
||||
return comp.trim().replace(re[t.STAR], '')
|
||||
return comp
|
||||
.trim()
|
||||
.replace(re[t.STAR], '')
|
||||
}
|
||||
|
||||
const replaceGTE0 = (comp, options) => {
|
||||
debug('replaceGTE0', comp, options)
|
||||
return comp.trim()
|
||||
return comp
|
||||
.trim()
|
||||
.replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
|
||||
}
|
||||
|
||||
|
|
@ -482,7 +496,7 @@ const hyphenReplace = incPr => ($0,
|
|||
to = `<=${to}`
|
||||
}
|
||||
|
||||
return (`${from} ${to}`).trim()
|
||||
return `${from} ${to}`.trim()
|
||||
}
|
||||
|
||||
const testSet = (set, version, options) => {
|
||||
|
|
|
|||
49
node_modules/semver/classes/semver.js
generated
vendored
49
node_modules/semver/classes/semver.js
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
const debug = require('../internal/debug')
|
||||
const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
|
||||
const { re, t } = require('../internal/re')
|
||||
const { safeRe: re, t } = require('../internal/re')
|
||||
|
||||
const parseOptions = require('../internal/parse-options')
|
||||
const { compareIdentifiers } = require('../internal/identifiers')
|
||||
|
|
@ -16,7 +16,7 @@ class SemVer {
|
|||
version = version.version
|
||||
}
|
||||
} else if (typeof version !== 'string') {
|
||||
throw new TypeError(`Invalid Version: ${version}`)
|
||||
throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
|
||||
}
|
||||
|
||||
if (version.length > MAX_LENGTH) {
|
||||
|
|
@ -175,36 +175,36 @@ class SemVer {
|
|||
|
||||
// preminor will bump the version up to the next minor release, and immediately
|
||||
// down to pre-release. premajor and prepatch work the same way.
|
||||
inc (release, identifier) {
|
||||
inc (release, identifier, identifierBase) {
|
||||
switch (release) {
|
||||
case 'premajor':
|
||||
this.prerelease.length = 0
|
||||
this.patch = 0
|
||||
this.minor = 0
|
||||
this.major++
|
||||
this.inc('pre', identifier)
|
||||
this.inc('pre', identifier, identifierBase)
|
||||
break
|
||||
case 'preminor':
|
||||
this.prerelease.length = 0
|
||||
this.patch = 0
|
||||
this.minor++
|
||||
this.inc('pre', identifier)
|
||||
this.inc('pre', identifier, identifierBase)
|
||||
break
|
||||
case 'prepatch':
|
||||
// If this is already a prerelease, it will bump to the next version
|
||||
// drop any prereleases that might already exist, since they are not
|
||||
// relevant at this point.
|
||||
this.prerelease.length = 0
|
||||
this.inc('patch', identifier)
|
||||
this.inc('pre', identifier)
|
||||
this.inc('patch', identifier, identifierBase)
|
||||
this.inc('pre', identifier, identifierBase)
|
||||
break
|
||||
// If the input is a non-prerelease version, this acts the same as
|
||||
// prepatch.
|
||||
case 'prerelease':
|
||||
if (this.prerelease.length === 0) {
|
||||
this.inc('patch', identifier)
|
||||
this.inc('patch', identifier, identifierBase)
|
||||
}
|
||||
this.inc('pre', identifier)
|
||||
this.inc('pre', identifier, identifierBase)
|
||||
break
|
||||
|
||||
case 'major':
|
||||
|
|
@ -246,9 +246,15 @@ class SemVer {
|
|||
break
|
||||
// This probably shouldn't be used publicly.
|
||||
// 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
|
||||
case 'pre':
|
||||
case 'pre': {
|
||||
const base = Number(identifierBase) ? 1 : 0
|
||||
|
||||
if (!identifier && identifierBase === false) {
|
||||
throw new Error('invalid increment argument: identifier is empty')
|
||||
}
|
||||
|
||||
if (this.prerelease.length === 0) {
|
||||
this.prerelease = [0]
|
||||
this.prerelease = [base]
|
||||
} else {
|
||||
let i = this.prerelease.length
|
||||
while (--i >= 0) {
|
||||
|
|
@ -259,27 +265,36 @@ class SemVer {
|
|||
}
|
||||
if (i === -1) {
|
||||
// didn't increment anything
|
||||
this.prerelease.push(0)
|
||||
if (identifier === this.prerelease.join('.') && identifierBase === false) {
|
||||
throw new Error('invalid increment argument: identifier already exists')
|
||||
}
|
||||
this.prerelease.push(base)
|
||||
}
|
||||
}
|
||||
if (identifier) {
|
||||
// 1.2.0-beta.1 bumps to 1.2.0-beta.2,
|
||||
// 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
|
||||
let prerelease = [identifier, base]
|
||||
if (identifierBase === false) {
|
||||
prerelease = [identifier]
|
||||
}
|
||||
if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
|
||||
if (isNaN(this.prerelease[1])) {
|
||||
this.prerelease = [identifier, 0]
|
||||
this.prerelease = prerelease
|
||||
}
|
||||
} else {
|
||||
this.prerelease = [identifier, 0]
|
||||
this.prerelease = prerelease
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
}
|
||||
default:
|
||||
throw new Error(`invalid increment argument: ${release}`)
|
||||
}
|
||||
this.format()
|
||||
this.raw = this.version
|
||||
this.raw = this.format()
|
||||
if (this.build.length) {
|
||||
this.raw += `+${this.build.join('.')}`
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
node_modules/semver/functions/coerce.js
generated
vendored
2
node_modules/semver/functions/coerce.js
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
const SemVer = require('../classes/semver')
|
||||
const parse = require('./parse')
|
||||
const { re, t } = require('../internal/re')
|
||||
const { safeRe: re, t } = require('../internal/re')
|
||||
|
||||
const coerce = (version, options) => {
|
||||
if (version instanceof SemVer) {
|
||||
|
|
|
|||
76
node_modules/semver/functions/diff.js
generated
vendored
76
node_modules/semver/functions/diff.js
generated
vendored
|
|
@ -1,23 +1,65 @@
|
|||
const parse = require('./parse')
|
||||
const eq = require('./eq')
|
||||
const parse = require('./parse.js')
|
||||
|
||||
const diff = (version1, version2) => {
|
||||
if (eq(version1, version2)) {
|
||||
const v1 = parse(version1, null, true)
|
||||
const v2 = parse(version2, null, true)
|
||||
const comparison = v1.compare(v2)
|
||||
|
||||
if (comparison === 0) {
|
||||
return null
|
||||
} else {
|
||||
const v1 = parse(version1)
|
||||
const v2 = parse(version2)
|
||||
const hasPre = v1.prerelease.length || v2.prerelease.length
|
||||
const prefix = hasPre ? 'pre' : ''
|
||||
const defaultResult = hasPre ? 'prerelease' : ''
|
||||
for (const key in v1) {
|
||||
if (key === 'major' || key === 'minor' || key === 'patch') {
|
||||
if (v1[key] !== v2[key]) {
|
||||
return prefix + key
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultResult // may be undefined
|
||||
}
|
||||
|
||||
const v1Higher = comparison > 0
|
||||
const highVersion = v1Higher ? v1 : v2
|
||||
const lowVersion = v1Higher ? v2 : v1
|
||||
const highHasPre = !!highVersion.prerelease.length
|
||||
const lowHasPre = !!lowVersion.prerelease.length
|
||||
|
||||
if (lowHasPre && !highHasPre) {
|
||||
// Going from prerelease -> no prerelease requires some special casing
|
||||
|
||||
// If the low version has only a major, then it will always be a major
|
||||
// Some examples:
|
||||
// 1.0.0-1 -> 1.0.0
|
||||
// 1.0.0-1 -> 1.1.1
|
||||
// 1.0.0-1 -> 2.0.0
|
||||
if (!lowVersion.patch && !lowVersion.minor) {
|
||||
return 'major'
|
||||
}
|
||||
|
||||
// Otherwise it can be determined by checking the high version
|
||||
|
||||
if (highVersion.patch) {
|
||||
// anything higher than a patch bump would result in the wrong version
|
||||
return 'patch'
|
||||
}
|
||||
|
||||
if (highVersion.minor) {
|
||||
// anything higher than a minor bump would result in the wrong version
|
||||
return 'minor'
|
||||
}
|
||||
|
||||
// bumping major/minor/patch all have same result
|
||||
return 'major'
|
||||
}
|
||||
|
||||
// add the `pre` prefix if we are going to a prerelease version
|
||||
const prefix = highHasPre ? 'pre' : ''
|
||||
|
||||
if (v1.major !== v2.major) {
|
||||
return prefix + 'major'
|
||||
}
|
||||
|
||||
if (v1.minor !== v2.minor) {
|
||||
return prefix + 'minor'
|
||||
}
|
||||
|
||||
if (v1.patch !== v2.patch) {
|
||||
return prefix + 'patch'
|
||||
}
|
||||
|
||||
// high and low are preleases
|
||||
return 'prerelease'
|
||||
}
|
||||
|
||||
module.exports = diff
|
||||
|
|
|
|||
5
node_modules/semver/functions/inc.js
generated
vendored
5
node_modules/semver/functions/inc.js
generated
vendored
|
|
@ -1,7 +1,8 @@
|
|||
const SemVer = require('../classes/semver')
|
||||
|
||||
const inc = (version, release, options, identifier) => {
|
||||
const inc = (version, release, options, identifier, identifierBase) => {
|
||||
if (typeof (options) === 'string') {
|
||||
identifierBase = identifier
|
||||
identifier = options
|
||||
options = undefined
|
||||
}
|
||||
|
|
@ -10,7 +11,7 @@ const inc = (version, release, options, identifier) => {
|
|||
return new SemVer(
|
||||
version instanceof SemVer ? version.version : version,
|
||||
options
|
||||
).inc(release, identifier).version
|
||||
).inc(release, identifier, identifierBase).version
|
||||
} catch (er) {
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
27
node_modules/semver/functions/parse.js
generated
vendored
27
node_modules/semver/functions/parse.js
generated
vendored
|
|
@ -1,32 +1,15 @@
|
|||
const { MAX_LENGTH } = require('../internal/constants')
|
||||
const { re, t } = require('../internal/re')
|
||||
const SemVer = require('../classes/semver')
|
||||
|
||||
const parseOptions = require('../internal/parse-options')
|
||||
const parse = (version, options) => {
|
||||
options = parseOptions(options)
|
||||
|
||||
const parse = (version, options, throwErrors = false) => {
|
||||
if (version instanceof SemVer) {
|
||||
return version
|
||||
}
|
||||
|
||||
if (typeof version !== 'string') {
|
||||
return null
|
||||
}
|
||||
|
||||
if (version.length > MAX_LENGTH) {
|
||||
return null
|
||||
}
|
||||
|
||||
const r = options.loose ? re[t.LOOSE] : re[t.FULL]
|
||||
if (!r.test(version)) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
return new SemVer(version, options)
|
||||
} catch (er) {
|
||||
return null
|
||||
if (!throwErrors) {
|
||||
return null
|
||||
}
|
||||
throw er
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
1
node_modules/semver/index.js
generated
vendored
1
node_modules/semver/index.js
generated
vendored
|
|
@ -83,6 +83,7 @@ module.exports = {
|
|||
src: internalRe.src,
|
||||
tokens: internalRe.t,
|
||||
SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
|
||||
RELEASE_TYPES: constants.RELEASE_TYPES,
|
||||
compareIdentifiers: identifiers.compareIdentifiers,
|
||||
rcompareIdentifiers: identifiers.rcompareIdentifiers,
|
||||
}
|
||||
|
|
|
|||
17
node_modules/semver/internal/constants.js
generated
vendored
17
node_modules/semver/internal/constants.js
generated
vendored
|
|
@ -9,9 +9,22 @@ const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
|
|||
// Max safe segment length for coercion.
|
||||
const MAX_SAFE_COMPONENT_LENGTH = 16
|
||||
|
||||
const RELEASE_TYPES = [
|
||||
'major',
|
||||
'premajor',
|
||||
'minor',
|
||||
'preminor',
|
||||
'patch',
|
||||
'prepatch',
|
||||
'prerelease',
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
SEMVER_SPEC_VERSION,
|
||||
MAX_LENGTH,
|
||||
MAX_SAFE_INTEGER,
|
||||
MAX_SAFE_COMPONENT_LENGTH,
|
||||
MAX_SAFE_INTEGER,
|
||||
RELEASE_TYPES,
|
||||
SEMVER_SPEC_VERSION,
|
||||
FLAG_INCLUDE_PRERELEASE: 0b001,
|
||||
FLAG_LOOSE: 0b010,
|
||||
}
|
||||
|
|
|
|||
24
node_modules/semver/internal/parse-options.js
generated
vendored
24
node_modules/semver/internal/parse-options.js
generated
vendored
|
|
@ -1,11 +1,15 @@
|
|||
// parse out just the options we care about so we always get a consistent
|
||||
// obj with keys in a consistent order.
|
||||
const opts = ['includePrerelease', 'loose', 'rtl']
|
||||
const parseOptions = options =>
|
||||
!options ? {}
|
||||
: typeof options !== 'object' ? { loose: true }
|
||||
: opts.filter(k => options[k]).reduce((o, k) => {
|
||||
o[k] = true
|
||||
return o
|
||||
}, {})
|
||||
// parse out just the options we care about
|
||||
const looseOption = Object.freeze({ loose: true })
|
||||
const emptyOpts = Object.freeze({ })
|
||||
const parseOptions = options => {
|
||||
if (!options) {
|
||||
return emptyOpts
|
||||
}
|
||||
|
||||
if (typeof options !== 'object') {
|
||||
return looseOption
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
module.exports = parseOptions
|
||||
|
|
|
|||
11
node_modules/semver/internal/re.js
generated
vendored
11
node_modules/semver/internal/re.js
generated
vendored
|
|
@ -4,16 +4,27 @@ exports = module.exports = {}
|
|||
|
||||
// The actual regexps go on exports.re
|
||||
const re = exports.re = []
|
||||
const safeRe = exports.safeRe = []
|
||||
const src = exports.src = []
|
||||
const t = exports.t = {}
|
||||
let R = 0
|
||||
|
||||
const createToken = (name, value, isGlobal) => {
|
||||
// Replace all greedy whitespace to prevent regex dos issues. These regex are
|
||||
// used internally via the safeRe object since all inputs in this library get
|
||||
// normalized first to trim and collapse all extra whitespace. The original
|
||||
// regexes are exported for userland consumption and lower level usage. A
|
||||
// future breaking change could export the safer regex only with a note that
|
||||
// all input should have extra whitespace removed.
|
||||
const safe = value
|
||||
.split('\\s*').join('\\s{0,1}')
|
||||
.split('\\s+').join('\\s')
|
||||
const index = R++
|
||||
debug(name, index, value)
|
||||
t[name] = index
|
||||
src[index] = value
|
||||
re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
|
||||
safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
|
||||
}
|
||||
|
||||
// The following Regular Expressions can be used for tokenizing,
|
||||
|
|
|
|||
15
node_modules/semver/package.json
generated
vendored
15
node_modules/semver/package.json
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "semver",
|
||||
"version": "7.3.8",
|
||||
"version": "7.5.2",
|
||||
"description": "The semantic version parser used by npm.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
"template-oss-apply": "template-oss-apply --force"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@npmcli/eslint-config": "^3.0.1",
|
||||
"@npmcli/template-oss": "4.4.4",
|
||||
"@npmcli/eslint-config": "^4.0.0",
|
||||
"@npmcli/template-oss": "4.15.1",
|
||||
"tap": "^16.0.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
"range.bnf"
|
||||
],
|
||||
"tap": {
|
||||
"check-coverage": true,
|
||||
"timeout": 30,
|
||||
"coverage-map": "map.js",
|
||||
"nyc-arg": [
|
||||
"--exclude",
|
||||
|
|
@ -53,9 +53,8 @@
|
|||
"author": "GitHub Inc.",
|
||||
"templateOSS": {
|
||||
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
||||
"version": "4.4.4",
|
||||
"version": "4.15.1",
|
||||
"engines": ">=10",
|
||||
"content": "./scripts",
|
||||
"ciVersions": [
|
||||
"10.0.0",
|
||||
"10.x",
|
||||
|
|
@ -64,6 +63,7 @@
|
|||
"16.x",
|
||||
"18.x"
|
||||
],
|
||||
"npmSpec": "8",
|
||||
"distPaths": [
|
||||
"classes/",
|
||||
"functions/",
|
||||
|
|
@ -81,6 +81,7 @@
|
|||
"/index.js",
|
||||
"/preload.js",
|
||||
"/range.bnf"
|
||||
]
|
||||
],
|
||||
"publish": "true"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
node_modules/semver/ranges/intersects.js
generated
vendored
2
node_modules/semver/ranges/intersects.js
generated
vendored
|
|
@ -2,6 +2,6 @@ const Range = require('../classes/range')
|
|||
const intersects = (r1, r2, options) => {
|
||||
r1 = new Range(r1, options)
|
||||
r2 = new Range(r2, options)
|
||||
return r1.intersects(r2)
|
||||
return r1.intersects(r2, options)
|
||||
}
|
||||
module.exports = intersects
|
||||
|
|
|
|||
9
node_modules/semver/ranges/subset.js
generated
vendored
9
node_modules/semver/ranges/subset.js
generated
vendored
|
|
@ -68,6 +68,9 @@ const subset = (sub, dom, options = {}) => {
|
|||
return true
|
||||
}
|
||||
|
||||
const minimumVersionWithPreRelease = [new Comparator('>=0.0.0-0')]
|
||||
const minimumVersion = [new Comparator('>=0.0.0')]
|
||||
|
||||
const simpleSubset = (sub, dom, options) => {
|
||||
if (sub === dom) {
|
||||
return true
|
||||
|
|
@ -77,9 +80,9 @@ const simpleSubset = (sub, dom, options) => {
|
|||
if (dom.length === 1 && dom[0].semver === ANY) {
|
||||
return true
|
||||
} else if (options.includePrerelease) {
|
||||
sub = [new Comparator('>=0.0.0-0')]
|
||||
sub = minimumVersionWithPreRelease
|
||||
} else {
|
||||
sub = [new Comparator('>=0.0.0')]
|
||||
sub = minimumVersion
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +90,7 @@ const simpleSubset = (sub, dom, options) => {
|
|||
if (options.includePrerelease) {
|
||||
return true
|
||||
} else {
|
||||
dom = [new Comparator('>=0.0.0')]
|
||||
dom = minimumVersion
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
12
package-lock.json
generated
12
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "codeql",
|
||||
"version": "2.20.1",
|
||||
"version": "2.20.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "codeql",
|
||||
"version": "2.20.1",
|
||||
"version": "2.20.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^1.1.0",
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
"jsonschema": "1.4.1",
|
||||
"long": "^5.2.0",
|
||||
"path": "^0.12.7",
|
||||
"semver": "^7.3.2",
|
||||
"semver": "^7.5.2",
|
||||
"uuid": "^9.0.0",
|
||||
"zlib": "^1.0.5"
|
||||
},
|
||||
|
|
@ -5277,9 +5277,9 @@
|
|||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.3.8",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
||||
"version": "7.5.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
|
||||
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "codeql",
|
||||
"version": "2.20.1",
|
||||
"version": "2.20.2",
|
||||
"private": true,
|
||||
"description": "CodeQL action",
|
||||
"scripts": {
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
"jsonschema": "1.4.1",
|
||||
"long": "^5.2.0",
|
||||
"path": "^0.12.7",
|
||||
"semver": "^7.3.2",
|
||||
"semver": "^7.5.2",
|
||||
"uuid": "^9.0.0",
|
||||
"zlib": "^1.0.5"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -315,6 +315,25 @@ export type ActionStatus =
|
|||
| "failure"
|
||||
| "user-error";
|
||||
|
||||
// Any status report may include an array of EventReports associated with it.
|
||||
export interface EventReport {
|
||||
/** An enumerable description of the event. */
|
||||
event: string;
|
||||
/** Time this event started. */
|
||||
started_at: string;
|
||||
/** Time this event ended. */
|
||||
completed_at: string;
|
||||
/** eg: `success`, `failure`, `timeout`, etc. */
|
||||
exit_status?: string;
|
||||
/** If the event is language-specific. */
|
||||
language?: string;
|
||||
/**
|
||||
* A generic JSON blob of data related to this event.
|
||||
* Use Object.assign() to append additional fields to the object.
|
||||
*/
|
||||
properties?: object;
|
||||
}
|
||||
|
||||
export interface StatusReportBase {
|
||||
/**
|
||||
* UUID representing the job run that this status report belongs to. We
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ import {
|
|||
CODEQL_ACTION_DID_AUTOBUILD_GOLANG,
|
||||
} from "./shared-environment";
|
||||
import { getTotalCacheSize, uploadTrapCaches } from "./trap-caching";
|
||||
import * as upload_lib from "./upload-lib";
|
||||
import * as uploadLib from "./upload-lib";
|
||||
import { UploadResult } from "./upload-lib";
|
||||
import * as util from "./util";
|
||||
import { checkForTimeout, wrapError } from "./util";
|
||||
|
||||
interface AnalysisStatusReport
|
||||
extends upload_lib.UploadStatusReport,
|
||||
extends uploadLib.UploadStatusReport,
|
||||
QueriesStatusReport {}
|
||||
|
||||
interface FinishStatusReport
|
||||
|
|
@ -269,7 +269,7 @@ async function run() {
|
|||
core.setOutput("db-locations", dbLocations);
|
||||
const uploadInput = actionsUtil.getOptionalInput("upload");
|
||||
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
|
||||
uploadResult = await upload_lib.uploadFromActions(
|
||||
uploadResult = await uploadLib.uploadFromActions(
|
||||
outputDir,
|
||||
actionsUtil.getRequiredInput("checkout_path"),
|
||||
actionsUtil.getOptionalInput("category"),
|
||||
|
|
@ -296,7 +296,7 @@ async function run() {
|
|||
uploadResult !== undefined &&
|
||||
actionsUtil.getRequiredInput("wait-for-processing") === "true"
|
||||
) {
|
||||
await upload_lib.waitForProcessing(
|
||||
await uploadLib.waitForProcessing(
|
||||
parseRepositoryNwo(util.getRequiredEnvParam("GITHUB_REPOSITORY")),
|
||||
uploadResult.sarifID,
|
||||
getActionsLogger()
|
||||
|
|
|
|||
|
|
@ -18,13 +18,18 @@ import { Feature } from "./feature-flags";
|
|||
import { Language } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { setupTests, setupActionsVars, createFeatures } from "./testing-utils";
|
||||
import * as uploadLib from "./upload-lib";
|
||||
import * as util from "./util";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
// Checks that the duration fields are populated for the correct language
|
||||
// and correct case of builtin or custom. Also checks the correct search
|
||||
// paths are set in the database analyze invocation.
|
||||
/** Checks that the duration fields are populated for the correct language
|
||||
* and correct case of builtin or custom. Also checks the correct search
|
||||
* paths are set in the database analyze invocation.
|
||||
*
|
||||
* Mocks the QA telemetry feature flag and checks the appropriate status report
|
||||
* fields.
|
||||
*/
|
||||
test("status report fields and search path setting", async (t) => {
|
||||
let searchPathsUsed: Array<string | undefined> = [];
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
|
|
@ -38,6 +43,8 @@ test("status report fields and search path setting", async (t) => {
|
|||
[Language.java]: ["c/d@2.0.0"],
|
||||
};
|
||||
|
||||
sinon.stub(uploadLib, "validateSarifFileSchema");
|
||||
|
||||
for (const language of Object.values(Language)) {
|
||||
setCodeQL({
|
||||
packDownload: async () => ({ packs: [] }),
|
||||
|
|
@ -135,12 +142,12 @@ test("status report fields and search path setting", async (t) => {
|
|||
undefined,
|
||||
config,
|
||||
getRunnerLogger(true),
|
||||
createFeatures([])
|
||||
createFeatures([Feature.QaTelemetryEnabled])
|
||||
);
|
||||
const hasPacks = language in packs;
|
||||
const statusReportKeys = Object.keys(builtinStatusReport).sort();
|
||||
if (hasPacks) {
|
||||
t.deepEqual(statusReportKeys.length, 3, statusReportKeys.toString());
|
||||
t.deepEqual(statusReportKeys.length, 4, statusReportKeys.toString());
|
||||
t.deepEqual(
|
||||
statusReportKeys[0],
|
||||
`analyze_builtin_queries_${language}_duration_ms`
|
||||
|
|
@ -149,8 +156,9 @@ test("status report fields and search path setting", async (t) => {
|
|||
statusReportKeys[1],
|
||||
`analyze_custom_queries_${language}_duration_ms`
|
||||
);
|
||||
t.deepEqual(statusReportKeys[2], "event_reports");
|
||||
t.deepEqual(
|
||||
statusReportKeys[2],
|
||||
statusReportKeys[3],
|
||||
`interpret_results_${language}_duration_ms`
|
||||
);
|
||||
} else {
|
||||
|
|
@ -158,11 +166,17 @@ test("status report fields and search path setting", async (t) => {
|
|||
statusReportKeys[0],
|
||||
`analyze_builtin_queries_${language}_duration_ms`
|
||||
);
|
||||
t.deepEqual(statusReportKeys[1], "event_reports");
|
||||
t.deepEqual(
|
||||
statusReportKeys[1],
|
||||
statusReportKeys[2],
|
||||
`interpret_results_${language}_duration_ms`
|
||||
);
|
||||
}
|
||||
if (builtinStatusReport.event_reports) {
|
||||
for (const eventReport of builtinStatusReport.event_reports) {
|
||||
t.deepEqual(eventReport.event, "codeql database interpret-results");
|
||||
}
|
||||
}
|
||||
|
||||
config.queries[language] = {
|
||||
builtin: [],
|
||||
|
|
@ -185,9 +199,9 @@ test("status report fields and search path setting", async (t) => {
|
|||
undefined,
|
||||
config,
|
||||
getRunnerLogger(true),
|
||||
createFeatures([])
|
||||
createFeatures([Feature.QaTelemetryEnabled])
|
||||
);
|
||||
t.deepEqual(Object.keys(customStatusReport).length, 2);
|
||||
t.deepEqual(Object.keys(customStatusReport).length, 3);
|
||||
t.true(
|
||||
`analyze_custom_queries_${language}_duration_ms` in customStatusReport
|
||||
);
|
||||
|
|
@ -196,6 +210,12 @@ test("status report fields and search path setting", async (t) => {
|
|||
: [undefined, "/1", "/2"];
|
||||
t.deepEqual(searchPathsUsed, expectedSearchPathsUsed);
|
||||
t.true(`interpret_results_${language}_duration_ms` in customStatusReport);
|
||||
t.true("event_reports" in customStatusReport);
|
||||
if (customStatusReport.event_reports) {
|
||||
for (const eventReport of customStatusReport.event_reports) {
|
||||
t.deepEqual(eventReport.event, "codeql database interpret-results");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
verifyQuerySuites(tmpDir);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import * as toolrunner from "@actions/exec/lib/toolrunner";
|
|||
import del from "del";
|
||||
import * as yaml from "js-yaml";
|
||||
|
||||
import { DatabaseCreationTimings } from "./actions-util";
|
||||
import { DatabaseCreationTimings, EventReport } from "./actions-util";
|
||||
import * as analysisPaths from "./analysis-paths";
|
||||
import { CodeQL, getCodeQL } from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
|
|
@ -14,6 +14,7 @@ import { FeatureEnablement, Feature } from "./feature-flags";
|
|||
import { isScannedLanguage, Language } from "./languages";
|
||||
import { Logger } from "./logging";
|
||||
import { endTracingForCluster } from "./tracer-config";
|
||||
import { validateSarifFileSchema } from "./upload-lib";
|
||||
import * as util from "./util";
|
||||
|
||||
export class CodeQLAnalysisError extends Error {
|
||||
|
|
@ -78,6 +79,8 @@ export interface QueriesStatusReport {
|
|||
interpret_results_swift_duration_ms?: number;
|
||||
/** Name of language that errored during analysis (or undefined if no language failed). */
|
||||
analyze_failure_language?: string;
|
||||
/** Reports on discrete events associated with this status report. */
|
||||
event_reports?: EventReport[];
|
||||
}
|
||||
|
||||
async function setupPythonExtractor(
|
||||
|
|
@ -242,6 +245,9 @@ export async function runQueries(
|
|||
const packsWithVersion = config.packs[language] || [];
|
||||
|
||||
try {
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
let startTimeInterpretResults: number;
|
||||
let endTimeInterpretResults: number;
|
||||
if (await util.useCodeScanningConfigInCli(codeql, features)) {
|
||||
// If we are using the code scanning config in the CLI,
|
||||
// much of the work needed to generate the query suites
|
||||
|
|
@ -257,16 +263,16 @@ export async function runQueries(
|
|||
new Date().getTime() - startTimeBuiltIn;
|
||||
|
||||
logger.startGroup(`Interpreting results for ${language}`);
|
||||
const startTimeInterpretResults = new Date().getTime();
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
startTimeInterpretResults = new Date().getTime();
|
||||
const analysisSummary = await runInterpretResults(
|
||||
language,
|
||||
undefined,
|
||||
sarifFile,
|
||||
config.debugMode
|
||||
);
|
||||
endTimeInterpretResults = new Date().getTime();
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
endTimeInterpretResults - startTimeInterpretResults;
|
||||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
} else {
|
||||
|
|
@ -342,19 +348,37 @@ export async function runQueries(
|
|||
}
|
||||
logger.endGroup();
|
||||
logger.startGroup(`Interpreting results for ${language}`);
|
||||
const startTimeInterpretResults = new Date().getTime();
|
||||
const sarifFile = path.join(sarifFolder, `${language}.sarif`);
|
||||
startTimeInterpretResults = new Date().getTime();
|
||||
const analysisSummary = await runInterpretResults(
|
||||
language,
|
||||
querySuitePaths,
|
||||
sarifFile,
|
||||
config.debugMode
|
||||
);
|
||||
endTimeInterpretResults = new Date().getTime();
|
||||
statusReport[`interpret_results_${language}_duration_ms`] =
|
||||
new Date().getTime() - startTimeInterpretResults;
|
||||
endTimeInterpretResults - startTimeInterpretResults;
|
||||
logger.endGroup();
|
||||
logger.info(analysisSummary);
|
||||
}
|
||||
if (await features.getValue(Feature.QaTelemetryEnabled)) {
|
||||
const perQueryAlertCounts = getPerQueryAlertCounts(sarifFile, logger);
|
||||
|
||||
const perQueryAlertCountEventReport: EventReport = {
|
||||
event: "codeql database interpret-results",
|
||||
started_at: startTimeInterpretResults.toString(),
|
||||
completed_at: endTimeInterpretResults.toString(),
|
||||
exit_status: "success",
|
||||
language,
|
||||
properties: perQueryAlertCounts,
|
||||
};
|
||||
|
||||
if (statusReport["event_reports"] === undefined) {
|
||||
statusReport["event_reports"] = [];
|
||||
}
|
||||
statusReport["event_reports"].push(perQueryAlertCountEventReport);
|
||||
}
|
||||
|
||||
await runPrintLinesOfCode(language);
|
||||
} catch (e) {
|
||||
logger.info(String(e));
|
||||
|
|
@ -392,6 +416,34 @@ export async function runQueries(
|
|||
);
|
||||
}
|
||||
|
||||
/** Get an object with all queries and their counts parsed from a SARIF file path. */
|
||||
function getPerQueryAlertCounts(
|
||||
sarifPath: string,
|
||||
log: Logger
|
||||
): Record<string, number> {
|
||||
validateSarifFileSchema(sarifPath, log);
|
||||
const sarifObject = JSON.parse(
|
||||
fs.readFileSync(sarifPath, "utf8")
|
||||
) as util.SarifFile;
|
||||
// We do not need to compute fingerprints because we are not sending data based off of locations.
|
||||
|
||||
// Generate the query: alert count object
|
||||
const perQueryAlertCounts: Record<string, number> = {};
|
||||
|
||||
// All rules (queries), from all results, from all runs
|
||||
for (const sarifRun of sarifObject.runs) {
|
||||
if (sarifRun.results) {
|
||||
for (const result of sarifRun.results) {
|
||||
const query = result.rule?.id || result.ruleId;
|
||||
if (query) {
|
||||
perQueryAlertCounts[query] = (perQueryAlertCounts[query] || 0) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return perQueryAlertCounts;
|
||||
}
|
||||
|
||||
async function runPrintLinesOfCode(language: Language): Promise<string> {
|
||||
const databasePath = util.getCodeQLDatabasePath(config, language);
|
||||
return await codeql.databasePrintBaseline(databasePath);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ export enum Feature {
|
|||
ExportCodeScanningConfigEnabled = "export_code_scanning_config_enabled",
|
||||
ExportDiagnosticsEnabled = "export_diagnostics_enabled",
|
||||
MlPoweredQueriesEnabled = "ml_powered_queries_enabled",
|
||||
QaTelemetryEnabled = "qa_telemetry_enabled",
|
||||
UploadFailedSarifEnabled = "upload_failed_sarif_enabled",
|
||||
}
|
||||
|
||||
|
|
@ -76,6 +77,11 @@ export const featureConfig: Record<
|
|||
minimumVersion: "2.7.5",
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.QaTelemetryEnabled]: {
|
||||
envVar: "CODEQL_ACTION_QA_TELEMETRY",
|
||||
minimumVersion: undefined,
|
||||
defaultValue: false,
|
||||
},
|
||||
[Feature.UploadFailedSarifEnabled]: {
|
||||
envVar: "CODEQL_ACTION_UPLOAD_FAILED_SARIF",
|
||||
minimumVersion: "2.11.3",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import * as workflow from "./workflow";
|
|||
|
||||
// Takes a list of paths to sarif files and combines them together,
|
||||
// returning the contents of the combined sarif file.
|
||||
export function combineSarifFiles(sarifFiles: string[]): SarifFile {
|
||||
function combineSarifFiles(sarifFiles: string[]): SarifFile {
|
||||
const combinedSarif: SarifFile = {
|
||||
version: null,
|
||||
runs: [],
|
||||
|
|
@ -198,7 +198,7 @@ function getSarifFilePaths(sarifPath: string) {
|
|||
}
|
||||
|
||||
// Counts the number of results in the given SARIF file
|
||||
export function countResultsInSarif(sarif: string): number {
|
||||
function countResultsInSarif(sarif: string): number {
|
||||
let numResults = 0;
|
||||
let parsedSarif;
|
||||
try {
|
||||
|
|
@ -224,7 +224,7 @@ export function countResultsInSarif(sarif: string): number {
|
|||
// Validates that the given file path refers to a valid SARIF file.
|
||||
// Throws an error if the file is invalid.
|
||||
export function validateSarifFileSchema(sarifFilePath: string, logger: Logger) {
|
||||
const sarif = JSON.parse(fs.readFileSync(sarifFilePath, "utf8"));
|
||||
const sarif = JSON.parse(fs.readFileSync(sarifFilePath, "utf8")) as SarifFile;
|
||||
const schema = require("../src/sarif-schema-2.1.0.json") as jsonschema.Schema;
|
||||
|
||||
const result = new jsonschema.Validator().validate(sarif, schema);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ export interface SarifInvocation {
|
|||
|
||||
export interface SarifResult {
|
||||
ruleId?: string;
|
||||
rule?: {
|
||||
id?: string;
|
||||
};
|
||||
message?: {
|
||||
text?: string;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue