Skip to content

Commit 3dc8bf7

Browse files
committed
ci: daily dependabot, auto-merge, pnpm 10 hardening; revert pnpm 11
1 parent edf1076 commit 3dc8bf7

6 files changed

Lines changed: 2653 additions & 5846 deletions

File tree

.github/dependabot.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,30 @@ updates:
1212
- package-ecosystem: "github-actions"
1313
directory: "/"
1414
schedule:
15-
interval: "weekly"
16-
day: "monday"
17-
time: "09:00"
18-
timezone: "Etc/UTC"
19-
open-pull-requests-limit: 5
15+
interval: "daily"
16+
open-pull-requests-limit: 10
17+
cooldown:
18+
default-days: 1
2019
commit-message:
2120
prefix: "chore(ci)"
2221
include: "scope"
2322
labels:
2423
- "dependencies"
2524
- "github-actions"
2625
- "security"
27-
# Group low-risk version bumps so reviewers don't drown in tiny PRs.
28-
# Major bumps stay separate so they get a real review.
2926
groups:
30-
actions-minor-and-patch:
27+
minor-and-patch:
28+
patterns:
29+
- "*"
3130
update-types:
3231
- "minor"
3332
- "patch"
33+
# Workaround for dependabot/dependabot-core#14202: without an explicit
34+
# major group, major updates matching the minor-and-patch pattern are
35+
# silently suppressed. Remove this group when #14202 is fixed to get
36+
# individual (ungrouped) PRs per major bump instead.
37+
major:
38+
patterns:
39+
- "*"
40+
update-types:
41+
- "major"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Dependabot Auto-Merge (Minor/Patch)
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, synchronize]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
11+
jobs:
12+
auto-merge:
13+
runs-on: ubuntu-latest
14+
if: github.event.pull_request.user.login == 'dependabot[bot]'
15+
steps:
16+
- name: Fetch Dependabot metadata
17+
id: metadata
18+
uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
19+
with:
20+
github-token: ${{ secrets.GITHUB_TOKEN }}
21+
22+
- name: Auto-approve and merge minor/patch github-actions updates
23+
if: >-
24+
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
25+
(steps.metadata.outputs.update-type == 'version-update:semver-minor' ||
26+
steps.metadata.outputs.update-type == 'version-update:semver-patch')
27+
env:
28+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
PR_URL: ${{ github.event.pull_request.html_url }}
30+
run: |
31+
gh pr review "$PR_URL" --approve
32+
gh pr merge "$PR_URL" --auto --merge
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
name: Dependabot Major Version Analysis
2+
3+
on:
4+
pull_request_target:
5+
types: [opened]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
11+
jobs:
12+
analyze-major:
13+
runs-on: ubuntu-latest
14+
if: github.event.pull_request.user.login == 'dependabot[bot]'
15+
steps:
16+
- name: Fetch Dependabot metadata
17+
id: metadata
18+
uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
19+
with:
20+
github-token: ${{ secrets.GITHUB_TOKEN }}
21+
22+
- name: Analyze major version bump
23+
if: >-
24+
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
25+
steps.metadata.outputs.update-type == 'version-update:semver-major'
26+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
27+
env:
28+
DEP_NAME: ${{ steps.metadata.outputs.dependency-names }}
29+
PREV_VERSION: ${{ steps.metadata.outputs.previous-version }}
30+
NEW_VERSION: ${{ steps.metadata.outputs.new-version }}
31+
with:
32+
github-token: ${{ secrets.GITHUB_TOKEN }}
33+
script: |
34+
const depName = process.env.DEP_NAME;
35+
const prevVersion = process.env.PREV_VERSION;
36+
const newVersion = process.env.NEW_VERSION;
37+
const parts = depName.split('/');
38+
const owner = parts[0];
39+
const repo = parts[1];
40+
const repoSlug = `${owner}/${repo}`;
41+
42+
let releases = [];
43+
try {
44+
const { data } = await github.rest.repos.listReleases({ owner, repo, per_page: 50 });
45+
releases = data;
46+
} catch (err) {
47+
core.warning(`Could not fetch releases for ${repoSlug}: ${err.message}`);
48+
}
49+
50+
const prevMajor = parseInt(prevVersion.replace(/^v/, ''), 10);
51+
const newMajor = parseInt(newVersion.replace(/^v/, ''), 10);
52+
53+
const relevantReleases = releases.filter(r => {
54+
const major = parseInt(r.tag_name.replace(/^v/, ''), 10);
55+
return major > prevMajor && major <= newMajor;
56+
});
57+
58+
let releaseNotesSummary = '';
59+
let breakingChanges = '';
60+
61+
if (relevantReleases.length === 0) {
62+
releaseNotesSummary = '_No releases found between these versions._';
63+
breakingChanges = `_Unable to determine breaking changes automatically. Please review the [full changelog](https://github.com/${repoSlug}/releases)._`;
64+
} else {
65+
for (const release of relevantReleases.slice(0, 10)) {
66+
const body = release.body || '_No release notes._';
67+
releaseNotesSummary += `### ${release.tag_name}${release.name && release.name !== release.tag_name ? ' — ' + release.name : ''}\n\n`;
68+
releaseNotesSummary += body.substring(0, 2000);
69+
if (body.length > 2000) releaseNotesSummary += '\n\n_...truncated_';
70+
releaseNotesSummary += '\n\n---\n\n';
71+
const lines = body.split('\n');
72+
for (const line of lines) {
73+
if (/breaking|BREAKING|removed|deprecated|incompatible|migration/i.test(line)) {
74+
breakingChanges += `- ${line.trim()}\n`;
75+
}
76+
}
77+
}
78+
}
79+
80+
if (!breakingChanges) {
81+
breakingChanges = '_No explicit breaking changes detected in release notes. Manual review recommended._';
82+
}
83+
84+
let commentBody = `## :warning: Major Version Update — Manual Review Required
85+
86+
| Field | Value |
87+
|-------|-------|
88+
| **Action** | [\`${depName}\`](https://github.com/${repoSlug}) |
89+
| **Previous** | \`v${prevVersion}\` |
90+
| **New** | \`v${newVersion}\` |
91+
| **Type** | Major (\`v${prevMajor}\` → \`v${newMajor}\`) |
92+
93+
### Breaking Changes
94+
95+
${breakingChanges}
96+
97+
### Release Notes (v${prevMajor + 1} → v${newMajor})
98+
99+
${releaseNotesSummary}
100+
101+
### Next Steps
102+
103+
1. Review breaking changes above
104+
2. Check if workflow inputs/outputs changed
105+
3. Verify compatibility with your CI/CD configuration
106+
107+
> Full changelog: https://github.com/${repoSlug}/releases
108+
109+
---
110+
_Generated automatically for Dependabot major version PRs._`.replace(/^ /gm, '');
111+
112+
if (commentBody.length > 64000) {
113+
commentBody = commentBody.substring(0, 63900) + '\n\n_...comment truncated due to size limit._';
114+
}
115+
116+
await github.rest.issues.createComment({
117+
owner: context.repo.owner,
118+
repo: context.repo.repo,
119+
issue_number: context.payload.pull_request.number,
120+
body: commentBody,
121+
});
122+
123+
try {
124+
const labelsToAdd = ['major-update', 'needs-review'];
125+
for (const label of labelsToAdd) {
126+
try {
127+
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
128+
} catch {
129+
const colors = { 'major-update': 'B60205', 'needs-review': 'FBCA04' };
130+
await github.rest.issues.createLabel({
131+
owner: context.repo.owner, repo: context.repo.repo,
132+
name: label, color: colors[label] || 'EDEDED',
133+
});
134+
}
135+
}
136+
await github.rest.issues.addLabels({
137+
owner: context.repo.owner,
138+
repo: context.repo.repo,
139+
issue_number: context.payload.pull_request.number,
140+
labels: labelsToAdd,
141+
});
142+
} catch (err) {
143+
core.warning(`Could not add labels: ${err.message}`);
144+
}

.npmrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
minimum-release-age=1440
2+
block-exotic-subdeps=true

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"engines": {
7272
"node": ">=18"
7373
},
74-
"packageManager": "pnpm@11.1.2",
74+
"packageManager": "pnpm@10.33.4",
7575
"pnpm": {
7676
"peerDependencyRules": {
7777
"ignoreMissing": [

0 commit comments

Comments
 (0)