From bee9fdd2072d5b83a1d5cd9d9cec4217b7a4226b Mon Sep 17 00:00:00 2001 From: zvictor Date: Fri, 6 Mar 2026 21:21:28 -0300 Subject: [PATCH] ci: split workflows and move pnpm lockfile ownership to GitHub Actions --- .github/workflows/pr-policy.yml | 49 ++++++++++++++ .github/workflows/{ci.yml => pr-verify.yml} | 11 ++- .github/workflows/refresh-lockfile.yml | 74 +++++++++++++++++++++ doc/DEVELOPING.md | 8 +++ 4 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/pr-policy.yml rename .github/workflows/{ci.yml => pr-verify.yml} (80%) create mode 100644 .github/workflows/refresh-lockfile.yml diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml new file mode 100644 index 00000000..36612abc --- /dev/null +++ b/.github/workflows/pr-policy.yml @@ -0,0 +1,49 @@ +name: PR Policy + +on: + pull_request: + branches: + - master + +concurrency: + group: pr-policy-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + policy: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.15.4 + run_install: false + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - name: Block manual lockfile edits + run: | + changed="$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}")" + if printf '%s\n' "$changed" | grep -qx 'pnpm-lock.yaml'; then + echo "Do not commit pnpm-lock.yaml in pull requests. CI owns lockfile updates." + exit 1 + fi + + - name: Validate dependency resolution when manifests change + run: | + changed="$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}")" + manifest_pattern='(^|/)package\.json$|^pnpm-workspace\.yaml$|^\.npmrc$|^pnpmfile\.(cjs|js|mjs)$' + if printf '%s\n' "$changed" | grep -Eq "$manifest_pattern"; then + pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile + fi diff --git a/.github/workflows/ci.yml b/.github/workflows/pr-verify.yml similarity index 80% rename from .github/workflows/ci.yml rename to .github/workflows/pr-verify.yml index 4a44003c..51410f52 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/pr-verify.yml @@ -1,15 +1,12 @@ -name: CI +name: PR Verify on: pull_request: branches: - master - push: - branches: - - master concurrency: - group: ci-${{ github.workflow }}-${{ github.ref }} + group: pr-verify-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: @@ -20,6 +17,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup pnpm uses: pnpm/action-setup@v4 @@ -33,7 +32,7 @@ jobs: cache: pnpm - name: Install dependencies - run: pnpm install --frozen-lockfile + run: pnpm install --no-frozen-lockfile - name: Typecheck run: pnpm -r typecheck diff --git a/.github/workflows/refresh-lockfile.yml b/.github/workflows/refresh-lockfile.yml new file mode 100644 index 00000000..8b88f019 --- /dev/null +++ b/.github/workflows/refresh-lockfile.yml @@ -0,0 +1,74 @@ +name: Refresh Lockfile + +on: + push: + branches: + - master + workflow_dispatch: + +concurrency: + group: refresh-lockfile-master + cancel-in-progress: false + +jobs: + refresh_and_verify: + runs-on: ubuntu-latest + timeout-minutes: 25 + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.15.4 + run_install: false + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - name: Refresh pnpm lockfile + run: pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile + + - name: Fail on unexpected file changes + run: | + changed="$(git status --porcelain)" + if [ -z "$changed" ]; then + exit 0 + fi + if printf '%s\n' "$changed" | grep -Fvq ' pnpm-lock.yaml'; then + echo "Unexpected files changed during lockfile refresh:" + echo "$changed" + exit 1 + fi + + - name: Commit refreshed lockfile + run: | + if git diff --quiet -- pnpm-lock.yaml; then + exit 0 + fi + git config user.name "lockfile-bot" + git config user.email "lockfile-bot@users.noreply.github.com" + git add pnpm-lock.yaml + git commit -m "chore(lockfile): refresh pnpm-lock.yaml" + git push + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Typecheck + run: pnpm -r typecheck + + - name: Run tests + run: pnpm test:run + + - name: Build + run: pnpm build diff --git a/doc/DEVELOPING.md b/doc/DEVELOPING.md index bb287623..d3362600 100644 --- a/doc/DEVELOPING.md +++ b/doc/DEVELOPING.md @@ -15,6 +15,14 @@ Current implementation status: - Node.js 20+ - pnpm 9+ +## Dependency Lockfile Policy + +GitHub Actions owns `pnpm-lock.yaml`. + +- Do not commit `pnpm-lock.yaml` in pull requests. +- Pull request CI validates dependency resolution when manifests change. +- Pushes to `master` regenerate `pnpm-lock.yaml` with `pnpm install --lockfile-only --no-frozen-lockfile`, commit it back if needed, and then run verification with `--frozen-lockfile`. + ## Start Dev From repo root: