diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index babe8d2..70b00f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,18 @@ jobs: contents: read id-token: write steps: + # `submodules` is load-bearing for tests/test_skills_hook.py, which + # dereferences the .claude/hooks/ symlink into skills-vendor/ — an + # unpopulated submodule makes that link dangle and the test cannot pass. + # Both submodules are public HTTPS in .gitmodules, so no token is needed, + # and neither nests, so `true` is enough (`recursive` would only add a + # foreach pass). The coupling this buys: an upstream force-push that GCs a + # pinned SHA fails the job *at checkout*, which looks nothing like a test + # failure. The lint job deliberately omits this — ruff never reads + # skills-vendor/. - uses: actions/checkout@v5 + with: + submodules: true - name: Install uv uses: astral-sh/setup-uv@v5 diff --git a/tests/test_skills_hook.py b/tests/test_skills_hook.py index dc3697f..78fd0f8 100644 --- a/tests/test_skills_hook.py +++ b/tests/test_skills_hook.py @@ -26,5 +26,8 @@ def test_the_session_start_hook_is_a_symlink_into_the_submodule(): def test_the_hook_the_symlink_points_at_actually_exists(): """A populated submodule is the other half — a dangling link is a silent no-op.""" - assert HOOK.exists(), "skills-vendor/ is not checked out: run .skills/doctor.sh" + assert HOOK.exists(), ( + "skills-vendor/ is not checked out: run .skills/doctor.sh locally, " + "or add `submodules: true` to the CI job's actions/checkout (#27)" + ) assert os.access(HOOK, os.X_OK)