Skip to content

Commit fff4bfd

Browse files
authored
Merge pull request #1568 from cdrini/feature/fewer-renovate-prs
Group renovate PRs by dependency type to reduce number of PRs
2 parents 0eeb4dc + 112ebea commit fff4bfd

4 files changed

Lines changed: 125 additions & 25 deletions

File tree

jsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"include": [
1111
"src/**/*.js",
12-
"tests/**/*.js",
12+
"tests/jest/**/*.js",
1313
],
1414
"exclude": [
1515
"node_modules",

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,17 @@
132132
"test:e2e": "npm run build && npx testcafe",
133133
"test:e2e:dev": "npx testcafe --live --dev",
134134
"DOCS:update:test-deps": "If CI succeeds, these should be good to update",
135-
"update:test-deps": "npm i @babel/eslint-parser@latest @open-wc/testing-helpers@latest @types/jest@latest eslint@7 eslint-plugin-testcafe@latest jest@latest jest-environment-jsdom@latest sinon@latest testcafe@latest",
135+
"update:test-deps": "npm i @babel/eslint-parser@latest @open-wc/testing-helpers@latest @types/jest@latest eslint@7 eslint-plugin-no-jquery@latest eslint-plugin-testcafe@latest jest@latest jest-environment-jsdom@latest sinon@latest testcafe@latest",
136136
"update:test-deps:test": "npm run lint && npm run test && npm run test:e2e",
137137
"DOCS:update:build-deps": "These can cause strange changes, so do an npm run build + check file size (git diff --stat), and check the site is as expected",
138138
"update:build-deps": "npm i @babel/core@latest @babel/preset-env@latest @babel/plugin-proposal-class-properties@latest @babel/plugin-proposal-decorators@latest babel-loader@latest core-js@latest regenerator-runtime@latest sass@latest svgo@latest webpack@latest webpack-cli@latest",
139139
"update:build-deps:test": "npm run build",
140140
"DOCS:update:dev-deps": "Packages used for development",
141-
"update:dev-deps": "npm i @iiif/presentation-2@latest @iiif/presentation-3@latest concurrently@latest cpx2@latest http-server@latest live-server@latest",
141+
"update:dev-deps": "npm i @iiif/presentation-2@latest @iiif/presentation-3@latest concurrently@latest cpx2@latest http-server@latest hypothesis@latest live-server@latest testcafe-browser-provider-browserstack@latest",
142+
"DOCS:update:runtime-deps": "Core runtime dependencies; do an npm run build + visual check after updating",
143+
"update:runtime-deps": "npm i @webcomponents/webcomponentsjs@latest interactjs@latest iso-language-codes@latest jquery@latest jquery-colorbox@latest jquery-ui@latest jquery-ui-touch-punch@latest jquery.browser@latest lit@latest soundmanager2@latest",
144+
"update:runtime-deps:test": "npm run build",
142145
"DOCS:update:ia-deps": "Packages by @internetarchive",
143-
"update:ia-deps": "npm i @internetarchive/ia-activity-indicator@latest @internetarchive/ia-item-navigator@latest @internetarchive/icon-bookmark@latest @internetarchive/icon-close@latest @internetarchive/icon-dl@latest @internetarchive/icon-edit-pencil@latest @internetarchive/icon-ia-logo@latest @internetarchive/icon-magnify-minus@latest @internetarchive/icon-magnify-plus@latest @internetarchive/icon-search@latest @internetarchive/icon-share@latest @internetarchive/icon-toc@latest @internetarchive/icon-visual-adjustment@latest @internetarchive/modal-manager@latest @internetarchive/shared-resize-observer@latest"
146+
"update:ia-deps": "npm i @internetarchive/bergamot-translator@latest @internetarchive/ia-activity-indicator@latest @internetarchive/ia-item-navigator@latest @internetarchive/icon-bookmark@latest @internetarchive/icon-close@latest @internetarchive/icon-dl@latest @internetarchive/icon-edit-pencil@latest @internetarchive/icon-ia-logo@latest @internetarchive/icon-magnify-minus@latest @internetarchive/icon-magnify-plus@latest @internetarchive/icon-search@latest @internetarchive/icon-share@latest @internetarchive/icon-toc@latest @internetarchive/icon-visual-adjustment@latest @internetarchive/modal-manager@latest @internetarchive/shared-resize-observer@latest"
144147
}
145148
}

renovate.json

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,32 @@
33
"config:base",
44
"schedule:monthly"
55
],
6+
"minimumReleaseAge": "14 days",
67
"packageRules": [
78
{
9+
"matchPackagePatterns": ["*"],
10+
"rangeStrategy": "bump"
11+
},
12+
{
13+
"matchManagers": ["github-actions"],
14+
"groupName": "GitHub Actions",
15+
"automerge": false
16+
},
17+
{
18+
"groupName": "ia deps",
19+
"matchPackagePatterns": ["^@internetarchive/"],
20+
"automerge": false
21+
},
22+
{
23+
"matchPackageNames": ["eslint"],
24+
"allowedVersions": "^7.0.0"
25+
},
26+
{
27+
"groupName": "test deps",
828
"matchPackageNames": [
929
"@babel/eslint-parser",
1030
"@open-wc/testing-helpers",
1131
"@types/jest",
12-
"codecov/codecov-action",
1332
"eslint",
1433
"eslint-plugin-no-jquery",
1534
"eslint-plugin-testcafe",
@@ -21,32 +40,48 @@
2140
"automerge": false
2241
},
2342
{
43+
"groupName": "build deps",
44+
"matchPackageNames": [
45+
"@babel/core",
46+
"@babel/plugin-proposal-class-properties",
47+
"@babel/plugin-proposal-decorators",
48+
"@babel/preset-env",
49+
"babel-loader",
50+
"core-js",
51+
"regenerator-runtime",
52+
"sass",
53+
"svgo",
54+
"webpack",
55+
"webpack-cli"
56+
]
57+
},
58+
{
59+
"groupName": "dev deps",
2460
"matchPackageNames": [
61+
"@iiif/presentation-2",
62+
"@iiif/presentation-3",
2563
"concurrently",
64+
"cpx2",
2665
"http-server",
66+
"hypothesis",
2767
"live-server",
28-
"node-fetch"
29-
],
30-
"matchUpdateTypes": ["minor", "patch"],
31-
"automerge": false
32-
},
33-
{
34-
"matchPackagePatterns": ["^@internetarchive/icon-"],
35-
"groupName": "@internetarchive icons",
36-
"rangeStrategy": "bump"
68+
"testcafe-browser-provider-browserstack"
69+
]
3770
},
3871
{
39-
"matchPackagePatterns": ["*"],
40-
"rangeStrategy": "bump"
41-
},
42-
{
43-
"matchPackagePatterns": ["^actions/"],
44-
"groupName": "GitHub Actions",
45-
"automerge": false
46-
},
47-
{
48-
"matchPackagePatterns": ["^@internetarchive"],
49-
"schedule": ["at any time"]
72+
"groupName": "runtime deps",
73+
"matchPackageNames": [
74+
"@webcomponents/webcomponentsjs",
75+
"interactjs",
76+
"iso-language-codes",
77+
"jquery",
78+
"jquery-colorbox",
79+
"jquery-ui",
80+
"jquery-ui-touch-punch",
81+
"jquery.browser",
82+
"lit",
83+
"soundmanager2"
84+
]
5085
}
5186
]
5287
}

tests/jest/dependencies.test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// @ts-check
2+
import pkg from '../../package.json';
3+
import renovate from '../../renovate.json';
4+
5+
const packageJsonDeps = [
6+
...Object.keys(pkg.dependencies ?? {}),
7+
...Object.keys(pkg.devDependencies ?? {}),
8+
];
9+
10+
/** @type {{ groupName?: string, matchPackageNames?: string[], matchPackagePatterns?: string[] }[]} */
11+
const groupRules = renovate.packageRules.filter(r => r.groupName);
12+
const groupedRenovateDeps = groupRules.flatMap(r => r.matchPackageNames ?? []);
13+
const groupedRenovatePatterns = groupRules.flatMap(r => (r.matchPackagePatterns ?? []).map(p => new RegExp(p)));
14+
15+
/** Strip the version specifier from an `npm install` argument, handling scoped packages.
16+
* @param {string} arg e.g. "eslint@7", "@babel/core@latest", "@scope/pkg"
17+
* @returns {string} e.g. "eslint", "@babel/core", "@scope/pkg"
18+
*/
19+
const depNameFromNpmArg = (arg) => {
20+
const start = arg.startsWith('@') ? 1 : 0;
21+
const i = arg.indexOf('@', start);
22+
return i === -1 ? arg : arg.slice(0, i);
23+
};
24+
25+
// Collect all packages listed in update:* scripts (excludes update:*:test variants)
26+
const updateScriptDeps = new Set(
27+
Object.entries(pkg.scripts)
28+
.filter(([key]) => /^update:[^:]+$/.test(key))
29+
.flatMap(([, script]) => script.split(/\s+/).slice(2).map(depNameFromNpmArg)),
30+
);
31+
32+
describe('renovate.json', () => {
33+
test('all package.json dependencies belong to a renovate group', () => {
34+
const ungrouped = packageJsonDeps.filter(dep => (
35+
!groupedRenovateDeps.includes(dep) && !groupedRenovatePatterns.some(re => re.test(dep))
36+
));
37+
expect(ungrouped).toEqual([]);
38+
});
39+
});
40+
41+
describe('package.json update:* scripts', () => {
42+
test('all package.json dependencies appear in an update:* script', () => {
43+
const missing = packageJsonDeps.filter(dep => !updateScriptDeps.has(dep));
44+
expect(missing).toEqual([]);
45+
});
46+
47+
test('explicit renovate groups match their corresponding update:* script', () => {
48+
const scripts = /** @type {Record<string, string>} */ (pkg.scripts);
49+
for (const rule of groupRules) {
50+
const { groupName, matchPackageNames } = rule;
51+
if (!groupName || !matchPackageNames) continue;
52+
const scriptKey = `update:${groupName.replace(/ /g, '-')}`;
53+
const script = scripts[scriptKey];
54+
if (!script) continue;
55+
56+
const scriptPackages = new Set(script.split(/\s+/).slice(2).map(depNameFromNpmArg));
57+
const groupPackages = new Set(matchPackageNames);
58+
expect({ group: rule.groupName, packages: [...scriptPackages].sort() })
59+
.toEqual({ group: rule.groupName, packages: [...groupPackages].sort() });
60+
}
61+
});
62+
});

0 commit comments

Comments
 (0)