Skip to content
Bitcoin Roots

v31.1-roots.1 · Commit 8: [PATCH 08/17] chore(roots): integrate v31 identity and maintenance tooling

ci/test/test_workflow_selection.py

Before: /dev/null · After: ci/test/test_workflow_selection.py

File metadata
new file mode 100644
index 0000000000000000000000000000000000000000..5520cc40bde154f28d6621f5682abdcb8f5abafc

Download original patch · Release notes

Diff rows 1–70 of 70. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.

ci/test/test_workflow_selection.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2026-present The Bitcoin Roots developers
3
+ # Distributed under the MIT software license, see the accompanying file COPYING.
4
+ """Execute the actual nightly matrix selector and PR result gate locally."""
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ import re
9
+ import subprocess
10
+ import tempfile
11
+ import unittest
12
+
13
+ ROOT = Path(__file__).resolve().parents[2]
14
+
15
+
16
+ def run_block(file, name):
17
+ text = file.read_text()
18
+ start = text.index('- name: ' + name)
19
+ rest = text[start:]
20
+ match = re.search(r' run: \|\n((?: [^\n]*\n|\n)+)', rest)
21
+ if not match:
22
+ raise AssertionError(name)
23
+ return '\n'.join(line[10:] if line.startswith(' ') else line for line in match[1].splitlines())
24
+
25
+
26
+ class WorkflowSelectionTest(unittest.TestCase):
27
+ def nightly(self, suite):
28
+ block = run_block(ROOT / '.github/workflows/nightly.yml', 'Select requested Linux assurance suites')
29
+ with tempfile.TemporaryDirectory() as directory:
30
+ output = Path(directory) / 'output'
31
+ result = subprocess.run(['bash', '-c', block], env=os.environ | {'SUITE': suite, 'GITHUB_OUTPUT': str(output)}, capture_output=True, text=True, timeout=5)
32
+ matrices = dict(line.split('=', 1) for line in output.read_text().splitlines()) if output.exists() else {}
33
+ return result, {key: json.loads(value) for key, value in matrices.items()}
34
+
35
+ def test_all_preserves_extended_platform_and_sanitizer_coverage(self):
36
+ result, matrices = self.nightly('all')
37
+ self.assertEqual(result.returncode, 0, result.stderr)
38
+ self.assertEqual(len(matrices['value']['include']), 4)
39
+ self.assertEqual(len(matrices['sanitizers']['include']), 3)
40
+ for matrix in matrices.values():
41
+ for row in matrix['include']:
42
+ self.assertTrue((ROOT / row['file-env']).is_file())
43
+ self.assertGreater(row['timeout'], 60)
44
+
45
+ def test_specific_suites_do_not_create_unrelated_matrix_jobs(self):
46
+ for suite in ['tsan', 'msan', 'sanitizers', 'tidy', 'i686', 'platforms', 'previous-releases', 'extended-functional', 'fuzz', 'macos-fuzz', 'windows-fuzz', 'arm32', 'kernel', 'macos-smoke', 'windows-smoke']:
47
+ with self.subTest(suite=suite):
48
+ result, matrices = self.nightly(suite)
49
+ self.assertEqual(result.returncode, 0, result.stderr)
50
+ self.assertLessEqual(sum(len(m['include']) for m in matrices.values()), 3)
51
+ result, _ = self.nightly('unrecognized-suite')
52
+ self.assertNotEqual(result.returncode, 0)
53
+
54
+ def test_selected_failures_cannot_pass_the_pr_result_gate(self):
55
+ block = run_block(ROOT / '.github/workflows/ci.yml', 'Enforce selected required results')
56
+ env = {'CLASSIFY': 'success', 'LINT': 'success'}
57
+ for key in ['GUI', 'SANITIZERS', 'FUZZ', 'NIGHTLY_SANITIZERS', 'NIGHTLY_FUZZ', 'NIGHTLY_PLATFORMS', 'NIGHTLY_FULL']:
58
+ env[key] = 'skipped'
59
+ env[key + '_SELECTED'] = 'false'
60
+ base = subprocess.run(['bash', '-c', block], env=os.environ | env, capture_output=True, timeout=5)
61
+ self.assertEqual(base.returncode, 0, base.stderr)
62
+ for name in ['GUI', 'SANITIZERS', 'FUZZ', 'NIGHTLY_FUZZ']:
63
+ for status in ['failure', 'cancelled', 'skipped']:
64
+ with self.subTest(job=name, status=status):
65
+ failed = subprocess.run(['bash', '-c', block], env=os.environ | env | {name + '_SELECTED': 'true', name: status}, capture_output=True, timeout=5)
66
+ self.assertNotEqual(failed.returncode, 0)
67
+
68
+
69
+ if __name__ == '__main__':
70
+ unittest.main()