Optimize CI caches#37387
Merged
silverwind merged 27 commits intogo-gitea:mainfrom Apr 26, 2026
Merged
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
All five jobs in pull-db-tests.yml relied on setup-go@v6's default cache, which keys solely on hash(go.sum). Each job builds with a different combination of TAGS, GOEXPERIMENT and -race, producing disjoint Go build-cache entries — but GitHub Actions cache is first-writer-wins on a given key, so only one job's entries survived, making the restore a near-total miss for the other four. Disable setup-go's built-in cache and add a per-job actions/cache step keyed by job name, so each configuration gets its own slot. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
The test-unit job invoked 'make unit-test-coverage', which passes
-coverprofile to 'go test'. That flag is not in Go's cacheable-flags
allowlist, so it silently disables the test result cache for every
unit-test package on every run.
The coverage.out output is unused: no workflow calls 'make coverage'
(its only consumer), and no codecov/coveralls integration exists.
The matching test-mysql job comment ('at the moment, no coverage is
really handled') confirms coverage has been dead for some time.
Switch to 'make test-backend', preserving the 20m timeout via
GOTESTFLAGS. On warm runs with an intact build cache, unchanged
unit-test packages are now skipped entirely.
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
With a fixed key, actions/cache skips the save step on an exact-key
restore ('Cache hit occurred on the primary key ..., not saving
cache.'). That traps $GOCACHE at whatever state first populated it
— any newly-added entries (including Go's test result cache, now
that -coverprofile is gone) are discarded at job end.
Add ${{ github.run_id }} to the primary key and move the original
key into restore-keys. Every run saves a fresh snapshot; subsequent
runs restore the latest one via the prefix fallback. Old entries
age out via GitHub's 7-day cache TTL and 10 GB per-repo LRU.
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Cosmetic. Each job's prefix word is unique in our cache namespace, so no cross-job partial match is possible. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
- Module cache (~/go/pkg/mod) now lives in its own actions/cache step with a deterministic key shared across every Go job (all workflows). Identical content for a given go.sum regardless of TAGS/race/tool, so one snapshot serves all. Cuts ~500 MB of duplicated storage per job. - Build cache (~/.cache/go-build) stays per-job and keeps the run_id rotation so newly-populated entries (including the test result cache) actually persist. Single restore-key prefix; the bare-prefix fallback removed as unnecessary. - Added runner.arch to all keys for safety. - Extended the same pattern to test-e2e (which also compiles the gitea binary) and to the compliance Go jobs (lint-backend, lint-go-windows, lint-go-gogit, checks-backend, backend). - Added a golangci-lint cache (~/.cache/golangci-lint) to the three lint-go* jobs, keyed on go.sum + .golangci.yml. 'make lint-go' uses 'go run', which picks up the cache automatically without any Makefile change. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Race detection roughly doubles test-execution time. Integration tests rarely surface races that unit tests don't: the 239-file integration suite has only 13 occurrences of go func / sync primitives across 6 files, and zero t.Parallel() calls. Recent race fixes in this repo (e.g. container blob upload, go-gitea#36524) were developed with targeted unit tests, not caught by integration runs. Keep -race on test-unit (where all t.Parallel() tests live) and test-sqlite (preserves one integration-level race signal without a DB container). Drop it from pgsql and mysql, which are the critical-path jobs. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Both jobs have small gobuild caches relative to their value: - checks-backend: cache was 244 MB, job runs ~2 min cold - test-e2e: Go compile is a small fraction of runtime (dominated by playwright setup and browser tests) Keep the shared gomod cache on both (single slot, benefits everyone). Trading ~1 GB of cache storage for ~30s-1min extra compile on two non-critical-path jobs. The 'actions' compliance lint job was already uncached; left untouched. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Replace the per-workflow actions/cache@v5 blocks with a shared .github/actions/go-cache composite action. All 11 Go jobs across pull-db-tests, pull-compliance, and pull-e2e-tests now call it with a job name (and optionally build-cache / lint-cache / build-cache-rotate). Storage shape after this: - gomod cache: deterministic key shared across every Go job; one save per unique go.sum. - gobuild cache: stable key for every job except test-unit, which rotates with github.run_id so Go's test result cache can accumulate (~60% speedup on that job once populated). - golangci-lint cache: stable key per lint job, saves once per (go.sum + .golangci.yml) change. Effect: most PR runs write ~1.8 GB of fresh cache (test-unit only) instead of ~14 GB across all jobs. Steady-state fits comfortably under GitHub's 10 GB per-repo cap. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
d82d9ef to
f896743
Compare
- Stable gobuild cache key drops per-job segment; all non-rotating Go jobs share one slot (test-unit still rotates). Go's content-addressing keeps multi-config entries safely coexisting. - Add restore-keys prefix fallbacks on stable gobuild and golangci-lint keys so go.sum bumps and release-branch PRs still get partial cache restores via main's default-branch scope. - New cache-seeder.yml: on push to main, populates gobuild (three TAGS configs in one $GOCACHE, saved to the shared slot) and the three golangci-lint caches. PRs then read those seeds via GitHub's cross-scope fallback. Storage footprint in main's scope: ~3 GB seeded (gomod ~900 MB + shared gobuild ~1.5 GB + 3 lint ~900 MB), comfortably under the 10 GB per-repo cap. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Yamllint rejects the column-aligned inline mappings; collapse to single spaces after commas. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Signed-off-by: silverwind <me@silverwind.io>
actionlint requires 'description' in composite action metadata; removing it fails lint-actions. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Rotating cache's restore-keys previously only fell back to other
test-unit-specific keys, leaving first-ever PR runs of test-unit
cold on the build cache even when the main-branch seeder had
populated the shared 'gobuild-${os}-${arch}-${gosum}' slot.
Add two more fallback prefixes so the rotating key can prefix-match
the seeded shared key and restore its compile-cache content.
Collapsed the blank lines between cache steps for compactness.
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a new Go caching strategy for CI intended to reduce workflow runtime by reusing Go module/build and golangci-lint caches across jobs and runs, and adjusts test invocations/flags to improve cache hit rates.
Changes:
- Add a composite action (
.github/actions/go-cache) and wire it into PR workflows, disablingsetup-go’s built-in cache. - Add a
cache-seederworkflow onpushtomainto pre-populate caches for PR fallback restores. - Adjust unit test commands/flags (drop coverage target; add
GOTESTFLAGS) and removeRACE_ENABLEDfrom MySQL/Postgres integration jobs.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/pull-e2e-tests.yml | Disables setup-go cache and adds go-cache action for the e2e job (build cache disabled). |
| .github/workflows/pull-db-tests.yml | Adds go-cache usage across DB/unit jobs; adjusts unit test make targets/flags; removes race for mysql/pgsql. |
| .github/workflows/pull-compliance.yml | Adds go-cache usage for backend build/lint/check jobs (including golangci-lint cache). |
| .github/workflows/cache-seeder.yml | New workflow to warm caches on main pushes by building and running lints with caches enabled. |
| .github/actions/go-cache/action.yml | New composite action implementing Go module/build and golangci-lint caches via actions/cache. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wxiaoguang
reviewed
Apr 24, 2026
wxiaoguang
reviewed
Apr 24, 2026
Addressing maintainer feedback: 'name:' clashes with top-level action metadata and reads ambiguously at call sites. 'cache-name:' labels exactly what the value represents. Also adds a header comment on cache-seeder explaining the per-ref cache scoping and why the seeder only runs on push-to-main. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
silverwind
commented
Apr 24, 2026
Signed-off-by: silverwind <me@silverwind.io>
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Member
Author
|
|
bircni
approved these changes
Apr 26, 2026
silverwind
added a commit
to silverwind/gitea
that referenced
this pull request
Apr 26, 2026
* origin/main: Optimize CI caches (go-gitea#37387)
silverwind
added a commit
to McMichalK/gitea
that referenced
this pull request
Apr 26, 2026
* origin/main: (176 commits) Refactor pull request view (3) (go-gitea#37439) Update 1.26.1 changelog in main (go-gitea#37442) Make GetPossibleUserByID can handle deleted user (go-gitea#37430) Fix fetch action redirect (go-gitea#37437) Refactor integration test DecodeJSON calls to use generic return value (go-gitea#37432) Integrate renovate bot for all dependency updates (go-gitea#37050) Refactor pull request view (2) (go-gitea#37428) Use MarkLongPolling instead of hard-coded route path (go-gitea#37427) Optimize CI caches (go-gitea#37387) Update AGENTS.md (go-gitea#37420) Update Nix flake (go-gitea#37425) [skip ci] Updated translations via Crowdin remove excessive quote from terraform instructions (go-gitea#37424) Improve testing init, clean up webhook tests (go-gitea#37412) Fix color regressions, add `priority` color (go-gitea#37417) [skip ci] Updated translations via Crowdin Stabilize e2e logout propagation test (go-gitea#37403) refactor: serve site manifest via `/assets/site-manifest.json` endpoint (go-gitea#37405) feat(security): set X-Content-Type-Options: nosniff by default (go-gitea#37354) Refactor pull request view (1) (go-gitea#37380) ... # Conflicts: # templates/repo/diff/box.tmpl
zjjhot
added a commit
to zjjhot/gitea
that referenced
this pull request
Apr 27, 2026
* main: (33 commits) refactor: use named `Permission` field in `Repository` struct instead of anonymous embedding (go-gitea#37441) Refactor pull request view (3) (go-gitea#37439) Update 1.26.1 changelog in main (go-gitea#37442) Make GetPossibleUserByID can handle deleted user (go-gitea#37430) Fix fetch action redirect (go-gitea#37437) Refactor integration test DecodeJSON calls to use generic return value (go-gitea#37432) Integrate renovate bot for all dependency updates (go-gitea#37050) Refactor pull request view (2) (go-gitea#37428) Use MarkLongPolling instead of hard-coded route path (go-gitea#37427) Optimize CI caches (go-gitea#37387) Update AGENTS.md (go-gitea#37420) Update Nix flake (go-gitea#37425) [skip ci] Updated translations via Crowdin remove excessive quote from terraform instructions (go-gitea#37424) Improve testing init, clean up webhook tests (go-gitea#37412) Fix color regressions, add `priority` color (go-gitea#37417) [skip ci] Updated translations via Crowdin Stabilize e2e logout propagation test (go-gitea#37403) refactor: serve site manifest via `/assets/site-manifest.json` endpoint (go-gitea#37405) feat(security): set X-Content-Type-Options: nosniff by default (go-gitea#37354) ...
silverwind
added a commit
to hanism01/gitea
that referenced
this pull request
Apr 27, 2026
…-review-feedback * origin/main: (144 commits) Add API endpoint to reply to pull request review comments (go-gitea#36683) Add CurrentURL template variable back (go-gitea#37444) refactor: use named `Permission` field in `Repository` struct instead of anonymous embedding (go-gitea#37441) Refactor pull request view (3) (go-gitea#37439) Update 1.26.1 changelog in main (go-gitea#37442) Make GetPossibleUserByID can handle deleted user (go-gitea#37430) Fix fetch action redirect (go-gitea#37437) Refactor integration test DecodeJSON calls to use generic return value (go-gitea#37432) Integrate renovate bot for all dependency updates (go-gitea#37050) Refactor pull request view (2) (go-gitea#37428) Use MarkLongPolling instead of hard-coded route path (go-gitea#37427) Optimize CI caches (go-gitea#37387) Update AGENTS.md (go-gitea#37420) Update Nix flake (go-gitea#37425) [skip ci] Updated translations via Crowdin remove excessive quote from terraform instructions (go-gitea#37424) Improve testing init, clean up webhook tests (go-gitea#37412) Fix color regressions, add `priority` color (go-gitea#37417) [skip ci] Updated translations via Crowdin Stabilize e2e logout propagation test (go-gitea#37403) ... # Conflicts: # models/project/column.go # routers/web/repo/issue_page_meta.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cache includes go, lint and unittests. Integration tests with their standalone binaries are uncacheable with their current architecture. Summary from Claude below.
Every Go job uses a new composite action (
.github/actions/go-cache) that restores and saves the Go module cache, a shared build cache, and the golangci-lint cache. Acache-seederworkflow runs onpush: mainto pre-populate those slots; PRs read them via GitHub's default-branch fallback, so the common case is warm from the first commit.Also dropped
-coverprofilefromtest-unit(it silently disabled Go's test result cache), and-racefromtest-pgsqlandtest-mysql(kept ontest-unitandtest-sqlite).Warm-cache runtime (last run before this PR vs latest run here)
This PR was written with the help of Claude Opus 4.7