fix overly aggressive L1 cache reuse

This commit is contained in:
Emil Lerch 2024-04-29 00:15:04 -07:00
parent 5ad6acd0b1
commit 50b2f79905
Signed by: lobo
GPG Key ID: A7B62D657EF764F8
4 changed files with 34 additions and 15 deletions

9
dist/index.js vendored
View File

@ -82166,17 +82166,18 @@ var require_versions = __commonJS({
x64: "x86_64" x64: "x86_64"
}[arch]; }[arch];
const host = `${resolvedArch}-${resolvedOs}`; const host = `${resolvedArch}-${resolvedOs}`;
const machIndex = await getJSON({ url: "https://machengine.org/zig/index.json" }); const index = version3.includes("mach") ? await getJSON({ url: "https://machengine.org/zig/index.json" }) : await getJSON({ url: "https://ziglang.org/download/index.json" });
const availableVersions = Object.keys(machIndex); const availableVersions = Object.keys(index);
const useVersion = semver2.valid(version3) ? semver2.maxSatisfying(availableVersions.filter((v) => semver2.valid(v)), version3) : null; const useVersion = semver2.valid(version3) ? semver2.maxSatisfying(availableVersions.filter((v) => semver2.valid(v)), version3) : null;
const meta = machIndex[useVersion || version3] || (await getJSON({ url: "https://ziglang.org/download/index.json" }))[useVersion || version3]; const meta = index[useVersion || version3] || (await getJSON({ url: "https://ziglang.org/download/index.json" }))[useVersion || version3];
if (!meta || !meta[host]) { if (!meta || !meta[host]) {
throw new Error(`Could not find version ${useVersion || version3} for platform ${host}`); throw new Error(`Could not find version ${useVersion || version3} for platform ${host}`);
} }
const downloadUrl = meta[host].tarball; const downloadUrl = meta[host].tarball;
const fileWithoutFileType = downloadUrl.match(/.*\/(.*)(\.zip|\.tar\..*$)/)[1]; const fileWithoutFileType = downloadUrl.match(/.*\/(.*)(\.zip|\.tar\..*$)/)[1];
const variantName = path2.basename(meta[host].tarball).replace(`.${ext}`, "").replace(/\+\S*$/, ""); const variantName = path2.basename(meta[host].tarball).replace(`.${ext}`, "").replace(/\+\S*$/, "");
return { downloadUrl, fileWithoutFileType, variantName, version: useVersion || version3 }; const versionFromDownloadUrl = variantName.match(/[^-]*-[^-]*-[^-]*-(.*)/)[1];
return { downloadUrl, fileWithoutFileType, variantName, version: versionFromDownloadUrl };
} }
__name(resolveVersion2, "resolveVersion"); __name(resolveVersion2, "resolveVersion");
module2.exports = { module2.exports = {

View File

@ -17,6 +17,12 @@ const TOOL_NAME = 'zig'
async function downloadZig (arch, platform, version, useCache = true) { async function downloadZig (arch, platform, version, useCache = true) {
const ext = extForPlatform(platform) const ext = extForPlatform(platform)
// There are three levels of data here:
// 1. Local cache - this is literally cache already established with the job
// container, and is a pre-unpacked directory
// 2. Runner cache - this is a cache that is outside the job, but still
// on the host that is running jobs
// 3. The canonical source
const { const {
downloadUrl, downloadUrl,
fileWithoutFileType, fileWithoutFileType,
@ -26,12 +32,14 @@ async function downloadZig (arch, platform, version, useCache = true) {
? resolveCommit(arch, platform, version) ? resolveCommit(arch, platform, version)
: await resolveVersion(arch, platform, version) : await resolveVersion(arch, platform, version)
// Check L1 and return on hit
const cachedPath = toolCache.find(TOOL_NAME, useVersion) const cachedPath = toolCache.find(TOOL_NAME, useVersion)
if (cachedPath) { if (cachedPath) {
actions.info(`using cached zig install (version ${useVersion}): ${cachedPath}`) actions.info(`using cached zig install (version ${useVersion}): ${cachedPath}`)
return cachedPath return cachedPath
} }
// Check L2 and return on hit
const cacheKey = `${TOOL_NAME}-${variantName}` const cacheKey = `${TOOL_NAME}-${variantName}`
if (useCache) { if (useCache) {
const restorePath = path.join(process.env.RUNNER_TOOL_CACHE, TOOL_NAME, useVersion, arch) const restorePath = path.join(process.env.RUNNER_TOOL_CACHE, TOOL_NAME, useVersion, arch)
@ -43,6 +51,7 @@ async function downloadZig (arch, platform, version, useCache = true) {
} }
} }
// Miss on L1 and on L2. Need to go to canonical source
actions.info(`no cached version found. downloading zig ${variantName}`) actions.info(`no cached version found. downloading zig ${variantName}`)
const downloadPath = await toolCache.downloadTool(downloadUrl) const downloadPath = await toolCache.downloadTool(downloadUrl)
const zigPath = ext === 'zip' const zigPath = ext === 'zip'

11
test.js
View File

@ -52,25 +52,25 @@ async function test () {
downloadUrl: 'https://pkg.machengine.org/zig/zig-macos-aarch64-0.12.0-dev.2063+804cee3b9.tar.xz', downloadUrl: 'https://pkg.machengine.org/zig/zig-macos-aarch64-0.12.0-dev.2063+804cee3b9.tar.xz',
fileWithoutFileType: 'zig-macos-aarch64-0.12.0-dev.2063+804cee3b9', fileWithoutFileType: 'zig-macos-aarch64-0.12.0-dev.2063+804cee3b9',
variantName: 'zig-macos-aarch64-0.12.0-dev.2063', variantName: 'zig-macos-aarch64-0.12.0-dev.2063',
version: '2024.1.0-mach' version: '0.12.0-dev.2063'
}) })
assert.deepEqual(await resolveVersion('x64', 'linux', '2024.3.0-mach'), { assert.deepEqual(await resolveVersion('x64', 'linux', '2024.3.0-mach'), {
downloadUrl: 'https://pkg.machengine.org/zig/zig-linux-x86_64-0.12.0-dev.3180+83e578a18.tar.xz', downloadUrl: 'https://pkg.machengine.org/zig/zig-linux-x86_64-0.12.0-dev.3180+83e578a18.tar.xz',
fileWithoutFileType: 'zig-linux-x86_64-0.12.0-dev.3180+83e578a18', fileWithoutFileType: 'zig-linux-x86_64-0.12.0-dev.3180+83e578a18',
variantName: 'zig-linux-x86_64-0.12.0-dev.3180', variantName: 'zig-linux-x86_64-0.12.0-dev.3180',
version: '2024.3.0-mach' version: '0.12.0-dev.3180'
}) })
assert.deepEqual(await resolveVersion('x64', 'win32', '2024.1.0-mach'), { assert.deepEqual(await resolveVersion('x64', 'win32', '2024.1.0-mach'), {
downloadUrl: 'https://pkg.machengine.org/zig/zig-windows-x86_64-0.12.0-dev.2063+804cee3b9.zip', downloadUrl: 'https://pkg.machengine.org/zig/zig-windows-x86_64-0.12.0-dev.2063+804cee3b9.zip',
fileWithoutFileType: 'zig-windows-x86_64-0.12.0-dev.2063+804cee3b9', fileWithoutFileType: 'zig-windows-x86_64-0.12.0-dev.2063+804cee3b9',
variantName: 'zig-windows-x86_64-0.12.0-dev.2063', variantName: 'zig-windows-x86_64-0.12.0-dev.2063',
version: '2024.1.0-mach' version: '0.12.0-dev.2063'
}) })
assert.deepEqual(await resolveVersion('arm64', 'darwin', '2024.3.0-mach'), { assert.deepEqual(await resolveVersion('arm64', 'darwin', '2024.3.0-mach'), {
downloadUrl: 'https://pkg.machengine.org/zig/zig-macos-aarch64-0.12.0-dev.3180+83e578a18.tar.xz', downloadUrl: 'https://pkg.machengine.org/zig/zig-macos-aarch64-0.12.0-dev.3180+83e578a18.tar.xz',
fileWithoutFileType: 'zig-macos-aarch64-0.12.0-dev.3180+83e578a18', fileWithoutFileType: 'zig-macos-aarch64-0.12.0-dev.3180+83e578a18',
variantName: 'zig-macos-aarch64-0.12.0-dev.3180', variantName: 'zig-macos-aarch64-0.12.0-dev.3180',
version: '2024.3.0-mach' version: '0.12.0-dev.3180'
}) })
await assert.doesNotReject(resolveVersion('x64', 'linux', 'mach-latest')) await assert.doesNotReject(resolveVersion('x64', 'linux', 'mach-latest'))
await assert.doesNotReject(resolveVersion('x64', 'win32', 'mach-latest')) await assert.doesNotReject(resolveVersion('x64', 'win32', 'mach-latest'))
@ -78,6 +78,9 @@ async function test () {
await assert.doesNotReject(resolveVersion('x64', 'linux', 'master')) await assert.doesNotReject(resolveVersion('x64', 'linux', 'master'))
await assert.doesNotReject(resolveVersion('x64', 'win32', 'master')) await assert.doesNotReject(resolveVersion('x64', 'win32', 'master'))
await assert.doesNotReject(resolveVersion('arm64', 'darwin', 'master')) await assert.doesNotReject(resolveVersion('arm64', 'darwin', 'master'))
assert.notEqual((await resolveVersion('arm64', 'darwin', 'mach-latest')).version, 'mach-latest')
assert.notEqual((await resolveVersion('arm64', 'darwin', 'master')).version, 'master')
} }
test().catch((error) => { test().catch((error) => {

View File

@ -70,8 +70,8 @@ function getJSON (opts) {
* *
* @returns {string} download URL for the version * @returns {string} download URL for the version
* @returns {string} file without file type (to match the function above) * @returns {string} file without file type (to match the function above)
* @returns {string} variant name for the version - should be used as cache key * @returns {string} variant name for the version - used as L2 (runner) cache key
* @returns {string} version name - use for display only * @returns {string} version name - used as the L1 (job) cache key
*/ */
async function resolveVersion (arch, platform, version) { async function resolveVersion (arch, platform, version) {
const ext = extForPlatform(platform) const ext = extForPlatform(platform)
@ -91,17 +91,21 @@ async function resolveVersion (arch, platform, version) {
const host = `${resolvedArch}-${resolvedOs}` const host = `${resolvedArch}-${resolvedOs}`
// const index = await getJSON({ url: 'https://ziglang.org/download/index.json' }) // Mach json is advertised as a superset, but it's not updated on the same
const machIndex = await getJSON({ url: 'https://machengine.org/zig/index.json' }) // timeframe as the ZSF index.json. So notably, 'master' will be an old version
// on machengine.org
const index = version.includes('mach')
? await getJSON({ url: 'https://machengine.org/zig/index.json' })
: await getJSON({ url: 'https://ziglang.org/download/index.json' })
const availableVersions = Object.keys(machIndex) const availableVersions = Object.keys(index)
const useVersion = semver.valid(version) const useVersion = semver.valid(version)
? semver.maxSatisfying(availableVersions.filter((v) => semver.valid(v)), version) ? semver.maxSatisfying(availableVersions.filter((v) => semver.valid(v)), version)
: null : null
// The mach index is advertised as a strict superset of the ziglang index, // The mach index is advertised as a strict superset of the ziglang index,
// but we will fall back to the the ziglang index just in case // but we will fall back to the the ziglang index just in case
const meta = machIndex[useVersion || version] || const meta = index[useVersion || version] ||
(await getJSON({ url: 'https://ziglang.org/download/index.json' }))[useVersion || version] (await getJSON({ url: 'https://ziglang.org/download/index.json' }))[useVersion || version]
if (!meta || !meta[host]) { if (!meta || !meta[host]) {
@ -117,7 +121,9 @@ async function resolveVersion (arch, platform, version) {
// it. This is important as it is used as the cache key // it. This is important as it is used as the cache key
const variantName = path.basename(meta[host].tarball).replace(`.${ext}`, '').replace(/\+\S*$/, '') const variantName = path.basename(meta[host].tarball).replace(`.${ext}`, '').replace(/\+\S*$/, '')
return { downloadUrl, fileWithoutFileType, variantName, version: useVersion || version } const versionFromDownloadUrl = variantName.match(/[^-]*-[^-]*-[^-]*-(.*)/)[1]
return { downloadUrl, fileWithoutFileType, variantName, version: versionFromDownloadUrl }
} }
module.exports = { module.exports = {