feat: re-run a failed run from its detail page #9

Merged
SebastienDenooz merged 1 commit from agent/issue-8-permit-to-re-run-the-failed-runs into main 2026-10-28 22:07:55 +00:00
Owner

Summary

Adds a Re-run button in the top-right corner of the run detail page (/runs/{id}).

  • Visible when the run is failed and is the latest run of its mailbox, no run of the mailbox is pending/running, the mailbox is neither running nor cancelling, the target is open, and the issue is blocked with a failed phase or in functional_analysis, technical_analysis, in_development, in_ci or in_review.
  • Authorization: owners only (RunPolicy::rerun → ProjectPolicy::update). Members see the page without the button, and their POST gets 403.
  • Confirmation through <x-confirm>, which gets a new non-destructive variant prop (it defaults to danger).
  • Behaviour: an internal.rerun_requested event is buffered.
    • Blocked issue → RetryCommand: exactly what the retry label does.
    • Working status → the new RerunRequested trigger keeps the status, resets the counter of the failed phase and runs that phase again with the failed run's trigger events (attempt + 1). The "Retrying phase." comment is posted and the status label restored. This is how lease_expired and stale_run runs get restarted.
    • MR mailbox → the review runs again.
  • Stale requests are checked again under the mailbox lock: nothing happens and an error explains why. On success the user lands on the new run, or sees a "Re-run requested" message when admission defers it.
  • MailboxWaker now dispatches ProcessMailbox after commit.
  • The spec is updated in §9.5, §11.5, §11.7, §13.5, §27.2 and §27.6.

Tests

  • Unit: TriggerResolverTest and IssueLifecycleTest cover the new trigger, its precedence and its invalid states.
  • Feature: tests/Feature/Lifecycle/RerunTest.php covers a lease-expired re-run, the counter reset, equivalence with the retry label, an MR review, and a comment for each re-run. tests/Feature/Admin/Runs/RunRerunTest.php covers visibility for each state and eligibility case, 403/404/login, success, stale requests and the double click.
  • E2E (Playwright): tests/Browser/Runs/RunRerunTest.php covers cancel, then confirm, then landing on the new run.
  • Fixed a time-dependent dataset in RunDispatcherTest that failed in long full runs.
  • The existing GitLab CI, GitHub Actions and Forgejo pipelines already run php artisan test with Playwright chromium, so they pick up the new tests unchanged.

The full suite passes (2,139 tests), and pint and phpstan pass.

Closes #8

## Summary Adds a **Re-run** button in the top-right corner of the run detail page (`/runs/{id}`). - **Visible when** the run is `failed` and is the latest run of its mailbox, no run of the mailbox is `pending`/`running`, the mailbox is neither `running` nor `cancelling`, the target is open, and the issue is `blocked` with a failed phase or in `functional_analysis`, `technical_analysis`, `in_development`, `in_ci` or `in_review`. - **Authorization:** owners only (`RunPolicy::rerun` → `ProjectPolicy::update`). Members see the page without the button, and their POST gets 403. - **Confirmation** through `<x-confirm>`, which gets a new non-destructive `variant` prop (it defaults to `danger`). - **Behaviour:** an `internal.rerun_requested` event is buffered. - Blocked issue → `RetryCommand`: exactly what the `retry` label does. - Working status → the new `RerunRequested` trigger keeps the status, resets the counter of the failed phase and runs that phase again with the failed run's trigger events (`attempt + 1`). The "Retrying `phase`." comment is posted and the status label restored. This is how `lease_expired` and `stale_run` runs get restarted. - MR mailbox → the review runs again. - **Stale requests** are checked again under the mailbox lock: nothing happens and an error explains why. On success the user lands on the new run, or sees a "Re-run requested" message when admission defers it. - `MailboxWaker` now dispatches `ProcessMailbox` after commit. - The spec is updated in §9.5, §11.5, §11.7, §13.5, §27.2 and §27.6. ## Tests - Unit: `TriggerResolverTest` and `IssueLifecycleTest` cover the new trigger, its precedence and its invalid states. - Feature: `tests/Feature/Lifecycle/RerunTest.php` covers a lease-expired re-run, the counter reset, equivalence with the `retry` label, an MR review, and a comment for each re-run. `tests/Feature/Admin/Runs/RunRerunTest.php` covers visibility for each state and eligibility case, 403/404/login, success, stale requests and the double click. - E2E (Playwright): `tests/Browser/Runs/RunRerunTest.php` covers cancel, then confirm, then landing on the new run. - Fixed a time-dependent dataset in `RunDispatcherTest` that failed in long full runs. - The existing GitLab CI, GitHub Actions and Forgejo pipelines already run `php artisan test` with Playwright chromium, so they pick up the new tests unchanged. The full suite passes (2,139 tests), and pint and phpstan pass. <!-- agent:key=8e5514ef2a31:kind=merge_request --> Closes #8
feat: re-run a failed run from its detail page
All checks were successful
CI / checks (pull_request) Successful in 3m1s
CI / checks (push) Successful in 2m51s
52b52666c9
Add a "Re-run" button in the top-right corner of /runs/{id}. It appears for
the latest run of a mailbox when that run failed and nothing else is pending
or running there. Only those who manage the project see it, and the click
must be confirmed.

The button buffers a new internal.rerun_requested event through the
MailboxWaker. On a blocked issue, the dispatcher resolves it to the existing
RetryCommand, so the re-run does exactly what the `retry` label does. On
functional_analysis, technical_analysis, in_development, in_ci or in_review,
a new RerunRequested trigger keeps the status, resets the counter of the
failed phase and runs that phase again with the failed run's trigger events.
RetryCommandHandler then posts "Retrying `phase`." and restores the status
label. This covers runs that failed as lease_expired or stale_run, which
nothing restarted until now. On an MR mailbox the review runs again.

RerunFailedRun is the single source of eligibility. The controller checks it
again under the mailbox lock. A stale request changes nothing and flashes the
reason. On success the user lands on the newly planned run.

MailboxWaker now queues ProcessMailbox after commit, so that a worker never
reads the mailbox before its new version is saved.

Also make the "window still open" dataset of RunDispatcherTest lazy: it
evaluated now() when the file loaded and failed in long runs of the suite.

Refs: #8
Alfred self-assigned this 2026-10-28 13:51:42 +00:00
SebastienDenooz changed title from WIP: feat: re-run a failed run from its detail page to feat: re-run a failed run from its detail page 2026-10-28 22:07:45 +00:00
SebastienDenooz deleted branch agent/issue-8-permit-to-re-run-the-failed-runs 2026-10-28 22:07:55 +00:00
Alfred removed their assignment 2026-10-28 22:08:15 +00:00
Sign in to join this conversation.
No description provided.