Skip to content

Commit 1d70997

Browse files
trim21rarkins
authored andcommitted
fix(manager/gomod): perfer to use go version defined as toolchain to update artifacts (renovatebot#34564)
Co-authored-by: Rhys Arkins <[email protected]>
1 parent d78e7e2 commit 1d70997

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

lib/modules/manager/gomod/artifacts.spec.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2121,6 +2121,86 @@ describe('modules/manager/gomod/artifacts', () => {
21212121
expect(execSnapshots).toMatchObject(expectedResult);
21222122
});
21232123

2124+
it('go.mod file contains go toolchain version', async () => {
2125+
GlobalConfig.set({ ...adminConfig, binarySource: 'install' });
2126+
fs.readLocalFile.mockResolvedValueOnce('Current go.sum');
2127+
fs.readLocalFile.mockResolvedValueOnce(null); // vendor modules filename
2128+
const execSnapshots = mockExecAll();
2129+
git.getRepoStatus.mockResolvedValueOnce(
2130+
partial<StatusResult>({
2131+
modified: ['go.sum'],
2132+
}),
2133+
);
2134+
fs.readLocalFile
2135+
.mockResolvedValueOnce('New go.sum')
2136+
.mockResolvedValueOnce('New go.mod');
2137+
2138+
const res = await gomod.updateArtifacts({
2139+
packageFileName: 'go.mod',
2140+
updatedDeps: [{ depName: 'golang.org/x/crypto', newVersion: '0.35.0' }],
2141+
newPackageFileContent: `someText\n\ngo 1.13\n\ntoolchain go1.23.6\n\n${gomod1}`,
2142+
config: {
2143+
updateType: 'minor',
2144+
},
2145+
});
2146+
2147+
expect(res).toEqual([
2148+
{ file: { type: 'addition', path: 'go.sum', contents: 'New go.sum' } },
2149+
{ file: { type: 'addition', path: 'go.mod', contents: 'New go.mod' } },
2150+
]);
2151+
2152+
expect(execSnapshots).toMatchObject([
2153+
{
2154+
cmd: 'install-tool golang 1.23.6',
2155+
},
2156+
{
2157+
cmd: 'go get -d -t ./...',
2158+
},
2159+
]);
2160+
2161+
expect(datasource.getPkgReleases).toBeCalledTimes(0);
2162+
});
2163+
2164+
it('go.mod file contains full go version without toolchain', async () => {
2165+
GlobalConfig.set({ ...adminConfig, binarySource: 'install' });
2166+
fs.readLocalFile.mockResolvedValueOnce('Current go.sum');
2167+
fs.readLocalFile.mockResolvedValueOnce(null); // vendor modules filename
2168+
const execSnapshots = mockExecAll();
2169+
git.getRepoStatus.mockResolvedValueOnce(
2170+
partial<StatusResult>({
2171+
modified: ['go.sum'],
2172+
}),
2173+
);
2174+
fs.readLocalFile
2175+
.mockResolvedValueOnce('New go.sum')
2176+
.mockResolvedValueOnce('New go.mod');
2177+
2178+
const res = await gomod.updateArtifacts({
2179+
packageFileName: 'go.mod',
2180+
updatedDeps: [{ depName: 'golang.org/x/crypto', newVersion: '0.35.0' }],
2181+
newPackageFileContent: `someText\n\ngo 1.23.5\n\n${gomod1}`,
2182+
config: {
2183+
updateType: 'minor',
2184+
},
2185+
});
2186+
2187+
expect(res).toEqual([
2188+
{ file: { type: 'addition', path: 'go.sum', contents: 'New go.sum' } },
2189+
{ file: { type: 'addition', path: 'go.mod', contents: 'New go.mod' } },
2190+
]);
2191+
2192+
expect(execSnapshots).toMatchObject([
2193+
{
2194+
cmd: 'install-tool golang 1.23.5',
2195+
},
2196+
{
2197+
cmd: 'go get -d -t ./...',
2198+
},
2199+
]);
2200+
2201+
expect(datasource.getPkgReleases).toBeCalledTimes(0);
2202+
});
2203+
21242204
it('returns artifact notices', async () => {
21252205
artifactsExtra.getExtraDepsNotice.mockReturnValue('some extra notice');
21262206
GlobalConfig.set({ ...adminConfig, binarySource: 'docker' });
@@ -2144,7 +2224,7 @@ describe('modules/manager/gomod/artifacts', () => {
21442224
updatedDeps: [
21452225
{ depName: 'github.com/google/go-github/v24', newVersion: 'v28.0.0' },
21462226
],
2147-
newPackageFileContent: gomod1,
2227+
newPackageFileContent: `someText\n\ngo 1.17\n\n${gomod1}`,
21482228
config: {
21492229
updateType: 'major',
21502230
postUpdateOptions: ['gomodUpdateImportPaths'],

lib/modules/manager/gomod/artifacts.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,32 @@ export async function updateArtifacts({
444444
}
445445

446446
function getGoConstraints(content: string): string | undefined {
447+
// prefer toolchain directive when go.mod has one
448+
const toolchainMatch = regEx(/^toolchain\s*go(?<gover>\d+\.\d+\.\d+)$/m).exec(
449+
content,
450+
);
451+
const toolchainVer = toolchainMatch?.groups?.gover;
452+
if (toolchainVer) {
453+
logger.debug(
454+
`Using go version ${toolchainVer} found in toolchain directive`,
455+
);
456+
return toolchainVer;
457+
}
458+
459+
// If go.mod doesn't have toolchain directive and has a full go version spec,
460+
// for example `go 1.23.6`, pick this version, this doesn't match major.minor version spec.
461+
//
462+
// This is because when go.mod have same version defined in go directive and toolchain directive,
463+
// go will remove toolchain directive from go.mod.
464+
//
465+
// For example, go will rewrite `go 1.23.5\ntoolchain go1.23.5` to `go 1.23.5` by default,
466+
// in this case, the go directive is the toolchain directive.
467+
const goFullVersion = regEx(/^go\s*(?<gover>\d+\.\d+\.\d+)$/m).exec(content)
468+
?.groups?.gover;
469+
if (goFullVersion) {
470+
return goFullVersion;
471+
}
472+
447473
const re = regEx(/^go\s*(?<gover>\d+\.\d+)$/m);
448474
const match = re.exec(content);
449475
if (!match?.groups?.gover) {

0 commit comments

Comments
 (0)