Review: Set up CI/CD pipeline: Woodpecker + Harbor + ArgoCD

review-1372-2026-06-06 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- Standalone, discovered from undeployed Stripe PRs
  • [x] Repo -- ldraney/westside-ror
  • [x] User Story -- present and well-formed
  • [x] Context -- thorough, references landscaping-assistant pattern
  • [x] File Targets -- present with both modify/create and do-not-touch sections
  • [x] Acceptance Criteria -- 10 items, clear and specific
  • [x] Test Expectations -- present with run commands
  • [x] Constraints -- present with platform patterns, base images, access requirements
  • [x] Checklist -- present
  • [x] Related -- present
All required sections for the Feature template are present.

Traceability

  • [x] story:ci-pipeline label -- present on board item
  • [ ] story note MISSING -- [SCOPE] No project page project-westside-ror exists in pal-e-docs, so user-stories section cannot be verified. Create project page with user story entry for ci-pipeline.
  • [x] arch:ci-cd label -- present on board item
  • [ ] arch note MISSING -- [SCOPE] No architecture note arch-ci-cd found in pal-e-docs. Create architecture note arch-ci-cd for CI/CD pipeline component.
  • [x] Forgejo issue -- ldraney/westside-ror#40, open

File Targets

  • [x] .woodpecker.yaml -- confirmed does NOT exist yet (new file, correct)
  • [x] Dockerfile -- exists, currently uses docker.io/library/ruby:3.4-slim. Needs update to platform base images (ruby-rails-build, ruby-rails-runtime). Verified reference impl at landscaping-assistant/Dockerfile uses harbor.tail5b443a.ts.net/library/ruby-rails-build:latest.
  • [x] k8s/ -- exists with only dev.yaml. Currently references ruby:3.4-slim image with hostPath mount. Ticket correctly identifies need for proper prod manifests referencing Harbor image.
  • [x] bin/docker-entrypoint -- exists and already runs db:prepare on startup. No changes needed.
  • [x] k8s/dev.yaml -- correctly listed under "do not touch"
  • [x] pal-e-services/terraform/k3s.tfvars -- verified: westside-ror is NOT in the services block (line 137-225). Needs to be added. Confirmed other services follow the pattern: forgejo_repo, image_repo, port, funnel, source_repo, source_path.

Repo Placement

This ticket correctly identifies work across TWO repos:
  • ldraney/westside-ror -- .woodpecker.yaml, Dockerfile, k8s manifests (Forgejo issue is filed here)
  • ldraney/pal-e-services -- terraform/k3s.tfvars services block
The issue body explicitly documents the cross-repo file target. However, there is no separate Forgejo issue on pal-e-services for the terraform change. This is acceptable since the terraform change is a single-line addition and is clearly documented in the file targets. A separate issue would be over-engineering.

Dependencies

  • No board items currently blocking this ticket. Item #1372 is in backlog.
  • Items #1207 (issue #2, in_progress) and #1222 (issue #13, in_progress) are unrelated feature work.
  • Done items #1334 (issue #24) and #1357 (issue #27) are the Stripe work this ticket aims to deploy -- they are completed, not blocking.
  • Done item #1358 (issue #28, "Commit prod deployment manifests") is DIRECTLY related -- it committed deployment manifests but those are the dev overlay. This ticket replaces those with proper Harbor-image manifests. No conflict.
  • The ticket requires platform base images (ruby-rails-build, ruby-rails-runtime) to exist in Harbor. The constraints section mentions this but does not verify it. The landscaping-assistant reference already uses these images successfully.
  • Requires Harbor admin access, Woodpecker admin access, and terraform access to pal-e-services. Documented in Constraints.
  • The westsidekingsandqueens-funnel ingress currently exists in the cluster (verified via kubectl) -- created manually. AC #8 requires preserving both funnel ingresses. The terraform services block will create a new westside-ror funnel, but the westsidekingsandqueens funnel needs special handling since it is a second hostname for the same service. This is not addressed in the file targets.

Acceptance Criteria

10 acceptance criteria present. Assessment:
  • AC 1-4 (Harbor project, .woodpecker.yaml, Dockerfile, Woodpecker activation) -- agent-verifiable via API/file checks
  • AC 5-6 (terraform services block, ArgoCD app) -- agent-verifiable via file diff and ArgoCD API
  • AC 7 (k8s manifests reference Harbor image) -- agent-verifiable via file content check
  • AC 8 (both funnel ingresses preserved) -- [BODY] This is the most complex criterion. The westsidekingsandqueens funnel was created via kubectl apply (see docs/consolidation.md). When terraform creates the ArgoCD app, the deployment manifests need to include this second ingress OR it will be lost. The file targets do not mention creating a second ingress manifest. Recommend adding explicit file target for the westsidekingsandqueens funnel ingress in k8s prod manifests.
  • AC 9 (docker-entrypoint runs db:prepare) -- already satisfied, verified in code
  • AC 10 (first pipeline builds and deploys) -- manual verification needed post-implementation

Blast Radius

  • The westsidekingsandqueens-funnel ingress was manually created (kubectl apply) and is NOT managed by ArgoCD or terraform. When this ticket transitions westside-ror to ArgoCD management, the ArgoCD app will only sync what is in the deployment manifests. If the funnel ingress manifest is not included, the westsidekingsandqueens URL will be lost. This is the highest-risk item.
  • The current dev overlay (k8s/dev.yaml) contains hardcoded secrets (POSTGRES_PASSWORD, SECRET_KEY_BASE). These should NOT be committed to prod manifests. The ticket correctly says to keep dev.yaml as-is.
  • The external CNPG database connection (pal-e-postgres-rw.postgres.svc:5432, database: basketball) must be preserved in the prod manifests. The current dev.yaml references this via env vars -- prod manifests will need equivalent secret references.
  • No other services are affected -- this is a new pipeline for an existing service.

Decomposition Assessment

5-minute rule assessment:
  • File targets: 4 files in westside-ror + 1 in pal-e-services = 5 files across 2 repos
  • Acceptance criteria: 10 items
  • Estimated agent work: >5 minutes (Harbor project creation, Woodpecker activation, terraform apply, ArgoCD sync, pipeline validation)
  • However, several AC items require manual admin operations (Harbor project creation, Woodpecker repo activation, terraform apply) that cannot be done by a code agent alone.
NEEDS DECOMPOSITION -- 10 AC across 2 repos with manual admin steps. However, the decomposition is natural: (1) code changes PR (Dockerfile, .woodpecker.yaml, k8s manifests), (2) infra provisioning (Harbor, Woodpecker, terraform), (3) validation. Route to skill-decompose-ticket.

Recommendation

  • [BODY] Add explicit file target for westsidekingsandqueens funnel ingress manifest in k8s prod directory -- without it, ArgoCD sync will drop the second hostname.
  • [BODY] Add file target for Stripe-related env vars/secrets in prod manifests (STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, etc.) -- these are needed for the Stripe features to actually work in prod.
  • [SCOPE] Create project page project-westside-ror in pal-e-docs with user-stories section including ci-pipeline story.
  • [SCOPE] Create architecture note arch-ci-cd documenting the platform CI/CD pipeline pattern.
  • [DECOMPOSE] 10 AC across 2 repos with manual admin operations. Route to skill-decompose-ticket for sub-ticket creation: (1) code changes PR, (2) infra provisioning, (3) end-to-end validation.