Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ff77a92
ci: improve cache reuse and drop redundant build work
silverwind May 8, 2026
ad9b633
ci: restore make backend in db-test jobs
silverwind May 8, 2026
8d6615f
ci: shard integration tests across 2 runners per database
silverwind May 8, 2026
4037cd5
ci: derive gogit test packages dynamically from imports
silverwind May 8, 2026
9b6cd19
ci: 3-shard db tests, split test-unit into bindata/gogit jobs
silverwind May 8, 2026
b266c64
ci: fix LFS test pollution and exclude integration packages from gogi…
silverwind May 9, 2026
28e7263
ci: rename test-unit-bindata, simplify and address review comments
silverwind May 9, 2026
8337e1c
ci: combine unit shards (3-way), drop rotation, use make generate-go
silverwind May 9, 2026
5c2bcdb
ci: bump test-unit-shards from 3 to 4
silverwind May 9, 2026
4cab370
ci: address review feedback on shard scripts
silverwind May 9, 2026
7f545d5
Merge branch 'main' into ci-cache-improvements
silverwind May 10, 2026
73d9cf8
ci: simplify shard logic per review feedback
silverwind May 10, 2026
ccbae10
Apply suggestion from @silverwind
silverwind May 10, 2026
9a17fab
ci: reduce shard count to 2 for db tests and unit tests
silverwind May 10, 2026
ecc14c5
ci: drop sharding for sqlite/mysql/mssql
silverwind May 10, 2026
530a737
Merge branch 'main' into ci-cache-improvements
silverwind May 10, 2026
3105f72
ci: consolidate shard scripts into a single tools/test-go.sh
silverwind May 10, 2026
1bc9df7
Apply suggestion from @silverwind
silverwind May 10, 2026
5e8c032
ci: split test-unit by build tag instead of sharding
silverwind May 10, 2026
9f27b47
ci: drop external services from test-unit-gogit; rename helper script
silverwind May 10, 2026
777d92a
ci: include cache-name in non-rotated build-cache key
silverwind May 10, 2026
51ff3e3
ci: restore test-unit aggregator job
silverwind May 10, 2026
2c8b153
skip unnecessary tests for gogit
wxiaoguang May 10, 2026
204d09d
fix skip msg
wxiaoguang May 10, 2026
544d7cf
fix skip msg
wxiaoguang May 10, 2026
766a30f
fix tests
wxiaoguang May 10, 2026
9c2b7ba
fix lint
wxiaoguang May 10, 2026
a10ba21
fix more
wxiaoguang May 10, 2026
3e1ef11
fix
wxiaoguang May 10, 2026
728e6dc
fix
wxiaoguang May 10, 2026
20212d8
Merge branch 'main' into ci-cache-improvements
silverwind May 10, 2026
d30d1c4
Merge branch 'main' into ci-cache-improvements
silverwind May 11, 2026
cd0fc37
ci: drop test-pgsql and test-unit aggregator jobs
silverwind May 11, 2026
4f51abb
ci: restrict cache writes to the cache-seeder workflow
silverwind May 12, 2026
5eb68c1
ci: warm test compile cache in seeder and un-split test-unit
silverwind May 12, 2026
8665350
ci(cache-seeder): warm integration test compile cache
silverwind May 12, 2026
cf6f648
ci(cache-seeder): route integration warm through make, fix GOEXPERIMENT
silverwind May 12, 2026
e7e670d
ci: remove cache-name input, drop "seed" identifier
silverwind May 18, 2026
751acd4
Merge remote-tracking branch 'origin/main' into ci-cache-improvements
silverwind May 18, 2026
f2e4ba3
ci(cache-seeder): warm deps-tools in gobuild job
silverwind May 18, 2026
44bbf96
ci: keep original test-unit step names
silverwind May 18, 2026
1c1de6a
Merge branch 'main' into ci-cache-improvements
bircni May 18, 2026
e5ad951
Merge branch 'main' into ci-cache-improvements
silverwind May 18, 2026
b006ecf
Merge branch 'main' into ci-cache-improvements
silverwind May 19, 2026
ddfa8c7
Merge branch 'main' into ci-cache-improvements
silverwind May 21, 2026
b65f349
Merge branch 'main' into ci-cache-improvements
silverwind May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions .github/actions/go-cache/action.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,51 @@
name: go-caches
description: Restore and save go module, build, and golangci-lint caches
description: Restore the go module, build, and golangci-lint caches. Save only on the cache-seeder workflow.

# Only the cache-seeder workflow saves; rename requires updating cache-seeder.yml.
# The lint job restores but does not save the gobuild cache, so only one writer
# (the gobuild job) populates it and there is no contention on the cache key.

inputs:
cache-name:
description: Short identifier used in the per-caller build cache key
required: true
build-cache:
description: Whether to include ~/.cache/go-build
default: "true"
build-cache-rotate:
description: Whether to rotate the build cache key per run so Go's test result cache can accumulate across runs
default: "false"
lint-cache:
description: Whether to include ~/.cache/golangci-lint
description: Restore (and save in cache-seeder) ~/.cache/golangci-lint
default: "false"

runs:
using: composite
steps:
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
- if: ${{ github.workflow == 'cache-seeder' }}
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/go/pkg/mod
key: gomod-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
restore-keys: gomod-${{ runner.os }}-${{ runner.arch }}
- if: ${{ github.workflow != 'cache-seeder' }}
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/go/pkg/mod
key: gomod-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
restore-keys: gomod-${{ runner.os }}-${{ runner.arch }}
- if: ${{ inputs.build-cache == 'true' && inputs.build-cache-rotate == 'true' }}
- if: ${{ github.workflow == 'cache-seeder' && inputs.lint-cache != 'true' }}
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/go-build
key: gobuild-${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache-name }}-${{ hashFiles('go.sum') }}-${{ github.run_id }}
restore-keys: |
gobuild-${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache-name }}-${{ hashFiles('go.sum') }}
gobuild-${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache-name }}
gobuild-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
gobuild-${{ runner.os }}-${{ runner.arch }}
- if: ${{ inputs.build-cache == 'true' && inputs.build-cache-rotate != 'true' }}
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
key: gobuild-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
restore-keys: gobuild-${{ runner.os }}-${{ runner.arch }}
- if: ${{ github.workflow != 'cache-seeder' || inputs.lint-cache == 'true' }}
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/go-build
key: gobuild-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
restore-keys: gobuild-${{ runner.os }}-${{ runner.arch }}
- if: ${{ inputs.lint-cache == 'true' }}
- if: ${{ inputs.lint-cache == 'true' && github.workflow == 'cache-seeder' }}
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/golangci-lint
key: golangci-${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache-name }}-${{ hashFiles('go.sum', '.golangci.yml') }}
restore-keys: golangci-${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache-name }}
key: golint-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum', '.golangci.yml') }}
restore-keys: golint-${{ runner.os }}-${{ runner.arch }}
- if: ${{ inputs.lint-cache == 'true' && github.workflow != 'cache-seeder' }}
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/golangci-lint
key: golint-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum', '.golangci.yml') }}
restore-keys: golint-${{ runner.os }}-${{ runner.arch }}
39 changes: 23 additions & 16 deletions .github/workflows/cache-seeder.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
# Populates the go module, build, and golangci-lint caches under the default
# branch's cache scope so that PR runs have a warm fallback to restore from.
# Populates main's cache scope so PR runs warm-start from it. Saves the go
# module, go build (incl. test compile), and golangci-lint caches.
#
# GitHub Actions caches are scoped per ref: a PR run can only write to its own
# branch's scope, but can read from the base branch's scope as a fallback.
# PRs therefore cannot seed main's scope themselves. Running the same cache
# steps on push-to-main is the only opportunity to populate that fallback
# scope so fresh PR branches start with a useful cache on first run.

# A PR job's exact key lives in its own PR-scope (empty on first run, filled
# by later runs of the same PR); on miss, actions/cache's restore-keys fall
# back to prefix matches against entries this seeder saves in main's scope.
# Caches are ref-scoped: PR runs read their own scope then fall back to the
# base branch. Per .github/actions/go-cache/action.yml, PRs are restore-only,
# so push-to-main is the only opportunity to populate the fallback scope.

name: cache-seeder

Expand Down Expand Up @@ -41,19 +35,33 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: seed
- run: make deps-backend
- run: make deps-backend deps-tools
- run: TAGS="bindata" make backend
- run: TAGS="bindata gogit" GOEXPERIMENT="" make backend
- name: warm test compile cache (bindata)
env:
TAGS: bindata
GOTEST_FLAGS: -race -list=^$$ -count=1
run: make test-backend
- name: warm test compile cache (bindata gogit)
env:
TAGS: bindata gogit
GOEXPERIMENT:
GOTEST_FLAGS: -race -list=^$$ -count=1
run: make test-backend
- name: warm integration compile cache
run: |
TAGS="bindata" make test-integration-compile
TAGS="bindata gogit" GOEXPERIMENT="" make test-integration-compile
TAGS="bindata gogit" GOTEST_FLAGS="-race" make test-integration-compile

lint:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- { job: lint-backend, tags: "bindata", target: "lint-backend" }
- { tags: "bindata", target: "lint-backend" }
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
Expand All @@ -63,7 +71,6 @@ jobs:
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: ${{ matrix.job }}
lint-cache: "true"
- run: make deps-backend deps-tools
- run: make generate-go
Expand Down
6 changes: 0 additions & 6 deletions .github/workflows/pull-compliance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ jobs:
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: lint-backend
lint-cache: "true"
- run: make deps-backend deps-tools
- run: TAGS="bindata" make generate-go # lint-go also lints with "bindata" tags which requires "_bindata.go"
Expand Down Expand Up @@ -75,9 +74,6 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: checks-backend
build-cache: "false"
- run: make deps-backend deps-tools
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs

Expand Down Expand Up @@ -111,8 +107,6 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: compliance-backend
- run: make deps-backend generate-go
# no frontend build here as backend should be able to build, even without any frontend files
# CGO is not used when cross-compile, so these steps also test if the code is compatible with CGO disabled
Expand Down
34 changes: 15 additions & 19 deletions .github/workflows/pull-db-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ jobs:
files-changed:
uses: ./.github/workflows/files-changed.yml

test-pgsql:
test-pgsql-shards:
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
needs: files-changed
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2]
services:
pgsql:
image: postgres:14
Expand Down Expand Up @@ -48,15 +52,14 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: pgsql
- name: Add hosts to /etc/hosts
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts'
- run: make deps-backend
- run: make backend
env:
TAGS: bindata
- name: run migration tests
if: matrix.shard == 1
run: GITEA_TEST_DATABASE=pgsql make test-migration
- name: run tests
run: GITEA_TEST_DATABASE=pgsql make test-integration
Expand All @@ -66,6 +69,8 @@ jobs:
GOTEST_FLAGS: -race -timeout=40m
TAGS: bindata gogit
TEST_LDAP: 1
TEST_SHARD: ${{ matrix.shard }}
TEST_TOTAL_SHARDS: ${{ strategy.job-total }}

test-sqlite:
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
Expand All @@ -79,15 +84,12 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: sqlite
- run: make deps-backend
- run: make backend
env:
TAGS: bindata gogit
GOEXPERIMENT:
- name: run migration tests
run: GITEA_TEST_DATABASE=sqlite make test-migration
- run: GITEA_TEST_DATABASE=sqlite make test-migration
env:
TAGS: bindata gogit
- name: run tests
Expand Down Expand Up @@ -145,28 +147,27 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: unit
build-cache-rotate: "true"
- name: Add hosts to /etc/hosts
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 minio devstoreaccount1.azurite.local mysql elasticsearch meilisearch smtpimap" | sudo tee -a /etc/hosts'
- run: make deps-backend
- run: make backend
- run: make generate-go
env:
TAGS: bindata
- name: unit-tests
run: make test-backend test-check
run: make test-backend
env:
GOTEST_FLAGS: -race -timeout=20m
TAGS: bindata
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
- name: unit-tests-gogit
run: make test-backend test-check
run: make test-backend
env:
GOTEST_FLAGS: -race -timeout=20m
TAGS: bindata gogit
GOEXPERIMENT:
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
GITEA_TEST_CI_SKIP_EXTERNAL: true
- run: make test-check

test-mysql:
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
Expand Down Expand Up @@ -205,16 +206,13 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: mysql
- name: Add hosts to /etc/hosts
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
- run: make deps-backend
- run: make backend
env:
TAGS: bindata
- name: run migration tests
run: GITEA_TEST_DATABASE=mysql make test-migration
- run: GITEA_TEST_DATABASE=mysql make test-migration
- name: run tests
run: GITEA_TEST_DATABASE=mysql make test-integration
env:
Expand Down Expand Up @@ -246,8 +244,6 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: mssql
- name: Add hosts to /etc/hosts
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mssql devstoreaccount1.azurite.local" | sudo tee -a /etc/hosts'
- run: make deps-backend
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/pull-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ jobs:
check-latest: true
cache: false
- uses: ./.github/actions/go-cache
with:
cache-name: e2e
build-cache: "false"
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,11 @@ test-integration:
@# would flood output per passing test. testcache can't help these tests anyway —
@# they mutate the work directory, so cache inputs change between runs.
$(GO) test $(GOTEST_FLAGS) -tags '$(TAGS)' -c code.gitea.io/gitea/tests/integration -o ./test-integration-$(GITEA_TEST_DATABASE).test
./test-integration-$(GITEA_TEST_DATABASE).test
./tools/test-integration.sh ./test-integration-$(GITEA_TEST_DATABASE).test

.PHONY: test-integration-compile
test-integration-compile:
$(GO) test $(GOTEST_FLAGS) -tags '$(TAGS)' -c -o /dev/null code.gitea.io/gitea/tests/integration

.PHONY: test-integration\#%
test-integration\#%:
Expand Down
31 changes: 31 additions & 0 deletions tools/test-integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
set -euo pipefail

# Run a compiled *.test binary. When TEST_SHARD is set, enumerate top-level
# tests via -test.list and run only the shard's slice; TestMain skips
# environment setup in -test.list mode. Without TEST_SHARD, runs the binary
# directly.

BINARY=${1:?usage: $0 BINARY}

if [ -z "${TEST_SHARD:-}" ]; then
exec "$BINARY"
fi

if ! [[ "${TEST_TOTAL_SHARDS:-}" =~ ^[1-9][0-9]*$ ]]; then
echo "TEST_TOTAL_SHARDS must be a positive integer, got: ${TEST_TOTAL_SHARDS:-}" >&2
exit 2
fi
if ! [[ "$TEST_SHARD" =~ ^[1-9][0-9]*$ ]] || [ "$TEST_SHARD" -gt "$TEST_TOTAL_SHARDS" ]; then
echo "TEST_SHARD must be in [1, $TEST_TOTAL_SHARDS], got: $TEST_SHARD" >&2
exit 2
fi

NAMES=$("$BINARY" -test.list='^Test' | LC_ALL=C sort -u | awk -v r=$((TEST_SHARD - 1)) -v t="$TEST_TOTAL_SHARDS" '(NR - 1) % t == r')
if [ -z "$NAMES" ]; then
echo "shard $TEST_SHARD/$TEST_TOTAL_SHARDS has no tests assigned" >&2
exit 1
fi
PATTERN=$(echo "$NAMES" | paste -sd '|' -)
echo "Running shard $TEST_SHARD/$TEST_TOTAL_SHARDS ($(echo "$NAMES" | wc -l | tr -d ' ') tests)"
exec "$BINARY" -test.run "^($PATTERN)\$"
Loading