diff --git a/.github/workflows/ci-e2e.yml b/.github/workflows/ci-e2e.yml index 94d33e1e5..822c106ad 100644 --- a/.github/workflows/ci-e2e.yml +++ b/.github/workflows/ci-e2e.yml @@ -39,12 +39,17 @@ on: # comments get a group of their own (keyed by comment id) so they cancel nothing. The # `/retest` predicate is kept identical to the one in `resolve.if`, so exactly the # comments that can start a run are the comments that can cancel one. +# +# workflow_dispatch has no pull_request.number / issue.number, so the group used +# to fall through to github.ref (refs/heads/main for every dispatch) and +# cancel-in-progress killed the previous GPU smoke. Key on inputs.head_sha +# (then head_ref) so two fork-PR dispatches can run without cancelling each other. concurrency: group: >- ci-e2e-${{ (github.event_name == 'issue_comment' && !contains(github.event.comment.body, '/retest')) && format('noop-comment-{0}', github.event.comment.id) - || (github.event.pull_request.number || github.event.issue.number || github.ref) + || (github.event.pull_request.number || github.event.issue.number || inputs.head_sha || inputs.head_ref || github.ref) }} cancel-in-progress: true diff --git a/.github/workflows/forge-e2e.yml b/.github/workflows/forge-e2e.yml index d81cdac1b..0f3614003 100644 --- a/.github/workflows/forge-e2e.yml +++ b/.github/workflows/forge-e2e.yml @@ -190,7 +190,7 @@ jobs: # Concurrency starts only after resolve has authenticated and parsed the # event. A no-op comment therefore cannot cancel an in-flight GPU job. concurrency: - group: forge-e2e-${{ needs.resolve.outputs.pr_number || needs.resolve.outputs.head_ref || github.ref }} + group: forge-e2e-${{ needs.resolve.outputs.pr_number || needs.resolve.outputs.head_sha || needs.resolve.outputs.head_ref || github.ref }} cancel-in-progress: true runs-on: ubuntu-latest steps: @@ -240,7 +240,7 @@ jobs: needs: resolve if: needs.resolve.outputs.run == 'true' concurrency: - group: forge-e2e-${{ needs.resolve.outputs.pr_number || needs.resolve.outputs.head_ref || github.ref }} + group: forge-e2e-${{ needs.resolve.outputs.pr_number || needs.resolve.outputs.head_sha || needs.resolve.outputs.head_ref || github.ref }} cancel-in-progress: true runs-on: ${{ vars.FORGE_E2E_RUNNER_LABEL || 'Hyperloom-e2e-ci' }} timeout-minutes: ${{ fromJSON(vars.FORGE_E2E_JOB_TIMEOUT_MIN || '240') }} diff --git a/scripts/tests/test_forge_e2e_gate.py b/scripts/tests/test_forge_e2e_gate.py index cdf999af9..59f75578f 100644 --- a/scripts/tests/test_forge_e2e_gate.py +++ b/scripts/tests/test_forge_e2e_gate.py @@ -107,7 +107,7 @@ def test_only_resolved_events_can_cancel_an_in_flight_forge_run() -> None: assert "github.event.comment.author_association == 'MEMBER'" in jobs assert "github.event.comment.author_association == 'COLLABORATOR'" in jobs - group = "forge-e2e-${{ needs.resolve.outputs.pr_number || needs.resolve.outputs.head_ref || github.ref }}" + group = "forge-e2e-${{ needs.resolve.outputs.pr_number || needs.resolve.outputs.head_sha || needs.resolve.outputs.head_ref || github.ref }}" assert workflow.count(group) == 2 assert workflow.count("cancel-in-progress: true") == 2 diff --git a/src/hyperloom/inference_optimizer/tests/test_ci_e2e_concurrency_guard.py b/src/hyperloom/inference_optimizer/tests/test_ci_e2e_concurrency_guard.py index f48251b3f..28becc635 100644 --- a/src/hyperloom/inference_optimizer/tests/test_ci_e2e_concurrency_guard.py +++ b/src/hyperloom/inference_optimizer/tests/test_ci_e2e_concurrency_guard.py @@ -91,6 +91,11 @@ def test_every_trigger_still_resolves_to_a_group(concurrency_group: str) -> None for key in ( "github.event.pull_request.number", # pull_request "github.event.issue.number", # issue_comment (/retest) - "github.ref", # workflow_dispatch + "inputs.head_sha", # workflow_dispatch (fork PR smoke) + "inputs.head_ref", + "github.ref", # last-resort fallback ): assert key in concurrency_group + # Dispatch used to share refs/heads/main and cancel-in-progress the + # previous GPU run. head_sha must win over github.ref. + assert concurrency_group.index("inputs.head_sha") < concurrency_group.index("github.ref")