Repository navigation
Releases: jdx/mr-boxington-action
Release list
v1.7.2: Fix isolated objects-cache cleanup with mbx 1.22 and add clean-target-before-export
Cleanup of the isolated objects cache now works with the read-only object trees that mbx 1.22 creates. A new opt-in input, clean-target-before-export, frees runner disk space before the bundle is exported. Both changes apply only with isolate-objects-cache: true.
Added
-
clean-target-before-exportinput (#68, @donbeave). Defaults tofalse. When set, the post step runsmbx cleanfor the configured workspace just before it exports the isolated objects bundle. This removes the workspace's managed Cargo target and learned incremental state, so the target and the staged bundle are not both on disk at the same time. The mbx action results and objects stay in the isolated store and are exported as usual.- uses: jdx/mr-boxington-action@v1 with: github-cache-mode: objects isolate-objects-cache: true clean-target-before-export: true
The input requires
isolate-objects-cache: true, and setup fails without it. Cleanup runs only when the action is going to save after a cache miss. Restore-only runs and exact cache hits skip it. If cleanup fails, the action doesn't export the bundle. Enable this input only when no later step in the job needs the target tree. The disk-usage diagnostics also record a sample after cleanup and before export.
Fixed
- Removing isolated objects-cache directories with mbx 1.22 (#62, @donbeave). mbx 1.22 creates object-cache
OUT_DIRtrees that are read-only. Because of this, the action could not delete the isolated store or bundle after a successful import or during post-step cleanup. The action now restores owner write access across its own tree before deleting it. On Windows, it also clears the read-only flag on files. Symlinks inside the tree are not followed, so their targets outside the tree are left unchanged.
Full Changelog: v1.7.1...v1.7.2
v1.7.1: More accurate disk-usage reporting in isolated objects-cache mode
Fixes the disk-usage diagnostics that the post step logs when isolate-objects-cache: true is set. Cache restore and save behavior is unchanged.
Fixed
- Disk-usage summary for
isolate-objects-cache(#60, @donbeave). TheObjects cache samplesummary in the post step is now more accurate and more reliable:- The action now waits for any sample still in progress and takes one last sample before it prints the summary. Before, the summary could be printed before sampling had finished, so it could miss the final disk usage.
- When a diagnostic sample fails, the failure no longer replaces the actual result of the cache operation. If the restore or save itself failed, that original error is still the one reported. The summary records the number of sampling failures and a short reason code, such as
code:EIO, without including file paths. - The archive-size figures now count
cache.tarstaging files, which are used on Windows runners, as well ascache.tgz.
Full Changelog: v1.7.0...v1.7.1
v1.7.0: Isolated objects cache and cache key suffixes
Parallel jobs can now save under their own primary keys with cache-key-suffix. On disposable hosted runners, the GitHub objects payload can now run from a private, job-scoped store with isolate-objects-cache. Both inputs are opt-in, so existing workflows are unaffected.
Added
-
cache-key-suffixinput (#58, @donbeave). The suffix is added to the end of the generated primary key, so matrix or parallel jobs save their own entries. It does not change the generated restore prefixes, so any job can still warm-start from another job's compatible entry.- uses: jdx/mr-boxington-action@v1 with: cache-key-suffix: ${{ matrix.job }}
The suffix may only contain ASCII letters, numbers, periods, underscores, and hyphens. The final key must be at most 512 characters. Setting both
cache-key-suffixandcache-keyis an error, so usecache-keyon its own when you supply the full primary key. Explicitrestore-keysare used as given. -
isolate-objects-cacheinput (#58, @donbeave). Defaults tofalseand requiresbackend: githubwithgithub-cache-mode: objects. Setup fails if you enable it with any other backend or mode. When it is on:- The live mbx store (
MBX_CACHE_DIR) is placed in a private directory underRUNNER_TEMP. - On restore, the bundle is imported and then deleted.
- On save, the action exports a bundle and checks it. It then deletes the isolated store before
actions/cachepacks its upload archive, so the job doesn't keep two copies on disk at once. Only the exported bundle is saved.
- uses: jdx/mr-boxington-action@v1 with: github-cache-mode: objects isolate-objects-cache: true
The private directory is cleaned up whether the post step succeeds or fails. Use this mode only on disposable hosted runners. Leave it off on persistent runners that rely on mbx's normal warm store. Use one isolated objects-cache step per job. The bundle path is fixed so the cache version matches across jobs and runs.
In this mode, the post step also logs disk usage at each stage. It sorts save failures by cause:
- Another job reserving or finalizing the same key, GitHub cache service 5xx errors, and network failures produce a warning, and the job continues.
- Running out of disk while staging the archive, or any save result the action can't identify, fails the step.
- The live mbx store (
New Contributors
Full Changelog: v1.6.0...v1.7.0
v1.6.0: Opt-in cache saves from pull requests and protected branches, plus a `remote` backend
With the GitHub backend, pull requests and protected branches can now save their own cache entries, so later PR revisions reuse what earlier ones built. A new remote backend uses MBX_REMOTE_* settings exported by earlier steps instead of overwriting them. backend: server now works as an alias of remote, with small behavior changes listed below.
Added
-
Opt-in saving from pull requests and protected branches (#48, #52, @garysassano). Until now, only default-branch pushes and opted-in
workflow_dispatchruns saved, so every PR revision restored the default branch's baseline and rebuilt what the previous revision had already compiled. Two new inputs, both defaulting tofalse:save-on-pull-requestsaves after a successfulpull_requestrun from the same repository onrefs/pull/<number>/merge. GitHub scopes these entries to that PR. Fork PRs andpull_request_targetruns never save.save-on-protected-branchsaves after a successful push to a non-default branch whereGITHUB_REF_PROTECTED=true.
- uses: jdx/mr-boxington-action@v1 with: save-on-pull-request: true
A saving PR run gets a run-unique primary key (
<sha>-run-<id>-<attempt>), socache-hitis alwaysfalseon those runs. Whenrestore-keysis not set, the generated restore keys check the PR's own entries on the current base first, then the PR's newest entry on any base, then the base branch's latest entry. An explicitcache-keyis used as given, with no per-run suffix. PR entries count toward the 10 GB repository cache limit. You can remove them when a PR closes withgh cache delete --all --ref refs/pull/<number>/merge. -
New
cache-save-eligibleandcache-save-reasonoutputs (#48, @garysassano) show whether a run may save and why, for examplerestore only (fork pull request). The same reason appears in the log and the job summary. The action now also follows the job'sACTIONS_CACHE_MODE: if it isreadornone, a run that would otherwise save is reported as not saving, and the action no longer prunes and exports a payload that would be thrown away. -
remotebackend (#53, @jdx). This backend installs mbx and uses whatever remote an earlier step already set up, such as a runner action that exportsMBX_REMOTE_URLfor an S3 bucket. Each input you set is exported as itsMBX_REMOTE_*variable and overrides the environment. Settings with no input are left alone, including anyAWS_*credentials. Newremote-url(a cache server URL or ans3://bucket) andremote-modeinputs are added.server-urlandserver-modestill work as aliases, but setting both spellings to different values is an error.- run: | echo "MBX_REMOTE_URL=s3://acme-build-cache/mbx" >> "$GITHUB_ENV" echo "MBX_REMOTE_NAMESPACE=acme/backend" >> "$GITHUB_ENV" - uses: jdx/mr-boxington-action@v1 with: backend: remote
During setup, the action runs
mbx doctor --jsonto check the remote:- If no remote is configured, the step fails.
- If mbx rejects the configuration, the step fails with mbx's reason.
- If the remote can't be reached, the step only warns, so a cache outage doesn't fail the job.
The job summary shows the remote and both the configured and effective mode.
Fixed
- The README said mbx disables the remote cache on tags and releases. That was wrong: those runs can still read from it but not write to it (#53).
- Updated the bundled
undicito 6.29.0 andbrace-expansionto 1.1.21 to fixnpm auditfindings (#57, @jdx).
Breaking Changes
These apply to existing backend: server users (#53):
server-modeno longer defaults toread-write. Before, the action always exportedMBX_REMOTE_MODE=read-write, which overrode any mode set earlier in the job. mbx's own default is stillread-write, so workflows that set no mode anywhere behave the same as before.- Setup now makes one network request to the remote through
mbx doctor. A configuration mbx rejects now fails setup instead of the first build. A missing namespace still fails setup, as it did before. - With
backend: remote/server, the step now fails if no remote is configured anywhere. Before, it fell back to the local cache without saying so. Make sure any step that setsMBX_REMOTE_*runs before this action.
Full Changelog: v1.5.0...v1.6.0
v1.5.0: Cache a Cargo workspace below the checkout root
A new working-directory input lets the default target payload cache a Cargo workspace that lives in a subdirectory of the repository, such as rust/ next to a TypeScript package. It defaults to ., so existing workflows work the same as before.
Added
-
working-directoryinput for thetargetpayload (#46, @garysassano). Until now, thetargetpayload always cached./targetand rancargo metadatafrom the job's working directory. That broke when the workspace sat below the checkout root: the restore went to a roottarget/that Cargo never writes to. On saving runs, the post step then either skipped the save or failed because there was no root manifest. Withworking-directoryset, the action now:- caches
<working-directory>/target - sets up build-script shims in that directory
- runs the post-step
cargo metadataprune in that workspace
The path is resolved relative to the job's working directory. If the directory doesn't exist, setup fails instead of silently caching nothing.
- uses: jdx/mr-boxington-action@v1 with: working-directory: rust - run: mbx test --workspace working-directory: rust
The cached tree is still always
<workspace>/target. A customCARGO_TARGET_DIRorbuild.target-diris not followed. - caches
New Contributors
- @garysassano made their first contribution in #46
Full Changelog: v1.4.0...v1.5.0
v1.4.0: Faster object-mode restores from a directory bundle
github-cache-mode: objects now transports the mbx bundle as a directory instead of a tar when the installed mbx is 1.12.0 or newer, cutting warm-restore import time substantially. No workflow changes are needed, but object-mode caches restore cold once after the switch.
Changed
- Object-mode caches are saved and restored as a directory bundle (#41, @jdx).
actions/cachearchives whatever path it is given, so wrapping a tar inside it meant every byte was unpacked twice on a warm restore: once by the cache action and again bymbx cache import. The post step now runsmbx cache export --format directoryand the importer reads the restored tree in place. On a warm restore of a 4,071-object / 1.4 GiB closure onubuntu-24.04,mbx cache importdropped from 6.46s to 2.02s; the cache action's own restore got about 1.3s slower because it handles ~5,000 files instead of one archive, for a net saving of roughly 3.1s before the build starts (single-trial measurements).targetmode is unchanged.- Version-gated.
--format directoryarrived in mbx 1.12.0 and older binaries reject the flag, so the form follows the version actually installed. Versions below 1.12.0, and anything that does not parse as a version, keep using a tar so exports do not fail. - Separate cache keys. A tar entry and a directory entry cannot restore each other. Directory bundles add a
-dirsuffix to the generation segment of the generated key (for examplelinux-x64-mbx-v1-dir-rust-<hash>-<sha>), while the tar form keeps the bare generation it has always used, so entries saved before this release still restore for older mbx versions. Workflows that assert oncache-primary-keyoutput should allow for the extra segment. - The job summary's Payload row now reports
mbx objects (directory)ormbx objects (tar)so you can see which form a run used.
- Version-gated.
Breaking Changes
- The first object-mode job after the installed mbx crosses 1.12.0 (including
version: latestpicking it up automatically) restores cold once because the directory bundle uses a new cache key. Warm caches rebuild on the next default-branch save; no configuration change is required.
Full Changelog: v1.3.1...v1.4.0
v1.3.1: Preserve imported objects on hosted runners
A small release. The main change fixes cache eviction that could break object-mode caching on GitHub-hosted runners, plus a documentation cleanup.
Fixed
- Imported objects survive automatic GC on GitHub-hosted runners (#37, @jdx). A restored object bundle can exceed mbx's local disk budget on a GitHub-hosted runner, so automatic garbage collection could evict objects after the first build. That caused later commands to miss the cache and the post-job export to fail with
action result is missing. Forbackend: githubwithgithub-cache-mode: objects, the action now defaultsMBX_GC_AUTO=0whenRUNNER_ENVIRONMENTisgithub-hostedand the variable is unset, exporting it before invoking mbx so it applies for the whole job. ExplicitMBX_GC_AUTOvalues are respected, and self-hosted/unknown runners,targetmode, and other backends are unchanged. With cleanup disabled the cache can grow for the duration of the job; setMBX_GC_AUTO=1to keep automatic cleanup, or setMBX_GC_AUTO=0on a disposable self-hosted runner to opt into the same behavior.
Documentation
- Dropped the CI performance warning (#32, @jdx). Removed the README note advising that mbx does not yet consistently outperform
Swatinem/rust-cacheon GitHub-hosted runners; the defaulttargetpayload now measures within noise on paired same-runner trials. The cache-mode section still carries the measured numbers and tradeoffs.
Full Changelog: v1.3.0...v1.3.1
v1.3.0: Warm target-tree caching by default, plus a local backend
This release changes what the GitHub Actions backend caches by default: it now transports Cargo's pruned target tree and registry so restored jobs incremental-compile like a rust-cache-style workflow, with the previous portable objects closure still available behind a new input. It also adds a local filesystem backend and removes the long-deprecated max-size input.
Added
localbackend (#28, @jdx). Setbackend: localto install or reusembxand keep its store on the filesystem, with no GitHub Actions cache restore/save and no remote transport. Useful on persistent runners or when a volume action mountsmbx's cache directory.- uses: jdx/mr-boxington-action@v1 with: backend: local - run: mbx test --workspace
github-cache-modeinput (#31, @jdx). Chooses the GitHub cache payload: the newtargettree (default) or the portableobjectsclosure. Useobjectsfor workflows whose builds must share across differing target directories or checkout layouts.- uses: jdx/mr-boxington-action@v1 with: github-cache-mode: objects - run: mbx test --workspace
Changed
- GitHub cache defaults to a warm Cargo target tree (#31, @jdx). The default backend now restores Cargo's pruned
targetdirectory and registry from the previous compatible build, so a job that edits a few files recompiles only those crates. Before saving, the post step removes final products and unrelated Cargo state while retaining fingerprints, dependencies, build-script state, and the registry. Fullmbxexecutables used by build-script shims (including legacy hard-linked copies) are stripped from the archive and rehydrated from the installedmbxafter restore; tiny launchers and Cargo freshness timestamps stay intact. Intargetmode the action disables mbx-managed target views and native-link object caching so it transports a single archive. Whenversionpins an exact release, that archive also carries onembxexecutable so later warm jobs skip a separate release download. Opt back into the old behavior withgithub-cache-mode: objects. In paired GitHub-hosted measurements thetargetpayload restored and built a small edit roughly ten seconds faster thanobjects.
Removed
max-sizeinput (#30, @jdx). Removed the deprecated input, which has done nothing since the GitHub backend moved to closure-bundle exports. There is no runtime behavior change; a workflow still passingmax-sizewill only get an unexpected-input warning from the runner.
Breaking Changes
- The GitHub backend's default cache payload changed from
objectstotarget, using a distinct cache key, so existing entries will not be reused on the first run after upgrading. Warm caches rebuild automatically on the next default-branch save. To keep the prior behavior, setgithub-cache-mode: objects. - The
max-sizeinput no longer exists; remove it from workflows to avoid an unexpected-input warning.
Full Changelog: v1.2.0...v1.3.0
v1.2.0: Use mbx from PATH when version is omitted
A small release. The action now reuses an existing mbx on PATH when you leave version unset, only downloading a release when none is found, and it prefers an exported GITHUB_TOKEN for release metadata lookups. The README also gains an honest look at current CI caching performance.
Changed
versionnow defaults to usingmbxfromPATH(#27, @jdx). Whenversionis omitted, the action probes for an existingmbx(viambx --version) and uses it as-is, downloading the latest release only when nothing is found. Settingversionexplicitly (includinglatest) still forces the verified release install path. This avoids reinstallingmbxon runners that already provide it. Version parsing also accepts prerelease and build-metadata formats such as1.3.1-beta.2+build.4.# Reuse mbx already on PATH, fall back to latest if absent - uses: jdx/mr-boxington-action@v1 # Always install a specific release - uses: jdx/mr-boxington-action@v1 with: version: "0.4.0"
- Release metadata requests prefer
GITHUB_TOKEN(#27, @jdx). When aGITHUB_TOKENis exported in the environment, it is used to resolve mbx release metadata; otherwise the action falls back to thegithub-tokeninput. Either path still requirescontents: read.
Documentation
- Current CI performance disclosure (#23, @jdx). The README now states plainly that mbx does not yet reliably outperform
Swatinem/rust-cacheon GitHub-hosted runners, publishes warm benchmark comparisons for both the server and GitHub-cache backends, and advises benchmarking your complete job (including restore/import/export overhead) before switching.
Full Changelog: v1.1.0...v1.2.0
v1.1.0: Exact build closures and toolchain-scoped cache keys
This release reworks GitHub Actions caching to store exact mbx build closures instead of the whole local store, scopes generated cache keys by Rust toolchain identity so caches survive compiler bumps, and adds opt-in cache seeding for trusted manual dispatches. It also improves diagnostics when the GitHub cache runtime is unavailable.
Highlights
- Cache keys are now scoped to the exact Rust compiler your build uses, so a runner-image toolchain rollout no longer silently discards a warm cache. A new
toolchaininput lets you point the key at the toolchain your build names directly. - GitHub cache saves now upload a single portable build closure bundle rather than the whole store, cutting payload size substantially (measured at ~48% fewer uncompressed bytes on a real project after one historical revision accumulated).
Added
- Toolchain-scoped cache keys (#16, @jdx). Generated primary keys and restore prefixes now carry a
rust-<sha256(rustc -vV)[..12]>segment (${platform}-${architecture}-mbx-${generation}-${toolchain}-${commit}), giving each toolchain its own cache entry. This fixes warm caches reporting zero hits after a runner image bumps its preinstalled Rust. Runners with norustconPATHfall back to the literalnorustand log guidance to install the toolchain before this action. toolchaininput (#17, @jdx). Tell the action which toolchain your build uses so the key follows that compiler instead of whateverrustconPATHresolves to. Useful when a build invokes a specific toolchain on its own command line:Either- uses: jdx/mr-boxington-action@v1 with: toolchain: "1.91" - run: mbx +1.91 check --workspace
1.91or+1.91works. The input scopes the key only; it does not install or select a toolchain. Leaving it unset keeps the barerustc -vVprobe sorust-toolchain.tomloverrides are still honored.save-on-workflow-dispatchinput (#18, @jdx). Off by default. When enabled, trusted manualworkflow_dispatchruns may write the cache (including from non-default branches), letting benchmark and seeding workflows warm a fresh cache generation. Pull requests and non-default-branch pushes remain restore-only.cache-linksinput (#15, @jdx). Controls native link caching viaMBX_CACHE_LINKS. Defaults toauto, which enables it only on Linux; settrue/falseto force it on other platforms. A controlled warm Linux build fell from 124.7s to 84.9s (~32% faster) in benchmarking.
Changed
- GitHub cache stores exact build closures (#20, @jdx). Instead of archiving the entire local store, each job is assigned a unique
MBX_CACHE_EXPORT_GROUP, restores a single portable bundle viambx cache import, and exports its deduplicated closure in the post step. Jobs that never completed an mbx build skip the save while real export failures still surface. Requires mbx 1.1.0 or newer. The new cache path uses a distinct GitHub cache version, so existing whole-store entries are not misread as bundles. - Rolling keys for saving dispatches (#19, @jdx). Because GitHub cache entries are immutable, opted-in
workflow_dispatchruns now receive a fresh primary key per run/attempt while still restoring from the compatible generation prefix, so repeated dispatches progressively warm the cache. Push, pull-request, and restore-only key behavior is unchanged.
Fixed
- Clearer diagnostics for an unavailable GitHub cache runtime (#22, @jdx). The action now validates runner-injected cache credentials (both cache service v1 and v2) before installing mbx and fails early with an explicit message, instead of proceeding and later reporting a misleading
No mbx cache found. Running the bundle outside auses:action step is now reported distinctly from an ordinary cache miss.
Deprecated
max-size(#20, @jdx). It no longer applies now that the cached payload is the exact action closure and is ignored for closure exports.
Full Changelog: v1.0.1...v1.1.0