mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 09:14:58 +00:00
Persist repository root from init action in CodeQL Action state
This commit is contained in:
43
lib/entry-points.js
generated
43
lib/entry-points.js
generated
@@ -150444,7 +150444,7 @@ async function initActionState({
|
||||
analysisKinds,
|
||||
logger,
|
||||
enableFileCoverageInformation
|
||||
}, userConfig) {
|
||||
}, userConfig, repositoryRoot) {
|
||||
const languages = await getLanguages(
|
||||
codeql,
|
||||
languagesInput,
|
||||
@@ -150480,6 +150480,7 @@ async function initActionState({
|
||||
);
|
||||
return {
|
||||
version: getActionVersion(),
|
||||
repositoryRoot,
|
||||
analysisKinds,
|
||||
languages,
|
||||
buildMode,
|
||||
@@ -150630,7 +150631,7 @@ async function checkRunnerResources(codeql, features, diskUsage, ramInput, logge
|
||||
}
|
||||
return new Success(void 0);
|
||||
}
|
||||
async function checkOverlayEnablement(codeql, features, languages, sourceRoot, buildMode, ramInput, codeScanningConfig, repositoryProperties, gitVersion, logger) {
|
||||
async function checkOverlayEnablement(codeql, features, languages, repositoryRoot, sourceRoot, buildMode, ramInput, codeScanningConfig, repositoryProperties, gitVersion, logger) {
|
||||
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
|
||||
if (modeEnv === "overlay" /* Overlay */ || modeEnv === "overlay-base" /* OverlayBase */ || modeEnv === "none" /* None */) {
|
||||
logger.info(
|
||||
@@ -150645,6 +150646,7 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
|
||||
true,
|
||||
codeql,
|
||||
languages,
|
||||
repositoryRoot,
|
||||
sourceRoot,
|
||||
buildMode,
|
||||
gitVersion,
|
||||
@@ -150717,13 +150719,14 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
|
||||
false,
|
||||
codeql,
|
||||
languages,
|
||||
repositoryRoot,
|
||||
sourceRoot,
|
||||
buildMode,
|
||||
gitVersion,
|
||||
logger
|
||||
);
|
||||
}
|
||||
async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, overlayModeSetExplicitly, codeql, languages, sourceRoot, buildMode, gitVersion, logger) {
|
||||
async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, overlayModeSetExplicitly, codeql, languages, repositoryRoot, sourceRoot, buildMode, gitVersion, logger) {
|
||||
if (buildMode !== "none" /* None */ && (await Promise.all(
|
||||
languages.map(
|
||||
async (l) => l !== "go" /* go */ && // Workaround to allow overlay analysis for Go with any build
|
||||
@@ -150744,14 +150747,13 @@ async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDataba
|
||||
);
|
||||
return new Failure("incompatible-codeql" /* IncompatibleCodeQl */);
|
||||
}
|
||||
const gitRoot = await getGitRoot(sourceRoot);
|
||||
if (gitRoot === void 0) {
|
||||
if (repositoryRoot === void 0) {
|
||||
logger.warning(
|
||||
`Cannot build an ${overlayDatabaseMode} database because the source root "${sourceRoot}" is not inside a git repository. Falling back to creating a normal full database instead.`
|
||||
);
|
||||
return new Failure("no-git-root" /* NoGitRoot */);
|
||||
}
|
||||
if (hasSubmodules(gitRoot)) {
|
||||
if (hasSubmodules(repositoryRoot)) {
|
||||
if (gitVersion === void 0) {
|
||||
logger.warning(
|
||||
`Cannot build an ${overlayDatabaseMode} database because the repository has submodules and the Git version could not be determined. Falling back to creating a normal full database instead.`
|
||||
@@ -150886,8 +150888,9 @@ async function determineUserConfig(action, tempDir, inputs) {
|
||||
async function initConfig(actionState, inputs) {
|
||||
const { logger, features } = actionState;
|
||||
const { tempDir } = inputs;
|
||||
const repositoryRoot = await getGitRoot(inputs.sourceRoot);
|
||||
const userConfig = await determineUserConfig(actionState, tempDir, inputs);
|
||||
const config = await initActionState(inputs, userConfig);
|
||||
const config = await initActionState(inputs, userConfig, repositoryRoot);
|
||||
if (config.analysisKinds.length === 1 && isCodeQualityEnabled(config)) {
|
||||
if (hasQueryCustomisation(config.computedConfig)) {
|
||||
throw new ConfigurationError(
|
||||
@@ -150940,6 +150943,7 @@ async function initConfig(actionState, inputs) {
|
||||
inputs.codeql,
|
||||
inputs.features,
|
||||
config.languages,
|
||||
repositoryRoot,
|
||||
inputs.sourceRoot,
|
||||
config.buildMode,
|
||||
inputs.ramInput,
|
||||
@@ -153801,8 +153805,27 @@ var CodeQLAnalysisError = class extends Error {
|
||||
message;
|
||||
error;
|
||||
};
|
||||
function determineCheckoutPath(action) {
|
||||
return action.actions.getRequiredInput("checkout_path");
|
||||
async function determineCheckoutPath(action) {
|
||||
const checkoutPathInput = action.actions.getRequiredInput("checkout_path");
|
||||
const repositoryRoot = await getGitRoot(checkoutPathInput);
|
||||
if (repositoryRoot === void 0) {
|
||||
action.logger.warning(
|
||||
[
|
||||
`The directory at '${checkoutPathInput}' is not in the work tree of a git repository.`,
|
||||
"If the repository being analyzed is checked out elsewhere,",
|
||||
"you must explicitly set the 'checkout_path' input for the 'codeql-action/analyze' step to",
|
||||
"the checkout path."
|
||||
].join(" ")
|
||||
);
|
||||
} else if (repositoryRoot !== path16.resolve(checkoutPathInput)) {
|
||||
action.logger.warning(
|
||||
[
|
||||
`The directory at '${checkoutPathInput}' is not the root of the repository ('${repositoryRoot}').`,
|
||||
"Set the 'checkout_path' input for the 'codeql-action/analyze' step to the root path of the checkout."
|
||||
].join(" ")
|
||||
);
|
||||
}
|
||||
return checkoutPathInput;
|
||||
}
|
||||
async function setupPythonExtractor(logger) {
|
||||
const codeqlPython = process.env["CODEQL_PYTHON"];
|
||||
@@ -156615,7 +156638,7 @@ async function run(action) {
|
||||
getOptionalInput("ram") || process.env["CODEQL_RAM"],
|
||||
logger
|
||||
);
|
||||
const checkoutPath = determineCheckoutPath(action);
|
||||
const checkoutPath = await determineCheckoutPath(action);
|
||||
const diffRangePackDir = await setupDiffInformedQueryRun(
|
||||
logger,
|
||||
checkoutPath
|
||||
|
||||
@@ -45,6 +45,7 @@ test.serial(
|
||||
requiredInputStub.withArgs("token").returns("fake-token");
|
||||
requiredInputStub.withArgs("upload-database").returns("false");
|
||||
requiredInputStub.withArgs("output").returns("out");
|
||||
requiredInputStub.withArgs("checkout_path").returns("");
|
||||
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
||||
optionalInputStub.withArgs("expect-error").returns("false");
|
||||
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
|
||||
@@ -104,6 +105,7 @@ test.serial(
|
||||
requiredInputStub.withArgs("token").returns("fake-token");
|
||||
requiredInputStub.withArgs("upload-database").returns("false");
|
||||
requiredInputStub.withArgs("output").returns("out");
|
||||
requiredInputStub.withArgs("checkout_path").returns("");
|
||||
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
||||
optionalInputStub.withArgs("expect-error").returns("false");
|
||||
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
|
||||
|
||||
@@ -310,7 +310,7 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) {
|
||||
logger,
|
||||
);
|
||||
|
||||
const checkoutPath = determineCheckoutPath(action);
|
||||
const checkoutPath = await determineCheckoutPath(action);
|
||||
|
||||
// Setup diff informed analysis if needed (based on whether init created the file)
|
||||
const diffRangePackDir = await setupDiffInformedQueryRun(
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
} from "./diff-informed-analysis-utils";
|
||||
import { EnvVar } from "./environment";
|
||||
import { FeatureEnablement, Feature } from "./feature-flags";
|
||||
import { getGitRoot } from "./git-utils";
|
||||
import { BuiltInLanguage, Language } from "./languages";
|
||||
import { Logger, withGroupAsync } from "./logging";
|
||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||
@@ -93,8 +94,33 @@ export interface QueriesStatusReport
|
||||
*
|
||||
* @param action The action state.
|
||||
*/
|
||||
export function determineCheckoutPath(action: ActionState<["Actions"]>) {
|
||||
return action.actions.getRequiredInput("checkout_path");
|
||||
export async function determineCheckoutPath(
|
||||
action: ActionState<["Logger", "Actions"]>,
|
||||
) {
|
||||
const checkoutPathInput = action.actions.getRequiredInput("checkout_path");
|
||||
|
||||
// Try to obtain the root path of the repository and validate that it matches the input.
|
||||
const repositoryRoot = await getGitRoot(checkoutPathInput);
|
||||
|
||||
if (repositoryRoot === undefined) {
|
||||
action.logger.warning(
|
||||
[
|
||||
`The directory at '${checkoutPathInput}' is not in the work tree of a git repository.`,
|
||||
"If the repository being analyzed is checked out elsewhere,",
|
||||
"you must explicitly set the 'checkout_path' input for the 'codeql-action/analyze' step to",
|
||||
"the checkout path.",
|
||||
].join(" "),
|
||||
);
|
||||
} else if (repositoryRoot !== path.resolve(checkoutPathInput)) {
|
||||
action.logger.warning(
|
||||
[
|
||||
`The directory at '${checkoutPathInput}' is not the root of the repository ('${repositoryRoot}').`,
|
||||
"Set the 'checkout_path' input for the 'codeql-action/analyze' step to the root path of the checkout.",
|
||||
].join(" "),
|
||||
);
|
||||
}
|
||||
|
||||
return checkoutPathInput;
|
||||
}
|
||||
|
||||
async function setupPythonExtractor(logger: Logger) {
|
||||
|
||||
@@ -172,6 +172,7 @@ test.serial("load empty config", async (t) => {
|
||||
createTestInitConfigInputs({
|
||||
languagesInput: languages,
|
||||
repository: { owner: "github", repo: "example" },
|
||||
sourceRoot: tempDir,
|
||||
tempDir,
|
||||
codeql,
|
||||
logger,
|
||||
@@ -186,6 +187,7 @@ test.serial("load empty config", async (t) => {
|
||||
logger,
|
||||
}),
|
||||
{},
|
||||
undefined,
|
||||
);
|
||||
|
||||
t.deepEqual(config, expectedConfig);
|
||||
@@ -216,6 +218,7 @@ test.serial("load code quality config", async (t) => {
|
||||
analysisKinds: [AnalysisKind.CodeQuality],
|
||||
languagesInput: languages,
|
||||
repository: { owner: "github", repo: "example" },
|
||||
sourceRoot: tempDir,
|
||||
tempDir,
|
||||
codeql,
|
||||
logger,
|
||||
@@ -296,6 +299,7 @@ test.serial(
|
||||
analysisKinds: [AnalysisKind.CodeQuality],
|
||||
languagesInput: languages,
|
||||
repository: { owner: "github", repo: "example" },
|
||||
sourceRoot: tempDir,
|
||||
tempDir,
|
||||
codeql,
|
||||
repositoryProperties,
|
||||
@@ -512,6 +516,7 @@ test.serial("load non-empty input", async (t) => {
|
||||
// And the config we expect it to parse to
|
||||
const expectedConfig = createTestConfig({
|
||||
languages: [BuiltInLanguage.javascript],
|
||||
repositoryRoot: undefined,
|
||||
buildMode: BuildMode.None,
|
||||
originalUserInput: userConfig,
|
||||
computedConfig: userConfig,
|
||||
@@ -532,6 +537,7 @@ test.serial("load non-empty input", async (t) => {
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
languagesInput,
|
||||
sourceRoot: tempDir,
|
||||
buildModeInput: "none",
|
||||
configFile: configFilePath,
|
||||
debugArtifactName: "my-artifact",
|
||||
@@ -1092,11 +1098,6 @@ const checkOverlayEnablementMacro = makeMacro({
|
||||
return lang === BuiltInLanguage.java;
|
||||
});
|
||||
|
||||
// Mock git root detection
|
||||
if (setup.gitRoot !== undefined) {
|
||||
sinon.stub(gitUtils, "getGitRoot").resolves(setup.gitRoot);
|
||||
}
|
||||
|
||||
// Mock submodule detection
|
||||
sinon.stub(gitUtils, "hasSubmodules").returns(setup.hasSubmodules);
|
||||
|
||||
@@ -1109,6 +1110,7 @@ const checkOverlayEnablementMacro = makeMacro({
|
||||
codeql,
|
||||
features,
|
||||
setup.languages,
|
||||
setup.gitRoot, // repositoryRoot
|
||||
tempDir, // sourceRoot
|
||||
setup.buildMode,
|
||||
undefined,
|
||||
|
||||
@@ -385,6 +385,7 @@ export async function initActionState(
|
||||
enableFileCoverageInformation,
|
||||
}: InitConfigInputs,
|
||||
userConfig: UserConfig,
|
||||
repositoryRoot: string | undefined,
|
||||
): Promise<Config> {
|
||||
const languages = await getLanguages(
|
||||
codeql,
|
||||
@@ -436,6 +437,7 @@ export async function initActionState(
|
||||
|
||||
return {
|
||||
version: getActionVersion(),
|
||||
repositoryRoot,
|
||||
analysisKinds,
|
||||
languages,
|
||||
buildMode,
|
||||
@@ -718,6 +720,7 @@ export async function checkOverlayEnablement(
|
||||
codeql: CodeQL,
|
||||
features: FeatureEnablement,
|
||||
languages: Language[],
|
||||
repositoryRoot: string | undefined,
|
||||
sourceRoot: string,
|
||||
buildMode: BuildMode | undefined,
|
||||
ramInput: string | undefined,
|
||||
@@ -747,6 +750,7 @@ export async function checkOverlayEnablement(
|
||||
true,
|
||||
codeql,
|
||||
languages,
|
||||
repositoryRoot,
|
||||
sourceRoot,
|
||||
buildMode,
|
||||
gitVersion,
|
||||
@@ -836,6 +840,7 @@ export async function checkOverlayEnablement(
|
||||
false,
|
||||
codeql,
|
||||
languages,
|
||||
repositoryRoot,
|
||||
sourceRoot,
|
||||
buildMode,
|
||||
gitVersion,
|
||||
@@ -855,6 +860,7 @@ async function validateOverlayDatabaseMode(
|
||||
overlayModeSetExplicitly: boolean,
|
||||
codeql: CodeQL,
|
||||
languages: Language[],
|
||||
repositoryRoot: string | undefined,
|
||||
sourceRoot: string,
|
||||
buildMode: BuildMode | undefined,
|
||||
gitVersion: GitVersionInfo | undefined,
|
||||
@@ -890,8 +896,7 @@ async function validateOverlayDatabaseMode(
|
||||
);
|
||||
return new Failure(OverlayDisabledReason.IncompatibleCodeQl);
|
||||
}
|
||||
const gitRoot = await getGitRoot(sourceRoot);
|
||||
if (gitRoot === undefined) {
|
||||
if (repositoryRoot === undefined) {
|
||||
logger.warning(
|
||||
`Cannot build an ${overlayDatabaseMode} database because ` +
|
||||
`the source root "${sourceRoot}" is not inside a git repository. ` +
|
||||
@@ -899,7 +904,7 @@ async function validateOverlayDatabaseMode(
|
||||
);
|
||||
return new Failure(OverlayDisabledReason.NoGitRoot);
|
||||
}
|
||||
if (hasSubmodules(gitRoot)) {
|
||||
if (hasSubmodules(repositoryRoot)) {
|
||||
if (gitVersion === undefined) {
|
||||
logger.warning(
|
||||
`Cannot build an ${overlayDatabaseMode} database because ` +
|
||||
@@ -1160,9 +1165,11 @@ export async function initConfig(
|
||||
const { logger, features } = actionState;
|
||||
const { tempDir } = inputs;
|
||||
|
||||
const repositoryRoot = await getGitRoot(inputs.sourceRoot);
|
||||
|
||||
const userConfig = await determineUserConfig(actionState, tempDir, inputs);
|
||||
|
||||
const config = await initActionState(inputs, userConfig);
|
||||
const config = await initActionState(inputs, userConfig, repositoryRoot);
|
||||
|
||||
// If Code Quality analysis is the only enabled analysis kind, then we will initialise
|
||||
// the database for Code Quality. That entails disabling the default queries and only
|
||||
@@ -1244,6 +1251,7 @@ export async function initConfig(
|
||||
inputs.codeql,
|
||||
inputs.features,
|
||||
config.languages,
|
||||
repositoryRoot,
|
||||
inputs.sourceRoot,
|
||||
config.buildMode,
|
||||
inputs.ramInput,
|
||||
|
||||
@@ -16,6 +16,11 @@ export interface Config {
|
||||
* The version of the CodeQL Action that the configuration is for.
|
||||
*/
|
||||
version: string;
|
||||
/**
|
||||
* The path at which the repository being analysed is checked out at, if available.
|
||||
* Persisted in the CodeQL Action configuration state, so that we can consult it in later workflow steps.
|
||||
*/
|
||||
repositoryRoot: string | undefined;
|
||||
/**
|
||||
* Set of analysis kinds that are enabled.
|
||||
*/
|
||||
|
||||
@@ -968,6 +968,7 @@ export function createTestConfig(overrides: Partial<Config>): Config {
|
||||
{},
|
||||
{
|
||||
version: getActionVersion(),
|
||||
repositoryRoot: undefined,
|
||||
analysisKinds: [AnalysisKind.CodeScanning],
|
||||
languages: [],
|
||||
buildMode: undefined,
|
||||
|
||||
Reference in New Issue
Block a user