Overlay: add automation ID to cache key

This commit adds automation ID to the overlay-base database cache key so
that we properly distinguish different analyses in the same repo for the
same language.

Since I am changing the cache key format, I also moved the CodeQL bundle
version to the end of the cache restore key, in case we want to remove
it from the restore key sometime in the future.

Note that I chose to leave CACHE_VERSION unchanged because the old and
the new cache keys are sufficiently different that there should be no
risk of confusion.
This commit is contained in:
Chuan-kai Lin
2025-09-04 14:13:15 -07:00
parent 2d2f57ed3a
commit 4c82ae2356
7 changed files with 183 additions and 76 deletions
+70 -32
View File
@@ -184,7 +184,7 @@ var require_file_command = __commonJS({
};
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.prepareKeyValueMessage = exports2.issueFileCommand = void 0;
var crypto = __importStar4(require("crypto"));
var crypto2 = __importStar4(require("crypto"));
var fs18 = __importStar4(require("fs"));
var os5 = __importStar4(require("os"));
var utils_1 = require_utils();
@@ -202,7 +202,7 @@ var require_file_command = __commonJS({
}
exports2.issueFileCommand = issueFileCommand;
function prepareKeyValueMessage(key, value) {
const delimiter = `ghadelimiter_${crypto.randomUUID()}`;
const delimiter = `ghadelimiter_${crypto2.randomUUID()}`;
const convertedValue = (0, utils_1.toCommandValue)(value);
if (key.includes(delimiter)) {
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
@@ -3637,11 +3637,11 @@ var require_util2 = __commonJS({
var assert = require("assert");
var { isUint8Array } = require("util/types");
var supportedHashes = [];
var crypto;
var crypto2;
try {
crypto = require("crypto");
crypto2 = require("crypto");
const possibleRelevantHashes = ["sha256", "sha384", "sha512"];
supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
supportedHashes = crypto2.getHashes().filter((hash) => possibleRelevantHashes.includes(hash));
} catch {
}
function responseURL(response) {
@@ -3918,7 +3918,7 @@ var require_util2 = __commonJS({
}
}
function bytesMatch(bytes, metadataList) {
if (crypto === void 0) {
if (crypto2 === void 0) {
return true;
}
const parsedMetadata = parseMetadata(metadataList);
@@ -3933,7 +3933,7 @@ var require_util2 = __commonJS({
for (const item of metadata) {
const algorithm = item.algo;
const expectedValue = item.hash;
let actualValue = crypto.createHash(algorithm).update(bytes).digest("base64");
let actualValue = crypto2.createHash(algorithm).update(bytes).digest("base64");
if (actualValue[actualValue.length - 1] === "=") {
if (actualValue[actualValue.length - 2] === "=") {
actualValue = actualValue.slice(0, -2);
@@ -5279,8 +5279,8 @@ var require_body = __commonJS({
var { parseMIMEType, serializeAMimeType } = require_dataURL();
var random;
try {
const crypto = require("node:crypto");
random = (max) => crypto.randomInt(0, max);
const crypto2 = require("node:crypto");
random = (max) => crypto2.randomInt(0, max);
} catch {
random = (max) => Math.floor(Math.random(max));
}
@@ -16330,9 +16330,9 @@ var require_connection = __commonJS({
channels.open = diagnosticsChannel.channel("undici:websocket:open");
channels.close = diagnosticsChannel.channel("undici:websocket:close");
channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error");
var crypto;
var crypto2;
try {
crypto = require("crypto");
crypto2 = require("crypto");
} catch {
}
function establishWebSocketConnection(url, protocols, ws, onEstablish, options) {
@@ -16351,7 +16351,7 @@ var require_connection = __commonJS({
const headersList = new Headers(options.headers)[kHeadersList];
request.headersList = headersList;
}
const keyValue = crypto.randomBytes(16).toString("base64");
const keyValue = crypto2.randomBytes(16).toString("base64");
request.headersList.append("sec-websocket-key", keyValue);
request.headersList.append("sec-websocket-version", "13");
for (const protocol of protocols) {
@@ -16380,7 +16380,7 @@ var require_connection = __commonJS({
return;
}
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
const digest = crypto.createHash("sha1").update(keyValue + uid).digest("base64");
const digest = crypto2.createHash("sha1").update(keyValue + uid).digest("base64");
if (secWSAccept !== digest) {
failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header.");
return;
@@ -16460,9 +16460,9 @@ var require_frame = __commonJS({
"node_modules/undici/lib/websocket/frame.js"(exports2, module2) {
"use strict";
var { maxUnsigned16Bit } = require_constants5();
var crypto;
var crypto2;
try {
crypto = require("crypto");
crypto2 = require("crypto");
} catch {
}
var WebsocketFrameSend = class {
@@ -16471,7 +16471,7 @@ var require_frame = __commonJS({
*/
constructor(data) {
this.frameData = data;
this.maskKey = crypto.randomBytes(4);
this.maskKey = crypto2.randomBytes(4);
}
createFrame(opcode) {
const bodyLength = this.frameData?.byteLength ?? 0;
@@ -36929,7 +36929,7 @@ var require_cacheUtils = __commonJS({
var exec2 = __importStar4(require_exec());
var glob2 = __importStar4(require_glob());
var io7 = __importStar4(require_io());
var crypto = __importStar4(require("crypto"));
var crypto2 = __importStar4(require("crypto"));
var fs18 = __importStar4(require("fs"));
var path19 = __importStar4(require("path"));
var semver9 = __importStar4(require_semver3());
@@ -36953,7 +36953,7 @@ var require_cacheUtils = __commonJS({
}
tempDirectory = path19.join(baseLocation, "actions", "temp");
}
const dest = path19.join(tempDirectory, crypto.randomUUID());
const dest = path19.join(tempDirectory, crypto2.randomUUID());
yield io7.mkdirP(dest);
return dest;
});
@@ -37069,7 +37069,7 @@ var require_cacheUtils = __commonJS({
components.push("windows-only");
}
components.push(versionSalt);
return crypto.createHash("sha256").update(components.join("|")).digest("hex");
return crypto2.createHash("sha256").update(components.join("|")).digest("hex");
}
exports2.getCacheVersion = getCacheVersion;
function getRuntimeToken() {
@@ -48813,7 +48813,7 @@ var require_dist7 = __commonJS({
var coreXml = require_commonjs9();
var logger$1 = require_dist();
var abortController = require_commonjs10();
var crypto = require("crypto");
var crypto2 = require("crypto");
var coreTracing = require_commonjs4();
var stream2 = require("stream");
var coreLro = require_dist6();
@@ -50321,7 +50321,7 @@ ${key}:${decodeURIComponent(lowercaseQueries[key])}`;
* @param stringToSign -
*/
computeHMACSHA256(stringToSign) {
return crypto.createHmac("sha256", this.accountKey).update(stringToSign, "utf8").digest("base64");
return crypto2.createHmac("sha256", this.accountKey).update(stringToSign, "utf8").digest("base64");
}
};
var AnonymousCredentialPolicy = class extends CredentialPolicy {
@@ -50519,7 +50519,7 @@ ${key}:${decodeURIComponent(lowercaseQueries[key])}`;
getHeaderValueToSign(request, HeaderConstants.IF_UNMODIFIED_SINCE),
getHeaderValueToSign(request, HeaderConstants.RANGE)
].join("\n") + "\n" + getCanonicalizedHeadersString(request) + getCanonicalizedResourceString(request);
const signature = crypto.createHmac("sha256", options.accountKey).update(stringToSign, "utf8").digest("base64");
const signature = crypto2.createHmac("sha256", options.accountKey).update(stringToSign, "utf8").digest("base64");
request.headers.set(HeaderConstants.AUTHORIZATION, `SharedKey ${options.accountName}:${signature}`);
}
function getHeaderValueToSign(request, headerName) {
@@ -64278,7 +64278,7 @@ ${key}:${decodeURIComponent(lowercaseQueries[key])}`;
* @param stringToSign -
*/
computeHMACSHA256(stringToSign) {
return crypto.createHmac("sha256", this.key).update(stringToSign, "utf8").digest("base64");
return crypto2.createHmac("sha256", this.key).update(stringToSign, "utf8").digest("base64");
}
};
function ipRangeToString(ipRange) {
@@ -80223,7 +80223,7 @@ var require_internal_hash_files = __commonJS({
};
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.hashFiles = void 0;
var crypto = __importStar4(require("crypto"));
var crypto2 = __importStar4(require("crypto"));
var core14 = __importStar4(require_core());
var fs18 = __importStar4(require("fs"));
var stream2 = __importStar4(require("stream"));
@@ -80236,7 +80236,7 @@ var require_internal_hash_files = __commonJS({
const writeDelegate = verbose ? core14.info : core14.debug;
let hasMatch = false;
const githubWorkspace = currentWorkspace ? currentWorkspace : (_d = process.env["GITHUB_WORKSPACE"]) !== null && _d !== void 0 ? _d : process.cwd();
const result = crypto.createHash("sha256");
const result = crypto2.createHash("sha256");
let count = 0;
try {
for (var _e = true, _f = __asyncValues4(globber.globGenerator()), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
@@ -80252,7 +80252,7 @@ var require_internal_hash_files = __commonJS({
writeDelegate(`Skip directory '${file}'.`);
continue;
}
const hash = crypto.createHash("sha256");
const hash = crypto2.createHash("sha256");
const pipeline = util.promisify(stream2.pipeline);
yield pipeline(fs18.createReadStream(file), hash);
result.write(hash.digest());
@@ -80646,7 +80646,7 @@ var require_tool_cache = __commonJS({
exports2.evaluateVersions = exports2.isExplicitVersion = exports2.findFromManifest = exports2.getManifestFromRepo = exports2.findAllVersions = exports2.find = exports2.cacheFile = exports2.cacheDir = exports2.extractZip = exports2.extractXar = exports2.extractTar = exports2.extract7z = exports2.downloadTool = exports2.HTTPError = void 0;
var core14 = __importStar4(require_core());
var io7 = __importStar4(require_io());
var crypto = __importStar4(require("crypto"));
var crypto2 = __importStar4(require("crypto"));
var fs18 = __importStar4(require("fs"));
var mm = __importStar4(require_manifest());
var os5 = __importStar4(require("os"));
@@ -80671,7 +80671,7 @@ var require_tool_cache = __commonJS({
var userAgent = "actions/tool-cache";
function downloadTool2(url, dest, auth, headers) {
return __awaiter4(this, void 0, void 0, function* () {
dest = dest || path19.join(_getTempDirectory(), crypto.randomUUID());
dest = dest || path19.join(_getTempDirectory(), crypto2.randomUUID());
yield io7.mkdirP(path19.dirname(dest));
core14.debug(`Downloading ${url}`);
core14.debug(`Destination ${dest}`);
@@ -81052,7 +81052,7 @@ var require_tool_cache = __commonJS({
function _createExtractFolder(dest) {
return __awaiter4(this, void 0, void 0, function* () {
if (!dest) {
dest = path19.join(_getTempDirectory(), crypto.randomUUID());
dest = path19.join(_getTempDirectory(), crypto2.randomUUID());
}
yield io7.mkdirP(dest);
return dest;
@@ -85649,6 +85649,12 @@ function isHostedRunner() {
process.env["RUNNER_TOOL_CACHE"]?.includes("hostedtoolcache")
);
}
function parseMatrixInput(matrixInput) {
if (matrixInput === void 0 || matrixInput === "null") {
return void 0;
}
return JSON.parse(matrixInput);
}
function wrapError(error2) {
return error2 instanceof Error ? error2 : new Error(String(error2));
}
@@ -86096,6 +86102,25 @@ async function getAnalysisKey() {
core5.exportVariable(analysisKeyEnvVar, analysisKey);
return analysisKey;
}
async function getAutomationID() {
const analysis_key = await getAnalysisKey();
const environment = getRequiredInput("matrix");
return computeAutomationID(analysis_key, environment);
}
function computeAutomationID(analysis_key, environment) {
let automationID = `${analysis_key}/`;
const matrix = parseMatrixInput(environment);
if (matrix !== void 0) {
for (const entry of Object.entries(matrix).sort()) {
if (typeof entry[1] === "string") {
automationID += `${entry[0]}:${entry[1]}/`;
} else {
automationID += `${entry[0]}:/`;
}
}
}
return automationID;
}
// src/caching-utils.ts
var core6 = __toESM(require_core());
@@ -86178,6 +86203,7 @@ var bundleVersion = "codeql-bundle-v2.23.0";
var cliVersion = "2.23.0";
// src/overlay-database-utils.ts
var crypto = __toESM(require("crypto"));
var fs6 = __toESM(require("fs"));
var path7 = __toESM(require("path"));
var actionsCache = __toESM(require_cache3());
@@ -86477,7 +86503,7 @@ async function downloadOverlayBaseDatabaseFromCache(codeql, config, logger) {
}
const dbLocation = config.dbLocation;
const codeQlVersion = (await codeql.getVersion()).version;
const restoreKey = getCacheRestoreKey(config, codeQlVersion);
const restoreKey = await getCacheRestoreKey(config, codeQlVersion);
logger.info(
`Looking in Actions cache for overlay-base database with restore key ${restoreKey}`
);
@@ -86529,9 +86555,21 @@ async function downloadOverlayBaseDatabaseFromCache(codeql, config, logger) {
databaseDownloadDurationMs
};
}
function getCacheRestoreKey(config, codeQlVersion) {
async function getCacheRestoreKey(config, codeQlVersion) {
const languages = [...config.languages].sort().join("_");
return `${CACHE_PREFIX}-${CACHE_VERSION}-${languages}-${codeQlVersion}-`;
const cacheKeyComponents = {
automationID: await getAutomationID()
// Add more components here as needed in the future
};
const componentsHash = createCacheKeyHash(cacheKeyComponents);
return `${CACHE_PREFIX}-${CACHE_VERSION}-${componentsHash}-${languages}-${codeQlVersion}-`;
}
function createCacheKeyHash(components) {
const componentsJson = JSON.stringify(
components,
Object.keys(components).sort()
);
return crypto.createHash("sha256").update(componentsJson).digest("hex").substring(0, 16);
}
// src/tools-features.ts