From 611586d148d2fd8c52614441e1af14e3c38859b7 Mon Sep 17 00:00:00 2001 From: an9xyz Date: Fri, 17 Jul 2026 15:32:52 +0800 Subject: [PATCH 1/5] test: define octo-docs-html module mapping contract --- .github/tests/test_auto_add_to_project.py | 30 +++++++++++++++++++++++ .github/workflows/workflow-sanity.yml | 17 +++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 .github/tests/test_auto_add_to_project.py diff --git a/.github/tests/test_auto_add_to_project.py b/.github/tests/test_auto_add_to_project.py new file mode 100644 index 0000000..5b855c1 --- /dev/null +++ b/.github/tests/test_auto_add_to_project.py @@ -0,0 +1,30 @@ +from pathlib import Path +import re +import unittest + + +WORKFLOW = Path(".github/workflows/auto-add-to-project.yml") + + +class RepositoryModuleMappingTest(unittest.TestCase): + def test_octo_docs_html_maps_to_server(self) -> None: + workflow = WORKFLOW.read_text(encoding="utf-8") + mapping_block = re.search( + r"const REPO_MODULE = \{(?P.*?)^\s*\};", + workflow, + flags=re.MULTILINE | re.DOTALL, + ) + + self.assertIsNotNone(mapping_block, "REPO_MODULE mapping block is missing") + mappings = dict( + re.findall( + r"^\s*'([^']+)':\s*'([^']+)',\s*$", + mapping_block.group("body"), + flags=re.MULTILINE, + ) + ) + self.assertEqual(mappings.get("octo-docs-html"), "server") + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/workflows/workflow-sanity.yml b/.github/workflows/workflow-sanity.yml index 22874cf..09b4e94 100644 --- a/.github/workflows/workflow-sanity.yml +++ b/.github/workflows/workflow-sanity.yml @@ -8,11 +8,13 @@ on: paths: - '.github/workflows/**' - '.github/actions/**' + - '.github/tests/**' push: branches: [main] paths: - '.github/workflows/**' - '.github/actions/**' + - '.github/tests/**' workflow_dispatch: permissions: {} @@ -22,6 +24,21 @@ concurrency: cancel-in-progress: true jobs: + contracts: + name: Workflow contracts + runs-on: ubuntu-24.04 + timeout-minutes: 5 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Test workflow contracts + run: python3 -m unittest discover -s .github/tests -p 'test_*.py' + no-tabs: name: No tabs in workflow files runs-on: ubuntu-24.04 From 9f9971ed894c403b9f765ffce2d7e8268e186ce0 Mon Sep 17 00:00:00 2001 From: an9xyz Date: Fri, 17 Jul 2026 15:34:49 +0800 Subject: [PATCH 2/5] ci: map octo-docs-html to server module --- .github/workflows/auto-add-to-project.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-add-to-project.yml b/.github/workflows/auto-add-to-project.yml index 639a67f..087d315 100644 --- a/.github/workflows/auto-add-to-project.yml +++ b/.github/workflows/auto-add-to-project.yml @@ -86,6 +86,7 @@ jobs: 'octo-cli': 'cli', 'octo-daemon-cli': 'cli', 'octo-deployment': 'deployment', + 'octo-docs-html': 'server', 'octo-fleet': 'server', 'octo-im': 'server', 'octo-ios': 'ios', @@ -317,4 +318,3 @@ jobs: }); core.info(`Inherited Sprint "${sprintTitle}" from linked issue onto PR item ${itemId}.`); - From ce8ff5515f31b2fffac98ce13a4dfde418f1ab99 Mon Sep 17 00:00:00 2001 From: an9xyz Date: Fri, 17 Jul 2026 15:40:27 +0800 Subject: [PATCH 3/5] test: reproduce reusable workflow contract failure --- .github/tests/test_auto_add_to_project.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/tests/test_auto_add_to_project.py b/.github/tests/test_auto_add_to_project.py index 5b855c1..a3bc9a0 100644 --- a/.github/tests/test_auto_add_to_project.py +++ b/.github/tests/test_auto_add_to_project.py @@ -4,6 +4,7 @@ WORKFLOW = Path(".github/workflows/auto-add-to-project.yml") +SANITY_WORKFLOW = Path(".github/workflows/workflow-sanity.yml") class RepositoryModuleMappingTest(unittest.TestCase): @@ -25,6 +26,20 @@ def test_octo_docs_html_maps_to_server(self) -> None: ) self.assertEqual(mappings.get("octo-docs-html"), "server") + def test_contract_job_only_runs_in_central_repository(self) -> None: + workflow = SANITY_WORKFLOW.read_text(encoding="utf-8") + contracts_job = re.search( + r"^ contracts:\n(?P.*?)(?=^ [a-z][a-z0-9-]*:\n)", + workflow, + flags=re.MULTILINE | re.DOTALL, + ) + + self.assertIsNotNone(contracts_job, "contracts job is missing") + self.assertIn( + "if: github.repository == 'Mininglamp-OSS/.github'", + contracts_job.group("body"), + ) + if __name__ == "__main__": unittest.main() From 5287a9bccb4b001cf3c5188ca1e7f57bfadf6f34 Mon Sep 17 00:00:00 2001 From: an9xyz Date: Fri, 17 Jul 2026 15:40:46 +0800 Subject: [PATCH 4/5] fix: isolate central workflow contract job --- .github/workflows/workflow-sanity.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/workflow-sanity.yml b/.github/workflows/workflow-sanity.yml index 09b4e94..9408ec4 100644 --- a/.github/workflows/workflow-sanity.yml +++ b/.github/workflows/workflow-sanity.yml @@ -26,6 +26,7 @@ concurrency: jobs: contracts: name: Workflow contracts + if: github.repository == 'Mininglamp-OSS/.github' runs-on: ubuntu-24.04 timeout-minutes: 5 permissions: From 8f56626a2b777304a9349b9bf057cb8ec0f2d4f1 Mon Sep 17 00:00:00 2001 From: an9xyz Date: Fri, 17 Jul 2026 15:49:34 +0800 Subject: [PATCH 5/5] docs(ci): explain central contract job guard --- .github/workflows/workflow-sanity.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/workflow-sanity.yml b/.github/workflows/workflow-sanity.yml index 9408ec4..e099143 100644 --- a/.github/workflows/workflow-sanity.yml +++ b/.github/workflows/workflow-sanity.yml @@ -26,6 +26,7 @@ concurrency: jobs: contracts: name: Workflow contracts + # Reusable callers check out their own repository, which has no central tests. if: github.repository == 'Mininglamp-OSS/.github' runs-on: ubuntu-24.04 timeout-minutes: 5