Skip to content

feat(action): single-test mode, partial-run fixes, and an end-to-end self-test - #1

Merged
fyZhang66 merged 12 commits into
devfrom
ci/selftest
Aug 18, 2026
Merged

feat(action): single-test mode, partial-run fixes, and an end-to-end self-test#1
fyZhang66 merged 12 commits into
devfrom
ci/selftest

Conversation

@fyZhang66

Copy link
Copy Markdown
Collaborator

Lands the composite action's hardening + a real-runner self-test that exercises it end-to-end against the dev backend.

action.yml

  • test-id input — run a single test by id instead of the whole project. Mutually exclusive with filter; produces no JUnit (the CLI's JUnit is batch-only) and never uploads/advertises a stale report at the default path. The job still goes red/green on the verdict + emits a summary.
  • allow-partial actually greens a skipped run — a frontend-only V2 project dispatches nothing and the CLI exits 7 (incomplete); the action used to propagate that via exit "$code" and red the job despite allow-partial: true. Now, under allow-partial (full-project runs) a skipped/deferred-only batch is GREEN, reddening only on a real test failure.
  • mkdir -p the report's parent dir so a nested report-file (e.g. results/junit.xml) doesn't fail.
  • Partial-run guard scoped to full-project runs; junit-file output empty in single-test mode.

selftest.yml (new)

Runs the action on a real GitHub runner against the dev backend — no credits (the V2 test project is frontend-only, so the V2 path skips execution):

  • v2-guard-blocks-partial — asserts the partial-run guard FAILS the job (FE skipped, allow-partial:false).
  • v2-allow-partial — same skip, job stays GREEN.
  • real-user-remote-ref — references the action remotely (@main, consumer shape); gated to main-only since a remote uses: resolves from the default branch.
  • v3-real-execution / v3-single-test (workflow_dispatch, manual — control credits) — real browser run producing a JUnit with cases; single-test-by-id mode + a stale-report-not-uploaded guard.

Validation

Self-test green on this branch: v2-guard-blocks-partial + v2-allow-partial both pass; the v3/remote jobs are correctly skipped off-main / off-dispatch.

Beta scope — not published to the Marketplace.

Single-test runs don't produce a JUnit report, but the upload step and junit-file output still keyed on the report path — so a stale testsprite-junit.xml (e.g. from a prior --all run in the same job) could be uploaded as this run's result and misattribute old data. Gate the upload on an empty test-id and emit an empty junit-file output in single-test mode. selftest v3-single-test now plants a stale report and asserts it is neither advertised nor uploaded.
…real-user-ref on main only

The self-test caught a real defect: with allow-partial=true, a frontend-only V2
project dispatches nothing and the CLI exits 7 (incomplete), which the action's
final `exit "$code"` propagated — reddening the job despite allow-partial. Under
allow-partial (full-project runs) accept a skipped/deferred-only batch as GREEN,
reddening only on a real test failure (failed>0).

Also point the real-user-remote-ref self-test job at @main and gate it to
main-only: a remote `uses:` resolves from the default branch, so pinning a stale
feature-branch SHA tested old code and always failed. It now validates the real
consumer shape against main after the change lands.
@fyZhang66
fyZhang66 requested a review from jangjos-128 August 18, 2026 22:58
…crets

Move the hardcoded dev endpoint (api.testsprite.com:11443) and the dev
project/test ids out of the workflow file and into repo secrets
(TESTSPRITE_ENDPOINT_URL / TESTSPRITE_V2_PROJECT / TESTSPRITE_V3_PROJECT /
TESTSPRITE_V3_TEST_ID). Secrets are masked in Actions logs and absent from the
YAML, so nothing dev-specific leaks if this repo is ever made public. The API
keys were already secrets.
… assertions

Adversarial-review follow-ups:

- allow-partial now reds only on a REAL test failure. `failed` was read from the
  CLI summary's `.failed` = total-passed-timedOut, which folds deferred / conflict
  / not-found (partials) into the count — so allow-partial would red a batch that
  merely couldn't dispatch everything. Now `failed` = runs[].status in
  {failed,blocked}, and allow-partial reds only on those.
- allow-partial that executed NOTHING (all skipped/deferred) now emits a loud
  ::warning instead of a silent green.
- Single-test verdict derives red/green from the run status (authoritative),
  not the CLI exit code alone, so a blocked/timeout single test can't leave the
  job green while the `failed` output is 1.
- New `skipped` action output.
- Self-test: v2-guard asserts skipped>0 (proves the guard fired, not that the
  action broke for an unrelated reason); v2-allow-partial asserts skipped>0 as a
  V2-skip-premise + account-drift/credit tripwire (skipped=0 => account may be V3,
  executing + burning credits). Real-backend jobs restricted to main + ci/**.
- Dropped an internal ticket ref from a comment.
@fyZhang66

Copy link
Copy Markdown
Collaborator Author

Adversarial-review hardening (60de336)

Ran a challenge-review of this PR and fixed the substantive findings; self-test green on a real runner after each.

Fixed

  • allow-partial now reds only on a REAL failure. failed was read from the CLI summary's .failed (= total − passed − timedOut), which folds deferred / conflict / not-found — partials, not failures — into the count, so allow-partial would red a batch that merely couldn't dispatch everything (the exact conflation the V3-deferral incident hit). Now failed = runs[].status ∈ {failed, blocked}, and allow-partial reds only on those.
  • Zero-execution is no longer a silent green. An allow-partial run that executed nothing (all skipped/deferred) now emits a loud ::warning ("nothing was verified") instead of passing quietly.
  • Single-test verdict is consistent. Red/green now derives from the run status (authoritative, matches the failed output), not the CLI exit code alone — a blocked/timeout single test can't leave the job green while failed=1.
  • New skipped output, and the self-test asserts on it:
    • v2-guard-blocks-partial now asserts skipped>0 — proving the partial-run guard fired, not that the action broke for an unrelated reason (CLI crash / bad key / dev down), which bare outcome==failure can't distinguish.
    • v2-allow-partial asserts skipped>0 as a V2-skip-premise + account-drift/credit tripwire: skipped=0 means the test account may have been flipped to V3 (tests execute + burn credits) — it fails loudly instead of silently spending. (This is exactly what bit the earlier run — the account was V3 for a few days.)
  • Real-backend jobs restricted to main + ci/** (a feature-branch commit no longer fires dev-backend runs).
  • Dropped an internal ticket ref from a comment (this repo is Marketplace-bound).

Acknowledged, deliberately not changed

  • v3-real-execution / v3-single-test stay workflow_dispatch-only (real V3 runs cost credits every push) — validated manually post-merge, tracked on the parent issue. So the single-test + V3 execution paths merge without push-CI evidence.
  • cli-version: latest default is kept for beta dogfooding; pinning is a separate product decision.
  • Dev host + project/test ids are parameterized to repo secrets; the standing plan is to remove selftest.yml entirely before the repo goes public.

@fyZhang66
fyZhang66 changed the base branch from main to dev August 18, 2026 23:38
@fyZhang66
fyZhang66 merged commit 23d3f36 into dev Aug 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant