@@ -10,7 +10,7 @@ import * as yaml from "js-yaml";
1010import * as semver from "semver" ;
1111
1212import * as apiCompatibility from "./api-compatibility.json" ;
13- import type { CodeQL , VersionInfo } from "./codeql" ;
13+ import type { CodeQL , VersionInfo , ResolveLanguagesOutput } from "./codeql" ;
1414import type { Pack } from "./config/db-config" ;
1515import type { Config } from "./config-utils" ;
1616import { EnvVar } from "./environment" ;
@@ -701,6 +701,75 @@ export function getCachedCodeQlVersion(cmd?: string): undefined | VersionInfo {
701701 return cachedCodeQlVersion ;
702702}
703703
704+ let cachedCodeQlResolveLanguages : undefined | ResolveLanguagesOutput =
705+ undefined ;
706+
707+ interface PersistedResolveLanguagesOutput {
708+ cmd : string ;
709+ output : ResolveLanguagesOutput ;
710+ }
711+
712+ export function cacheCodeQlResolveLanguages (
713+ cmd : string ,
714+ output : ResolveLanguagesOutput ,
715+ ) : void {
716+ if ( cachedCodeQlResolveLanguages !== undefined ) {
717+ throw new Error ( "cacheCodeQlResolveLanguages() should be called only once" ) ;
718+ }
719+ cachedCodeQlResolveLanguages = output ;
720+ // Persist the output so that subsequent Actions steps, which run in separate
721+ // processes, can reuse it rather than invoking `codeql resolve languages` again. We
722+ // record the CLI path so that a different step using a different CodeQL bundle
723+ // doesn't pick up a stale output.
724+ core . exportVariable (
725+ EnvVar . CODEQL_RESOLVE_LANGUAGES ,
726+ JSON . stringify ( { cmd, output } ) ,
727+ ) ;
728+ }
729+
730+ function isPersistedResolveLanguagesOutput (
731+ value : unknown ,
732+ ) : value is PersistedResolveLanguagesOutput {
733+ return (
734+ typeof value === "object" &&
735+ value !== null &&
736+ typeof ( value as Record < string , unknown > ) . cmd === "string" &&
737+ typeof ( value as Record < string , unknown > ) . output === "object" &&
738+ ( value as Record < string , unknown > ) . output !== null
739+ ) ;
740+ }
741+
742+ export function getCachedCodeQlResolveLanguages (
743+ cmd ?: string ,
744+ ) : undefined | ResolveLanguagesOutput {
745+ if ( cachedCodeQlResolveLanguages !== undefined ) {
746+ return cachedCodeQlResolveLanguages ;
747+ }
748+ // Fall back to the value persisted by an earlier Actions step, if any. This is
749+ // best-effort: any malformed or mismatched value is ignored so that the caller
750+ // invokes `codeql resolve languages` instead.
751+ const serialized = process . env [ EnvVar . CODEQL_RESOLVE_LANGUAGES ] ;
752+ if ( ! serialized ) {
753+ return undefined ;
754+ }
755+ let persisted : unknown ;
756+ try {
757+ persisted = JSON . parse ( serialized ) ;
758+ } catch {
759+ return undefined ;
760+ }
761+ if (
762+ ! isPersistedResolveLanguagesOutput ( persisted ) ||
763+ ( cmd !== undefined && persisted . cmd !== cmd )
764+ ) {
765+ return undefined ;
766+ }
767+ // Memoize the parsed value so that subsequent calls in this process don't
768+ // re-parse the environment variable.
769+ cachedCodeQlResolveLanguages = persisted . output ;
770+ return cachedCodeQlResolveLanguages ;
771+ }
772+
704773export async function codeQlVersionAtLeast (
705774 codeql : CodeQL ,
706775 requiredVersion : string ,
0 commit comments