Repository navigation
Bundler cache not working due to ephemeral workdir #904
Description
Ensure the following before filing this issue
-
I verified it reproduces with the latest version with
- uses: ruby/setup-ruby@v1(see Versioning policy) -
I tried to reproduce the issue locally by following the workflow steps (including all commands done byruby/setup-ruby, except forDownloading Ruby&Extracting Ruby),
and it did not reproduce locally (if it does reproduce locally, it's not a ruby/setup-ruby issue)
Are you running on a GitHub-hosted runner or a self-hosted runner?
self-hosted runner
Link to the failed workflow job (must be a public workflow job, so the necessary information is available)
N/A
Any other notes?
We use GitHub Actions runners on AWS CodeBuild with a custom Docker image. The Bundler gems caching is unfortunately not working for us - Bundler installs all gems from scratch on every run. I had a look into why, and noticed a difference in the cache key between jobs, e.g.:
# Run 1
Cache key: setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.6-wd-/codebuild/output/src3491982091/src/actions-runner/_work/better_caring/better_caring-with--without--only--Gemfile.lock-3f96ad38961e7a44e242400b976a8833512d7d013bd35c5f24b09672d2fd2667
# Run 2
Cache key: setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.6-wd-/codebuild/output/src1813367680/src/actions-runner/_work/better_caring/better_caring-with--without--only--Gemfile.lock-3f96ad38961e7a44e242400b976a8833512d7d013bd35c5f24b09672d2fd2667
That unfortunately results in being unable to reuse a previous cache.
The cause of the cache key difference is the differing working directory. This looks to be done by CodeBuild for run isolation, which seems fair. I vaguely recall seeing a similar thing with Buildkite.
I looked into the source code of this action to see if the cache key could be configured, and I don't see a way to do that. It seems there is no way to avoid the inclusion of the ephemeral working directory path in the cache key:
Lines 190 to 196 in 7372622
| // cache key | |
| const paths = [cachePath] | |
| const baseKey = await computeBaseKey(engine, rubyVersion, lockFile, cacheVersion) | |
| const key = `${baseKey}-${await common.hashFile(lockFile)}` | |
| // If only Gemfile.lock changes we can reuse part of the cache, and clean old gem versions below | |
| const restoreKeys = [`${baseKey}-`] | |
| console.log(`Cache key: ${key}`) |
One option for us could be to change to using a constant workdir; but I'm not confident we won't run into run isolation problems from doing that.
Please consider allowing omission of the workdir from the cache key. I'd suggest replacing it with another way to identify the project - perhaps the Git remote URL (with special characters substituted as necessary).
Thank you for your work on this project =)
Activity
eregon commentedon Apr 26, 2026
What are you concerned about isolation?
Isn't each build run in Docker, or at least with the directory removed between runs?
I think it's asking for caching issues to change the working directory between runs, especially since GitHub-hosted runners don't do that.
eregon commentedon Apr 26, 2026
IMO this seems a design mistake of AWS CodeBuild to change the working directory every time.
AFAIK it does not provide any extra isolation, unless I'm missing something?
This design choice is also likely to affect other caches & actions as well, I don't think it's good idea to workaround in N actions for something that's fundamentally incompatible due to a choice in AWS CodeBuild.
ntkme commentedon Apr 26, 2026
Yes, it does break other similar actions. For example: Swatinem/rust-cache#229
eregon commentedon Apr 28, 2026
Is there no way to configure AWS CodeBuild to use a stable workspace directory?
Maybe via setting the GITHUB_WORKSPACE env var or so?
If not, could you file an issue to AWS CodeBuild about this? IMO it's their choice making a mess for no reason here.
ZimbiX commentedon Sep 5, 2026
Sorry for the delay in continuing on this.
I couldn't find any documentation on CodeBuild using an ephemeral workdir or how to configure that.
I've recently started using Claude (under sufferance). Taking it through this problem, impressively it quickly came up with a solution. Omitting the most repetitive parts, here it is:
Here's the resulting
buildspec.yaml(the Docker stuff was there already):version: 0.2 phases: pre_build: commands: # CodeBuild gives every build a fresh ephemeral source directory (/codebuild/output/src<random>/src) and installs the GitHub Actions runner into $CODEBUILD_SRC_DIR/actions-runner, so GITHUB_WORKSPACE is different on every build. That breaks any cache keyed on the working directory - notably ruby/setup-ruby's Bundler cache, which embeds the working directory in its cache key. Pointing the runner directory at a static path gives us a stable GITHUB_WORKSPACE of /actions-runner/_work/better_caring/better_caring. # Deliberately swallows errors: if this phase fails, CodeBuild never starts the runner and the GitHub Actions job hangs until someone cancels it. Falling back to the ephemeral path just means slow caching, which is what we had before. - | set -x rm -rf /actions-runner mkdir -p /actions-runner if [ -e "$CODEBUILD_SRC_DIR/actions-runner" ] && [ ! -L "$CODEBUILD_SRC_DIR/actions-runner" ]; then cp -a "$CODEBUILD_SRC_DIR/actions-runner/." /actions-runner/ && rm -rf "$CODEBUILD_SRC_DIR/actions-runner" fi if [ ! -e "$CODEBUILD_SRC_DIR/actions-runner" ] || [ -L "$CODEBUILD_SRC_DIR/actions-runner" ]; then ln -sfn /actions-runner "$CODEBUILD_SRC_DIR/actions-runner" fi ls -la "$CODEBUILD_SRC_DIR" /actions-runner true - echo "Starting Docker daemon" - nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 & - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"And here's our corresponding piece of the GitHub Actions workflow YAML that tells CodeBuild to use this buildspec:
The code added to
pre_buildis not pretty, but it works.Thanks for your feedback and considering my PR. With a known solution now, I'll consider this issue resolved. Cheers