CI/CD Pipeline Overhaul
On this page
Context
The CI/CD pipeline has grown organically and has several issues that undermine reliability:
-
E2E tests are broken — Playwright
--with-depscallsapt-geton Alpine (docker:27), which doesn’t exist -
Integration test caches
target/— 20,000+ files uploaded/downloaded each run -
Integration test compiles Rust from scratch — installs rustup + nextest in
docker:27(Alpine), takes 20+ min -
Shell code duplicated 4× — Garage init and health checks copy-pasted between CI jobs and devstack scripts
-
8 identical container scan jobs — one per service, differing only by image name
-
Missing GitLab templates — no
.gitlab/MR/issue templates (CODEOWNERS and CONTRIBUTING.adoc already exist) -
Silent test failures —
allow_failure: trueon integration/E2E means failures on main go unnoticed -
stop_reviewblocks feature branch pipelines — manual job withoutallow_failure: trueleaves pipelines in "blocked" state -
No Docker layer caching — each
docker-buildstarts fresh in a new dind VM
Phases
Phase 1: Extract Reusable CI Scripts (DRY)
Extract duplicated Garage init (~30 lines × 2) and health-check wait (~30 lines × 2) into shared shell scripts.
Files:
-
Create
devstack/ci/garage-init.sh— extracted Garage init logic -
Create
devstack/ci/wait-healthy.sh— from inline CI script -
Edit
.gitlab-ci.yml— replace inline blocks inintegration-testande2e-testwithsh devstack/ci/*.sh -
Update
cargo xtask dev— source the shared scripts
Phase 2: Fix Integration Test Performance & 20K Artifacts
Switch RUST_IMAGE from rust:1.93-slim (Debian/glibc) to rust:1.93-alpine (musl). Use nextest archive to pass pre-compiled test binaries from rust-test to integration-test — zero recompilation. Remove target/ from cache.
Files:
-
Edit
.gitlab-ci.yml—RUST_IMAGE,.rust-build-deps(apk instead of apt-get, linux-musl nextest),rust-test(add archive),integration-test(use archive, remove cache/rustup) -
Edit
.config/nextest.toml— addtest-threads = 8tociandci-integrationprofiles
Phase 3: Fix E2E Playwright on Alpine
Replace broken npx playwright install chromium --with-deps (calls apt-get on Alpine) with docker compose --profile e2e run using the existing tests/e2e/Dockerfile (mcr.microsoft.com/playwright:v1.58.2-noble).
Files:
-
Edit
.gitlab-ci.yml— rewritee2e-testjob to use compose E2E service
Phase 4: Consolidate Container Scanning with Matrix
Replace 8 identical container-scan-* jobs (~40 lines) with a single parallel: matrix job.
Files:
-
Edit
.gitlab-ci.yml— replace 8 jobs with 1 matrix job
Phase 5: Add GitLab MR & Issue Templates
Add .gitlab/ templates for standardized MRs and issues. CODEOWNERS and CONTRIBUTING.adoc already exist.
Files:
-
Create
.gitlab/merge_request_templates/default.md -
Create
.gitlab/issue_templates/feature.md -
Create
.gitlab/issue_templates/bug.md
Phase 6: Harden Pipeline
-
Remove
allow_failure: truefromintegration-testande2e-teston main — failures should gate -
Add
allow_failure: truetostop_review— environment cleanup should not block feature branch pipelines -
Add BuildKit inline caching to
docker-build—--cache-from+BUILDKIT_INLINE_CACHE=1
Files:
-
Edit
.gitlab-ci.yml— integration/E2E rules, stop_review rules, docker-build job
Verification
-
Push to feature branch and verify CI pipeline runs (lint + test stages)
-
Phase 2: confirm no
target/cache upload, confirm nextest archive works -
Phase 3: confirm E2E tests pass (Playwright in noble container, no
apt-geterror) -
Phase 6: confirm
stop_reviewno longer blocks, manual integration/E2E failures are reported