/
ensure_actions_will_cancel.py
executable file
·67 lines (54 loc) · 2.11 KB
/
ensure_actions_will_cancel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/env python3
import argparse
import sys
import yaml
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
WORKFLOWS = REPO_ROOT / ".github" / "workflows"
EXPECTED_GROUP = "${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}" \
"-${{ github.event_name == 'workflow_dispatch' }}"
def should_check(filename: Path) -> bool:
with open(filename, "r") as f:
content = f.read()
data = yaml.safe_load(content)
on = data.get("on", data.get(True, {}))
return "pull_request" in on
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Ensure all relevant GitHub actions jobs will be cancelled based on a concurrency key"
)
args = parser.parse_args()
files = list(WORKFLOWS.glob("*.yml"))
errors_found = False
files = [f for f in files if should_check(f)]
names = set()
for filename in files:
with open(filename, "r") as f:
data = yaml.safe_load(f)
name = data.get("name")
if name is not None and name in names:
print("ERROR: duplicate workflow name:", name, file=sys.stderr)
errors_found = True
names.add(name)
actual = data.get("concurrency", {})
if not actual.get("group", "").startswith(EXPECTED_GROUP):
print(
f"'concurrency' incorrect or not found in '{filename.relative_to(REPO_ROOT)}'",
file=sys.stderr,
)
print(
f"concurrency group should start with {EXPECTED_GROUP} but found {actual.get('group', None)}",
file=sys.stderr,
)
errors_found = True
if not actual.get("cancel-in-progress", False):
print(
f"'concurrency' incorrect or not found in '{filename.relative_to(REPO_ROOT)}'",
file=sys.stderr,
)
print(
f"concurrency cancel-in-progress should be True but found {actual.get('cancel-in-progress', None)}",
file=sys.stderr,
)
if errors_found:
sys.exit(1)