Skip to content

Commit aa20fb5

Browse files
committed
feat: Add lockfile guard workflow to prevent unintended lockfile changes
1 parent 06cce0e commit aa20fb5

3 files changed

Lines changed: 83 additions & 0 deletions

File tree

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ _Add screenshots of relevant screens_
2424

2525
- [ ] My PR follows the style guidelines of this project
2626
- [ ] I have performed a self-check on my work
27+
- [ ] If `package.json` is unchanged, `package-lock.json` is also unchanged in this PR
2728

2829
**If changes are made in the code:**
2930

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Lockfile Guard
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- develop
7+
- main
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
lockfile-guard:
14+
name: Prevent unintended lockfile churn
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0
22+
23+
- name: Validate package and lockfile changes
24+
shell: bash
25+
run: |
26+
set -euo pipefail
27+
28+
BASE_SHA="${{ github.event.pull_request.base.sha }}"
29+
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
30+
31+
CHANGED_FILES="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
32+
33+
PACKAGE_CHANGED="false"
34+
LOCK_CHANGED="false"
35+
36+
if echo "$CHANGED_FILES" | grep -qx "package.json"; then
37+
PACKAGE_CHANGED="true"
38+
fi
39+
40+
if echo "$CHANGED_FILES" | grep -qx "package-lock.json"; then
41+
LOCK_CHANGED="true"
42+
fi
43+
44+
if [ "$LOCK_CHANGED" = "true" ] && [ "$PACKAGE_CHANGED" = "false" ]; then
45+
echo "❌ package-lock.json changed without package.json changes."
46+
echo "If your PR does not intentionally change dependencies, discard lockfile changes:"
47+
echo "git checkout -- package-lock.json"
48+
exit 1
49+
fi
50+
51+
echo "✅ Lockfile check passed."

CONTRIBUTING.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,37 @@ If your work depends on unreleased features or changes, base your work directly
4747

4848
## Code Contributions
4949

50+
### 🚨 Dependency & Lockfile Policy (Read Before PR!)
51+
52+
**When to Commit `package-lock.json`**
53+
54+
- **You MUST commit `package-lock.json` if:**
55+
- You add, remove, or upgrade a dependency in `package.json` (for example, when your new tool needs a new npm package).
56+
- You intentionally update any package version in `package.json`.
57+
- After such changes, always run `npm install` and commit both `package.json` and `package-lock.json` together.
58+
59+
- **You MUST NOT commit `package-lock.json` if:**
60+
- You are only editing, adding, or refactoring tool components, UI, or logic, and did not touch `package.json`.
61+
- You ran `npm install` after pulling latest develop, but did not change dependencies. If the lockfile changes, discard it (`git checkout -- package-lock.json`).
62+
63+
- **Dependency/toolchain upgrades (Next.js, ESLint, etc.) must be in a separate PR, never mixed with feature/tool PRs.**
64+
65+
**For Adding a New Tool:**
66+
67+
- If your tool needs a new npm package:
68+
1. Add the dependency to `package.json`.
69+
2. Run `npm install` (this updates `package-lock.json`).
70+
3. Commit both files in your PR.
71+
- If your tool does NOT need a new dependency, do NOT touch or commit `package-lock.json`.
72+
73+
**Why?**
74+
75+
- Our CI uses `npm ci`, which requires the lockfile to match `package.json` exactly.
76+
- Random lockfile churn (from different npm versions or accidental upgrades) causes huge, noisy diffs and can break builds.
77+
- Only the canonical lockfile in `develop` is valid.
78+
79+
---
80+
5081
Please ensure your pull request adheres to the following guidelines:
5182

5283
- Search [open pull requests](https://github.com/betterbugs/dev-tools/pulls) to ensure your change hasn't already been submitted

0 commit comments

Comments
 (0)