-
Notifications
You must be signed in to change notification settings - Fork 464
Cache CLI extractor paths across Actions steps #3950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -23,6 +23,12 @@ export enum EnvVar { | |||||
| */ | ||||||
| CODEQL_VERSION_INFO = "CODEQL_ACTION_CLI_VERSION_INFO", | ||||||
|
|
||||||
| /** | ||||||
| * `ResolveLanguagesOutput` for the CodeQL CLI, so later Actions steps can reuse it instead of | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor:
Suggested change
|
||||||
| * invoking `codeql resolve languages` again. | ||||||
| */ | ||||||
| CODEQL_RESOLVE_LANGUAGES = "CODEQL_ACTION_CLI_RESOLVE_LANGUAGES", | ||||||
|
|
||||||
| /** Whether the CodeQL Action has invoked the Go autobuilder. */ | ||||||
| DID_AUTOBUILD_GOLANG = "CODEQL_ACTION_DID_AUTOBUILD_GOLANG", | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ import * as yaml from "js-yaml"; | |
| import * as semver from "semver"; | ||
|
|
||
| import * as apiCompatibility from "./api-compatibility.json"; | ||
| import type { CodeQL, VersionInfo } from "./codeql"; | ||
| import type { CodeQL, VersionInfo, ResolveLanguagesOutput } from "./codeql"; | ||
| import type { Pack } from "./config/db-config"; | ||
| import type { Config } from "./config-utils"; | ||
| import { EnvVar } from "./environment"; | ||
|
|
@@ -701,6 +701,75 @@ export function getCachedCodeQlVersion(cmd?: string): undefined | VersionInfo { | |
| return cachedCodeQlVersion; | ||
| } | ||
|
|
||
| let cachedCodeQlResolveLanguages: undefined | ResolveLanguagesOutput = | ||
| undefined; | ||
|
|
||
| interface PersistedResolveLanguagesOutput { | ||
| cmd: string; | ||
| output: ResolveLanguagesOutput; | ||
| } | ||
|
|
||
| export function cacheCodeQlResolveLanguages( | ||
| cmd: string, | ||
| output: ResolveLanguagesOutput, | ||
| ): void { | ||
| if (cachedCodeQlResolveLanguages !== undefined) { | ||
| throw new Error("cacheCodeQlResolveLanguages() should be called only once"); | ||
| } | ||
| cachedCodeQlResolveLanguages = output; | ||
| // Persist the output so that subsequent Actions steps, which run in separate | ||
| // processes, can reuse it rather than invoking `codeql resolve languages` again. We | ||
| // record the CLI path so that a different step using a different CodeQL bundle | ||
| // doesn't pick up a stale output. | ||
| core.exportVariable( | ||
| EnvVar.CODEQL_RESOLVE_LANGUAGES, | ||
| JSON.stringify({ cmd, output }), | ||
| ); | ||
| } | ||
|
|
||
| function isPersistedResolveLanguagesOutput( | ||
| value: unknown, | ||
| ): value is PersistedResolveLanguagesOutput { | ||
| return ( | ||
| typeof value === "object" && | ||
| value !== null && | ||
| typeof (value as Record<string, unknown>).cmd === "string" && | ||
| typeof (value as Record<string, unknown>).output === "object" && | ||
| (value as Record<string, unknown>).output !== null | ||
| ); | ||
| } | ||
|
Comment on lines
+730
to
+740
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this mirrors what was done in #3943, but it would probably make sense to use the helper functions from the |
||
|
|
||
| export function getCachedCodeQlResolveLanguages( | ||
| cmd?: string, | ||
| ): undefined | ResolveLanguagesOutput { | ||
| if (cachedCodeQlResolveLanguages !== undefined) { | ||
| return cachedCodeQlResolveLanguages; | ||
| } | ||
| // Fall back to the value persisted by an earlier Actions step, if any. This is | ||
| // best-effort: any malformed or mismatched value is ignored so that the caller | ||
| // invokes `codeql resolve languages` instead. | ||
| const serialized = process.env[EnvVar.CODEQL_RESOLVE_LANGUAGES]; | ||
| if (!serialized) { | ||
| return undefined; | ||
| } | ||
| let persisted: unknown; | ||
| try { | ||
| persisted = JSON.parse(serialized); | ||
| } catch { | ||
| return undefined; | ||
| } | ||
| if ( | ||
| !isPersistedResolveLanguagesOutput(persisted) || | ||
| (cmd !== undefined && persisted.cmd !== cmd) | ||
| ) { | ||
| return undefined; | ||
| } | ||
| // Memoize the parsed value so that subsequent calls in this process don't | ||
| // re-parse the environment variable. | ||
| cachedCodeQlResolveLanguages = persisted.output; | ||
| return cachedCodeQlResolveLanguages; | ||
| } | ||
|
|
||
| export async function codeQlVersionAtLeast( | ||
| codeql: CodeQL, | ||
| requiredVersion: string, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this correctly handle language aliases? We do currently normalise languages to their original names, but it would be good to at least document this change of behaviour if not resolve aliases.
Also, we should make sure that
extractors[language]is defined and if not, error nicely.