5
from pathlib import Path
10
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
11
WORKFLOWS = REPO_ROOT / ".github" / "workflows"
12
EXPECTED_GROUP_PREFIX = (
13
"${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}"
16
EXPECTED_GROUP_PREFIX + "-${{ github.event_name == 'workflow_dispatch' }}"
20
def should_check(filename: Path) -> bool:
21
with open(filename) as f:
24
data = yaml.safe_load(content)
25
on = data.get("on", data.get(True, {}))
26
return "pull_request" in on
29
if __name__ == "__main__":
31
files = [f for f in WORKFLOWS.glob("*.yml") if should_check(f)]
33
for filename in files:
34
with open(filename) as f:
35
data = yaml.safe_load(f)
37
name = data.get("name")
38
if name is not None and name in names:
39
print("ERROR: duplicate workflow name:", name, file=sys.stderr)
42
actual = data.get("concurrency", {})
43
if filename.name == "create_release.yml":
44
if not actual.get("group", "").startswith(EXPECTED_GROUP_PREFIX):
46
f"'concurrency' incorrect or not found in '{filename.relative_to(REPO_ROOT)}'",
50
f"concurrency group should start with {EXPECTED_GROUP_PREFIX} but found {actual.get('group', None)}",
54
elif not actual.get("group", "").startswith(EXPECTED_GROUP):
56
f"'concurrency' incorrect or not found in '{filename.relative_to(REPO_ROOT)}'",
60
f"concurrency group should start with {EXPECTED_GROUP} but found {actual.get('group', None)}",
64
if not actual.get("cancel-in-progress", False):
66
f"'concurrency' incorrect or not found in '{filename.relative_to(REPO_ROOT)}'",
70
f"concurrency cancel-in-progress should be True but found {actual.get('cancel-in-progress', None)}",