fix(ci): fail closed on skipped security e2e and gate frontend tests #187
Labels
No labels
agent:implement
agent:ready
backend
bug
cannot-reproduce
confirmed
desktop
docs
documentation
duplicate
enhancement
feature
frontend
good first issue
help wanted
high-risk
in-review
invalid
mobile
needs-triage
P0-critical
P1-high
P2-medium
P3-low
qa
QA
question
ready
report
responsive
security
security-escalate
smart-contract
solana
tablet
test-pass
ux
wallet-issue
wallet:keplr
wallet:metamask
wallet:station
wallet:walletconnect
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-bridge-monorepo#187
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Security-critical CI is fail-open in four places on
main(2026-09-12). Bundle them; do not split.packages/e2etreatsTestResult::Skipas success.cl8y-e2e run/fullexit1only whenTestSuite::failed() > 0. Skip is printed, never fatal..github/workflows/e2e.ymlstillchmod +x ./scripts/e2e-test.shthen runs it. That path is gone fromscripts/(Rustcl8y-e2ereplaced it; README points atscripts/legacy/). The same file’s header says “ALL tests run on EVERY push / Do NOT add flags that skip tests.”.woodpecker.yamlfrom #172 / #174). Thefrontend-hash-verifystep runs three Vitest files only (hashVerifyExecuteBlocker,HashComparisonPanel,DestHashCard).packages/frontendhasnpm run test:unit(SKIP_INTEGRATION=true vitest run) plus a large Playwright tree undere2e/..github/workflows/test.ymldoes not even listpackages/frontend/**.packages/canceler/tests/integration_test.rsstay#[ignore = "requires Anvil…/LocalTerra…"].e2e.ymlalready starts Anvil, LocalTerra, and Postgres, thencargo test --release -- --nocapturewithout--ignored.should_run_integration()is true whenCIis set, but#[ignore]still wins unless--ignoredis passed.This is not #172 (Woodpecker enablement, operator redeploy, hash-verify minimum). Do not reopen or comment that ticket for this. This is not #186 (pipe-to-shell Solana installer). This is not #98 (Bridge vs AccessManager role IDs).
Internal review id: TEST-1 (high). Still in source 2026-09-12.
Repro
Given
packages/e2eTestSuiteandCommands::Run/Fullinsrc/main.rsWhen any test returns
TestResult::skip(...)(missing env,--no-terra, unsetSOLANA_ENABLED, missing contract address)Then the process still exits 0 if
failed() == 0Given
.github/workflows/e2e.ymlstepRun Full E2E Test Suite (Bash)When that step runs on a current checkout
Then
chmod +x ./scripts/e2e-test.shfails because the file is not inscripts/Given a PR that changes frontend unit tests outside the three hash-verify files
When Woodpecker is the required check
Then
npm run test:unitof those files never runs; Playwright never runsGiven
e2e.ymlhas started Anvil + LocalTerraWhen the canceler unit-test step runs
Then
#[ignore]integration tests are not executedExpected vs actual
cl8y-e2ecargo run -p cl8y-e2escripts/e2e-test.shtest:unit+ one Playwright smoke as a required Woodpecker stepWhy this is needed
A skipped fraud / canceler / operator-reject / hash-parity case looks like a green pipeline. The workflow comments claim the opposite. Frontend regressions outside Hash Verification never gate merge. Canceler watchtower paths that need Anvil/LocalTerra are documented as “run with
--ignored” and then never invoked in the job that has that infra.No contract, operator, or frontend runtime change. CI + test harness only.
Constraints / guardrails
SOLANA_ENABLEDis unset and the README already says GitHube2e.ymldoes not enable them;--quickconnectivity-only mode when explicitly requested. Do not allowlistfraud_detection*,canceler_*,operator_rejects_unverified*,operator_no_approve_solana,xchain_hash_*, watchtower / cancel-window cases.if suite.failed() > 0 || security_skips > 0 { exit 1 }(or!suite.all_passed()for the security subset). KeepTestResult::Skipfor the allowlist.scripts/e2e-test.shas a second runner.packages/e2e/README.mdalready maps it tocargo run -p cl8y-e2e -- run.--no-terra/--no-operator/--no-cancelerto the full CI job.operator-writers. Expandfrontend-hash-verifytonpm run test:unitwith no path filter. Playwright smoke must beE2E_UI_ONLY=1(no Docker compose, no contract deploy) — e.g.e2e/wallet-connect.spec.tsore2e/validation.spec.tswith a documented project. Full transfer Playwright stays out of Woodpecker in this ticket.#[ignore]socargo teston a laptop without Anvil stays green. In jobs that already have Anvil + LocalTerra (at leaste2e.yml), runcargo test --test integration_test -- --ignored --nocapturewithINTEGRATION_TEST=1and the bridge addresses that job already exports. Skip a test with a hard failure if requiredEVM_BRIDGE_ADDRESS/TERRA_BRIDGE_ADDRESSis missing in that job (no silent ignore).Relevant files
packages/e2e/src/lib.rsTestResult::Skip;TestSuite::failed/skipped/all_passedpackages/e2e/src/main.rs1only iffailed() > 0;--no-terraskip pathpackages/e2e/src/tests/TestResult::skip.github/workflows/e2e.ymlscripts/e2e-test.sh; cancelercargo testwithout--ignored.woodpecker.yamlpackages/frontend/package.jsontest:unit,test:e2epackages/frontend/e2e/packages/frontend/playwright.config.tsE2E_UI_ONLY/CIteardownpackages/canceler/tests/integration_test.rs#[ignore]integration suitedocs/testing.md./scripts/e2e-test.shas the master suiteRecommended direction
TestResult::skipas security-critical vs allowlisted. Security skip → fail the process. Unit-test the classifier with a fixture suite (no chain).e2e.yml(or replace withcargo run -p cl8y-e2e -- runwhich the job already ran). Grep CI YAML fore2e-test.sh.frontend-hash-verify:npm cithennpm run test:unit(all unit files). New stepfrontend-playwright-smoke:npx playwright install --with-deps chromium(or the pinned browsers the config already uses) thenE2E_UI_ONLY=1 npx playwright test <smoke-spec> --workers=1. Digest-pin the Node image already used.e2e.ymlcanceler step: after contracts exist,cargo test --test integration_test --release -- --ignored --nocapture. Keep the defaultcargo test(non-ignored) for unit tests.Acceptance criteria
cl8y-e2e runexits ≠ 0 if any security-critical test isSkip, even whenfailed() == 0.--quick) still exit 0 when everything else passed..github/workflows/e2e.ymlhas noscripts/e2e-test.sh. Grep of.github/workflowsand.woodpecker.yamlfinds no live reference except maybescripts/legacy/docs.packages/frontendnpm run test:unit(not a three-file filter) on PR/push.E2E_UI_ONLY=1(no compose). Failure fails the pipeline.e2e.yml(or equivalent job that already has Anvil + LocalTerra) runs cancelerintegration_testwith--ignored. Missing required bridge env fails that step.cd packages/canceler && cargo testwithout--ignoredstill skips integration tests (laptop without infra).docs/testing.mdno longer presents./scripts/e2e-test.shas the live runner; it points atcl8y-e2eand the Woodpecker frontend steps.Test plan (functional paths)
grep -R e2e-test.sh .github .woodpecker.yamlvitest runwithout the three-file argvE2E_UI_ONLY=1docker compose upcargo test -- --ignoredwith Anvil uptest_anvil_connectivityruns (not silently ignored)cargo test(no--ignored)docs/testing.md./scripts/e2e-test.sh” as current CITest plan (attack, hack, and abuse)
Non-exploitative. CI fixtures only. These catch fail-open test gating, not a drain recipe.
fraud_detectionbecause env is emptycanceler_solana_source_fraudbecauseSOLANA_ENABLEDunset if classified security-criticalchmod +x ./scripts/e2e-test.shtest:unitE2E_UI_ONLYpulling compose on Woodpeckercargo testin canceler job without--ignoredas the only canceler commandVerification criteria
TestSuiteexit policy (T1–T3) inpackages/e2e.e2e-test.sh.npm run test:unitwith no extra test-file argv; Playwright smoke envE2E_UI_ONLY=1.running 1 testfor an Anvil connectivity case), notignored.Out of scope
:latestdigest pins (includinge2e.ymllocalterra-cl8y:latest).cl8y-e2e fullonto Woodpecker.transfer-*-to-*.spec.ts) on Woodpecker.packages/operator/tests/integration_test.rs(sibling ignore; only if the samee2e.ymlstep is a one-line add — not required to close TEST-1).First-pass model recommendation
Recommendation: grok-high
Rationale: Cross-cutting CI policy across
packages/e2e(exit policy),.github/workflows/e2e.yml(dead script + canceler--ignored),.woodpecker.yaml(frontend unit + Playwright smoke), canceler integration attributes, anddocs/testing.md. More than three production files and more than one subsystem. Woodpecker is the required merge check — a wrong skip allowlist or a Playwright step that pulls compose will either hide security tests again or break every PR. File count does not make this Composer-eligible. Verify with T1–T3 fixtures, workflow greps, and a Woodpecker PR that fails on a deliberate security skip / omitted unit file — not by asserting a green pipeline that skipped the suite.cl8y-agent-control: queued
implementjob8ee641fd-213f-42e9-89d1-eef32a0a9139(not executed; no Hetzner VM).cl8y-agent-control: needs_human inbox card POST failed. Job stays parked.