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
|
|
@ -306,7 +306,8 @@ type ActionName =
|
|||
| "autobuild"
|
||||
| "finish"
|
||||
| "upload-sarif"
|
||||
| "init-post";
|
||||
| "init-post"
|
||||
| "resolve-environment";
|
||||
export type ActionStatus =
|
||||
| "starting"
|
||||
| "aborted"
|
||||
|
|
|
|||
|
|
@ -118,6 +118,13 @@ export interface CodeQL {
|
|||
queries: string[],
|
||||
extraSearchPath: string | undefined
|
||||
): Promise<ResolveQueriesOutput>;
|
||||
/**
|
||||
* Run 'codeql resolve build-environment'
|
||||
*/
|
||||
resolveBuildEnvironment(
|
||||
workingDir: string | undefined,
|
||||
language: Language
|
||||
): Promise<ResolveBuildEnvironmentOutput>;
|
||||
|
||||
/**
|
||||
* Run 'codeql pack download'.
|
||||
|
|
@ -229,6 +236,14 @@ export interface ResolveQueriesOutput {
|
|||
};
|
||||
}
|
||||
|
||||
export interface ResolveBuildEnvironmentOutput {
|
||||
configuration?: {
|
||||
[language: string]: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface PackDownloadOutput {
|
||||
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";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
@ -402,6 +422,10 @@ export function setCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
|||
"betterResolveLanguages"
|
||||
),
|
||||
resolveQueries: resolveFunction(partialCodeql, "resolveQueries"),
|
||||
resolveBuildEnvironment: resolveFunction(
|
||||
partialCodeql,
|
||||
"resolveBuildEnvironment"
|
||||
),
|
||||
packDownload: resolveFunction(partialCodeql, "packDownload"),
|
||||
databaseCleanup: resolveFunction(partialCodeql, "databaseCleanup"),
|
||||
databaseBundle: resolveFunction(partialCodeql, "databaseBundle"),
|
||||
|
|
@ -681,6 +705,29 @@ export async function getCodeQLForCmd(
|
|||
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(
|
||||
databasePath: string,
|
||||
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