Skip to content

ADR-022 — CI strategy

Context

AKKO needs a path from git push to an updated Netcup cluster. Three options were on the table:

  1. GitHub Actions — mature, free for public repos, widespread tooling.
  2. Woodpecker CI (self-hosted, Apache 2.0) — already packaged as akko-woodpecker sub-chart (disabled by default).
  3. Manual scripthelm/scripts/deploy-netcup-full.sh SSH'd on the Netcup host.

Current reality (2026-04-19): - One maintainer. - One production cluster (Netcup). - No external client depending on release artefacts yet. - Self-hosted CI surface adds attack area (even when private).

Decision

  1. Reject GitHub Actions. The AKKO stack is sovereign; a public CI vendor with undocumented observability of source is off-model.
  2. Keep Woodpecker as an opt-in, private-by-default, future-ready option. akko-woodpecker.ingress.enabled=false (ADR commit 47f43b7). Operators access it via kubectl port-forward or a private mesh. Exposure happens only through oauth2-proxy + IP allowlist.
  3. Default CI path is deploy-netcup-full.sh for now. SSH to Netcup → cd akko && git pull && bash helm/scripts/deploy-netcup-full.sh. Direct terminal logs, one layer of indirection, 5-minute feedback loop. Sufficient for solo dev + single cluster.
  4. Switch to Woodpecker when one of four thresholds hits (Sprint 46 in the roadmap, task #188):
  5. A 2nd contributor opens PRs
  6. A 2nd deployment target appears (staging, pilot customer)
  7. A commercial audit requires CI-traceable release evidence
  8. A public signed release (v* tag, Cosign OIDC-verifiable signatures from a known issuer)

Consequences

Positive

  • Zero wasted time debugging CI layers when there is no gain yet.
  • Operators get direct helm upgrade logs, shortest feedback loop.
  • .woodpecker/*.yml pipelines stay in the repo as executable specifications of what a full build looks like — a future contributor or auditor reads them as the build recipe even without Woodpecker running.
  • Security posture: no public CI URL, no OAuth App sitting idle.
  • No commercial CI dependency on a US vendor for a sovereign stack.

Negative

  • No PR gate — a push to main is accepted without automated lint. Mitigation: pre-commit hook locally + the user runs helm lint + lint-no-hardcoding.sh + check-licenses.sh as part of the commit workflow.
  • No auditable history of CI runs beyond terminal output. Mitigation: capture deploy-netcup-full.sh output with tee and store under /var/log/akko-deploys/<date>.log.
  • Slightly more friction when onboarding the 2nd maintainer. Mitigation: Sprint 46 trigger is explicit — once a 2nd contributor arrives, turning on Woodpecker is a 45-minute lift documented in docs/admin/woodpecker-access.md.

Alternatives considered but rejected

  • Drone CI — very similar to Woodpecker but Apache 2.0 is only the Drone OSS (Harness commercial pressure). Chose Woodpecker for license clarity.
  • Jenkins — too heavy (1.5 Gi RAM minimum), plugin security surface, XML configuration tax.
  • Forgejo Actions / Gitea Actions — interesting but would pull in a full Forgejo/Gitea install we don't otherwise need.
  • Argo Workflows / Tekton — excellent for k8s-native CI but stronger argument for automation at the commercial scale, not solo.

When to revisit

  • First external contributor pull request (Sprint 46 trigger 1).
  • First client demonstration of the release pipeline (Sprint 46 trigger 3).
  • Release v2026.07 or later if distributed signed artefacts become a contractual requirement (trigger 4).

Status

Accepted 2026-04-19. Revisit at the Sprint 46 kick-off meeting.