Skip to content

fix(system): ignore already_exists when saving to GitHub Actions cache - #1302

Open
Soner (shyim) wants to merge 1 commit into
mainfrom
fix/gh-actions-cache-already-exists
Open

fix(system): ignore already_exists when saving to GitHub Actions cache#1302
Soner (shyim) wants to merge 1 commit into
mainfrom
fix/gh-actions-cache-already-exists

Conversation

@shyim

Copy link
Copy Markdown
Member

Problem

Builds using the GitHub Actions cache can fail with:

ERROR	building assets: failed to save folder to GitHub Actions cache: already_exists

Real-world occurrence: FriendsOfShopware/FroshAdminDashboard run #30348425342, where shopware-cli extension zip exited 1 and took down the whole e2e job.

Cause

The GH Actions cache v2 API returns already_exists when an entry for a key has already been uploaded. The asset cache key is deterministic — sw-cli-<shopware-version>-<content-hash> — so this is hit whenever the same commit is re-run, or two jobs build the same extension concurrently.

go-actions-cache maps that response to an error matching os.ErrExist, but Set and StoreFolderCache wrapped every Save error unconditionally. A benign "this is already cached" response therefore propagated up through storeAssetCachebuilding assets and failed the command.

Worth noting: the cache store runs after the assets are already built successfully, so this aborted builds that had completed all their real work.

Fix

Treat os.ErrExist as success in both save paths, matching the idiom the upstream library already uses internally (cache.go:451).

To make this testable, the client field becomes a small actionsCacheClient interface covering the two methods used. *actionscache.Cache satisfies it as-is, so NewGitHubActionsCache is unchanged and there is no production behaviour change.

Tests

Four new cases in internal/system/cache_github_actions_test.go, using a fake client that returns the exact error shape the library builds from a v2 already_exists response (HTTPError{409, GithubAPIError{TypeKey: "ArtifactCacheItemAlreadyExistsException"}}):

Test Asserts
SetIgnoresAlreadyExists Set swallows already-exists
SetReturnsOtherErrors Set still propagates real failures
StoreFolderCacheIgnoresAlreadyExists folder save swallows already-exists
StoreFolderCacheReturnsOtherErrors folder save still propagates real failures

The negative cases pin down that the guard is narrow and genuine cache failures still fail the build.

Verified the tests actually catch the regression: with the errors.Is guards temporarily removed, both positive tests fail with the same message as the CI log, while the two negative tests keep passing.

go build ./..., the full go test ./... suite, and golangci-lint run ./internal/system/... (0 issues) all pass.

🤖 Generated with Claude Code

The GitHub Actions cache v2 API returns `already_exists` when an entry for
a key has already been uploaded. Since the asset cache key is deterministic
(`sw-cli-<shopware-version>-<content-hash>`), this happens on re-runs of the
same commit and when concurrent jobs build the same extension.

`go-actions-cache` maps that response to an error matching `os.ErrExist`,
but both save paths wrapped every error unconditionally, so a benign
"already cached" response propagated up and failed the whole command:

    ERROR building assets: failed to save folder to GitHub Actions cache: already_exists

The store happens after the assets are already built, so this aborted
builds that had completed their actual work.

Treat `os.ErrExist` as success in `Set` and `StoreFolderCache`, matching
the idiom the upstream library uses internally.

To make this testable, the client field is now a small `actionsCacheClient`
interface covering the two methods used, which `*actionscache.Cache`
satisfies as-is, so there is no production behaviour change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 54.20%. Comparing base (1561f6d) to head (1384a0a).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1302      +/-   ##
==========================================
+ Coverage   54.00%   54.20%   +0.19%     
==========================================
  Files         303      303              
  Lines       23453    23457       +4     
==========================================
+ Hits        12666    12715      +49     
+ Misses      10759    10714      -45     
  Partials       28       28              
Flag Coverage Δ
go-test 54.20% <100.00%> (+0.19%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants