Merge pull request #1684 from github/mbg/add-resolve-environment
This commit is contained in:
commit
0ac18158d1
15 changed files with 453 additions and 5 deletions
70
.github/workflows/__resolve-environment-action.yml
generated
vendored
Normal file
70
.github/workflows/__resolve-environment-action.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Warning: This file is generated automatically, and should not be modified.
|
||||||
|
# Instead, please modify the template in the pr-checks directory and run:
|
||||||
|
# (cd pr-checks; pip install ruamel.yaml && python3 sync.py)
|
||||||
|
# to regenerate this file.
|
||||||
|
|
||||||
|
name: PR Check - Resolve environment
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GO111MODULE: auto
|
||||||
|
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: 'true'
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- releases/v2
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
- ready_for_review
|
||||||
|
workflow_dispatch: {}
|
||||||
|
jobs:
|
||||||
|
resolve-environment-action:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.13.4
|
||||||
|
- os: macos-latest
|
||||||
|
version: stable-v2.13.4
|
||||||
|
- os: windows-latest
|
||||||
|
version: stable-v2.13.4
|
||||||
|
name: Resolve environment
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
timeout-minutes: 45
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Prepare test
|
||||||
|
id: prepare-test
|
||||||
|
uses: ./.github/actions/prepare-test
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.version }}
|
||||||
|
- name: Set environment variable for Swift enablement
|
||||||
|
if: >-
|
||||||
|
runner.os != 'Windows' && (
|
||||||
|
matrix.version == '20220908' ||
|
||||||
|
matrix.version == '20221211'
|
||||||
|
)
|
||||||
|
shell: bash
|
||||||
|
run: echo "CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT=true" >> $GITHUB_ENV
|
||||||
|
- uses: ./../action/init
|
||||||
|
with:
|
||||||
|
languages: go
|
||||||
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
|
|
||||||
|
- uses: ./../action/resolve-environment
|
||||||
|
id: resolve-environment
|
||||||
|
with:
|
||||||
|
language: go
|
||||||
|
|
||||||
|
- name: Fail if no Go configuration was returned
|
||||||
|
if: (!fromJSON(steps.resolve-environment.outputs.environment).configuration.go)
|
||||||
|
run: exit 1
|
||||||
|
env:
|
||||||
|
CODEQL_ACTION_TEST_MODE: true
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
No user facing changes.
|
- Experimental: add a new `resolve-environment` action which attempts to infer a configuration for the build environment that is required to build a given project. Do not use this in production as it is part of an internal experiment and subject to change at any time.
|
||||||
|
|
||||||
## 2.20.0 - 13 Jun 2023
|
## 2.20.0 - 13 Jun 2023
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
25
lib/codeql.js
generated
25
lib/codeql.js
generated
|
|
@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0;
|
exports.getExtraOptions = exports.getCodeQLForCmd = exports.getCodeQLForTesting = exports.getCachedCodeQL = exports.setCodeQL = exports.getCodeQL = exports.setupCodeQL = exports.CODEQL_VERSION_RESOLVE_ENVIRONMENT = exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = exports.CODEQL_VERSION_BETTER_RESOLVE_LANGUAGES = exports.CODEQL_VERSION_ML_POWERED_QUERIES_WINDOWS = exports.CODEQL_VERSION_GHES_PACK_DOWNLOAD = exports.CommandInvocationError = void 0;
|
||||||
const fs = __importStar(require("fs"));
|
const fs = __importStar(require("fs"));
|
||||||
const path = __importStar(require("path"));
|
const path = __importStar(require("path"));
|
||||||
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
const toolrunner = __importStar(require("@actions/exec/lib/toolrunner"));
|
||||||
|
|
@ -89,6 +89,10 @@ exports.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1";
|
||||||
* Versions 2.12.4+ of the CodeQL CLI support the `--qlconfig-file` flag in calls to `database init`.
|
* Versions 2.12.4+ of the CodeQL CLI support the `--qlconfig-file` flag in calls to `database init`.
|
||||||
*/
|
*/
|
||||||
exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
|
exports.CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
|
||||||
|
/**
|
||||||
|
* Versions 2.13.4+ of the CodeQL CLI support the `resolve build-environment` command.
|
||||||
|
*/
|
||||||
|
exports.CODEQL_VERSION_RESOLVE_ENVIRONMENT = "2.13.4";
|
||||||
/**
|
/**
|
||||||
* Set up CodeQL CLI access.
|
* Set up CodeQL CLI access.
|
||||||
*
|
*
|
||||||
|
|
@ -165,6 +169,7 @@ function setCodeQL(partialCodeql) {
|
||||||
resolveLanguages: resolveFunction(partialCodeql, "resolveLanguages"),
|
resolveLanguages: resolveFunction(partialCodeql, "resolveLanguages"),
|
||||||
betterResolveLanguages: resolveFunction(partialCodeql, "betterResolveLanguages"),
|
betterResolveLanguages: resolveFunction(partialCodeql, "betterResolveLanguages"),
|
||||||
resolveQueries: resolveFunction(partialCodeql, "resolveQueries"),
|
resolveQueries: resolveFunction(partialCodeql, "resolveQueries"),
|
||||||
|
resolveBuildEnvironment: resolveFunction(partialCodeql, "resolveBuildEnvironment"),
|
||||||
packDownload: resolveFunction(partialCodeql, "packDownload"),
|
packDownload: resolveFunction(partialCodeql, "packDownload"),
|
||||||
databaseCleanup: resolveFunction(partialCodeql, "databaseCleanup"),
|
databaseCleanup: resolveFunction(partialCodeql, "databaseCleanup"),
|
||||||
databaseBundle: resolveFunction(partialCodeql, "databaseBundle"),
|
databaseBundle: resolveFunction(partialCodeql, "databaseBundle"),
|
||||||
|
|
@ -374,6 +379,24 @@ async function getCodeQLForCmd(cmd, checkVersion) {
|
||||||
throw new Error(`Unexpected output from codeql resolve queries: ${e}`);
|
throw new Error(`Unexpected output from codeql resolve queries: ${e}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async resolveBuildEnvironment(workingDir, language) {
|
||||||
|
const codeqlArgs = [
|
||||||
|
"resolve",
|
||||||
|
"build-environment",
|
||||||
|
`--language=${language}`,
|
||||||
|
...getExtraOptionsFromEnv(["resolve", "build-environment"]),
|
||||||
|
];
|
||||||
|
if (workingDir !== undefined) {
|
||||||
|
codeqlArgs.push("--working-dir", workingDir);
|
||||||
|
}
|
||||||
|
const output = await runTool(cmd, codeqlArgs);
|
||||||
|
try {
|
||||||
|
return JSON.parse(output);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new Error(`Unexpected output from codeql resolve build-environment: ${e} in\n${output}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
async databaseRunQueries(databasePath, extraSearchPath, querySuitePath, flags, optimizeForLastQueryRun) {
|
async databaseRunQueries(databasePath, extraSearchPath, querySuitePath, flags, optimizeForLastQueryRun) {
|
||||||
const codeqlArgs = [
|
const codeqlArgs = [
|
||||||
"database",
|
"database",
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
82
lib/resolve-environment-action.js
generated
Normal file
82
lib/resolve-environment-action.js
generated
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const core = __importStar(require("@actions/core"));
|
||||||
|
const actions_util_1 = require("./actions-util");
|
||||||
|
const api_client_1 = require("./api-client");
|
||||||
|
const codeql_1 = require("./codeql");
|
||||||
|
const configUtils = __importStar(require("./config-utils"));
|
||||||
|
const languages_1 = require("./languages");
|
||||||
|
const logging_1 = require("./logging");
|
||||||
|
const resolve_environment_1 = require("./resolve-environment");
|
||||||
|
const util_1 = require("./util");
|
||||||
|
const ACTION_NAME = "resolve-environment";
|
||||||
|
const ENVIRONMENT_OUTPUT_NAME = "environment";
|
||||||
|
async function run() {
|
||||||
|
const startedAt = new Date();
|
||||||
|
const logger = (0, logging_1.getActionsLogger)();
|
||||||
|
const language = (0, languages_1.resolveAlias)((0, actions_util_1.getRequiredInput)("language"));
|
||||||
|
try {
|
||||||
|
if (!(await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)(ACTION_NAME, "starting", startedAt)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
|
||||||
|
(0, util_1.checkGitHubVersionInRange)(gitHubVersion, logger);
|
||||||
|
const config = await configUtils.getConfig((0, actions_util_1.getTemporaryDirectory)(), logger);
|
||||||
|
if (config === undefined) {
|
||||||
|
throw new Error("Config file could not be found at expected location. Has the 'init' action been called?");
|
||||||
|
}
|
||||||
|
const workingDirectory = (0, actions_util_1.getOptionalInput)("working-directory");
|
||||||
|
const result = await (0, resolve_environment_1.runResolveBuildEnvironment)(config.codeQLCmd, logger, workingDirectory, language);
|
||||||
|
core.setOutput(ENVIRONMENT_OUTPUT_NAME, result);
|
||||||
|
}
|
||||||
|
catch (unwrappedError) {
|
||||||
|
const error = (0, util_1.wrapError)(unwrappedError);
|
||||||
|
if (error instanceof codeql_1.CommandInvocationError) {
|
||||||
|
// If the CLI failed to run successfully for whatever reason,
|
||||||
|
// we just return an empty JSON object and proceed with the workflow.
|
||||||
|
core.setOutput(ENVIRONMENT_OUTPUT_NAME, {});
|
||||||
|
logger.warning(`Failed to resolve a build environment suitable for automatically building your code. ${error.message}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// For any other error types, something has more seriously gone wrong and we fail.
|
||||||
|
core.setFailed(`Failed to resolve a build environment suitable for automatically building your code. ${error.message}`);
|
||||||
|
await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)(ACTION_NAME, (0, actions_util_1.getActionsStatus)(error), startedAt, error.message, error.stack));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)(ACTION_NAME, "success", startedAt));
|
||||||
|
}
|
||||||
|
async function runWrapper() {
|
||||||
|
try {
|
||||||
|
await run();
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
core.setFailed(`${ACTION_NAME} action failed: ${(0, util_1.wrapError)(error).message}`);
|
||||||
|
}
|
||||||
|
await (0, util_1.checkForTimeout)();
|
||||||
|
}
|
||||||
|
void runWrapper();
|
||||||
|
//# sourceMappingURL=resolve-environment-action.js.map
|
||||||
1
lib/resolve-environment-action.js.map
Normal file
1
lib/resolve-environment-action.js.map
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"resolve-environment-action.js","sourceRoot":"","sources":["../src/resolve-environment-action.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAsC;AAEtC,iDAOwB;AACxB,6CAAgD;AAChD,qCAAkD;AAClD,4DAA8C;AAC9C,2CAAqD;AACrD,uCAA6C;AAC7C,+DAAmE;AACnE,iCAA+E;AAE/E,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAC1C,MAAM,uBAAuB,GAAG,aAAa,CAAC;AAE9C,KAAK,UAAU,GAAG;IAChB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,MAAM,QAAQ,GAAa,IAAA,wBAAY,EAAC,IAAA,+BAAgB,EAAC,UAAU,CAAC,CAAC,CAAC;IAEtE,IAAI;QACF,IACE,CAAC,CAAC,MAAM,IAAA,+BAAgB,EACtB,MAAM,IAAA,qCAAsB,EAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC,CACjE,CAAC,EACF;YACA,OAAO;SACR;QAED,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAA,oCAAqB,GAAE,EAAE,MAAM,CAAC,CAAC;QAC5E,IAAI,MAAM,KAAK,SAAS,EAAE;YACxB,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;SACH;QAED,MAAM,gBAAgB,GAAG,IAAA,+BAAgB,EAAC,mBAAmB,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,IAAA,gDAA0B,EAC7C,MAAM,CAAC,SAAS,EAChB,MAAM,EACN,gBAAgB,EAChB,QAAQ,CACT,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;KACjD;IAAC,OAAO,cAAc,EAAE;QACvB,MAAM,KAAK,GAAG,IAAA,gBAAS,EAAC,cAAc,CAAC,CAAC;QAExC,IAAI,KAAK,YAAY,+BAAsB,EAAE;YAC3C,6DAA6D;YAC7D,qEAAqE;YACrE,IAAI,CAAC,SAAS,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,OAAO,CACZ,wFAAwF,KAAK,CAAC,OAAO,EAAE,CACxG,CAAC;SACH;aAAM;YACL,kFAAkF;YAClF,IAAI,CAAC,SAAS,CACZ,wFAAwF,KAAK,CAAC,OAAO,EAAE,CACxG,CAAC;YAEF,MAAM,IAAA,+BAAgB,EACpB,MAAM,IAAA,qCAAsB,EAC1B,WAAW,EACX,IAAA,+BAAgB,EAAC,KAAK,CAAC,EACvB,SAAS,EACT,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,KAAK,CACZ,CACF,CAAC;SACH;QAED,OAAO;KACR;IAED,MAAM,IAAA,+BAAgB,EACpB,MAAM,IAAA,qCAAsB,EAAC,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,CAChE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,IAAI;QACF,MAAM,GAAG,EAAE,CAAC;KACb;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,SAAS,CAAC,GAAG,WAAW,mBAAmB,IAAA,gBAAS,EAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;KAC7E;IACD,MAAM,IAAA,sBAAe,GAAE,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
|
||||||
49
lib/resolve-environment.js
generated
Normal file
49
lib/resolve-environment.js
generated
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.runResolveBuildEnvironment = void 0;
|
||||||
|
const codeql_1 = require("./codeql");
|
||||||
|
const util = __importStar(require("./util"));
|
||||||
|
async function runResolveBuildEnvironment(cmd, logger, workingDir, language) {
|
||||||
|
logger.startGroup(`Attempting to resolve build environment for ${language}`);
|
||||||
|
const codeql = await (0, codeql_1.getCodeQL)(cmd);
|
||||||
|
let result = {};
|
||||||
|
// If the CodeQL version in use does not support the `resolve build-environment`
|
||||||
|
// command, just return an empty configuration. Otherwise invoke the CLI.
|
||||||
|
if (!(await util.codeQlVersionAbove(codeql, codeql_1.CODEQL_VERSION_RESOLVE_ENVIRONMENT))) {
|
||||||
|
logger.warning("Unsupported CodeQL CLI version for `resolve build-environment` command, " +
|
||||||
|
"returning an empty configuration.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (workingDir !== undefined) {
|
||||||
|
logger.info(`Using ${workingDir} as the working directory.`);
|
||||||
|
}
|
||||||
|
result = await codeql.resolveBuildEnvironment(workingDir, language);
|
||||||
|
}
|
||||||
|
logger.endGroup();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
exports.runResolveBuildEnvironment = runResolveBuildEnvironment;
|
||||||
|
//# sourceMappingURL=resolve-environment.js.map
|
||||||
1
lib/resolve-environment.js.map
Normal file
1
lib/resolve-environment.js.map
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"resolve-environment.js","sourceRoot":"","sources":["../src/resolve-environment.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyE;AAGzE,6CAA+B;AAExB,KAAK,UAAU,0BAA0B,CAC9C,GAAW,EACX,MAAc,EACd,UAA8B,EAC9B,QAAkB;IAElB,MAAM,CAAC,UAAU,CAAC,+CAA+C,QAAQ,EAAE,CAAC,CAAC;IAE7E,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAS,EAAC,GAAG,CAAC,CAAC;IACpC,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,gFAAgF;IAChF,yEAAyE;IACzE,IACE,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,2CAAkC,CAAC,CAAC,EAC5E;QACA,MAAM,CAAC,OAAO,CACZ,0EAA0E;YACxE,mCAAmC,CACtC,CAAC;KACH;SAAM;QACL,IAAI,UAAU,KAAK,SAAS,EAAE;YAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,UAAU,4BAA4B,CAAC,CAAC;SAC9D;QAED,MAAM,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;KACrE;IAED,MAAM,CAAC,QAAQ,EAAE,CAAC;IAClB,OAAO,MAAM,CAAC;AAChB,CAAC;AA9BD,gEA8BC"}
|
||||||
17
pr-checks/checks/resolve-environment-action.yml
Normal file
17
pr-checks/checks/resolve-environment-action.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: "Resolve environment"
|
||||||
|
description: "Tests that the resolve-environment action works for Go"
|
||||||
|
versions: ["stable-v2.13.4"]
|
||||||
|
steps:
|
||||||
|
- uses: ./../action/init
|
||||||
|
with:
|
||||||
|
languages: go
|
||||||
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
|
|
||||||
|
- uses: ./../action/resolve-environment
|
||||||
|
id: resolve-environment
|
||||||
|
with:
|
||||||
|
language: go
|
||||||
|
|
||||||
|
- name: "Fail if no Go configuration was returned"
|
||||||
|
if: (!fromJSON(steps.resolve-environment.outputs.environment).configuration.go)
|
||||||
|
run: exit 1
|
||||||
23
resolve-environment/action.yml
Normal file
23
resolve-environment/action.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
name: 'CodeQL: Resolve Build Environment'
|
||||||
|
description: '[Experimental] Attempt to infer a build environment suitable for automatic builds'
|
||||||
|
author: 'GitHub'
|
||||||
|
inputs:
|
||||||
|
token:
|
||||||
|
default: ${{ github.token }}
|
||||||
|
matrix:
|
||||||
|
default: ${{ toJson(matrix) }}
|
||||||
|
language:
|
||||||
|
description: The language to infer the build environment configuration for.
|
||||||
|
required: true
|
||||||
|
working-directory:
|
||||||
|
description: >-
|
||||||
|
Resolve the build environment based on the files located at the specified
|
||||||
|
path (relative to $GITHUB_WORKSPACE). If this input is not set, then the
|
||||||
|
build environment is resolved based on the files in $GITHUB_WORKSPACE.
|
||||||
|
required: false
|
||||||
|
outputs:
|
||||||
|
environment:
|
||||||
|
description: The inferred build environment configuration.
|
||||||
|
runs:
|
||||||
|
using: 'node16'
|
||||||
|
main: '../lib/resolve-environment-action.js'
|
||||||
|
|
@ -306,7 +306,8 @@ type ActionName =
|
||||||
| "autobuild"
|
| "autobuild"
|
||||||
| "finish"
|
| "finish"
|
||||||
| "upload-sarif"
|
| "upload-sarif"
|
||||||
| "init-post";
|
| "init-post"
|
||||||
|
| "resolve-environment";
|
||||||
export type ActionStatus =
|
export type ActionStatus =
|
||||||
| "starting"
|
| "starting"
|
||||||
| "aborted"
|
| "aborted"
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,13 @@ export interface CodeQL {
|
||||||
queries: string[],
|
queries: string[],
|
||||||
extraSearchPath: string | undefined
|
extraSearchPath: string | undefined
|
||||||
): Promise<ResolveQueriesOutput>;
|
): Promise<ResolveQueriesOutput>;
|
||||||
|
/**
|
||||||
|
* Run 'codeql resolve build-environment'
|
||||||
|
*/
|
||||||
|
resolveBuildEnvironment(
|
||||||
|
workingDir: string | undefined,
|
||||||
|
language: Language
|
||||||
|
): Promise<ResolveBuildEnvironmentOutput>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run 'codeql pack download'.
|
* Run 'codeql pack download'.
|
||||||
|
|
@ -229,6 +236,14 @@ export interface ResolveQueriesOutput {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ResolveBuildEnvironmentOutput {
|
||||||
|
configuration?: {
|
||||||
|
[language: string]: {
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface PackDownloadOutput {
|
export interface PackDownloadOutput {
|
||||||
packs: PackDownloadItem[];
|
packs: PackDownloadItem[];
|
||||||
}
|
}
|
||||||
|
|
@ -289,6 +304,11 @@ export const CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE = "2.12.1";
|
||||||
*/
|
*/
|
||||||
export const CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
|
export const CODEQL_VERSION_INIT_WITH_QLCONFIG = "2.12.4";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Versions 2.13.4+ of the CodeQL CLI support the `resolve build-environment` command.
|
||||||
|
*/
|
||||||
|
export const CODEQL_VERSION_RESOLVE_ENVIRONMENT = "2.13.4";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up CodeQL CLI access.
|
* Set up CodeQL CLI access.
|
||||||
*
|
*
|
||||||
|
|
@ -402,6 +422,10 @@ export function setCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||||
"betterResolveLanguages"
|
"betterResolveLanguages"
|
||||||
),
|
),
|
||||||
resolveQueries: resolveFunction(partialCodeql, "resolveQueries"),
|
resolveQueries: resolveFunction(partialCodeql, "resolveQueries"),
|
||||||
|
resolveBuildEnvironment: resolveFunction(
|
||||||
|
partialCodeql,
|
||||||
|
"resolveBuildEnvironment"
|
||||||
|
),
|
||||||
packDownload: resolveFunction(partialCodeql, "packDownload"),
|
packDownload: resolveFunction(partialCodeql, "packDownload"),
|
||||||
databaseCleanup: resolveFunction(partialCodeql, "databaseCleanup"),
|
databaseCleanup: resolveFunction(partialCodeql, "databaseCleanup"),
|
||||||
databaseBundle: resolveFunction(partialCodeql, "databaseBundle"),
|
databaseBundle: resolveFunction(partialCodeql, "databaseBundle"),
|
||||||
|
|
@ -681,6 +705,29 @@ export async function getCodeQLForCmd(
|
||||||
throw new Error(`Unexpected output from codeql resolve queries: ${e}`);
|
throw new Error(`Unexpected output from codeql resolve queries: ${e}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async resolveBuildEnvironment(
|
||||||
|
workingDir: string | undefined,
|
||||||
|
language: Language
|
||||||
|
) {
|
||||||
|
const codeqlArgs = [
|
||||||
|
"resolve",
|
||||||
|
"build-environment",
|
||||||
|
`--language=${language}`,
|
||||||
|
...getExtraOptionsFromEnv(["resolve", "build-environment"]),
|
||||||
|
];
|
||||||
|
if (workingDir !== undefined) {
|
||||||
|
codeqlArgs.push("--working-dir", workingDir);
|
||||||
|
}
|
||||||
|
const output = await runTool(cmd, codeqlArgs);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(output);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(
|
||||||
|
`Unexpected output from codeql resolve build-environment: ${e} in\n${output}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
async databaseRunQueries(
|
async databaseRunQueries(
|
||||||
databasePath: string,
|
databasePath: string,
|
||||||
extraSearchPath: string | undefined,
|
extraSearchPath: string | undefined,
|
||||||
|
|
|
||||||
98
src/resolve-environment-action.ts
Normal file
98
src/resolve-environment-action.ts
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
import * as core from "@actions/core";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createStatusReportBase,
|
||||||
|
getActionsStatus,
|
||||||
|
getOptionalInput,
|
||||||
|
getRequiredInput,
|
||||||
|
getTemporaryDirectory,
|
||||||
|
sendStatusReport,
|
||||||
|
} from "./actions-util";
|
||||||
|
import { getGitHubVersion } from "./api-client";
|
||||||
|
import { CommandInvocationError } from "./codeql";
|
||||||
|
import * as configUtils from "./config-utils";
|
||||||
|
import { Language, resolveAlias } from "./languages";
|
||||||
|
import { getActionsLogger } from "./logging";
|
||||||
|
import { runResolveBuildEnvironment } from "./resolve-environment";
|
||||||
|
import { checkForTimeout, checkGitHubVersionInRange, wrapError } from "./util";
|
||||||
|
|
||||||
|
const ACTION_NAME = "resolve-environment";
|
||||||
|
const ENVIRONMENT_OUTPUT_NAME = "environment";
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const startedAt = new Date();
|
||||||
|
const logger = getActionsLogger();
|
||||||
|
const language: Language = resolveAlias(getRequiredInput("language"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
!(await sendStatusReport(
|
||||||
|
await createStatusReportBase(ACTION_NAME, "starting", startedAt)
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gitHubVersion = await getGitHubVersion();
|
||||||
|
checkGitHubVersionInRange(gitHubVersion, logger);
|
||||||
|
|
||||||
|
const config = await configUtils.getConfig(getTemporaryDirectory(), logger);
|
||||||
|
if (config === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
"Config file could not be found at expected location. Has the 'init' action been called?"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const workingDirectory = getOptionalInput("working-directory");
|
||||||
|
const result = await runResolveBuildEnvironment(
|
||||||
|
config.codeQLCmd,
|
||||||
|
logger,
|
||||||
|
workingDirectory,
|
||||||
|
language
|
||||||
|
);
|
||||||
|
core.setOutput(ENVIRONMENT_OUTPUT_NAME, result);
|
||||||
|
} catch (unwrappedError) {
|
||||||
|
const error = wrapError(unwrappedError);
|
||||||
|
|
||||||
|
if (error instanceof CommandInvocationError) {
|
||||||
|
// If the CLI failed to run successfully for whatever reason,
|
||||||
|
// we just return an empty JSON object and proceed with the workflow.
|
||||||
|
core.setOutput(ENVIRONMENT_OUTPUT_NAME, {});
|
||||||
|
logger.warning(
|
||||||
|
`Failed to resolve a build environment suitable for automatically building your code. ${error.message}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// For any other error types, something has more seriously gone wrong and we fail.
|
||||||
|
core.setFailed(
|
||||||
|
`Failed to resolve a build environment suitable for automatically building your code. ${error.message}`
|
||||||
|
);
|
||||||
|
|
||||||
|
await sendStatusReport(
|
||||||
|
await createStatusReportBase(
|
||||||
|
ACTION_NAME,
|
||||||
|
getActionsStatus(error),
|
||||||
|
startedAt,
|
||||||
|
error.message,
|
||||||
|
error.stack
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await sendStatusReport(
|
||||||
|
await createStatusReportBase(ACTION_NAME, "success", startedAt)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runWrapper() {
|
||||||
|
try {
|
||||||
|
await run();
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`${ACTION_NAME} action failed: ${wrapError(error).message}`);
|
||||||
|
}
|
||||||
|
await checkForTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void runWrapper();
|
||||||
36
src/resolve-environment.ts
Normal file
36
src/resolve-environment.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { CODEQL_VERSION_RESOLVE_ENVIRONMENT, getCodeQL } from "./codeql";
|
||||||
|
import { Language } from "./languages";
|
||||||
|
import { Logger } from "./logging";
|
||||||
|
import * as util from "./util";
|
||||||
|
|
||||||
|
export async function runResolveBuildEnvironment(
|
||||||
|
cmd: string,
|
||||||
|
logger: Logger,
|
||||||
|
workingDir: string | undefined,
|
||||||
|
language: Language
|
||||||
|
) {
|
||||||
|
logger.startGroup(`Attempting to resolve build environment for ${language}`);
|
||||||
|
|
||||||
|
const codeql = await getCodeQL(cmd);
|
||||||
|
let result = {};
|
||||||
|
|
||||||
|
// If the CodeQL version in use does not support the `resolve build-environment`
|
||||||
|
// command, just return an empty configuration. Otherwise invoke the CLI.
|
||||||
|
if (
|
||||||
|
!(await util.codeQlVersionAbove(codeql, CODEQL_VERSION_RESOLVE_ENVIRONMENT))
|
||||||
|
) {
|
||||||
|
logger.warning(
|
||||||
|
"Unsupported CodeQL CLI version for `resolve build-environment` command, " +
|
||||||
|
"returning an empty configuration."
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (workingDir !== undefined) {
|
||||||
|
logger.info(`Using ${workingDir} as the working directory.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await codeql.resolveBuildEnvironment(workingDir, language);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.endGroup();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue