diff --git a/.github/workflows/test-freebsd.yml b/.github/workflows/test-freebsd.yml index 805dcf0..c6f9879 100644 --- a/.github/workflows/test-freebsd.yml +++ b/.github/workflows/test-freebsd.yml @@ -1,28 +1,17 @@ name: Shared FreeBSD workflow tests +# The suite covers every workflow and action, not only FreeBSD, so a change to any of them runs it. on: pull_request: paths: - - .github/workflows/freebsd.yml - - .github/workflows/release.yml - - .github/workflows/gate.yml - - actions/freebsd-cargo-cache/** - - actions/checkout-craft-i18n/** - - .github/workflows/windows-arm64.yml - - .github/workflows/test-freebsd.yml - - actions/install-apt-packages/** + - .github/workflows/** + - actions/** - tests/** push: branches: [main] paths: - - .github/workflows/freebsd.yml - - .github/workflows/release.yml - - .github/workflows/gate.yml - - actions/freebsd-cargo-cache/** - - actions/checkout-craft-i18n/** - - .github/workflows/windows-arm64.yml - - .github/workflows/test-freebsd.yml - - actions/install-apt-packages/** + - .github/workflows/** + - actions/** - tests/** workflow_dispatch: diff --git a/tests/test_unit_test_triggers.py b/tests/test_unit_test_triggers.py new file mode 100644 index 0000000..8480a83 --- /dev/null +++ b/tests/test_unit_test_triggers.py @@ -0,0 +1,41 @@ +"""The workflow that runs these tests must start for a change to anything they test.""" + +from pathlib import Path +import re +import unittest + +import yaml + + +ROOT = Path(__file__).resolve().parents[1] +WORKFLOW = yaml.load((ROOT / ".github/workflows/test-freebsd.yml").read_text(), Loader=yaml.BaseLoader) + + +def matches(path, pattern): + # GitHub path filters: * stops at /, ** crosses it. + regex = "".join(".*" if part == "**" else "[^/]*" if part == "*" else re.escape(part) + for part in re.split(r"(\*\*|\*)", pattern)) + return re.fullmatch(regex, path) is not None + + +class UnitTestTriggerTests(unittest.TestCase): + def test_every_workflow_action_and_test_file_triggers_the_tests(self): + files = [path.relative_to(ROOT).as_posix() + for directory in (".github/workflows", "actions", "tests") + for path in (ROOT / directory).rglob("*") + if path.is_file() and "__pycache__" not in path.parts] + self.assertIn(".github/workflows/sonarcloud.yml", files) + for event in ("pull_request", "push"): + patterns = WORKFLOW["on"][event]["paths"] + for file in files: + with self.subTest(event=event, file=file): + self.assertTrue(any(matches(file, pattern) for pattern in patterns)) + + def test_matches_follows_github_globs(self): + self.assertTrue(matches("actions/ast-grep/action.yml", "actions/**")) + self.assertFalse(matches("actions/ast-grep/action.yml", "actions/*")) + self.assertTrue(matches(".github/workflows/nix.yml", ".github/workflows/*.yml")) + + +if __name__ == "__main__": + unittest.main()