Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/workflows/format-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ jobs:
format-check:
name: Format Check
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.head_ref || github.ref }}

- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
Expand All @@ -24,5 +28,16 @@ jobs:
- name: Install dependencies
run: npm install

- name: Run format check
run: npm run format:check
- name: Apply formatting
run: npm run format:write

- name: Commit fixes if needed
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -u
if ! git diff --cached --quiet; then
git commit -m "chore: apply formatting and sync lockfile"
git push
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-push on pull_request events will break for fork PRs.

This workflow triggers on pull_request, but GitHub downgrades the GITHUB_TOKEN to read-only for PRs from forks regardless of the contents: write permission declared at the job level. The git push step will fail with a permission error, breaking CI for any external contributor.

Options:

  1. Skip the commit step when the event is a fork PR:
    if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
    added to the "Commit fixes if needed" step.
  2. Only run the auto-commit on push to main, not on pull_request events (keep a fail-only format:check step for PRs).

fi
2 changes: 1 addition & 1 deletion .github/workflows/lint-code.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
with:
node-version-file: '.node-version'
cache: 'npm'
- run: npm ci
- run: npm i
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm i silently updates in-memory resolution if the lockfile is stale, giving no signal when drift occurs. npm ci fails fast, which is precisely the symptom that motivated adding the sync workflow. Keeping npm ci here means the lint job fails loudly on drift → sync PR is created → once merged, CI is green again. The sync automation addresses the cause; removing the npm ci check just hides the symptom.

Suggested change
- run: npm i
- run: npm ci

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm ci should not be replaced with npm i in CI.

npm ci is the correct command for CI workflows:

  • Performs a clean install (removes node_modules first)
  • Fails if package-lock.json is out of sync with package.json — which is the signal that should trigger sync-lockfile.yml
  • Is deterministic and faster in CI environments

npm i will silently update package-lock.json if there's drift, masking the very condition the new sync-lockfile.yml workflow is meant to detect and fix. The lint job becomes non-reproducible.

Suggested change
- run: npm i
- run: npm ci

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm i in CI removes reproducibility guarantees.

npm ci is the right command here:

  • Installs exactly what the lockfile specifies (no implicit updates)
  • Fails fast when package-lock.json is inconsistent with package.json, making drift visible
  • Removes node_modules first for a clean install

With npm i, npm can silently update the lockfile during the lint run, meaning the linter could run against different package versions than what's locked — making lint results non-deterministic and drift invisible.

Now that this PR ships a freshly-synced lockfile and a sync-lockfile.yml to keep it current, npm ci should work correctly going forward.

Suggested change
- run: npm i
- run: npm ci

- run: npm run lint:required
38 changes: 38 additions & 0 deletions .github/workflows/sync-lockfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Sync Lock File

on:
push:
branches:
- main
paths:
- 'package.json'
schedule:
- cron: '0 9 * * 1' # Run every Monday at 09:00 UTC
workflow_dispatch:

jobs:
sync-lockfile:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: '.node-version'
cache: 'npm'
- name: Regenerate lock file
run: npm install --package-lock-only --ignore-scripts
- name: Create PR if lock file drifted
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step uses the default GITHUB_TOKEN. GitHub prevents GITHUB_TOKEN-authored events from triggering other workflow runs — so the unit-test, lint-code, and format-check workflows will never run on these sync PRs. If required status checks are configured, sync PRs will be permanently unmergeable without an admin bypass.

Pass a PAT or GitHub App token to let the created PR trigger normal CI:

Suggested change
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
token: ${{ secrets.GITHUB_BOT_TOKEN }}
commit-message: 'chore: sync package-lock.json with package.json'

with:
commit-message: 'chore: sync package-lock.json with package.json'
branch: chore/sync-lockfile
delete-branch: true
title: 'chore: sync package-lock.json with package.json'
body: |
`package-lock.json` has drifted from `package.json`. This PR regenerates the lock file.

Generated by the [Sync Lock File](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) workflow.
labels: dependencies
Loading
Loading