1
+ #! /bin/bash
2
+
3
+ # Test script to validate the race condition fix for Release Stage 1
4
+ # This script validates that the workflow uses max-parallel: 1 to prevent race conditions
5
+
6
+ set -e
7
+
8
+ echo " 🧪 Testing Race Condition Fix for Release Stage 1..."
9
+ echo
10
+
11
+ # Test 1: Validate YAML syntax
12
+ echo " Test 1: Validating YAML syntax..."
13
+ if python3 -c " import yaml; yaml.safe_load(open('.github/workflows/release-stage-1_update_dependencies.yml'))" 2> /dev/null; then
14
+ echo " ✅ YAML syntax is valid"
15
+ else
16
+ echo " ❌ YAML syntax error"
17
+ exit 1
18
+ fi
19
+
20
+ # Test 2: Check that matrix strategy still exists but with max-parallel constraint
21
+ echo
22
+ echo " Test 2: Checking matrix strategy with max-parallel constraint..."
23
+ WORKFLOW_FILE=" .github/workflows/release-stage-1_update_dependencies.yml"
24
+
25
+ # Check that matrix strategy is present
26
+ if grep -q " strategy:" " $WORKFLOW_FILE " ; then
27
+ echo " ✅ Matrix strategy found"
28
+ else
29
+ echo " ❌ Matrix strategy missing"
30
+ exit 1
31
+ fi
32
+
33
+ # Check that matrix configuration is present
34
+ if grep -q " matrix:" " $WORKFLOW_FILE " ; then
35
+ echo " ✅ Matrix configuration found"
36
+ else
37
+ echo " ❌ Matrix configuration missing"
38
+ exit 1
39
+ fi
40
+
41
+ # Test 3: Check that max-parallel: 1 constraint is present
42
+ echo
43
+ echo " Test 3: Checking max-parallel constraint..."
44
+
45
+ if grep -q " max-parallel: 1" " $WORKFLOW_FILE " ; then
46
+ echo " ✅ max-parallel: 1 constraint found"
47
+ else
48
+ echo " ❌ max-parallel: 1 constraint missing"
49
+ exit 1
50
+ fi
51
+
52
+ # Test 4: Check that single update_dependencies job exists (not separate jobs)
53
+ echo
54
+ echo " Test 4: Checking single matrix job structure..."
55
+
56
+ if grep -q " update_dependencies:" " $WORKFLOW_FILE " ; then
57
+ echo " ✅ Single update_dependencies job found"
58
+ else
59
+ echo " ❌ update_dependencies job missing"
60
+ exit 1
61
+ fi
62
+
63
+ # Ensure separate alpha/beta/stable jobs don't exist (those were from the old approach)
64
+ if grep -q " update_alpha_dependencies:" " $WORKFLOW_FILE " ; then
65
+ echo " ❌ Separate alpha job found (should use matrix instead)"
66
+ exit 1
67
+ else
68
+ echo " ✅ No separate alpha job (using matrix approach correctly)"
69
+ fi
70
+
71
+ # Ensure separate beta/stable jobs don't exist (those were from the old approach)
72
+ if grep -q " update_beta_dependencies:" " $WORKFLOW_FILE " ; then
73
+ echo " ❌ Separate beta job found (should use matrix instead)"
74
+ exit 1
75
+ else
76
+ echo " ✅ No separate beta job (using matrix approach correctly)"
77
+ fi
78
+
79
+ if grep -q " update_stable_dependencies:" " $WORKFLOW_FILE " ; then
80
+ echo " ❌ Separate stable job found (should use matrix instead)"
81
+ exit 1
82
+ else
83
+ echo " ✅ No separate stable job (using matrix approach correctly)"
84
+ fi
85
+
86
+ # Test 5: Check that the job still uses matrix variables properly
87
+ echo
88
+ echo " Test 5: Checking matrix variable usage..."
89
+
90
+ if grep -q " \$ {{ matrix.release_type }}" " $WORKFLOW_FILE " ; then
91
+ echo " ✅ Matrix release_type variable found"
92
+ else
93
+ echo " ❌ Matrix release_type variable missing"
94
+ exit 1
95
+ fi
96
+
97
+ if grep -q " \$ {{ matrix.config_file }}" " $WORKFLOW_FILE " ; then
98
+ echo " ✅ Matrix config_file variable found"
99
+ else
100
+ echo " ❌ Matrix config_file variable missing"
101
+ exit 1
102
+ fi
103
+
104
+ # Test 6: Check that the job name uses matrix variable
105
+ echo
106
+ echo " Test 6: Checking matrix job name..."
107
+
108
+ if grep -q " Update \$ {{ matrix.release_type }} Dependencies" " $WORKFLOW_FILE " ; then
109
+ echo " ✅ Job name uses matrix variable correctly"
110
+ else
111
+ echo " ❌ Job name does not use matrix variable"
112
+ exit 1
113
+ fi
114
+
115
+ # Test 7: Verify that race condition is prevented
116
+ echo
117
+ echo " Test 7: Verifying race condition prevention..."
118
+
119
+ # Check that max-parallel and matrix are in the same strategy block
120
+ STRATEGY_SECTION=$( python3 -c "
121
+ import yaml
122
+ with open('$WORKFLOW_FILE ') as f:
123
+ w = yaml.safe_load(f)
124
+ strategy = w['jobs']['update_dependencies']['strategy']
125
+ print('max-parallel' in strategy and 'matrix' in strategy)
126
+ " 2> /dev/null)
127
+
128
+ if [[ " $STRATEGY_SECTION " == " True" ]]; then
129
+ echo " ✅ max-parallel and matrix are properly configured in strategy"
130
+ else
131
+ echo " ❌ max-parallel and matrix not properly configured"
132
+ exit 1
133
+ fi
134
+
135
+ echo
136
+ echo " 🎉 All tests passed! The race condition fix is properly implemented."
137
+ echo
138
+ echo " Summary of changes:"
139
+ echo " - ✅ Kept the clean matrix strategy structure"
140
+ echo " - ✅ Added max-parallel: 1 constraint to prevent race conditions"
141
+ echo " - ✅ Maintained all existing matrix variable usage"
142
+ echo " - ✅ Preserved conditional execution logic"
143
+ echo " - ✅ Much simpler solution than sequential jobs"
144
+ echo
145
+ echo " This should resolve the race condition that caused:"
146
+ echo " - 'Base branch was modified. Review and try the merge again' errors"
147
+ echo " - Failed PR merges when multiple bots run simultaneously"
148
+ echo " - Release Stage 1 workflow failures"
149
+ echo
150
+ echo " The max-parallel: 1 constraint ensures that even though the matrix"
151
+ echo " defines multiple jobs (alpha, beta, stable), only one will run at a time,"
152
+ echo " preventing the race condition while maintaining the clean matrix structure."
0 commit comments