refactor(ci): plumb regenerated PR lockfile via artifact

The policy job already regenerates pnpm-lock.yaml in memory when a PR
changes any manifest (package.json, pnpm-workspace.yaml, .npmrc,
pnpmfile.*) but throws it away. Manifest-only PRs from non-dependabot,
non-chore/refresh-lockfile branches can't commit the lockfile (policy
blocks it) and can't satisfy --frozen-lockfile downstream, so every
test/build job fails with ERR_PNPM_OUTDATED_LOCKFILE until the
post-merge refresh-lockfile workflow runs on master.

This commit closes that gap by uploading the regenerated lockfile as
a workflow artifact (pr-lockfile) from policy and restoring it via
actions/download-artifact in each downstream job before pnpm install
--frozen-lockfile runs. The download step is best-effort
(continue-on-error: true) so PRs that did not change manifests are
unaffected — the artifact simply does not exist and downstream jobs
proceed with the committed lockfile as before. canary_dry_run's
pre-existing 'git checkout -- pnpm-lock.yaml' is guarded so it no
longer clobbers an artifact-restored lockfile.
This commit is contained in:
Devin Foley committed 2026-06-05 20:17:02 -07:00
1 parent 4693d770aa
commit d418d516b9
1 file changed
+72 -2
+72 -2
View File
@@ -13,6 +13,8 @@ jobs:
policy:
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
lockfile_regenerated: ${{ steps.regen_lockfile.outputs.regenerated }}
steps:
- name: Checkout repository
@@ -63,13 +65,30 @@ jobs:
node ./scripts/check-release-package-bootstrap.mjs "${changed_paths[@]}"
- name: Validate dependency resolution when manifests change
id: regen_lockfile
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
echo "regenerated=1" >> "$GITHUB_OUTPUT"
else
echo "regenerated=0" >> "$GITHUB_OUTPUT"
fi
# Manifest-only PRs (where pnpm-lock.yaml stays at base because the policy
# job above blocks committing it) need the regenerated lockfile for the
# downstream `pnpm install --frozen-lockfile` steps. Upload it here so
# every job consumes the same hash without recomputing.
- name: Upload regenerated lockfile for downstream jobs
if: steps.regen_lockfile.outputs.regenerated == '1'
uses: actions/upload-artifact@v4
with:
name: pr-lockfile
path: pnpm-lock.yaml
retention-days: 1
if-no-files-found: error
typecheck_release_registry:
name: Typecheck + Release Registry
needs: [policy]
@@ -85,6 +104,13 @@ jobs:
with:
version: 9.15.4
- name: Restore regenerated PR lockfile (if policy uploaded one)
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: pr-lockfile
path: .
- name: Setup Node.js
uses: actions/setup-node@v6
with:
@@ -125,6 +151,13 @@ jobs:
with:
version: 9.15.4
- name: Restore regenerated PR lockfile (if policy uploaded one)
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: pr-lockfile
path: .
- name: Setup Node.js
uses: actions/setup-node@v6
with:
@@ -171,6 +204,13 @@ jobs:
with:
version: 9.15.4
- name: Restore regenerated PR lockfile (if policy uploaded one)
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: pr-lockfile
path: .
- name: Setup Node.js
uses: actions/setup-node@v6
with:
@@ -214,6 +254,13 @@ jobs:
with:
version: 9.15.4
- name: Restore regenerated PR lockfile (if policy uploaded one)
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: pr-lockfile
path: .
- name: Setup Node.js
uses: actions/setup-node@v6
with:
@@ -241,6 +288,13 @@ jobs:
with:
version: 9.15.4
- name: Restore regenerated PR lockfile (if policy uploaded one)
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: pr-lockfile
path: .
- name: Setup Node.js
uses: actions/setup-node@v6
with:
@@ -251,11 +305,20 @@ jobs:
run: pnpm install --frozen-lockfile
# `release.sh` always executes its Step 2/7 workspace build, even when
# `--skip-verify` bypasses the initial verification gate.
# `--skip-verify` bypasses the initial verification gate. release.sh
# also requires a clean working tree, so any in-place lockfile churn
# from `pnpm install --frozen-lockfile` must be reverted first — unless
# the policy job uploaded a regenerated lockfile (manifest-only PRs),
# in which case we keep the artifact-restored copy so the workspace
# build sees a lockfile that matches the manifest.
- name: Release canary dry run via release.sh internal build
env:
USED_ARTIFACT_LOCKFILE: ${{ needs.policy.outputs.lockfile_regenerated || '0' }}
run: |
git checkout -B master HEAD
git checkout -- pnpm-lock.yaml
if [ "$USED_ARTIFACT_LOCKFILE" != "1" ]; then
git checkout -- pnpm-lock.yaml
fi
./scripts/release.sh canary --skip-verify --dry-run
e2e:
@@ -272,6 +335,13 @@ jobs:
with:
version: 9.15.4
- name: Restore regenerated PR lockfile (if policy uploaded one)
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: pr-lockfile
path: .
- name: Setup Node.js
uses: actions/setup-node@v6
with: