Skip to content

Commit d6edc8e

Browse files
committed
merge(main): adopt protected PR concurrency repair for release cut
2 parents ed965e0 + 493326f commit d6edc8e

4 files changed

Lines changed: 65 additions & 10 deletions

File tree

.github/workflows/cflite_pr.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: ClusterFuzzLite PR fuzzing
22

33
on:
44
pull_request:
5+
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft, closed]
56
paths:
67
- ".clusterfuzzlite/**"
78
- ".github/workflows/cflite_pr.yml"
@@ -14,12 +15,13 @@ permissions:
1415

1516
jobs:
1617
PR:
18+
if: ${{ !github.event.pull_request.draft && github.event.action != 'closed' }}
1719
runs-on: ubuntu-24.04
1820
permissions:
1921
contents: read
2022
security-events: write
2123
concurrency:
22-
group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }}
24+
group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number }}
2325
cancel-in-progress: true
2426
strategy:
2527
fail-fast: false

.github/workflows/ci.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches: [main, develop]
66
pull_request:
7+
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft, closed]
78

89
permissions:
910
contents: read
@@ -12,14 +13,15 @@ concurrency:
1213
# Keep one active CI run per PR while preserving independent push runs. A
1314
# synchronized head cancels its queued/running predecessor instead of
1415
# multiplying the hosted-runner backlog with stale evidence.
15-
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
16-
cancel-in-progress: true
16+
group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }}
17+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
1718

1819
jobs:
1920
# Matrix legs report as "python (3.12)" / "python (3.14)". Branch protection
2021
# still requires the exact check context name `python`, so a thin aggregate
2122
# job below re-exports matrix success under that name.
2223
python-matrix:
24+
if: ${{ github.event_name != 'pull_request' || (!github.event.pull_request.draft && github.event.action != 'closed') }}
2325
name: python (${{ matrix.python-version }})
2426
runs-on: ubuntu-latest
2527
strategy:
@@ -46,7 +48,7 @@ jobs:
4648
python:
4749
name: python
4850
needs: python-matrix
49-
if: always()
51+
if: ${{ always() && (github.event_name != 'pull_request' || (!github.event.pull_request.draft && github.event.action != 'closed')) }}
5052
runs-on: ubuntu-latest
5153
steps:
5254
- name: Require every CPython matrix leg
@@ -56,6 +58,7 @@ jobs:
5658
5759
5860
rust:
61+
if: ${{ github.event_name != 'pull_request' || (!github.event.pull_request.draft && github.event.action != 'closed') }}
5962
runs-on: ubuntu-latest
6063
steps:
6164
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
@@ -72,6 +75,7 @@ jobs:
7275
- run: cargo test --manifest-path crates/fast-mlsirm-py/Cargo.toml
7376

7477
gpu-smoke:
78+
if: ${{ github.event_name != 'pull_request' || (!github.event.pull_request.draft && github.event.action != 'closed') }}
7579
# One bounded explicit-GPU parity test remains on every PR. The full
7680
# paper-design GPU recovery study runs in the scheduled/manual workflow.
7781
runs-on: ubuntu-latest
@@ -152,6 +156,7 @@ jobs:
152156
PY
153157
154158
fuzz:
159+
if: ${{ github.event_name != 'pull_request' || (!github.event.pull_request.draft && github.event.action != 'closed') }}
155160
# Short, bounded coverage-guided fuzzing so PR cost stays low. The
156161
# property-based Hypothesis tests already run in the `python` job (via the
157162
# dev extra); this job adds the Atheris coverage-guided harnesses with a
@@ -184,6 +189,7 @@ jobs:
184189
-max_total_time=60 -timeout=25 fuzz/corpus/config
185190
186191
package:
192+
if: ${{ github.event_name != 'pull_request' || (!github.event.pull_request.draft && github.event.action != 'closed') }}
187193
runs-on: ubuntu-latest
188194
steps:
189195
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Contract test for pull-request fuzzing concurrency."""
2+
3+
from pathlib import Path
4+
5+
6+
def test_cflite_cancels_only_the_superseded_head_for_one_repository_pr() -> None:
7+
workflow = (
8+
Path(__file__).parents[1] / ".github" / "workflows" / "cflite_pr.yml"
9+
).read_text(encoding="utf-8")
10+
11+
assert (
12+
"group: ${{ github.workflow }}-${{ github.repository }}-"
13+
"${{ github.event.pull_request.number }}"
14+
) in workflow
15+
assert "cancel-in-progress: true" in workflow
16+
assert "ready_for_review" in workflow
17+
assert "converted_to_draft" in workflow
18+
assert "github.event.pull_request.draft" in workflow
19+
assert "github.event.action != 'closed'" in workflow

tests/test_ci_concurrency_contract.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
from __future__ import annotations
44

55
from pathlib import Path
6+
import re
67
from typing import Any
78

89

910
_WORKFLOW = Path(__file__).parents[1] / ".github" / "workflows" / "ci.yml"
1011
_EXPECTED_GROUP = (
11-
"ci-${{ github.workflow }}-"
12-
"${{ github.event.pull_request.number || github.ref }}"
12+
"${{ github.workflow }}-${{ github.repository }}-"
13+
"${{ github.event.pull_request.number || github.run_id }}"
1314
)
1415

1516

@@ -65,13 +66,40 @@ def test_ci_cancels_superseded_runs_for_the_same_pull_request():
6566
concurrency = _top_level_mapping("concurrency")
6667
assert concurrency == {
6768
"group": _EXPECTED_GROUP,
68-
"cancel-in-progress": True,
69+
"cancel-in-progress": "${{ github.event_name == 'pull_request' }}",
6970
}
7071

7172

72-
def test_ci_push_runs_remain_scoped_by_ref():
73-
"""Main/develop push evidence cannot cancel an unrelated branch or PR run."""
73+
def test_ci_push_runs_remain_independent():
74+
"""Main/develop push evidence cannot replace pending release evidence."""
7475
group = _top_level_mapping("concurrency")["group"]
7576
assert group == _EXPECTED_GROUP
77+
assert "github.repository" in group
7678
assert "github.event.pull_request.head.sha" not in group
77-
assert "github.run_id" not in group
79+
assert "github.run_id" in group
80+
assert _top_level_mapping("concurrency")["cancel-in-progress"] == (
81+
"${{ github.event_name == 'pull_request' }}"
82+
)
83+
84+
85+
def test_ci_skips_expensive_jobs_for_inactive_pull_requests():
86+
workflow = _WORKFLOW.read_text(encoding="utf-8")
87+
assert (
88+
"types: [opened, synchronize, reopened, ready_for_review, "
89+
"converted_to_draft, closed]"
90+
) in workflow
91+
for job_name in (
92+
"python-matrix",
93+
"python",
94+
"rust",
95+
"gpu-smoke",
96+
"fuzz",
97+
"package",
98+
):
99+
match = re.search(
100+
rf"(?ms)^ {re.escape(job_name)}:\n(.*?)(?=^ \S|\Z)", workflow
101+
)
102+
assert match is not None
103+
job = match.group(1)
104+
assert "!github.event.pull_request.draft" in job
105+
assert "github.event.action != 'closed'" in job

0 commit comments

Comments
 (0)