ci: cache what is rebuilt on every run

npm and Go module caches, the embedded Postgres binaries, Trivy's database, and
the daemon's own layer cache for image builds. The webmail Next build is no
longer run a second time outside the Dockerfile.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Sonnet 5.5 committed 2026-10-30 10:07:21 -03:00
1 parent 0ff9aaaf88
commit 5d4e7147ce
1 file changed
+42 -18
+42 -18
View File
@@ -70,6 +70,17 @@ jobs:
docker rm "$cid" >/dev/null docker rm "$cid" >/dev/null
exit "$status" exit "$status"
- run: go vet ./... - run: go vet ./...
# Module and build caches live under the unprivileged user's home, which
# setup-go's cache does not cover, and the embedded Postgres binaries are
# otherwise downloaded again by every test that starts one.
- uses: actions/cache@v4
with:
path: |
/home/tester/go/pkg/mod
/home/tester/.cache/go-build
/home/tester/.embedded-postgres-go
key: go-tester-${{ runner.arch }}-${{ hashFiles('services/protocols/go.sum') }}
restore-keys: go-tester-${{ runner.arch }}-
# The end-to-end suites start an embedded Postgres, and initdb refuses to # The end-to-end suites start an embedded Postgres, and initdb refuses to
# run as root, which is what a job container is. Run the tests as a # run as root, which is what a job container is. Run the tests as a
# throwaway unprivileged user (GitHub's hosted runners already are one). # throwaway unprivileged user (GitHub's hosted runners already are one).
@@ -78,7 +89,7 @@ jobs:
TEST_DATABASE_URL: postgres://lambdamail_test:lambdamail_test@localhost:5432/lambdamail_test?sslmode=disable TEST_DATABASE_URL: postgres://lambdamail_test:lambdamail_test@localhost:5432/lambdamail_test?sslmode=disable
run: | run: |
id tester >/dev/null 2>&1 || useradd -m -u 1001 tester id tester >/dev/null 2>&1 || useradd -m -u 1001 tester
chown -R tester:tester "$GITHUB_WORKSPACE" chown -R tester:tester "$GITHUB_WORKSPACE" /home/tester
runuser -u tester -- env "HOME=/home/tester" "PATH=$PATH" \ runuser -u tester -- env "HOME=/home/tester" "PATH=$PATH" \
"TEST_DATABASE_URL=$TEST_DATABASE_URL" go test ./... -v "TEST_DATABASE_URL=$TEST_DATABASE_URL" go test ./... -v
@@ -105,7 +116,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- uses: actions/setup-node@v7 - uses: actions/setup-node@v7
with: { node-version: "20" } with:
node-version: "20"
cache: npm
cache-dependency-path: services/auth/package-lock.json
# The auth suite asserts against real rows: password verification, # The auth suite asserts against real rows: password verification,
# lockout, TOTP replay and recovery-code consumption are all decided in # lockout, TOTP replay and recovery-code consumption are all decided in
# the database, so a mock would prove nothing. # the database, so a mock would prove nothing.
@@ -139,13 +153,16 @@ jobs:
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- uses: actions/setup-node@v7 - uses: actions/setup-node@v7
with: { node-version: "20" } with:
node-version: "20"
cache: npm
cache-dependency-path: services/storage/package-lock.json
- run: npm install - run: npm install
- run: npm run lint - run: npm run lint
- run: npm test - run: npm test
webmail-build: webmail-build:
name: Build (webmail) name: Testes (webmail)
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults: defaults:
run: run:
@@ -153,11 +170,15 @@ jobs:
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- uses: actions/setup-node@v7 - uses: actions/setup-node@v7
with: { node-version: "20" } with:
node-version: "20"
cache: npm
cache-dependency-path: services/webmail/package-lock.json
- run: npm install - run: npm install
- run: npm run lint - run: npm run lint
- run: npm test - run: npm test
- run: npm run build # No `npm run build` here: the webmail image job runs the same Next build
# inside its Dockerfile, so building it twice only doubles the wait.
security: security:
name: Trivy (dependências, segredos e Dockerfiles) name: Trivy (dependências, segredos e Dockerfiles)
@@ -174,7 +195,7 @@ jobs:
# which on Gitea is not GitHub. # which on Gitea is not GitHub.
- name: Repositório - name: Repositório
run: | run: |
cid=$(docker create --network host -w /src aquasec/trivy:0.70.0 \ cid=$(docker create --network host -v trivy-cache:/root/.cache/ -w /src aquasec/trivy:0.70.0 \
fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL --exit-code 1 \ fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL --exit-code 1 \
--skip-dirs services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next .) --skip-dirs services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next .)
docker cp . "$cid:/src" docker cp . "$cid:/src"
@@ -195,7 +216,7 @@ jobs:
# scanner something people learn to skip. # scanner something people learn to skip.
- name: Repositório (MEDIUM, informativo) - name: Repositório (MEDIUM, informativo)
run: | run: |
cid=$(docker create --network host -w /src aquasec/trivy:0.70.0 \ cid=$(docker create --network host -v trivy-cache:/root/.cache/ -w /src aquasec/trivy:0.70.0 \
fs --scanners vuln,secret --severity MEDIUM --exit-code 0 \ fs --scanners vuln,secret --severity MEDIUM --exit-code 0 \
--skip-dirs services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next .) --skip-dirs services/auth/node_modules,services/storage/node_modules,services/webmail/node_modules,services/webmail/.next .)
docker cp . "$cid:/src" docker cp . "$cid:/src"
@@ -214,18 +235,21 @@ jobs:
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- uses: docker/setup-buildx-action@v4
# Built but not pushed: this proves each Dockerfile still works on every # Built but not pushed: this proves each Dockerfile still works on every
# branch, while publishing stays in release.yml. # branch, while publishing stays in release.yml.
#
# Plain `docker build` on purpose. setup-buildx would start a fresh
# BuildKit container per job and throw its layer cache away; the daemon's
# own builder keeps the cache in the runner's persistent volume, and the
# "Stack completa" job reuses it for the same Dockerfiles.
- name: Build - name: Build
uses: docker/build-push-action@v7 run: |
with: case '${{ matrix.service }}' in
context: ${{ (matrix.service == 'migrations' || matrix.service == 'rspamd') && '.' || format('services/{0}', matrix.service) }} migrations|rspamd) context=. ;;
file: services/${{ matrix.service }}/Dockerfile *) context=services/${{ matrix.service }} ;;
push: false esac
load: true docker build -f services/${{ matrix.service }}/Dockerfile \
tags: lambdamail-${{ matrix.service }}:ci -t lambdamail-${{ matrix.service }}:ci "$context"
# Scanned only for the images whose contents we author. migrations and # Scanned only for the images whose contents we author. migrations and
# rspamd add .sql and .conf files to an upstream image and nothing else, # rspamd add .sql and .conf files to an upstream image and nothing else,
@@ -236,7 +260,7 @@ jobs:
- name: Trivy na imagem - name: Trivy na imagem
if: matrix.service != 'migrations' && matrix.service != 'rspamd' if: matrix.service != 'migrations' && matrix.service != 'rspamd'
run: | run: |
docker run --rm --network host -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \ docker run --rm --network host -v trivy-cache:/root/.cache/ -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \
image --severity HIGH,CRITICAL --exit-code 1 lambdamail-${{ matrix.service }}:ci image --severity HIGH,CRITICAL --exit-code 1 lambdamail-${{ matrix.service }}:ci
compose-up: compose-up: