Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/scripts/test_desktop_swift_ci_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,39 @@ def test_adversarial_remove_package_resolved_gate_detected(self):
"gate condition must be absent after removal",
)

# --- concurrency scoping (#10177) --------------------------------------

def test_main_push_concurrency_group_is_scoped_per_sha(self):
"""A push to main (no PR number) must group by commit SHA, not the ref.

A shared per-ref group with cancel-in-progress meant every main push
cancelled the previous commit's in-progress run, so the release source
gate never saw a green run for the newest desktop SHA (#10177). The
non-PR fallback must therefore be github.sha.
"""
group = re.search(r"^concurrency:\n group:\s*([^\n]+)", _workflow_text(), re.MULTILINE)
self.assertIsNotNone(group, "workflow must declare a concurrency group")
group_expr = group.group(1)
self.assertIn("github.event.pull_request.number", group_expr, "PRs still group by PR number")
self.assertIn("github.sha", group_expr, "non-PR (main push) runs must group per commit SHA")
self.assertNotRegex(
group_expr,
r"pull_request\.number\s*\}\}\s*\|\|\s*github\.ref\b|pull_request\.number\s*\|\|\s*github\.ref\b",
"main pushes must not share a per-ref cancel-in-progress group (#10177)",
)

def test_adversarial_shared_per_ref_concurrency_detected(self):
"""Reverting the fallback to github.ref re-introduces the shared
per-ref group that deadlocked the release source gate — the guard
above must reject it."""
tampered = _workflow_text().replace(
"github.event.pull_request.number || github.sha",
"github.event.pull_request.number || github.ref",
)
group_expr = re.search(r"^concurrency:\n group:\s*([^\n]+)", tampered, re.MULTILINE).group(1)
self.assertRegex(group_expr, r"pull_request\.number\s*\|\|\s*github\.ref\b")
self.assertNotIn("github.sha", group_expr)


if __name__ == "__main__":
unittest.main()
8 changes: 7 additions & 1 deletion .github/workflows/desktop-swift-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ on:
pull_request:
branches: main

# On a PR, group by PR number so a newer push supersedes the older run. On a
# push to main there is no PR number, so group by the commit SHA — NOT the ref:
# a shared per-ref group meant every main push cancelled the previous commit's
# in-progress run, so on a busy night the newest desktop commit never produced a
# green source-proof and desktop_auto_release deadlocked on its source gate
# (#10177). Per-SHA groups let each main commit's run complete.
concurrency:
group: desktop-swift-${{ github.event.pull_request.number || github.ref }}
group: desktop-swift-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
Expand Down
Loading