Files
StarPilot/tools/ci/tests/test_aggregate_cancellation.py
T
2026-10-23 14:56:13 -05:00

30 lines
1.7 KiB
Python

from pathlib import Path
import re
import unittest
class AggregateCancellationTests(unittest.TestCase):
def test_complete_catalogs_remain_mandatory_unless_workflow_cancelled(self):
workflow = Path(__file__).parents[3].joinpath('.github/workflows/tests.yaml').read_text()
for name, needs, command in (
('custom_pytest_complete', 'custom_pytest', 'custom_pytest_shards aggregate'),
('aol_lifecycle_complete', 'aol_lifecycles', 'lifecycle_shards.py ci-results/aol-lifecycles')):
with self.subTest(job=name):
job = re.search(r'^ ' + name + r':\n(.*?)(?=^ [a-z_]+:|\Z)', workflow, re.M | re.S)
self.assertIsNotNone(job)
body = job.group(1)
self.assertIn(' needs: ' + needs + '\n', body)
guard = re.search(r'^ if: (.+)$', body, re.M).group(1)
self.assertEqual(guard, '${{ always() && !cancelled() }}')
self.assertIn(command, body)
self.assertNotIn('continue-on-error', body)
# Failure, timeout or an individually missing shard must still reach the
# unmodified fail-closed aggregate whenever the workflow is not cancelled.
for upstream in ('success', 'failure', 'skipped', 'cancelled'):
for workflow_cancelled in (False, True):
with self.subTest(upstream=upstream, workflow_cancelled=workflow_cancelled):
expression = guard.removeprefix('${{ ').removesuffix(' }}')
expression = expression.replace('always()', 'True').replace('cancelled()', str(workflow_cancelled))
expression = expression.replace('&&', 'and').replace('!', 'not ')
self.assertEqual(eval(expression, {'__builtins__': {}}), not workflow_cancelled)