feat(e2e): add apps-e2e shared workflow + composite actions#43
feat(e2e): add apps-e2e shared workflow + composite actions#43MaximusHaximus wants to merge 1 commit into
Conversation
| run: | | ||
| # The consuming repo's e2e suite reads this env var to switch from the | ||
| # kurtosis CLI path to the sidecar JSON path. Writing to GITHUB_ENV | ||
| # propagates it to every subsequent step in the calling job without | ||
| # the consumer having to know the magic name. | ||
| echo "E2E_SNAPSHOT_ADDRESSES_JSON=${ADDRS_PATH}" >> "$GITHUB_ENV" |
| - name: Restore from snapshot | ||
| if: env.E2E_USE_SNAPSHOT == '1' | ||
| id: snapshot | ||
| uses: 0xPolygon/pipelines/.github/actions/e2e-snapshot-restore@main |
|
|
||
| - name: Cold-start kurtosis | ||
| if: env.E2E_USE_SNAPSHOT == '0' | ||
| uses: 0xPolygon/pipelines/.github/actions/e2e-cold-start@main |
|
Code Review2 issues found. Inline comments posted on
No bugs found. Shell scripts are well-written with proper error handling, quoting, and cleanup traps. |
Code Review - Inline DetailsIssue 1: Location: The comment at line 16-17 instructs consumers to call this workflow with Issue 2: Non-trivial inline shell in workflow YAML (Team Standards violation) Location: The "Dump devnet on failure" step has ~10 lines of branching shell logic (nested No bugs found. Shell scripts are well-written with proper error handling, quoting, and cleanup traps. |
| # they live upstream and we'd rather pin to a known kurtosis-pos commit than | ||
| # vendor copies that silently drift from the snapshot they're paired with. | ||
| echo "[restore] cloning kurtosis-pos@${KURTOSIS_POS_REF} into ${WORK_DIR}" | ||
| git clone --depth 1 --branch "$KURTOSIS_POS_REF" \ |
There was a problem hiding this comment.
--branch wouldn't work with a commit SHA
API review: is it sane, and flexible enough for proof-generation-api / pos-airdrop / matic.js?Reviewed the workflow + composite interfaces against the lst-api consumer side (#125) and the three candidate adopters. The call surface is sane and the right shape, but it's currently sized exactly for lst-api's existing adapter. Two flexibility gaps block clean matic.js / pos-airdrop adoption, plus a handful of correctness/footgun issues worth fixing in the same PR. Correctness bugs
Missing functionality (the real flexibility gaps)
Design issues
What I'd fix before merge
Per-consumer fitness
|
Correctness: - Guard apps-e2e-trigger.yml against firing on pipelines' own PRs (`github.repository != '0xPolygon/pipelines'`) — pipelines has no `pnpm run e2e` to run. No-op in any consumer, so still copy-verbatim. - restore.sh: `docker create --entrypoint /bin/true` so the addresses sidecar extraction overrides (not appends to) any ENTRYPOINT a future snapshot image declares. - cold-start.sh: verify the EL resource scale-down sed actually applied (grep the override marker, exit 1 if the file moved or vars renamed on an unexpected kurtosis_pos_ref) instead of silently OOM-killing. - restore.sh: fold state_hex_file / body_file into the cleanup trap so the ~2 MB temps don't leak when curl or the result check exits non-zero. - Drop the stale "compare boolean AND string" comment in the trigger (the expression only compares the toJSON string). Flexibility / standards: - Add REGISTRY_USERNAME / REGISTRY_PASSWORD (required: false) secrets to apps-e2e.yml and forward into the snapshot composite, falling back to the actor + GITHUB_TOKEN when unset. Unblocks a cross-org consumer (matic.js) pulling a private snapshot with its own credentials. - Remove the `secrets: inherit` recommendation from the header comment (prohibited by Team Standards). - Extract the on-failure dump shell into a new e2e-dump composite action (bundled script via github.action_path) rather than inline YAML — a reusable workflow can't reach a .github/scripts/ helper cross-repo. - Document the dual-path adapter contract and the secret-injection limitation on the e2e_command input; cold-start composite now exports E2E_KURTOSIS_ENCLAVE=pos for a symmetric, single-path consumer adapter. Deferred (design polish, tracked for follow-up): runner/fetch-depth inputs, jq-over-python, install-after-composite, enclave-name parameterisation, required snapshot_image. Generic suite-secret injection stays out — named secrets only, no secrets: inherit.
| # keeps this YAML thin and the shell locally runnable. | ||
| - name: Dump devnet on failure | ||
| if: failure() | ||
| uses: 0xPolygon/pipelines/.github/actions/e2e-dump@main |
|
Consumer-side kurtosis-pos e2e harness, shared so adopters (lst-api today, matic.js / proof-generation-api next) call one implementation instead of vendoring copies that drift. - apps-e2e.yml — reusable workflow. Snapshot mode (default, ~30s) restores a published GHCR image via the e2e-snapshot-restore composite; cold-start mode (~10m) runs kurtosis from source via the e2e-cold-start composite for unsnapshotted kurtosis-pos refs. The snapshot/cold-start switch uses `toJSON(inputs.use_snapshot) == 'false'` because Actions' loose equality treats `null == false` as true, which would otherwise drop null-input pull_request runs into cold-start. REGISTRY_USERNAME / REGISTRY_PASSWORD (optional) let a cross-org consumer pull a private snapshot with its own credentials, falling back to the actor + GITHUB_TOKEN when unset. - actions/e2e-snapshot-restore — pull + restore a snapshot image (extract volumes, patch the pos-anvil host port, replay anvil state). - actions/e2e-cold-start — install kurtosis-cli, scale EL resource limits down for ubuntu-latest (verified, fails loud if the patch no-ops on an unexpected ref), run the enclave; exports E2E_KURTOSIS_ENCLAVE for a symmetric consumer adapter. - actions/e2e-dump — capture devnet state on failure (compose logs or enclave dump). A composite, not an inline run: block or a .github/scripts/ helper, because a reusable workflow can't reach a repo-local script cross-repo. - apps-e2e-trigger.yml — canonical thin trigger, guarded against firing on pipelines' own PRs. - README — workflow + composite tables and usage notes. Out of scope: the snapshot publisher stays in lst-api against its GHCR namespace; moving + renaming it is a separate refactor. Generic suite-secret injection is documented as a known limitation — named secrets only, never `secrets: inherit` (Team Standards).
02f6294 to
baa6cfe
Compare
|




Summary
Consumer-side kurtosis-pos e2e harness, factored into
0xPolygon/pipelinesso adopters call one shared implementation instead of vendoring copies that drift. lst-api migrates onto it in a stacked PR (0xPolygon/lst-api#125); matic.js and proof-generation-api are the next candidates.apps-e2e.yml— reusable workflow. Snapshot mode (default, ~30s) restores a published GHCR image via thee2e-snapshot-restorecomposite; cold-start mode (~10m) runs kurtosis from source viae2e-cold-startfor kurtosis-pos refs that haven't been snapshotted. Runs the consumer'se2e_command, dumps devnet state on failure, uploads a 7-day artefact. OptionalREGISTRY_USERNAME/REGISTRY_PASSWORDsecrets let a cross-org consumer pull a private snapshot with its own credentials, falling back to the workflow actor +GITHUB_TOKENwhen unset.actions/e2e-snapshot-restore— pull + restore a snapshot image (extract volumes, patch thepos-anvilhost port, replay anvil state). Bundles itsrestore.shnext toaction.yml, referenced via${{ github.action_path }}.actions/e2e-cold-start— install kurtosis-cli, scale EL resource limits down to fitubuntu-latest, run the enclave from source. ExportsE2E_KURTOSIS_ENCLAVEso a consumer can write a single env-driven adapter across both modes.actions/e2e-dump— capture devnet state on failure (compose logs or kurtosis enclave dump). A composite rather than an inlinerun:block or a.github/scripts/helper, because a reusable workflow can't reach a repo-local script when it runs in a consumer's checkout.apps-e2e-trigger.yml— canonical thin trigger for consumers to copy, guarded against firing on pipelines' own PRs.use_snapshotboolean handlingThe snapshot/cold-start switch resolves via
toJSON(inputs.use_snapshot) == 'false'. GitHub Actions'==/!=use loose equality wherenull == falseevaluates to true, so a naiveinputs.use_snapshot == falsewould also match the null inputs thatpull_requestevents carry and silently drop label-triggered PR runs into the slow cold-start path. Stringifying viatoJSONfirst ("null"/"false"/"true") makes the comparison unambiguous; snapshot stays the strong default and only an explicit booleanfalseflips to cold-start.Review feedback (all resolved)
Addressing the API review on this PR plus the automated review:
github.repository != '0xPolygon/pipelines'so arun-e2elabel here doesn't spawn a run with nopnpm run e2e.e2e-snapshot-restoreusesdocker create --entrypoint /bin/trueso the addresses-sidecar extraction overrides anyENTRYPOINTa future snapshot declares.curlfailure).secrets: inheritrecommendation removed (prohibited by Team Standards); the dual-path adapter contract and the named-secrets-only limitation are documented on thee2e_commandinput.Deferred as design polish (tracked for follow-up, not blocking adoption):
runner/checkout_fetch_depthinputs,jq-over-python3, install-after-composite ordering, enclave-name parameterisation,requiredsnapshot_image. Generic suite-secret injection stays out — named secrets only.Out of scope
The snapshot publisher stays in lst-api against its GHCR namespace; moving and renaming it is a separate refactor once a second consumer hits a publisher-side bug.
Validation
Validated cross-repo against lst-api#125 before this branch was cleaned up:
run-e2elabel — restore + suite green end-to-end.e2e-cold-startbrought kurtosis up cleanly; the suite failure there is the documented pre-block-256eth_getLogslimitation (consumer-side), not the workflow.devnet-dump-<run-id>artefact.Cross-repo refs were pinned to this feature branch during validation, then reverted to
@main. History has since been squashed to a single commit on top of currentmain.