docs(adr-0028): propose CI/CD + git hosting migration Gitea -> GitLab #226

Merged
julien merged 1 commits from docs/adr-0028-gitlab-migration into main 2026-05-26 10:30:20 +02:00
Owner

Summary

Drafts ADR-0028 as proposed: migrate CI/CD + git hosting from Gitea (git.unespace.com) to GitLab CE self-hosted on vm-gitlab (10.100.201.10). The migration was anticipated by ADR-0015 ("level-2 implementation; will be superseded by a GitLab migration ADR within 6-18 months") — that window opens now. Decision-only PR — the actual 4-phase migration ships across follow-up PRs after acceptance.

ADR-0028's number was previously a placeholder reference in ADR-0026 and ADR-0027 for the Pléiades + Acteurs+ sync ADR. Renumbering: that future sync ADR shifts to ADR-0029, and the placeholder links in ADR-0026, ADR-0027 and CLAUDE.md update to match — included in the same PR so the chain stays consistent.

What lands

File Change
docs/decisions/0028-migrate-cicd-and-git-hosting-to-gitlab.md New. MADR 4.0.0 ADR, proposed. Decision = Option B (GitLab CE on vm-gitlab). Considered options A (status quo Gitea), C (Forgejo), D (cloud SaaS). Documents what carries over from ADR-0015 (architectural principles unchanged — thin YAML, trunk-based, all-gates-blocking, on-prem runners), what changes (host, pipeline file, runner type, scan tooling), the 4-phase migration sequence, and the signed-commits revisit.
docs/decisions/0026-person-user-portal-data-model.md All 11 ADR-0028 references → ADR-0029 (sync + facets shifts to 0029).
docs/decisions/0027-portal-side-organisational-hierarchy.md All 14 ADR-0028 references → ADR-0029.
docs/decisions/README.md New row for ADR-0028 (proposed, tags infrastructure, process, 2026-05-26).
CLAUDE.md Roll-up updated: ADRs 0001 → 0027 accepted; ADR-0028 + ADR-0029 proposed. ADR-0028's relationship to ADR-0015 spelled out inline ("supersedes ADR-0015's Gitea Actions platform choice — the rest of ADR-0015's architectural principles carry over unchanged"). ADR-0026 + ADR-0027 architecture bullets renumbered 0028 → 0029 to track.

Key choices in the ADR

  • What carries over from ADR-0015 vs what changes — explicit table so future readers see immediately that the migration is platform-only, not a re-litigation of CI principles. Trunk-based + squash, all-gates-blocking, thin YAML over portable scripts (pnpm ci:check etc. — unchanged), on-prem runners, Conventional Commits in CI + hook (defense in depth) — all carried over. Host, pipeline-file grammar, runner type, and scan tooling are the only things that move.
  • Native security scanning replaces the manual Trivy + gitleaks setup. GitLab CE's built-in Dependency-Scanning.gitlab-ci.yml + Secret-Detection.gitlab-ci.yml includes consolidate the ~30 lines of inline curl + tar install dance currently in .gitea/workflows/ci.yml. Same blocking thresholds (CRITICAL+HIGH dependency vulns, any secret).
  • vm-gitlab is already provisioned. No infra wait — the only sequencing constraint is operator-driven, not infrastructure-driven.
  • 4-phase migration, parallel pipelines for ~1 week before cutover. Phase 1 mirrors repos and bootstraps GitLab side (no .gitlab-ci.yml yet — Gitea still gates). Phase 2 lands .gitlab-ci.yml alongside .gitea/workflows/ci.yml so both pipelines run per PR until parity is confirmed. Phase 3 flips the remote URLs and deletes .gitea/workflows/ + infra/ci-runners.compose.yml. Phase 4 sweeps stale references.
  • Gitea moves to read-only / archive, not decommissioned at cutover. Existing references to Gitea PRs (#213, #217, #219, …) in commit messages and ADR bodies stay resolvable as historical artefacts. One VM at idle is a low long-term cost.
  • Signed commits revisit. ADR-0015 noted "signed commits recommended, revisited at GitLab migration". ADR-0028 makes the recommendation: enable required signed commits on main once GitLab is live, paired with GnuPG agent forwarding (already documented in docs/setup/01-dev-debian-vm-setup.md §8.5). apf-portal-bot (Renovate) gets a dedicated signing key at PR 1.

Renumbering — what moved and why

Before this PR, ADR-0026 and ADR-0027 used ADR-0028 as a placeholder link for the Pléiades + Acteurs+ sync ADR. That sync ADR hasn't been drafted yet — the number was reserved.

This PR claims ADR-0028 for the GitLab migration (the immediately-actionable decision), and shifts the sync placeholder to ADR-0029. All 25 link references across ADR-0026 (11) and ADR-0027 (14) update in lockstep — replace_all is safe here because in those files ADR-0028 consistently meant "the sync ADR".

Content of the sync ADR is unchanged — only the number. When that ADR is eventually drafted as 0029-…md, it gets the existing content reserved for it in the placeholder text.

Test plan

  • pnpm exec prettier --check clean on the touched files.
  • All ADR-0028 references in 0026-…md / 0027-…md / CLAUDE.md now read ADR-0029 (grep confirms zero remaining references to the old number in those files).
  • The new 0028-…md self-references (status frontmatter, title, internal anchors) are consistent — no leftover 0029.
  • Review focus — drivers / consequences / migration sequence in the ADR; the "what carries over from ADR-0015" table; the renumbering rationale.

What's next

Per ADR-0028 §"Migration sequence", post-acceptance:

  1. ADR-0028 acceptance PR — small status-flip, same pattern as #219 (ADR-0026 + ADR-0027 acceptance).
  2. mirror-and-bootstrap PRgit push --mirror Gitea → GitLab; GitLab side groups / projects / branch protection / MR templates / deploy keys / Renovate reconfig. No .gitlab-ci.yml yet, Gitea pipelines still gate.
  3. gitlab-ci-pipeline PR.gitlab-ci.yml alongside the existing .gitea/workflows/ci.yml. Parallel runs ~1 week for parity. GitLab Runner registered on vm-gitlab.
  4. cutover PR — remotes flip across docs, .gitea/workflows/ + infra/ci-runners.compose.yml deleted, Gitea read-only.
  5. cleanup PR — stale references sweep, signed-commit policy finalised on main.

In parallel — once the dev VM (#220 / #221 / #222 / #223 / #224) is fully bootstrapped — the paused ADR-0027 PR 1 (Region / Delegation / Structure Prisma schema + inline seed) and ADR-0026 PR 1 (Person / User / UserScope schema + provisioner) can ship on Gitea; they have no dependency on the GitLab migration and don't need to wait.

## Summary Drafts [ADR-0028](docs/decisions/0028-migrate-cicd-and-git-hosting-to-gitlab.md) as `proposed`: migrate CI/CD + git hosting from Gitea (`git.unespace.com`) to GitLab CE self-hosted on `vm-gitlab` (`10.100.201.10`). The migration was anticipated by [ADR-0015](docs/decisions/0015-cicd-gitea-actions.md) ("level-2 implementation; will be superseded by a GitLab migration ADR within 6-18 months") — that window opens now. **Decision-only PR** — the actual 4-phase migration ships across follow-up PRs after acceptance. ADR-0028's number was previously a placeholder reference in ADR-0026 and ADR-0027 for the Pléiades + Acteurs+ sync ADR. **Renumbering**: that future sync ADR shifts to `ADR-0029`, and the placeholder links in ADR-0026, ADR-0027 and `CLAUDE.md` update to match — included in the same PR so the chain stays consistent. ## What lands | File | Change | | --- | --- | | `docs/decisions/0028-migrate-cicd-and-git-hosting-to-gitlab.md` | **New.** MADR 4.0.0 ADR, `proposed`. Decision = Option B (GitLab CE on `vm-gitlab`). Considered options A (status quo Gitea), C (Forgejo), D (cloud SaaS). Documents what carries over from ADR-0015 (architectural principles unchanged — thin YAML, trunk-based, all-gates-blocking, on-prem runners), what changes (host, pipeline file, runner type, scan tooling), the 4-phase migration sequence, and the signed-commits revisit. | | `docs/decisions/0026-person-user-portal-data-model.md` | All 11 `ADR-0028` references → `ADR-0029` (sync + facets shifts to 0029). | | `docs/decisions/0027-portal-side-organisational-hierarchy.md` | All 14 `ADR-0028` references → `ADR-0029`. | | `docs/decisions/README.md` | New row for ADR-0028 (`proposed`, tags `infrastructure`, `process`, 2026-05-26). | | `CLAUDE.md` | Roll-up updated: `ADRs 0001 → 0027 accepted; ADR-0028 + ADR-0029 proposed`. ADR-0028's relationship to ADR-0015 spelled out inline ("supersedes ADR-0015's Gitea Actions platform choice — the rest of ADR-0015's architectural principles carry over unchanged"). ADR-0026 + ADR-0027 architecture bullets renumbered 0028 → 0029 to track. | ## Key choices in the ADR - **What carries over from ADR-0015 vs what changes** — explicit table so future readers see immediately that the migration is **platform-only**, not a re-litigation of CI principles. Trunk-based + squash, all-gates-blocking, thin YAML over portable scripts (`pnpm ci:check` etc. — unchanged), on-prem runners, Conventional Commits in CI + hook (defense in depth) — all carried over. Host, pipeline-file grammar, runner type, and scan tooling are the only things that move. - **Native security scanning replaces the manual Trivy + gitleaks setup.** GitLab CE's built-in `Dependency-Scanning.gitlab-ci.yml` + `Secret-Detection.gitlab-ci.yml` includes consolidate the ~30 lines of inline `curl + tar` install dance currently in `.gitea/workflows/ci.yml`. Same blocking thresholds (CRITICAL+HIGH dependency vulns, any secret). - **`vm-gitlab` is already provisioned.** No infra wait — the only sequencing constraint is operator-driven, not infrastructure-driven. - **4-phase migration, parallel pipelines for ~1 week before cutover.** Phase 1 mirrors repos and bootstraps GitLab side (no `.gitlab-ci.yml` yet — Gitea still gates). Phase 2 lands `.gitlab-ci.yml` alongside `.gitea/workflows/ci.yml` so both pipelines run per PR until parity is confirmed. Phase 3 flips the remote URLs and deletes `.gitea/workflows/` + `infra/ci-runners.compose.yml`. Phase 4 sweeps stale references. - **Gitea moves to read-only / archive, not decommissioned** at cutover. Existing references to Gitea PRs (`#213`, `#217`, `#219`, …) in commit messages and ADR bodies stay resolvable as historical artefacts. One VM at idle is a low long-term cost. - **Signed commits revisit.** ADR-0015 noted "signed commits recommended, revisited at GitLab migration". ADR-0028 makes the recommendation: enable required signed commits on `main` once GitLab is live, paired with GnuPG agent forwarding (already documented in `docs/setup/01-dev-debian-vm-setup.md` §8.5). `apf-portal-bot` (Renovate) gets a dedicated signing key at PR 1. ## Renumbering — what moved and why Before this PR, ADR-0026 and ADR-0027 used `ADR-0028` as a placeholder link for the Pléiades + Acteurs+ sync ADR. That sync ADR hasn't been drafted yet — the number was reserved. This PR claims `ADR-0028` for the GitLab migration (the immediately-actionable decision), and shifts the sync placeholder to **ADR-0029**. All 25 link references across ADR-0026 (11) and ADR-0027 (14) update in lockstep — replace_all is safe here because in those files `ADR-0028` consistently meant "the sync ADR". Content of the sync ADR is unchanged — only the number. When that ADR is eventually drafted as `0029-…md`, it gets the existing content reserved for it in the placeholder text. ## Test plan - [x] `pnpm exec prettier --check` clean on the touched files. - [x] All `ADR-0028` references in `0026-…md` / `0027-…md` / `CLAUDE.md` now read `ADR-0029` (grep confirms zero remaining references to the old number in those files). - [x] The new `0028-…md` self-references (status frontmatter, title, internal anchors) are consistent — no leftover `0029`. - [ ] **Review focus** — drivers / consequences / migration sequence in the ADR; the "what carries over from ADR-0015" table; the renumbering rationale. ## What's next Per ADR-0028 §"Migration sequence", post-acceptance: 1. **ADR-0028 acceptance PR** — small status-flip, same pattern as #219 (ADR-0026 + ADR-0027 acceptance). 2. **`mirror-and-bootstrap` PR** — `git push --mirror` Gitea → GitLab; GitLab side groups / projects / branch protection / MR templates / deploy keys / Renovate reconfig. No `.gitlab-ci.yml` yet, Gitea pipelines still gate. 3. **`gitlab-ci-pipeline` PR** — `.gitlab-ci.yml` alongside the existing `.gitea/workflows/ci.yml`. Parallel runs ~1 week for parity. GitLab Runner registered on `vm-gitlab`. 4. **`cutover` PR** — remotes flip across docs, `.gitea/workflows/` + `infra/ci-runners.compose.yml` deleted, Gitea read-only. 5. **`cleanup` PR** — stale references sweep, signed-commit policy finalised on `main`. In parallel — once the dev VM (#220 / #221 / #222 / #223 / #224) is fully bootstrapped — the paused **ADR-0027 PR 1** (Region / Delegation / Structure Prisma schema + inline seed) and **ADR-0026 PR 1** (Person / User / UserScope schema + provisioner) can ship on Gitea; they have no dependency on the GitLab migration and don't need to wait.
julien added 1 commit 2026-05-26 10:28:26 +02:00
docs(adr-0028): propose CI/CD + git hosting migration Gitea -> GitLab
CI / commits (pull_request) Successful in 3m41s
CI / scan (pull_request) Successful in 3m51s
CI / check (pull_request) Successful in 4m2s
CI / a11y (pull_request) Successful in 3m18s
Docs site / build (pull_request) Successful in 3m43s
CI / perf (pull_request) Successful in 7m28s
ddd05994e0
ADR-0015 framed Gitea Actions as a level-2 implementation explicitly
slated for a GitLab migration within 6-18 months. That window opens
now: vm-gitlab is provisioned, the team is about to scale, and the
Gitea-specific friction points documented inline in .gitea/workflows/
ci.yml (paywalled gitleaks-action, github.com-bound trivy-action,
manual curl+tar install dance) are accumulating maintenance tax.

ADR-0028 records the platform shift. Architectural principles from
ADR-0015 (trunk-based + squash, all-gates-blocking, thin YAML over
portable scripts in pnpm + Nx, on-prem runners, Conventional Commits)
carry over unchanged - only host / pipeline-file grammar / runner type
/ scan tooling change. Decision-only; 4-phase migration (mirror,
parallel pipelines, cutover, cleanup) lands in follow-up PRs.

Renumbering: ADR-0028 was a placeholder reference for the future
Pleiades + Acteurs+ sync ADR. That ADR shifts to 0029; the 25 link
references across ADR-0026 and ADR-0027 update in lockstep. CLAUDE.md
roll-up adjusted accordingly.

Status: proposed. Accept will be a separate small PR per the established
pattern (see #219 for ADR-0026/0027 acceptance).
julien merged commit 04ee535de9 into main 2026-05-26 10:30:20 +02:00
julien deleted branch docs/adr-0028-gitlab-migration 2026-05-26 10:30:21 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#226