Skip to content

Commit 0e9632f

Browse files
Copilothuangyiirene
andcommitted
feat: add automated pnpm-lock.yaml conflict resolution workflow
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
1 parent a66f4ae commit 0e9632f

2 files changed

Lines changed: 232 additions & 0 deletions

File tree

.github/WORKFLOWS.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,51 @@ Generates and updates CHANGELOG.md from git history.
240240

241241
**Note**: Requires `cliff.toml` configuration file for customization.
242242

243+
### 13. Auto-fix pnpm-lock.yaml Conflicts
244+
245+
**File**: `pnpm-lock-autofix.yml`
246+
**Triggers**: Pull Requests (when pnpm-lock.yaml or package.json files change)
247+
248+
Automatically detects and resolves `pnpm-lock.yaml` merge conflicts.
249+
250+
**What It Does**:
251+
1. Detects when a PR has merge conflicts with the base branch
252+
2. Checks if the conflict is only in `pnpm-lock.yaml`
253+
3. Automatically regenerates the lockfile by running `pnpm install`
254+
4. Commits and pushes the resolved lockfile back to the PR
255+
5. Notifies the PR author with a comment
256+
257+
**When It Runs**:
258+
- When a PR is opened, synchronized, or reopened
259+
- Only if `pnpm-lock.yaml` or any `package.json` files are modified
260+
- Only for PRs from the same repository (not forks, for security)
261+
262+
**Behavior**:
263+
264+
```mermaid
265+
graph TD
266+
A[PR Updated] --> B{Has merge conflicts?}
267+
B -->|No| C[Skip - No action needed]
268+
B -->|Yes| D{Only pnpm-lock.yaml?}
269+
D -->|Yes| E[Regenerate lockfile]
270+
E --> F[Commit & Push]
271+
F --> G[Comment: Success]
272+
D -->|No| H[Comment: Manual resolution needed]
273+
```
274+
275+
**Benefits**:
276+
- Eliminates manual resolution of lockfile conflicts
277+
- Reduces merge friction in monorepo environments
278+
- Saves developer time on routine lockfile conflicts
279+
- Ensures lockfile consistency across branches
280+
281+
**When Manual Resolution Is Needed**:
282+
- If conflicts exist in files other than `pnpm-lock.yaml`
283+
- If the PR is from a fork (security restriction)
284+
- If `pnpm install` fails for any reason
285+
286+
**Security**: Only runs on PRs from the same repository to prevent malicious code execution from forks.
287+
243288
## Security Features
244289

245290
### CodeQL Analysis
@@ -316,6 +361,10 @@ Add these badges to show workflow status:
316361
**Problem**: CodeQL analysis fails
317362
- **Solution**: Check for syntax errors, review CodeQL logs
318363

364+
**Problem**: pnpm-lock.yaml merge conflicts
365+
- **Solution**: The `pnpm-lock-autofix.yml` workflow automatically resolves these conflicts
366+
- **Manual Fix**: Run `pnpm install --no-frozen-lockfile` and commit the updated lockfile
367+
319368
### Getting Help
320369

321370
- Check [GitHub Actions documentation](https://docs.github.com/en/actions)
@@ -347,6 +396,7 @@ Potential workflow additions:
347396
- [ ] Integration tests with examples
348397
- [ ] Automated component documentation generation
349398
- [ ] npm package publishing automation
399+
- [x] Automatic pnpm-lock.yaml conflict resolution (implemented)
350400

351401
## Resources
352402

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
name: Auto-fix pnpm-lock.yaml Conflicts
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
paths:
7+
- 'pnpm-lock.yaml'
8+
- 'package.json'
9+
- '**/package.json'
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
jobs:
16+
autofix-lockfile:
17+
name: Auto-fix pnpm-lock.yaml
18+
runs-on: ubuntu-latest
19+
20+
# Only run on PRs from the same repository (not forks) for security
21+
if: github.event.pull_request.head.repo.full_name == github.repository
22+
23+
steps:
24+
- name: Checkout PR branch
25+
uses: actions/checkout@v4
26+
with:
27+
ref: ${{ github.event.pull_request.head.ref }}
28+
fetch-depth: 0
29+
token: ${{ secrets.GITHUB_TOKEN }}
30+
31+
- name: Configure Git
32+
run: |
33+
git config user.name "github-actions[bot]"
34+
git config user.email "github-actions[bot]@users.noreply.github.com"
35+
36+
- name: Check for merge conflicts
37+
id: check_conflicts
38+
run: |
39+
# Fetch the base branch
40+
git fetch origin ${{ github.event.pull_request.base.ref }}
41+
42+
# Try to merge base into current branch
43+
if git merge --no-commit --no-ff origin/${{ github.event.pull_request.base.ref }} 2>&1 | tee merge_output.txt; then
44+
echo "has_conflicts=false" >> $GITHUB_OUTPUT
45+
git merge --abort 2>/dev/null || true
46+
else
47+
# Check if conflicts exist
48+
if grep -q "CONFLICT" merge_output.txt; then
49+
echo "has_conflicts=true" >> $GITHUB_OUTPUT
50+
51+
# Check if pnpm-lock.yaml has conflicts
52+
if git status | grep -q "pnpm-lock.yaml"; then
53+
echo "lockfile_conflict=true" >> $GITHUB_OUTPUT
54+
else
55+
echo "lockfile_conflict=false" >> $GITHUB_OUTPUT
56+
fi
57+
58+
git merge --abort 2>/dev/null || true
59+
else
60+
echo "has_conflicts=false" >> $GITHUB_OUTPUT
61+
fi
62+
fi
63+
64+
- name: Setup pnpm
65+
if: steps.check_conflicts.outputs.lockfile_conflict == 'true'
66+
uses: pnpm/action-setup@v4
67+
with:
68+
version: 10
69+
70+
- name: Setup Node.js
71+
if: steps.check_conflicts.outputs.lockfile_conflict == 'true'
72+
uses: actions/setup-node@v4
73+
with:
74+
node-version: '20.x'
75+
cache: 'pnpm'
76+
77+
- name: Resolve lockfile conflicts
78+
if: steps.check_conflicts.outputs.lockfile_conflict == 'true'
79+
id: resolve
80+
run: |
81+
echo "🔧 Attempting to resolve pnpm-lock.yaml conflicts..."
82+
83+
# Merge the base branch
84+
git merge origin/${{ github.event.pull_request.base.ref }} || true
85+
86+
# Check if only pnpm-lock.yaml has conflicts
87+
CONFLICT_FILES=$(git diff --name-only --diff-filter=U)
88+
echo "Conflicted files: $CONFLICT_FILES"
89+
90+
if [ "$CONFLICT_FILES" = "pnpm-lock.yaml" ] || [ -z "$CONFLICT_FILES" ]; then
91+
echo "Only pnpm-lock.yaml has conflicts or no conflicts. Regenerating lockfile..."
92+
93+
# Remove the conflicted lockfile
94+
git checkout --theirs pnpm-lock.yaml || git checkout --ours pnpm-lock.yaml || rm -f pnpm-lock.yaml
95+
96+
# Regenerate the lockfile
97+
pnpm install --no-frozen-lockfile
98+
99+
# Check if lockfile was modified
100+
if git diff --quiet pnpm-lock.yaml; then
101+
echo "resolved=false" >> $GITHUB_OUTPUT
102+
echo "reason=no_changes" >> $GITHUB_OUTPUT
103+
else
104+
# Stage and commit the resolved lockfile
105+
git add pnpm-lock.yaml
106+
git commit -m "chore: auto-resolve pnpm-lock.yaml conflicts" \
107+
-m "" \
108+
-m "Automatically regenerated pnpm-lock.yaml to resolve merge conflicts." \
109+
-m "" \
110+
-m "Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
111+
112+
git push origin ${{ github.event.pull_request.head.ref }}
113+
114+
echo "resolved=true" >> $GITHUB_OUTPUT
115+
echo "✅ Successfully resolved and pushed pnpm-lock.yaml"
116+
fi
117+
else
118+
echo "⚠️ Multiple files have conflicts. Manual resolution required."
119+
echo "Conflicted files:"
120+
echo "$CONFLICT_FILES"
121+
echo "resolved=false" >> $GITHUB_OUTPUT
122+
echo "reason=multiple_conflicts" >> $GITHUB_OUTPUT
123+
fi
124+
125+
- name: Comment on PR - Success
126+
if: steps.resolve.outputs.resolved == 'true'
127+
uses: actions/github-script@v7
128+
with:
129+
script: |
130+
const message = `🤖 **Auto-fix Applied**
131+
132+
✅ Successfully resolved \`pnpm-lock.yaml\` merge conflicts!
133+
134+
The lockfile has been automatically regenerated and committed to this PR.
135+
Please review the changes and re-run any necessary checks.
136+
137+
<details>
138+
<summary>What happened?</summary>
139+
140+
When merging branches, \`pnpm-lock.yaml\` conflicts are common because multiple branches may have updated dependencies independently. This automation detected the conflict and regenerated the lockfile by running \`pnpm install\`, which merges the dependency changes from both branches.
141+
142+
</details>`;
143+
144+
await github.rest.issues.createComment({
145+
issue_number: context.issue.number,
146+
owner: context.repo.owner,
147+
repo: context.repo.repo,
148+
body: message
149+
});
150+
151+
- name: Comment on PR - Multiple Conflicts
152+
if: steps.resolve.outputs.reason == 'multiple_conflicts'
153+
uses: actions/github-script@v7
154+
with:
155+
script: |
156+
const message = `🤖 **Auto-fix Skipped**
157+
158+
⚠️ This PR has merge conflicts in multiple files, not just \`pnpm-lock.yaml\`.
159+
160+
**Action Required**: Please resolve the conflicts manually:
161+
162+
\`\`\`bash
163+
# Merge the base branch into your branch
164+
git fetch origin
165+
git merge origin/${{ github.event.pull_request.base.ref }}
166+
167+
# Resolve conflicts in other files first
168+
# Then regenerate pnpm-lock.yaml
169+
pnpm install --no-frozen-lockfile
170+
171+
# Commit and push
172+
git add .
173+
git commit -m "chore: resolve merge conflicts"
174+
git push
175+
\`\`\``;
176+
177+
await github.rest.issues.createComment({
178+
issue_number: context.issue.number,
179+
owner: context.repo.owner,
180+
repo: context.repo.repo,
181+
body: message
182+
});

0 commit comments

Comments
 (0)