chore(main): release 1.0.1 (#15) #41
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
| name: ci | |
| on: | |
| pull_request: | |
| # `edited` included: the PR TITLE is the squash subject the pr-title job | |
| # gates, so a title edit must re-evaluate CI (AND-1960) — the default | |
| # types (opened/synchronize/reopened) never see it. | |
| types: [opened, synchronize, reopened, edited] | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| # PR-event runs get a PER-RUN group on purpose (no dedup, nothing to cancel): | |
| # a run that ends "cancelled" on the head SHA can strand the required `ci` | |
| # context (AND-1960), and both cancel-in-progress settings can produce one — | |
| # true cancels in-flight runs, false still cancels queued ones. Push runs | |
| # keep the shared group + cancellation; nothing gates on them. | |
| group: ci-${{ github.ref }}-${{ github.event_name == 'push' && 'push' || github.run_id }} | |
| cancel-in-progress: ${{ github.event_name == 'push' }} | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| detect: | |
| name: detect stack | |
| runs-on: ubuntu-latest | |
| outputs: | |
| python: ${{ steps.set.outputs.python }} | |
| node: ${{ steps.set.outputs.node }} | |
| swift: ${{ steps.set.outputs.swift }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: set | |
| run: | | |
| echo "python=$([ -f pyproject.toml ] && echo true || echo false)" >> "$GITHUB_OUTPUT" | |
| echo "node=$([ -f package.json ] && echo true || echo false)" >> "$GITHUB_OUTPUT" | |
| echo "swift=$([ -f Package.swift ] && echo true || echo false)" >> "$GITHUB_OUTPUT" | |
| commitlint: | |
| name: conventional commits | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: { fetch-depth: 0 } | |
| - uses: wagoid/commitlint-github-action@v6 | |
| with: | |
| configFile: .commitlintrc.json | |
| pr-title: | |
| name: pr title (squash subject) | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v7 | |
| # This repo squash-merges: the PR TITLE becomes the commit subject on | |
| # main, so per-commit commitlint alone cannot protect main. Lint the | |
| # title against the same config the commit lint uses. | |
| # Title goes through env (never template-interpolated into the script). | |
| # Isolated temp prefix (Codex P2 on anders-repo-template#14): npm install | |
| # in the checkout would first install the PROJECT's own dependency tree — | |
| # a private/heavy dep could fail the gate on a valid title. The prefix | |
| # holds only the two exact-pinned lint packages (--ignore-scripts), and | |
| # the config is copied beside them because commitlint resolves `extends` | |
| # from the CONFIG FILE's directory. | |
| - name: lint PR title against commitlint config | |
| env: | |
| TITLE: ${{ github.event.pull_request.title }} | |
| PRNUM: ${{ github.event.pull_request.number }} | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/title-lint" | |
| cp .commitlintrc.json "$RUNNER_TEMP/title-lint/" | |
| npm install --prefix "$RUNNER_TEMP/title-lint" --no-save --no-audit --no-fund \ | |
| --ignore-scripts @commitlint/cli@21.2.1 @commitlint/config-conventional@21.2.0 | |
| # Lint the REAL squash subject: GitHub appends " (#N)" on squash-merge | |
| # (Codex P2 on anders-skills-lite#6), so a title at the length limit | |
| # would land over it on main. | |
| printf '%s (#%s)\n' "$TITLE" "$PRNUM" \ | |
| | npx --prefix "$RUNNER_TEMP/title-lint" --no-install commitlint \ | |
| --config "$RUNNER_TEMP/title-lint/.commitlintrc.json" | |
| gitleaks: | |
| name: secret scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: { fetch-depth: 0 } | |
| - uses: gitleaks/gitleaks-action@v3 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shellcheck: | |
| name: shellcheck | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - run: shellcheck scripts/*.sh | |
| python: | |
| name: python lint + test | |
| needs: detect | |
| if: needs.detect.outputs.python == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: astral-sh/setup-uv@v7 | |
| with: { version: "latest" } | |
| # --all-extras: PEP 621 [project.optional-dependencies] | |
| # --all-groups: PEP 735 [dependency-groups] | |
| - run: uv sync --frozen --all-extras --all-groups | |
| - name: ruff check | |
| run: uvx ruff@0.6.9 check . | |
| - name: ruff format check | |
| run: uvx ruff@0.6.9 format --check . | |
| - name: pytest | |
| if: hashFiles('tests/**') != '' | |
| run: uv run pytest -q | |
| node: | |
| name: node lint + test | |
| needs: detect | |
| if: needs.detect.outputs.node == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '20' | |
| # npm install (not ci) tolerates lockfile drift and missing lockfile. | |
| # Lock down to `npm ci` per-repo once the lockfile is reliably in sync. | |
| - run: npm install --no-audit --no-fund | |
| - name: lint | |
| run: npm run lint --if-present | |
| - name: test | |
| run: npm test --if-present | |
| swift: | |
| name: swift build + test | |
| needs: detect | |
| if: needs.detect.outputs.swift == 'true' | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: swift build | |
| run: swift build | |
| - name: swift test | |
| if: hashFiles('Tests/**') != '' | |
| run: swift test | |
| ci: | |
| name: ci | |
| needs: [commitlint, pr-title, gitleaks, shellcheck, python, node, swift] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: aggregate | |
| run: | | |
| # Fail if any required upstream job failed (skipped is OK for stack-conditional jobs) | |
| for r in "${{ needs.commitlint.result }}" "${{ needs.pr-title.result }}" "${{ needs.gitleaks.result }}" \ | |
| "${{ needs.shellcheck.result }}" \ | |
| "${{ needs.python.result }}" "${{ needs.node.result }}" "${{ needs.swift.result }}"; do | |
| if [ "$r" = "failure" ] || [ "$r" = "cancelled" ]; then | |
| echo "Upstream job failed: $r" | |
| exit 1 | |
| fi | |
| done | |
| echo "All required checks passed." |