name: Refresh Lockfile on: pull_request: branches: - master types: - opened - synchronize - reopened - ready_for_review concurrency: group: refresh-lockfile-pr-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: refresh: runs-on: ubuntu-latest timeout-minutes: 10 permissions: contents: write pull-requests: read steps: - name: Detect dependency manifest changes id: changes env: GH_TOKEN: ${{ github.token }} run: | changed="$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" --paginate --jq '.[].filename')" manifest_pattern='(^|/)package\.json$|^pnpm-workspace\.yaml$|^\.npmrc$|^pnpmfile\.(cjs|js|mjs)$' if printf '%s\n' "$changed" | grep -Eq "$manifest_pattern"; then echo "manifest_changed=true" >> "$GITHUB_OUTPUT" else echo "manifest_changed=false" >> "$GITHUB_OUTPUT" fi if [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ]; then echo "same_repo=true" >> "$GITHUB_OUTPUT" else echo "same_repo=false" >> "$GITHUB_OUTPUT" fi - name: Checkout pull request head if: steps.changes.outputs.manifest_changed == 'true' uses: actions/checkout@v4 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} fetch-depth: 0 - name: Setup pnpm if: steps.changes.outputs.manifest_changed == 'true' uses: pnpm/action-setup@v4 with: version: 9.15.4 run_install: false - name: Setup Node.js if: steps.changes.outputs.manifest_changed == 'true' uses: actions/setup-node@v4 with: node-version: 20 cache: pnpm - name: Refresh pnpm lockfile if: steps.changes.outputs.manifest_changed == 'true' run: pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile - name: Fail on unexpected file changes if: steps.changes.outputs.manifest_changed == 'true' run: | changed="$(git status --porcelain)" if [ -z "$changed" ]; then echo "Lockfile is already up to date." 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 to same-repo PR branch if: steps.changes.outputs.manifest_changed == 'true' && steps.changes.outputs.same_repo == 'true' run: | if git diff --quiet -- pnpm-lock.yaml; then echo "Lockfile unchanged, nothing to do." 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 origin "HEAD:${{ github.event.pull_request.head.ref }}" - name: Fail fork PRs that need a lockfile refresh if: steps.changes.outputs.manifest_changed == 'true' && steps.changes.outputs.same_repo != 'true' run: | if git diff --quiet -- pnpm-lock.yaml; then echo "Lockfile unchanged, nothing to do." exit 0 fi echo "This fork PR changes dependency manifests and requires a refreshed pnpm-lock.yaml." >&2 echo "Run: pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile" >&2 echo "Then commit pnpm-lock.yaml to the PR branch." >&2 exit 1