chore(deps): update semantic-release monorepo (major) #657
Workflow file for this run
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: Validate CI | |
| on: | |
| pull_request: | |
| branches: | |
| - next | |
| - main | |
| types: | |
| - opened | |
| - synchronize | |
| - ready_for_review | |
| - reopened | |
| # `edited` re-runs validation when the PR base branch changes, since the | |
| # base-dependent guards below (changelog/plan-file history) compare | |
| # against it. It also fires on title/body edits — a small amount of extra | |
| # runs we accept to keep base-change reruns correct. | |
| - edited | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Run Unit Tests on Node v${{ matrix.node-version }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # 22 = engines support floor; 24 = project default (.nvmrc). | |
| node-version: [22, 24] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup and build | |
| uses: ./.github/actions/setup | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - name: Run unit tests | |
| run: npm test | |
| lint: | |
| name: Run Code Checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup and build | |
| uses: ./.github/actions/setup | |
| - name: Biome check | |
| run: npm run check:ci | |
| - name: TypeScript type check | |
| run: npx tsc --noEmit | |
| - name: TypeScript type check (tests) | |
| run: npm run typecheck:test | |
| actionlint: | |
| name: Lint Workflows | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Run actionlint | |
| uses: docker://rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667 # v1.7.12 | |
| with: | |
| args: -color | |
| env: | |
| # SC2016 (single-quoted `${...}` don't expand) fires on the many | |
| # intentional literal strings we echo into PR comments (markdown + | |
| # bash examples that must stay literal). Exclude just that one | |
| # info-level rule; all other shellcheck findings still fail the job. | |
| SHELLCHECK_OPTS: --exclude=SC2016 | |
| knip: | |
| name: Detect Dead Code | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| # Build runs codegen (prebuild) so src/gql exists and imports resolve. | |
| - name: Setup and build | |
| uses: ./.github/actions/setup | |
| - name: Run knip | |
| id: knip | |
| run: | | |
| set +e | |
| npm run --silent knip:ci > knip-report.md | |
| echo "exit_code=$?" >> "$GITHUB_OUTPUT" | |
| set -e | |
| - name: Compose PR comment | |
| if: always() | |
| run: | | |
| if [ "${{ steps.knip.outputs.exit_code }}" = "0" ]; then | |
| { | |
| echo '## ✅ knip — no dead code' | |
| echo | |
| echo 'No unused files, exports, types, or dependencies detected.' | |
| } > knip-comment.md | |
| else | |
| { | |
| echo '## 🧹 knip found dead code' | |
| echo | |
| cat knip-report.md | |
| echo | |
| echo '### Fix it locally' | |
| echo | |
| echo '```bash' | |
| echo 'npm run generate # ensure generated GraphQL types exist' | |
| echo 'npm run knip # see the full report' | |
| echo 'npx knip --fix --allow-remove-files # auto-remove unused exports/files, then review the diff' | |
| echo '```' | |
| echo | |
| echo 'If a finding is a false positive (dynamically-wired code knip cannot trace), add a narrow entry to `knip.json` explaining why.' | |
| } > knip-comment.md | |
| fi | |
| - name: Save PR number | |
| if: always() | |
| run: echo "${{ github.event.pull_request.number }}" > pr-number.txt | |
| # GITHUB_TOKEN is forced read-only for pull_request events from forks, | |
| # so this job can't post the comment itself regardless of permissions:. | |
| # Upload the rendered comment + PR number as an artifact; a separate | |
| # workflow_run-triggered workflow (which does get a writable token) | |
| # downloads it and posts the comment. See .github/workflows/knip-comment.yml. | |
| - name: Upload knip comment artifact | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: knip-comment | |
| path: | | |
| knip-comment.md | |
| pr-number.txt | |
| retention-days: 1 | |
| - name: Fail if dead code found | |
| if: steps.knip.outputs.exit_code != '0' | |
| run: | | |
| echo "::error::knip found dead code — see the PR comment for details" | |
| exit 1 | |
| commitlint: | |
| name: Validate Commit Messages | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup (no build) | |
| uses: ./.github/actions/setup | |
| with: | |
| build: "false" | |
| - name: Validate PR commit range | |
| run: | | |
| npx commitlint \ | |
| --from "${{ github.event.pull_request.base.sha }}" \ | |
| --to "${{ github.event.pull_request.head.sha }}" \ | |
| --verbose | |
| smoke-test: | |
| name: Run Package Install Smoke Test | |
| runs-on: ubuntu-latest | |
| needs: [test] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| # No build here: verify:packed-binaries runs `npm pack`, whose `prepack` | |
| # builds (and generates) the package the same way a consumer install would. | |
| - name: Setup (no build) | |
| uses: ./.github/actions/setup | |
| with: | |
| build: "false" | |
| - name: Verify packed binaries | |
| run: npm run verify:packed-binaries | |
| guard-plan-files: | |
| name: Reject Plan Files | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for docs/plans/*.md in branch history | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| base_ref="origin/${GITHUB_BASE_REF:-main}" | |
| plan_files=$(git log "$base_ref"..HEAD \ | |
| --diff-filter=A --name-only --pretty=format: \ | |
| -- 'docs/plans/*.md' | sed '/^$/d') | |
| if [ -n "$plan_files" ]; then | |
| echo "::error::Found plan files in branch history" | |
| # GITHUB_TOKEN is forced read-only for pull_request events from | |
| # forks, so posting a comment would fail there regardless of | |
| # permissions:. The ::error:: above still surfaces in the checks | |
| # UI, so skip the comment rather than fail this step on forks. | |
| if [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ]; then | |
| printf '%s\n' \ | |
| '<!-- linearis:guard-plan-files -->' \ | |
| '' \ | |
| '> [!WARNING]' \ | |
| '> Found `docs/plans/*.md` files in this branch'"'"'s history.' \ | |
| '>' \ | |
| '> Plan files in `docs/plans/` are working artifacts created by AI agents during the design phase. Once the implementation they describe is complete and the PR is ready for review, these files serve no further purpose — they are not reference docs, not changelogs, and not part of the shipped project.' \ | |
| '>' \ | |
| '> Leaving them in the commit history would add noise and suggest unresolved or incomplete work.' \ | |
| '>' \ | |
| '> **Remove them by rebasing and dropping the commits that introduced them:**' \ | |
| '> ```bash' \ | |
| '> git rebase -i main' \ | |
| '> # drop the commits that added docs/plans/*.md, then force-push' \ | |
| '> git push --force-with-lease' \ | |
| '> ```' \ | |
| | gh pr comment ${{ github.event.pull_request.number }} --body-file - | |
| fi | |
| exit 1 | |
| fi | |
| echo "No plan files found — OK" | |
| guard-changelog-history: | |
| name: Guard CHANGELOG History in PR | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect CHANGELOG.md in branch history | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ "${GITHUB_HEAD_REF:-}" = "next" ] && [ "${GITHUB_BASE_REF:-}" = "main" ]; then | |
| echo "Promotion PR next -> main detected. Skipping changelog history guard." | |
| exit 0 | |
| fi | |
| base_ref="origin/${GITHUB_BASE_REF:-main}" | |
| # Repairing notes the release workflow itself lost is the one | |
| # legitimate reason for a PR to touch CHANGELOG.md — see | |
| # "Changelog ownership" in CONTRIBUTING.md. Exempt commits whose | |
| # subject is exactly the reserved backfill subject, and only when | |
| # they change nothing outside CHANGELOG.md and only add lines. | |
| exempt_subject="chore(release): backfill changelog notes" | |
| # Capture into a variable rather than feeding `git log` straight into | |
| # a here-string: a here-string swallows the command substitution's | |
| # exit status, so an unresolvable "$base_ref" would read as an empty | |
| # commit list and the guard would silently pass. | |
| candidates=$(git log "$base_ref"..HEAD --format=%H -- CHANGELOG.md) | |
| offenders="" | |
| while read -r sha; do | |
| [ -n "$sha" ] || continue | |
| subject=$(git log -1 --format=%s "$sha") | |
| if [ "$subject" = "$exempt_subject" ]; then | |
| violation="" | |
| extra=$(git show --name-only --pretty=format: "$sha" | sed '/^$/d' | grep -v '^CHANGELOG.md$' || true) | |
| if [ -n "$extra" ]; then | |
| echo "::error::$exempt_subject commit $sha also touches files other than CHANGELOG.md" | |
| echo "$extra" | |
| violation="yes" | |
| fi | |
| deletions=$(git show --numstat --pretty=format: "$sha" -- CHANGELOG.md | awk 'NF { total += $2 } END { print total + 0 }') | |
| if [ "$deletions" -ne 0 ]; then | |
| echo "::error::$exempt_subject commit $sha removes $deletions CHANGELOG.md line(s); a backfill may only add notes" | |
| violation="yes" | |
| fi | |
| if [ -z "$violation" ]; then | |
| continue | |
| fi | |
| fi | |
| offenders="$offenders$sha $subject"$'\n' | |
| done <<< "$candidates" | |
| if [ -n "$offenders" ]; then | |
| echo "::error::CHANGELOG.md is release-workflow-owned and must not appear in PR branch history" | |
| echo "Drop or amend commits that touch CHANGELOG.md, then push with --force-with-lease" | |
| echo "The only exception is an additions-only, CHANGELOG.md-only commit whose subject is exactly: $exempt_subject" | |
| echo | |
| echo "$offenders" | |
| exit 1 | |
| fi | |
| echo "No CHANGELOG.md history violations — OK" |