Review: linkedin-scheduler-remote — Add Woodpecker CI pipeline and k8s manifests

review-65-2026-03-27 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

Compared against template-issue-feature:
  • [ ] ### Type — missing (defaults to Feature, acceptable)
  • [ ] ### Lineage — missing. References plan-2026-02-25-mcp-gateway-migration Phase 3, but uses non-standard "### Plan" header
  • [x] ### Repo — present: linkedin-scheduler-remote
  • [x] ### User Story — present and well-formed
  • [ ] ### Context — missing. "Additional Information" provides technical details but not motivation for zero-knowledge reader
  • [ ] ### File Targets — missing as formal section. File list in "Changes" under Additional Information doesn't follow template format
  • [x] ### Acceptance Criteria — present (2 criteria)
  • [ ] ### Test Expectations — missing. No test commands or verification steps
  • [ ] ### Constraints — missing
  • [x] ### Checklist — present
  • [x] ### Related — present

Traceability

  • [x] story:superuser-onboard — present on board item
  • [x] arch:ci-pipeline — present on board item
  • [x] Forgejo issue — forgejo_admin/linkedin-scheduler-remote#3, open
  • [x] type:feature — present on board item

File Targets

CRITICAL FINDING: Most work described in the issue is ALREADY DONE. Verified against current repo state on main branch:
  • [x] .woodpecker.yml — ALREADY EXISTS (note: .yml not .yaml as issue states). Has test step (ruff) + build-and-push step (kaniko to Harbor). Uses Forgejo PyPI for private deps.
  • [x] Dockerfile — ALREADY EXISTS (named Dockerfile not Dockerfile.k8s as issue states). Multi-stage build with requirements.txt.
  • [x] k8s/deployment.yaml — ALREADY EXISTS. All env vars present. Port 8000. 256Mi memory limit. Health checks. imagePullSecrets.
  • [ ] k8s/service.yaml — Does NOT exist as separate file. Service is defined inline at bottom of deployment.yaml.
  • [ ] k8s/pvc.yaml — Does NOT exist as separate file. PVC is defined inline at bottom of deployment.yaml.
  • [x] k8s/servicemonitor.yaml — ALREADY EXISTS
  • [x] k8s/kustomization.yaml — ALREADY EXISTS but only lists deployment.yaml + servicemonitor.yaml
  • [ ] server.py — EXISTS but NO /metrics endpoint found
  • [ ] pyproject.toml — needs verification for dev deps and ruff config

Repo Placement

Correct — issue is filed on linkedin-scheduler-remote and work happens there. Note: current server.py has PORT default 8002, but k8s deployment already sets PORT=8000 via env var, so this is fine.

Dependencies

  • Board item #64 (gcal-scheduler CI+k8s) is in done — no blocker
  • notion-mcp-remote (reference pattern) is merged — no blocker
  • Harbor project appears to already exist (Woodpecker CI references harbor.tail5b443a.ts.net/linkedin-scheduler-remote/server)
  • Woodpecker secrets appear configured (build step references harbor_username, harbor_password, forgejo_publish_user, forgejo_publish_token)
  • No dependency on other board items

Acceptance Criteria

  • CI criterion: "Woodpecker runs ruff lint/format checks and builds a container image to Harbor" — this appears to ALREADY WORK based on existing .woodpecker.yml.
  • Deploy criterion: "deploys with correct env vars, port 8000, PVC, and ServiceMonitor" — mostly already in place. Only missing: separate service.yaml/pvc.yaml files and /metrics endpoint.
  • Missing criterion: No verification that /metrics endpoint works. No criterion for splitting inline resources into separate files.

Blast Radius

Low blast radius. The remaining work is minor:
  • Extract Service and PVC from deployment.yaml into separate files (cosmetic, aligns with pattern)
  • Update kustomization.yaml to reference all 4 resources
  • Add /metrics endpoint to server.py
  • Add ruff config to pyproject.toml if missing
The .woodpecker.yml uses .yml extension while the notion-mcp-remote pattern uses .yaml. Woodpecker supports both, but convention alignment may be desired.

Decomposition

Remaining scope is small (3-4 file changes). Single agent pass is fine IF the scope is narrowed to reflect what is actually left to do.

Recommendation

The issue scope is fundamentally stale — it describes creating files that already exist. Before moving to next_up:
  • Audit and rewrite scope — the issue body describes work that is roughly 80% done. Rewrite to reflect only remaining delta: split inline resources, add /metrics, add ruff config
  • Add File Targets section — list ONLY the files that still need changes, with what exactly changes
  • Add Test Expectations — at minimum: ruff passes, /metrics returns valid Prometheus output, kubectl apply dry-run succeeds for all k8s/ files
  • Decide on .yml vs .yaml — current file is .woodpecker.yml, reference pattern is .woodpecker.yaml. Specify which is canonical.
  • Consider closing as mostly-done — if the remaining delta is trivial enough, it may make more sense to close this issue and open a new, smaller one for just the /metrics + file split work