Ticket: Woodpecker pipeline — build westside-ops to Harbor

ticket-westside-ops-woodpecker-pipeline Doc

active backlog westside-ops ticket

Ticket: Woodpecker pipeline — build westside-ops to Harbor

Story: story-westside-ops-spreadsheet-access
Architecture: arch-deployment-westside-ops (Harbor-mirrored image decision)
Labels: story:spreadsheet-access,arch:woodpecker-ci,type:infra,track:devops,scope:planned
Blocks: k8s overlay (needs an image in Harbor to deploy)
Blocked by: repo bootstrap, streamlit_admin.py implementation, services-entry (needs Harbor project + CI robot credentials)

Purpose

Wire up the Woodpecker pipeline so every push to main builds the Streamlit image with Kaniko and pushes it to harbor.tail5b443a.ts.net/westside-ops/app:{CI_COMMIT_SHA}. Inherits the westsidekingsandqueens pattern exactly — single pipeline, Kaniko build, Harbor secrets, path exclude for Image Updater write-backs.

Scope

  • Replace the skeleton .woodpecker.yaml from the repo bootstrap ticket with the real pipeline (see YAML below)
  • Register the repo in Woodpecker UI at https://woodpecker.tail5b443a.ts.net by clicking "Add repository"
  • Add two secrets to the Woodpecker repo settings:
  • Push a trivial commit to trigger the first build; verify it succeeds and the image appears in Harbor

.woodpecker.yaml

Gotchas (from existing services' lessons)

  • Use $CI_COMMIT_SHA, NOT ${CI_COMMIT_SHA}. Curly braces break Woodpecker's compiler. Per SERVICE_ONBOARDING.md.
  • Path exclude k8s/.argocd-source-* is mandatory. Without it, Image Updater write-backs trigger infinite build loops. Per feedback_ci_pipeline_lessons.
  • Only two secrets needed. No ArgoCD deploy step — that's handled by the Image Updater + ArgoCD sync loop provisioned by pal-e-services.
  • YAML parse validation. Per feedback_yaml_parse_validation, run python -c "import yaml; yaml.safe_load(open('.woodpecker.yaml'))" before committing to catch unquoted colons and similar gotchas.

Acceptance Criteria

  • [ ] .woodpecker.yaml parses cleanly with yaml.safe_load
  • [ ] Woodpecker repo registered at https://woodpecker.tail5b443a.ts.net, pipeline visible in UI
  • [ ] harbor_username and harbor_password secrets set in Woodpecker (values from the services-entry ticket's tofu outputs)
  • [ ] First build after push to main succeeds, visible in Woodpecker UI
  • [ ] harbor.tail5b443a.ts.net/westside-ops/app:{commit-sha} exists and is pullable (verify in Harbor UI)
  • [ ] Subsequent writeback commits from Image Updater do NOT trigger additional builds (path exclude working)

Files touched

  • ~/westside-ops/.woodpecker.yaml (replace skeleton)
  • Woodpecker UI state (repo registration, secrets)

Rollback

Delete the Woodpecker repo registration. Delete the Harbor project (tofu destroys it when services-entry is reverted). No cluster impact.

Out of scope

  • Test step in the pipeline — v1 has no tests per the streamlit-app ticket's scope. Add a test step later if/when tests are added.
  • Multi-arch builds — amd64 only for v1
  • Semver tagging — commit SHA only, matching existing services

Dependencies

Blocked by: repo bootstrap, streamlit-app implementation, services-entry (for Harbor project + CI robot credentials).