Repository navigation
ci: run the Go and Docker heavy jobs on ubuntu-24.04-arm - #1405
Conversation
On main's last three runs the same cold Dockerfile build took 124-142s on the arm64 runner against 201-207s on ubuntu-latest, and `go install govulncheck` took under 3s against 12-16s. Lint, Unit Tests, Integration Tests, Security Scanning and E2E are compile-bound and make up the critical path, so they move to ubuntu-24.04-arm, as does the selection self-test (go list). arm64 is also what the AWS deploys run. The amd64 image leg stays native on ubuntu-latest for GCP and Azure. Snyk (a Docker action), Terraform (provider lock files) and the seconds-long jobs stay there too. Every cache key already includes the runner architecture, so nothing restores across architectures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. Walkthrough
Merge Risk:
|
|
CI on f66b316 is all green on arm64 (run 40187507363), including This was the first arm run, so every arm cache was empty. For comparison, main's run 40186406525 (x64) had warm caches.
On integration, the x64 cold run of the same six shards in #1402 took 142-319s, so arm is faster cold-for-cold as well. Warm arm numbers will show up on the next run. The longest jobs are now Security Scanning (gosec, which is no faster on arm and is skipped on a results-cache hit) and the amd64 Docker build, which stays on x64. |
…r create/update (#1205) The view-only/write-capable contradiction check existed only in the frontend (validateGroupCombination, #1405), so POST /api/users and PUT /api/users/{id} accepted a contradictory membership from any non-UI API consumer. Port the frontend's classification to internal/auth, reading each group's stored permissions (never its name): view-only means at least one permission and all actions == "view"; write-capable means any action other than "view"; empty and missing groups are neutral. Wire it into CreateUser (via checkCreateUserGroups) and guardGroupChange, after the existing access guards so an escalation is still reported as a 403. It returns a new ErrContradictoryGroups sentinel, mapped to 400 by mapAuthError like ErrNoGroups. An unchanged membership (groups omitted, or echoed back in any order) is not re-checked, so users who already hold a contradictory combination can still be renamed or deactivated; any real change is checked against the full resulting set, as the frontend does. Existing tests whose "ordinary group" fixture was view-only next to an admin group now use a write-capable group, since that combination is exactly what this change refuses. Closes #78 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Why
The longest CI jobs are compile-bound: Security Scanning 329s, Unit Tests 324s, E2E 237s, Lint 186s, and the integration shards up to 151s (main run 40186406525). The arm64 runner compiles Go noticeably faster. On main's last three runs:
go install golang.org/x/vuln/cmd/govulncheck@v1.1.4ubuntu-24.04-armis free for public repos, has the same 4 vCPUs asubuntu-latest, and is already used here: the arm64docker-buildleg, and the AWS deploys, which run arm64 on Graviton.What changed
.github/workflows/ci.yml:runs-on: ubuntu-24.04-armfor:There's also a header comment explaining the split. No steps change.
Left on
ubuntu-latest, on purpose:continue-on-errorand off the critical path.init -lockfile=readonly. A lock file missing the arm64 hash could fail there, and the job takes under a minute.Compatibility checked
postgres:16-alpineservice,golang:1.26.10-alpine3.24,node:24-alpine,alpine:3.24.1, testcontainers'postgres:16-alpineandtestcontainers/ryuk:0.13.0.RUNNER_ARCH: setup-go's, the integration GOCACHE/GOMODCACHE keys and the gosec keys. So the first arm run compiles cold, and nothing is restored across architectures.Verification
Local, on an amd64 host:
GOARCH=arm64 go vet ./...,GOARCH=arm64 go vet -tags integration ./...and(cd tests/e2e && GOARCH=arm64 go vet -tags e2e ./...): all clean.CGO_ENABLED=0 GOARCH=arm64 go test -exec /bin/true ./..., untagged and with-tags integration: every test binary builds (36 and 38 packages).pre-commit run --files .github/workflows/ci.yml: all hooks pass, zizmor included. Trivy config, run throughaquasec/trivy:0.69.3because trivy isn't installed locally: rc 0.scripts/test-git-secrets-allowlist.sh: 137 pass, 0 fail.Not verified locally: running the tests on arm64, including
-race. That needs an arm64 machine or a cross C toolchain, and I have neither. This PR's own CI run is the real test. It will also be a cold-cache run on arm, so the per-job times to compare are its second run, or main's after merge.Expected effect
Compile-heavy steps should be roughly 30-40% faster, going by the Docker build numbers above. The amd64 Docker leg (262s with its layer cache export) may become the longest job.
Note for cristim
Unit and integration tests now run on arm64 only. That matches AWS (Graviton), while the amd64 binaries for GCP and Azure are still built and smoke-run by the amd64 Docker leg. Go behaves the same on both for this code. One known difference is FMA fusion of float expressions on arm64, which could shift the last bit of a float result. If an exact-float test fails here, that's a real arm64 production difference rather than CI noise. If you'd rather keep amd64 test coverage too, Unit Tests could become a two-arch matrix at no wall-time cost.
🤖 Generated with Claude Code
Summary by CodeRabbit