Clear Zig cache directory when it grows too large

Resolves: #21
This commit is contained in:
mlugg
2025-03-10 17:28:47 +00:00
parent 0a889b2ab1
commit 9ac9efd667
3 changed files with 38 additions and 0 deletions
+5
View File
@@ -56,6 +56,11 @@ with all of your matrix variables to ensure that every job is correctly cached.
provide any means for the Action to automatically distinguish jobs in a matrix. However, variables which select
the runner OS can be omitted from the `cache-key`, since the runner OS is included in the cache key by default.
Zig cache directories can get incredibly large over time. By default, this Action will clear the cache directory
once its size exceeds 2 GiB. This threshold can be changed by setting the `cache-size-limit` option to a different
value (in MiB); for instance, `cache-size-limit: 4096` for a 4 GiB limit. The limit can be disabled entirely by
setting `cache-size-limit: 0`.
[mach-nominated]: https://machengine.org/about/nominated-zig/
[matrix]: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow
+4
View File
@@ -16,6 +16,10 @@ inputs:
description: 'Additional cache key component to include when caching the global Zig cache directory. When using a matrix strategy, this should include the matrix variables to ensure all jobs are cached. Matrix variables which decide the OS can be omitted, since the OS is always included in the cache key.'
required: false
default: ''
cache-size-limit:
description: 'The maximum permitted size of the global Zig cache directory, in MiB. When the cache directory exceeds this size, it is cleared. Default is 2048 (2 GiB). 0 means no limit.'
required: true
default: 2048
runs:
using: 'node20'
main: 'main.js'
+29
View File
@@ -1,3 +1,4 @@
const path = require('path');
const fs = require('fs').promises;
const core = require('@actions/core');
const github = require('@actions/github');
@@ -17,6 +18,16 @@ async function main() {
}
if (accessible) {
const size = await totalSize(cache_path);
const size_limit = core.getInput('cache-size-limit') * 1024 * 1024; // MiB -> bytes
if (size_limit !== 0 && size > size_limit) {
core.info(`Cache directory reached ${size} bytes, exceeding limit of ${size_limit} bytes; clearing cache`);
// We want to clear the cache and start over. Unfortunately, we can't programmatically
// remove the old cache entries, so we instead want to save an empty cache directory.
// To do this, delete all the contents of the cache directory before saving the cache.
await rmDirContents(cache_path);
}
const prefix = await common.getCachePrefix();
const name = prefix + github.context.runId;
await cache.saveCache([cache_path], name);
@@ -27,4 +38,22 @@ async function main() {
}
}
async function totalSize(p) {
const stat = await fs.stat(p);
if (stat.isFile()) return stat.size;
if (stat.isDirectory()) {
let total = 0;
for (const entry of await fs.readdir(p)) {
total += await totalSize(path.join(p, entry));
}
return total;
}
return 0;
}
async function rmDirContents(dir) {
const entries = await fs.readdir(dir);
await Promise.all(entries.map(e => fs.rm(path.join(dir, e), { recursive: true, force: true })));
}
main();