Skip to content
Merged
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
12 changes: 11 additions & 1 deletion renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"rebaseWhen": "behind-base-branch"
},
{
"description": "Enable all Go library updates, including indirect dependencies",
"description": "Look up Go libraries compatible with the approved compiler release line",
"matchManagers": ["gomod"],
"matchDepTypes": ["require", "indirect", "replace"],
"enabled": true,
Expand All @@ -54,6 +54,8 @@
{
"description": "Review major migrations after compatible updates",
"matchUpdateTypes": ["major"],
"labels": ["dependencies/major"],
"addLabels": ["dependencies/major"],
"groupName": null,
"groupSlug": null,
"automerge": false,
Expand Down Expand Up @@ -199,6 +201,14 @@
"matchUpdateTypes": ["patch"],
"prPriority": 10
},
{
"description": "Only update indirect Go dependencies for known vulnerabilities",
"matchManagers": ["gomod"],
"matchDepTypes": ["indirect"],
"matchUpdateTypes": ["major", "minor", "patch", "pin", "digest", "pinDigest", "lockFileMaintenance", "rollback", "replacement"],
"matchJsonata": ["$not(isVulnerabilityAlert = true or $exists(vulnerabilityFixVersion))"],
"enabled": false
},
{
"description": "Let Kubernetes consumer upgrades select a compatible kube-openapi revision",
"matchManagers": ["gomod"],
Expand Down
48 changes: 45 additions & 3 deletions scripts/renovate-config-test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,38 @@ async function main() {
const branches = await flattenUpdates(config, {
gomod: [{ packageFile: 'go.mod', deps: [{ ...dep, updates: val.updates }] }],
});
if (depType === 'indirect') {
assert.equal(policy.enabled, true);
assert.deepEqual(branches, []);
const routineBranches = await flattenUpdates(config, {
gomod: [{
packageFile: 'go.mod',
deps: [{
...dep,
updates: [
{ updateType: 'major', newValue: 'v2.0.0', newVersion: 'v2.0.0', newMajor: 2 },
{ updateType: 'digest', newValue: 'v0.0.0-20260101000000-abcdefabcdef' },
...val.updates.map(update => ({ ...update, isVulnerabilityAlert: false })),
],
}],
}],
});
assert.deepEqual(routineBranches, []);
for (const security of [{ isVulnerabilityAlert: true }, { vulnerabilityFixVersion: 'v1.0.1' }]) {
const securityBranches = await flattenUpdates(config, {
gomod: [{
packageFile: 'go.mod',
deps: [{ ...dep, updates: val.updates.map(update => ({ ...update, ...security })) }],
}],
});
assert.equal(securityBranches.length, 2);
for (const branch of securityBranches) {
assert.equal(branch.minimumReleaseAge, null);
assert.equal(branch.prPriority, 20);
}
}
continue;
}
const patch = branches.find(branch => branch.updateType === 'patch');
const minor = branches.find(branch => branch.updateType === 'minor');
assert.equal(patch.branchName, 'renovate/patch-go-libraries');
Expand Down Expand Up @@ -240,6 +272,7 @@ async function main() {
};
const moduleBranches = await flattenUpdates(config, modulePackageFiles);
for (const branch of moduleBranches) {
assert.deepEqual(branch.labels, [branch.updateType === 'major' ? 'dependencies/major' : 'dependencies']);
const group = modules.find(([name, type]) =>
name === branch.depName && type === branch.updateType)[2];
const automerge = branch.updateType === 'patch' || (branch.updateType === 'minor' && group !== 'kubernetes-go-modules');
Expand Down Expand Up @@ -292,13 +325,18 @@ async function main() {
}],
}],
});
for (const name of ['github.com/stretchr/testify', 'github.com/aws/smithy-go', 'k8s.io/api']) {
for (const [name, depType] of [
['github.com/stretchr/testify', 'require'],
['github.com/aws/smithy-go', 'require'],
['k8s.io/api', 'require'],
['example.com/indirect', 'indirect'],
]) {
const securityConfig = { ...config, packageRules: [...config.packageRules] };
const packageFiles = {
gomod: [{
packageFile: 'go.mod',
deps: [{
depName: name, packageName: name, depType: 'require', datasource: 'go', currentValue: 'v1.0.0',
depName: name, packageName: name, depType, datasource: 'go', currentValue: 'v1.0.0',
updates: [
{ updateType: 'patch', newValue: 'v1.0.1', newVersion: 'v1.0.1' },
{ updateType: 'minor', newValue: 'v1.1.0', newVersion: 'v1.1.0' },
Expand All @@ -316,6 +354,8 @@ async function main() {
assert.equal(branch.minimumReleaseAge, null, name);
assert.equal(branch.prPriority, 20, name);
assert.equal(branch.groupName, null, name);
assert.deepEqual(branch.labels, ['security'], name);
assert.deepEqual([...new Set(branch.addLabels ?? [])], branch.updateType === 'major' ? ['dependencies/major'] : [], name);
assert.equal(branch.automerge, branch.updateType === 'patch'
|| (branch.updateType === 'minor' && name !== 'k8s.io/api'), name);
}
Expand Down Expand Up @@ -379,13 +419,15 @@ async function main() {
}
console.log('PASS: module patches and minors automerge in separate branches');
console.log('PASS: compatible GitHub Actions updates automerge separately; major actions stay manual');
console.log('PASS: Kubernetes minors, module majors and non-builder CI tools stay manual; other module minors and all patches automerge');
console.log('PASS: Kubernetes minors, module majors and non-builder CI tools stay manual; eligible library updates automerge');
console.log('PASS: unsupported Go versions are filtered; PR creation is paced without a concurrent cap');
console.log('PASS: security and patch updates precede minors and manual family-grouped majors');
console.log('PASS: routine releases wait seven days; known vulnerability fixes and build-environment patches remain immediate');
console.log('PASS: OSV rules bypass the release delay without automerging Kubernetes minors or majors');
console.log('PASS: extracted GoReleaser patches and both Go compiler directives share one automerge branch');
console.log('PASS: standalone kube-openapi revision updates are disabled without blocking Kubernetes updates');
console.log('PASS: indirect lookups remain enabled; only known vulnerability fixes produce updates');
console.log('PASS: majors use dependencies/major; security majors retain the security label');
}

main().catch(error => {
Expand Down
Loading