Review: Add Woodpecker CI pipeline and k8s manifests (gcal-mcp-remote)

review-63-2026-03-27b Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Second review pass after issue body was updated per first review (review-63-2026-03-27). The issue body is substantially improved but still has fixable issues.

Template Completeness

  • [x] Repo
  • [x] User Story
  • [x] Context
  • [x] File Targets -- detailed with create/modify/not-touch sections
  • [x] Acceptance Criteria
  • [x] Constraints -- well documented (Harbor, Woodpecker secrets, ArgoCD, src layout)
  • [x] Checklist
  • [x] Related
  • [ ] Type -- missing header (defaults to Feature, acceptable but should be explicit)
  • [ ] Lineage -- uses legacy ### Plan header instead of ### Lineage
  • [ ] Test Expectations -- missing entirely. No test commands, no verification steps.

Traceability

  • [x] story:superuser-onboard label -- present on board item
  • [x] arch:ci-pipeline label -- present on board item
  • [x] Forgejo issue -- forgejo_admin/gcal-mcp-remote#3, open

File Targets

  • [ ] .woodpecker.yml -- ISSUE: ticket says .yml, but the reference implementation (notion-mcp-remote) and existing PR#4 both use .woodpecker.yaml. Must correct to .yaml.
  • [ ] Dockerfile -- ISSUE: ticket says Dockerfile, but reference and existing PR#4 use Dockerfile.k8s. The kaniko step references dockerfile: Dockerfile.k8s. Must correct to Dockerfile.k8s.
  • [x] k8s/deployment.yaml -- verified: does not exist on main, correctly targeted for creation
  • [x] k8s/service.yaml -- verified: does not exist on main, correctly targeted for creation
  • [x] k8s/pvc.yaml -- verified: does not exist on main, correctly targeted for creation
  • [x] k8s/servicemonitor.yaml -- verified: does not exist on main, correctly targeted for creation
  • [x] k8s/kustomization.yaml -- verified: does not exist on main, correctly targeted for creation
  • [x] src/gcal_mcp_remote/server.py -- verified: exists on main, port 8001, no /metrics. Correctly targeted for modification.
  • [x] pyproject.toml -- verified: exists on main, no ruff config or dev deps. Correctly targeted for modification.
  • [ ] systemd/gcal-mcp-remote.service -- MISSING from targets. Exists on main. Port change 8001 to 8000 likely affects this file.
  • [ ] .env.example -- MISSING from targets. Exists on main. PORT default change may need documenting here.

Repo Placement

OK -- issue filed on gcal-mcp-remote, work happens in gcal-mcp-remote. ArgoCD Application wiring in pal-e-deployments is correctly documented as out-of-scope dependency in Constraints.

Dependencies

  • Harbor project -- documented in Constraints. Must exist before first CI push.
  • Woodpecker secrets -- documented in Constraints (harbor_username, harbor_password, forgejo_token).
  • ArgoCD Application -- documented in Constraints. Separate downstream task.
  • CRITICAL -- Stale PR#4: Open PR (forgejo_admin/gcal-mcp-remote#4) already implements this scope. Created 2026-03-02, BEFORE the mcp-remote-auth migration (PR#36, merged 2026-03-02+). Branch 3-add-woodpecker-ci-pipeline-and-k8s-manif is 25 days stale. server.py was substantially refactored in the auth migration -- the PR branch's server.py changes will conflict. An agent must either rebase or start fresh. This is undocumented in the issue.
  • Sibling ticket -- board item #65 (linkedin-scheduler-remote) is identical pattern in todo. Not a blocker but same file naming issues likely apply there too.

Acceptance Criteria

Two criteria present. Testable but underspecified:
  • AC1 ("Woodpecker runs lint checks and builds a container image to Harbor") -- verifiable via Woodpecker pipeline status. OK.
  • AC2 ("ArgoCD syncs... deploys on port 8000 with health checks, PVC, and ServiceMonitor") -- depends on ArgoCD Application in pal-e-deployments (out of scope). K8s manifests verifiable structurally, not end-to-end. Partially testable.
Missing specifics: health check path not specified, no /metrics endpoint verification command, no ruff check/format commands listed.

Blast Radius

  • linkedin-scheduler-remote (board item #65) -- identical pattern in todo, same file naming issues.
  • gcal-scheduler (board item #64) -- same pattern, already done. Additional reference.
  • Port change (8001 to 8000) affects systemd/gcal-mcp-remote.service and .env.example -- neither in file targets.

Decomposition

9 file targets across 1 repo. 2 acceptance criteria. PR#4 proves achievable in a single agent pass (2 commits). No decomposition needed. However, agent must handle stale branch situation (rebase or fresh start).

Recommendation

  • [BODY] Fix file name: .woodpecker.yml to .woodpecker.yaml (match reference pattern from notion-mcp-remote)
  • [BODY] Fix file name: Dockerfile to Dockerfile.k8s (match reference pattern and kaniko config)
  • [BODY] Add ### Type\nFeature header at top of issue
  • [BODY] Replace ### Plan with ### Lineage format
  • [BODY] Add ### Test Expectations section with: ruff check ., ruff format --check ., verify /metrics returns Prometheus text, docker build -f Dockerfile.k8s .
  • [BODY] Add systemd/gcal-mcp-remote.service and .env.example to file targets (port 8001-to-8000 affects both)
  • [BODY] Add Context note: stale PR#4 exists. Agent must close PR#4 and start fresh from current main (post mcp-remote-auth migration).
  • [SCOPE] Clarify: should agent rebase stale PR#4 or close and start fresh? Recommendation: close PR#4, start fresh -- the auth migration changed server.py fundamentally.