ci: run the unit tests when any workflow or action they cover changes

test-freebsd.yml is the only workflow that runs tests/, but its path filter
still lists the FreeBSD-era files. A change to sonarcloud.yml,
supply-chain.yml, nix.yml, ast-grep.yml, or to actions such as arch-package,
resolve-version, ast-grep or checkout-craft-fonts ran none of their tests:
#86 (sonarcloud.yml and the README) and #90 (sonarcloud.yml) merged without
test_sonarcloud.py running. Match every workflow, action and test file, and
test that the filter does, with GitHub's glob rules.
This commit is contained in:
g1obalworlds committed 2026-10-26 17:22:20 -07:00
1 parent 86bc2ce420
commit 160d46a16b
2 files changed
+46 -16

No files matched your search

+5 -16
View File
@@ -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:
+41
View File
@@ -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()