OPER-220
Shared Playwright-install retry composite action across Portico + Roster + Piper DX
Suggested
Justin Cooke
Body
---
feature_id: FEAT-operant-shared-devops-tooling
---
## Context
Follow-up from ROST-[REDACTED-PHONE] (Roster CI-red bundle) per the DOC Memo [REDACTED-DOB] Chair explicit punt:
> What I explicitly punt: (a) migrating the retry wrapper into a shared Portico+Roster+Piper DX composite action -- that's a cross-repo cleanup, worth a follow-up ticket in `operant-health/operant-studio` per OPERANT-BOILERPLATE.md's shared-tooling section.
ROST-[REDACTED-PHONE] ships a `scripts/ci/playwright-install-with-retry.sh` local to the roster repo. But Portico and Piper DX have the same Playwright install pattern in their CI + main-e2e-guard workflows, and if we hit a similar apt-race there we get the same 8-day-stuck-red mode. This ticket promotes the retry script to a shared composite action so all three repos consume one source of truth.
## Design
Create `operant-health/operant-studio/actions/playwright-install-with-retry/action.yml` as a composite GitHub Action. Rewrite the three repos' workflows to consume it via:
```yaml
- uses: operant-health/operant-studio/actions/playwright-install-with-retry@v1
with:
force-first-fail: ${{ inputs.force-first-fail || 'false' }}
```
Action API contract:
- Input `force-first-fail: 'true'|'false'` (default `'false'`)
- Input `max-attempts: '3'` (default `'3'`)
- Output `signature: apt-race|npm-race|timeout|unknown` -- what tripped the last-failed attempt, useful for the caller's telemetry
- Output `attempts-used: '1'|'2'|'3'` -- how many attempts fired
- Emits the same structured JSON per attempt as the local script does today
## Migration steps
1. Copy `scripts/ci/playwright-install-with-retry.sh` from roster into `operant-studio/actions/playwright-install-with-retry/`, wrap in `action.yml`.
2. Tag `v1` on operant-studio.
3. Open one PR per repo to swap the local invocation for the composite-action reference:
- `operant-health/roster` -- delete local script + reference composite action.
- `operant-health/portico` -- add composite-action reference (Portico did NOT have this hardening; ROST-[REDACTED-PHONE] shipped it first).
- `operant-health/piperdx` -- add composite-action reference.
## Effort
One Ledger ticket family. Parallelizable across the three consumer-repo PRs (they don't depend on each other once the action is tagged). The tag step is a blocker before the consumer PRs open.
## Prerequisite
ROST-[REDACTED-PHONE] must be MERGED before this ticket starts. The composite action is the extraction of that script, not a from-scratch rewrite. Also add the composite-action registration to `OPERANT-BOILERPLATE.md` in operant-studio so future workflows know it exists.
## Verification
1. `operant-studio/actions/playwright-install-with-retry/action.yml` exists and is tagged `v1`
2. Manual `workflow_dispatch` of a smoke workflow in each of the three consumer repos with `force-first-fail=true` -> action reports attempts-used='2', signature='apt-race' or 'unknown'
3. `OPERANT-BOILERPLATE.md` in operant-studio has a "Shared composite actions" section listing this action
## Related
- ROST-[REDACTED-PHONE] (prerequisite -- ships the local script)
- DOC Memo [REDACTED-DOB] Chair punt (a) -- rationale for this follow-up
- ROST-30 / OPER-D3 -- Main E2E Guard pattern that this action supports across all three repos
## Acceptance Criteria
- [ ] `operant-studio/actions/playwright-install-with-retry/action.yml` exists, tagged `v1`
- [ ] Action has inputs `force-first-fail`, `max-attempts` and outputs `signature`, `attempts-used`
- [ ] Action emits per-attempt structured JSON matching the ROST-[REDACTED-PHONE] script contract
- [ ] Three consumer PRs (one per repo: roster, portico, piperdx) each pass CI with the composite-action reference
- [ ] Roster PR deletes local `scripts/ci/playwright-install-with-retry.sh` after swapping to the composite action
- [ ] Portico + Piper DX PRs replace the `pnpm exec playwright install --with-deps chromium` invocations in their respective `ci.yml` + `main-e2e-guard.yml` with the composite-action reference
- [ ] `OPERANT-BOILERPLATE.md` in operant-studio gains a "Shared composite actions" section documenting this action
---
<!-- admission-rejected -->
**Admission rejected (unknown_feature_id):** feature_id=FEAT-operant-shared-devops-tooling is not declared in the feature-map.md of any admission-enabled product owned by this team.
Valid feature_ids for product studio (products/studio/feature-map.md):
- FEAT-studio-agent-workers
- FEAT-studio-audit
- FEAT-studio-audit-log
- FEAT-studio-branch-protection-rulesets
- FEAT-studio-coverage-policy
- FEAT-studio-dependency-map-policy
- FEAT-studio-dispatcher
- FEAT-studio-env-protection
- FEAT-studio-fabricated-evidence-tripwire
- FEAT-studio-guard-inventory
- FEAT-studio-incident-runbook
- FEAT-studio-mutation-testing
- FEAT-studio-phi-guard
- FEAT-studio-pipeline-observability
- FEAT-studio-planning-validation
- FEAT-studio-platform
- FEAT-studio-product-manifest
- FEAT-studio-qa
- FEAT-studio-qa-autogen-auto-promote
- FEAT-studio-qa-bff-pattern
... and 8 more; see products/studio/feature-map.md
Attachments
Loading attachments…
Comments
Loading comments…