Review: Woodpecker agent label routing — pipeline contract

review-425-2026-03-26 Review

review ready

Verdict: READY

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — discovered during incident #184
  • [x] Repo — primary + cross-repo identified
  • [x] User Story — platform operator, label routing, prevents random CI failures
  • [x] Context — thorough incident analysis, work-stealing explanation, immediate mitigation documented
  • [x] File Targets — modify + do-not-touch + cross-repo follow-ups all listed
  • [x] Acceptance Criteria — 7 criteria, all verifiable
  • [x] Test Expectations — tofu validate, plan, post-apply agent routing verification
  • [x] Constraints — tofu not terraform, -lock=false, salt hands-off, #174 dependency
  • [x] Checklist — PR, tests, no unrelated changes, convention note, cross-repo follow-ups
  • [x] Related — #184, #174, #166, #179, project-pal-e-platform

Traceability

  • [x] story:superuser-deploy label — present on board item #425
  • [x] arch:ci-pipeline label — present on board item #425
  • [x] Forgejo issue — forgejo_admin/pal-e-platform#191, open

File Targets

  • [x] terraform/main.tf — verified: agent env block at lines 775-785 has no WOODPECKER_FILTER_LABELS or WOODPECKER_CONNECT_RETRY_COUNT. Changes are additive to existing env map.
  • [x] .woodpecker.yaml — verified: no labels: directive on any workflow. Addition needed at workflow level.
  • [x] salt/pillar/mac-agent.sls — verified: already has filter_labels: "platform=darwin" at line 21. Correctly marked do-not-touch.
  • [x] salt/states/mac-agent/com.woodpecker.agent.plist.j2 — verified: renders WOODPECKER_FILTER_LABELS from pillar. Correctly marked do-not-touch.

Repo Placement

OK. Primary changes are in forgejo_admin/pal-e-platform (Helm values + this repo's pipeline). Cross-repo .woodpecker.yaml updates are explicitly deferred to separate follow-up issues. Issue is filed on the correct repo.

Dependencies

  • #184 (Harbor connectivity timeout / parent incident) — currently in_progress on board. This ticket was discovered during #184 investigation. Not a hard blocker — can proceed in parallel.
  • #174 (Mac build agent — Salt managed) — currently next_up on board. The ticket correctly documents that Mac agent re-enablement (acceptance criterion 6) depends on #174 being far enough along. This is a soft dependency — the k8s-side changes can land first.
  • #179 (Woodpecker agent secret duplication) — done. No conflict.
  • Phase 30: Mac CI Agent (board item #287) — in backlog. Broader Mac CI phase. This ticket is a prerequisite for that phase's success.

Acceptance Criteria

All 7 criteria are agent-verifiable:
  • Criteria 1-3: verifiable via tofu plan output inspection
  • Criterion 4: verifiable via tofu plan diff analysis
  • Criterion 5: verifiable by checking if convention-pipeline-labels note exists in pal-e-docs
  • Criterion 6: requires manual Mac agent re-enablement + pipeline trigger — correctly gated behind #174
  • Criterion 7: verifiable by listing created Forgejo issues
Note: Criterion 6 (Mac agent re-enablement) may need to be split into a separate follow-up if #174 is not ready at PR time. The ticket acknowledges this in Constraints.

Blast Radius

Confirmed 15+ repos have .woodpecker.yaml files with NO labels: directive, including: basketball-api, pal-e-deployments, pal-e-docs, pal-e-app, westside-app, westside-contracts, mcd-tracker-api, mcd-tracker-app, minio-api, pal-e-mail, platform-validation, and several MCP servers. All are currently vulnerable to the same work-stealing bug if the Mac agent is re-enabled without label routing.
The ticket correctly identifies this blast radius and defers cross-repo updates to follow-up issues. The k8s agent filter label change will protect existing pipelines even before cross-repo labels are added — unlabeled pipelines will still route to the k8s agent as long as only the Mac agent has restrictive filter labels. However, once the k8s agent also gets WOODPECKER_FILTER_LABELS=platform=linux, any pipeline WITHOUT labels: { platform: linux } will match NO agent. The cross-repo follow-ups are therefore not optional — they must land before or simultaneously with the k8s agent filter label change.

Recommendation

No action needed — scope is solid. All file targets verified, traceability complete, dependencies documented, acceptance criteria testable. One sequencing note: the cross-repo .woodpecker.yaml label updates must land before or at the same time as the k8s agent WOODPECKER_FILTER_LABELS change, otherwise unlabeled pipelines will match no agent. The ticket's acceptance criteria implicitly handle this (criterion 6 tests routing end-to-end), but the implementation agent should be aware of this ordering constraint. Ready to move to next_up.