Merge pull request #26 from jlevy/claude/trusting-maxwell-iz7cjc #11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # CI for the template repo itself: renders the template and exercises the renders, | |
| # checks the update path from the previous release, and validates the agent skill. | |
| # (Released template versions are additionally gated on the downstream | |
| # jlevy/simple-modern-uv-template repo's CI; see updating.md.) | |
| name: CI | |
| on: | |
| push: | |
| branches: ["main"] | |
| pull_request: | |
| branches: ["main"] | |
| permissions: | |
| contents: read | |
| env: | |
| # Pinned tool versions used to exercise the template. Keep the uv version in | |
| # sync with template/.github/workflows/ci.yml when updating. | |
| UV_VERSION: "0.11.17" | |
| COPIER_SPEC: "copier@9.15.1" | |
| # Default answers for test renders. | |
| RENDER_ARGS: >- | |
| --data package_name=smoke-test | |
| --data "package_description=Render smoke test" | |
| --data "package_author_name=Test Author" | |
| --data package_author_email=test@example.com | |
| --data package_github_org=testorg | |
| jobs: | |
| format-check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "0.11.17" | |
| - name: Check doc formatting | |
| run: make format-check | |
| render-test: | |
| strategy: | |
| matrix: | |
| include: | |
| - variant: default | |
| extra_args: "" | |
| - variant: no-publish-proprietary | |
| extra_args: "--data package_license=Proprietary --data publish_to_pypi=false" | |
| - variant: no-license | |
| extra_args: "--data package_license=None" | |
| runs-on: ubuntu-latest | |
| env: | |
| # Supply-chain cool-off for template dependency resolution, matching the | |
| # template's own CI (see updating.md). Scoped to the render/update jobs: | |
| # the format-check job runs only the Makefile's explicitly pinned formatter, | |
| # which may legitimately be newer than the cool-off window. | |
| UV_EXCLUDE_NEWER: "14 days" | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "0.11.17" | |
| enable-cache: true | |
| python-version: "3.12" | |
| - name: Render template (${{ matrix.variant }}) | |
| run: | | |
| eval uvx "$COPIER_SPEC" copy --defaults --vcs-ref=$GITHUB_SHA \ | |
| $RENDER_ARGS ${{ matrix.extra_args }} "$GITHUB_WORKSPACE" /tmp/render | |
| - name: Inspect variant-specific output | |
| run: | | |
| cd /tmp/render | |
| case "${{ matrix.variant }}" in | |
| default) | |
| test -f .github/workflows/publish.yml | |
| test -f docs/publishing.md | |
| grep -q 'license = "MIT"' pyproject.toml | |
| head -1 LICENSE | grep -q "MIT License" | |
| # Only the commented-out form may appear in the default render: | |
| ! grep -qE '^\s*"Private :: Do Not Upload",' pyproject.toml | |
| ;; | |
| no-publish-proprietary) | |
| test ! -e .github/workflows/publish.yml | |
| test ! -e docs/publishing.md | |
| grep -q 'license = "LicenseRef-Proprietary"' pyproject.toml | |
| grep -qE '^\s*"Private :: Do Not Upload",' pyproject.toml | |
| ;; | |
| no-license) | |
| test ! -e LICENSE | |
| ! grep -qE '^license = ' pyproject.toml | |
| grep -q "No license chosen yet" pyproject.toml | |
| test -f .github/workflows/publish.yml | |
| ;; | |
| esac | |
| test -f AGENTS.md | |
| test -f CLAUDE.md | |
| grep -q '@AGENTS.md' CLAUDE.md | |
| test -f .copier-answers.yml | |
| - name: Init git and install (the documented setup sequence) | |
| # Mirrors the next-steps the template prints: commit first, then sync, so | |
| # dynamic versioning gives the editable install a real version. | |
| run: | | |
| cd /tmp/render | |
| git init -q --initial-branch=main | |
| git add -A | |
| git -c user.email=ci@example.com -c user.name=CI commit -qm "Initial commit" | |
| uv sync --all-extras | |
| V=$(uv run python -c "from importlib.metadata import version; print(version('smoke-test'))") | |
| echo "installed version: $V" | |
| test "$V" != "0.0.0" | |
| - name: Lint, test, build | |
| run: | | |
| cd /tmp/render | |
| uv run python devtools/lint.py --check | |
| uv run pytest | |
| git tag v0.1.0 | |
| uv build | |
| ls dist/ | grep -q "smoke_test-0.1.0-py3-none-any.whl" | |
| update-path: | |
| # D2 "answer-schema evolution" rule 4: a project rendered from the previous | |
| # release must update cleanly to this commit. With --defaults the result must | |
| # converge to a fresh render (no conflicts, no surprise file changes), and | |
| # explicit --data overrides for newer questions must be honored. | |
| runs-on: ubuntu-latest | |
| env: | |
| UV_EXCLUDE_NEWER: "14 days" | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "0.11.17" | |
| - name: Render from previous release tag | |
| run: | | |
| PREV_TAG=$(git describe --tags --abbrev=0 "$GITHUB_SHA") | |
| echo "Updating from $PREV_TAG to $GITHUB_SHA" | |
| eval uvx "$COPIER_SPEC" copy --defaults --vcs-ref="$PREV_TAG" \ | |
| $RENDER_ARGS "$GITHUB_WORKSPACE" /tmp/old | |
| cd /tmp/old | |
| git init -q --initial-branch=main | |
| git add -A | |
| git -c user.email=ci@example.com -c user.name=CI commit -qm "From $PREV_TAG" | |
| - name: Update to candidate commit with defaults | |
| run: | | |
| cd /tmp/old | |
| eval uvx "$COPIER_SPEC" update --defaults --skip-answered \ | |
| --vcs-ref=$GITHUB_SHA | |
| # No conflicts: | |
| REJ=$(find . -name '*.rej' | wc -l); test "$REJ" -eq 0 | |
| # Converges to a fresh render of the candidate (the answers file differs | |
| # only by _commit/_src_path bookkeeping, so exclude it): | |
| eval uvx "$COPIER_SPEC" copy --defaults --vcs-ref=$GITHUB_SHA \ | |
| $RENDER_ARGS "$GITHUB_WORKSPACE" /tmp/fresh | |
| diff -r --exclude=.git --exclude=.copier-answers.yml /tmp/old /tmp/fresh | |
| - name: Update honors --data overrides for newer questions | |
| run: | | |
| eval uvx "$COPIER_SPEC" copy --defaults \ | |
| --vcs-ref="$(git describe --tags --abbrev=0 "$GITHUB_SHA")" \ | |
| $RENDER_ARGS "$GITHUB_WORKSPACE" /tmp/old2 | |
| cd /tmp/old2 | |
| git init -q --initial-branch=main | |
| git add -A | |
| git -c user.email=ci@example.com -c user.name=CI commit -qm "old" | |
| eval uvx "$COPIER_SPEC" update --defaults --skip-answered \ | |
| --vcs-ref=$GITHUB_SHA --data publish_to_pypi=false | |
| test ! -e .github/workflows/publish.yml | |
| grep -qE '^\s*"Private :: Do Not Upload",' pyproject.toml | |
| skill-validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - name: Validate skill structure and frontmatter | |
| run: npx --yes skills-ref@0.1.5 validate skills/simple-modern-uv | |
| - name: Check that relative links in skill docs resolve | |
| run: | | |
| cd skills/simple-modern-uv | |
| FAIL=0 | |
| for f in SKILL.md references/*.md; do | |
| dir=$(dirname "$f") | |
| for link in $(grep -oE '\]\(([^)#]+)\)' "$f" | sed 's/](\(.*\))/\1/'); do | |
| case "$link" in | |
| http*|mailto:*) continue ;; | |
| esac | |
| if [ ! -e "$dir/$link" ]; then | |
| echo "BROKEN: $f -> $link"; FAIL=1 | |
| fi | |
| done | |
| done | |
| exit $FAIL |