diff --git a/.github/workflows/ontology-pages.yml b/.github/workflows/ontology-pages.yml index 383600baa..a4c911dc7 100644 --- a/.github/workflows/ontology-pages.yml +++ b/.github/workflows/ontology-pages.yml @@ -38,6 +38,8 @@ permissions: contents: read concurrency: + # Pull-request lifecycle events share the PR-scoped group: Draft/closed + # transitions skip validation while cancelling any older active validation. group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} diff --git a/.github/workflows/prov-o-contract.yml b/.github/workflows/prov-o-contract.yml index 008f73405..6f24a61c7 100644 --- a/.github/workflows/prov-o-contract.yml +++ b/.github/workflows/prov-o-contract.yml @@ -29,6 +29,8 @@ permissions: contents: read concurrency: + # Draft/closed events intentionally skip the product job but retain the + # workflow event needed to cancel an older active run for this same PR. group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b82226a7e..635495d23 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,9 +10,8 @@ permissions: contents: read concurrency: - # A merged pull request can report the base ref on ``closed``. Keying PR - # events by number lets that close run cancel an older queued synchronize - # run for the same PR instead of consuming runners after the PR is closed. + # Draft/closed events deliberately create a no-job run in this workflow so + # workflow-level concurrency can cancel any older active run for the same PR. group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} diff --git a/tests/test_tests_workflow_contract.py b/tests/test_tests_workflow_contract.py index b0953f6f9..d32cc5624 100644 --- a/tests/test_tests_workflow_contract.py +++ b/tests/test_tests_workflow_contract.py @@ -17,15 +17,23 @@ "converted_to_draft, closed]" ) _DRAFT_ADMISSION = "github.event.pull_request.draft == false" +_INACTIVE_ADMISSION = ( + "github.event.action != 'closed' && github.event.pull_request.draft == false" +) -def test_pull_request_concurrency_survives_closed_ref_change() -> None: - """Key synchronize and closed events by PR number so close cancels stale work.""" - - workflow = (_WORKFLOW_DIRECTORY / "tests.yml").read_text(encoding="utf-8") +def test_lifecycle_events_cancel_inactive_pr_work() -> None: + """Keep lifecycle events so Draft/close transitions cancel active local work.""" - assert _PULL_REQUEST_TYPES in workflow - assert workflow.count("github.event.action != 'closed'") == 2 + expected_inactive_guards = { + "tests.yml": 2, + "prov-o-contract.yml": 1, + "ontology-pages.yml": 1, + } + for workflow_name, expected_guard_count in expected_inactive_guards.items(): + workflow = (_WORKFLOW_DIRECTORY / workflow_name).read_text(encoding="utf-8") + assert _PULL_REQUEST_TYPES in workflow, workflow_name + assert workflow.count(_INACTIVE_ADMISSION) == expected_guard_count, workflow_name def test_pull_request_workflows_cancel_only_superseded_same_pr_runs() -> None: