mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-10 14:06:30 +00:00
Merge 89f4276560
into 1d2c1a35e3
This commit is contained in:
commit
f0c725909d
5 changed files with 177 additions and 28 deletions
|
@ -3170,7 +3170,6 @@ Managers which do not support replacement:
|
|||
|
||||
- `bazel`
|
||||
- `git-submodules`
|
||||
- `gomod`
|
||||
- `gradle`
|
||||
- `homebrew`
|
||||
- `maven`
|
||||
|
|
|
@ -4,7 +4,7 @@ import { join } from 'upath';
|
|||
import { envMock, mockExecAll } from '../../../../test/exec-util';
|
||||
import { env, fs, git, mocked, partial } from '../../../../test/util';
|
||||
import { GlobalConfig } from '../../../config/global';
|
||||
import type { RepoGlobalConfig } from '../../../config/types';
|
||||
import type { RepoGlobalConfig, UpdateType } from '../../../config/types';
|
||||
import * as docker from '../../../util/exec/docker';
|
||||
import type { StatusResult } from '../../../util/git/types';
|
||||
import * as _hostRules from '../../../util/host-rules';
|
||||
|
@ -1547,6 +1547,67 @@ describe('modules/manager/gomod/artifacts', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('updates import paths with gomodUpdateImportPaths when performing a replacement', async () => {
|
||||
fs.readLocalFile.mockResolvedValueOnce('Current go.sum');
|
||||
fs.readLocalFile.mockResolvedValueOnce(null); // vendor modules filename
|
||||
const execSnapshots = mockExecAll();
|
||||
git.getRepoStatus.mockResolvedValueOnce(
|
||||
partial<StatusResult>({
|
||||
modified: ['go.sum', 'main.go'],
|
||||
}),
|
||||
);
|
||||
fs.readLocalFile
|
||||
.mockResolvedValueOnce('New go.sum')
|
||||
.mockResolvedValueOnce('New main.go')
|
||||
.mockResolvedValueOnce('New go.mod');
|
||||
expect(
|
||||
await gomod.updateArtifacts({
|
||||
packageFileName: 'go.mod',
|
||||
updatedDeps: [
|
||||
{
|
||||
depName: 'github.com/google/go-github/v24',
|
||||
newVersion: 'v28.0.0',
|
||||
|
||||
updateType: 'replacement' as UpdateType,
|
||||
newName: 'github.com/forkzilla/go-github/v28',
|
||||
},
|
||||
],
|
||||
newPackageFileContent: gomod1,
|
||||
config: {
|
||||
...config,
|
||||
updateType: 'major',
|
||||
postUpdateOptions: ['gomodUpdateImportPaths'],
|
||||
},
|
||||
}),
|
||||
).toEqual([
|
||||
{ file: { type: 'addition', path: 'go.sum', contents: 'New go.sum' } },
|
||||
{ file: { type: 'addition', path: 'main.go', contents: 'New main.go' } },
|
||||
{ file: { type: 'addition', path: 'go.mod', contents: 'New go.mod' } },
|
||||
]);
|
||||
expect(execSnapshots).toMatchObject([
|
||||
{
|
||||
cmd: 'go get -d -t ./...',
|
||||
options: { cwd: '/tmp/github/some/repo' },
|
||||
},
|
||||
{
|
||||
cmd: 'go install github.com/marwan-at-work/mod/cmd/mod@latest',
|
||||
options: { cwd: '/tmp/github/some/repo' },
|
||||
},
|
||||
{
|
||||
cmd: 'mod upgrade --mod-name=github.com/forkzilla/go-github/v28 -t=28',
|
||||
options: { cwd: '/tmp/github/some/repo' },
|
||||
},
|
||||
{
|
||||
cmd: 'go mod tidy',
|
||||
options: { cwd: '/tmp/github/some/repo' },
|
||||
},
|
||||
{
|
||||
cmd: 'go mod tidy',
|
||||
options: { cwd: '/tmp/github/some/repo' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('updates correct import paths with gomodUpdateImportPaths and multiple dependencies', async () => {
|
||||
fs.readLocalFile.mockResolvedValueOnce('Current go.sum');
|
||||
fs.readLocalFile.mockResolvedValueOnce(null); // vendor modules filename
|
||||
|
|
|
@ -21,7 +21,7 @@ import { getGitEnvironmentVariables } from '../../../util/git/auth';
|
|||
import { regEx } from '../../../util/regex';
|
||||
import { isValid } from '../../versioning/semver';
|
||||
import type {
|
||||
PackageDependency,
|
||||
Upgrade,
|
||||
UpdateArtifact,
|
||||
UpdateArtifactsConfig,
|
||||
UpdateArtifactsResult,
|
||||
|
@ -31,7 +31,7 @@ import { getExtraDepsNotice } from './artifacts-extra';
|
|||
const { major, valid } = semver;
|
||||
|
||||
function getUpdateImportPathCmds(
|
||||
updatedDeps: PackageDependency[],
|
||||
updatedDeps: Upgrade[],
|
||||
{ constraints }: UpdateArtifactsConfig,
|
||||
): string[] {
|
||||
// Check if we fail to parse any major versions and log that they're skipped
|
||||
|
@ -52,8 +52,8 @@ function getUpdateImportPathCmds(
|
|||
({ newVersion }) =>
|
||||
valid(newVersion) && !newVersion!.endsWith('+incompatible'),
|
||||
)
|
||||
.map(({ depName, newVersion }) => ({
|
||||
depName: depName!,
|
||||
.map(({ depName, newVersion, newName }) => ({
|
||||
depName: newName || depName!,
|
||||
newMajor: major(newVersion!),
|
||||
}))
|
||||
// Skip path updates going from v0 to v1
|
||||
|
@ -247,10 +247,10 @@ export async function updateArtifacts({
|
|||
logger.trace({ cmd, args }, 'go get command included');
|
||||
execCommands.push(`${cmd} ${args}`);
|
||||
|
||||
// Update import paths on major updates
|
||||
// Update import paths on major updates, or when performing replacements
|
||||
const isImportPathUpdateRequired =
|
||||
config.postUpdateOptions?.includes('gomodUpdateImportPaths') &&
|
||||
config.updateType === 'major';
|
||||
(config.updateType === 'major' || config.updateType == 'replacement');
|
||||
|
||||
if (isImportPathUpdateRequired) {
|
||||
const updateImportCmds = getUpdateImportPathCmds(updatedDeps, config);
|
||||
|
|
|
@ -384,14 +384,6 @@ describe('modules/manager/gomod/update', () => {
|
|||
expect(res).toContain('k8s.io/client-go/v2 => k8s.io/client-go v2.2.2');
|
||||
});
|
||||
|
||||
it('should return null for replacement', () => {
|
||||
const res = updateDependency({
|
||||
fileContent: '',
|
||||
upgrade: { updateType: 'replacement' },
|
||||
});
|
||||
expect(res).toBeNull();
|
||||
});
|
||||
|
||||
it('should perform indirect upgrades when top-level', () => {
|
||||
const upgrade = {
|
||||
depName: 'github.com/davecgh/go-spew',
|
||||
|
@ -415,5 +407,84 @@ describe('modules/manager/gomod/update', () => {
|
|||
expect(res).not.toEqual(gomod2);
|
||||
expect(res).toContain(`${upgrade.newValue} // indirect`);
|
||||
});
|
||||
|
||||
it('should perform package replacements', () => {
|
||||
const upgrade = {
|
||||
depName: 'github.com/aws/aws-sdk-go',
|
||||
managerData: { lineNumber: 3 },
|
||||
newValue: 'v1.27.1',
|
||||
depType: 'require',
|
||||
|
||||
updateType: 'replacement' as UpdateType,
|
||||
newName: 'github.com/aws/aws-sdk-go-v2',
|
||||
};
|
||||
const res = updateDependency({ fileContent: gomod1, upgrade });
|
||||
expect(res).not.toEqual(gomod1);
|
||||
expect(res).toContain(`github.com/aws/aws-sdk-go-v2 v1.27.1`);
|
||||
});
|
||||
|
||||
it('should perform package replacements for indirect packages', () => {
|
||||
const upgrade = {
|
||||
depName: 'github.com/davecgh/go-spew',
|
||||
managerData: { lineNumber: 4 },
|
||||
newValue: 'v1.1.1',
|
||||
depType: 'indirect',
|
||||
|
||||
updateType: 'replacement' as UpdateType,
|
||||
newName: 'github.com/spew/go-spew',
|
||||
};
|
||||
const res = updateDependency({ fileContent: gomod1, upgrade });
|
||||
expect(res).not.toEqual(gomod1);
|
||||
expect(res).toContain(
|
||||
`${upgrade.newName} ${upgrade.newValue} // indirect`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should perform package replacements for a digest version', () => {
|
||||
const upgrade = {
|
||||
depName: 'golang.org/x/net',
|
||||
managerData: { lineNumber: 54, multiLine: true },
|
||||
currentDigest: 'c39426892332',
|
||||
newDigest: 'foo',
|
||||
depType: 'require',
|
||||
|
||||
updateType: 'replacement' as UpdateType,
|
||||
newName: 'golang.org/foo-x-bar/net',
|
||||
};
|
||||
const res = updateDependency({ fileContent: gomod2, upgrade });
|
||||
expect(res).not.toEqual(gomod2);
|
||||
expect(res).toContain(`golang.org/foo-x-bar/net foo`);
|
||||
});
|
||||
|
||||
it('should perform package replacements for a major version', () => {
|
||||
const upgrade = {
|
||||
depName: 'github.com/stretchr/testify',
|
||||
managerData: { lineNumber: 48, multiLine: true },
|
||||
newValue: 'v2.0.0',
|
||||
newMajor: 2,
|
||||
depType: 'require',
|
||||
|
||||
updateType: 'replacement' as UpdateType,
|
||||
newName: 'github.com/testify-core/testify/v2',
|
||||
};
|
||||
const res = updateDependency({ fileContent: gomod2, upgrade });
|
||||
expect(res).not.toEqual(gomod2);
|
||||
expect(res).toContain(`github.com/testify-core/testify/v2 v2.0.0`);
|
||||
});
|
||||
|
||||
it('should perform package replacements for a replace directive', () => {
|
||||
const upgrade = {
|
||||
depName: 'github.com/pravesht/gocql',
|
||||
managerData: { lineNumber: 11 },
|
||||
newValue: 'v0.0.1',
|
||||
depType: 'replace',
|
||||
|
||||
updateType: 'replacement' as UpdateType,
|
||||
newName: 'github.com/pravesht/gocql-new',
|
||||
};
|
||||
const res = updateDependency({ fileContent: gomod1, upgrade });
|
||||
expect(res).not.toEqual(gomod1);
|
||||
expect(res).toContain(`github.com/pravesht/gocql-new v0.0.1`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,12 +17,8 @@ export function updateDependency({
|
|||
}: UpdateDependencyConfig): string | null {
|
||||
try {
|
||||
logger.debug(`gomod.updateDependency: ${upgrade.newValue}`);
|
||||
const { depType, updateType } = upgrade;
|
||||
const { depType } = upgrade;
|
||||
const currentName = upgrade.depName;
|
||||
if (updateType === 'replacement') {
|
||||
logger.warn('gomod manager does not support replacement updates yet');
|
||||
return null;
|
||||
}
|
||||
// istanbul ignore if: should never happen
|
||||
if (!currentName || !upgrade.managerData) {
|
||||
return null;
|
||||
|
@ -56,19 +52,21 @@ export function updateDependency({
|
|||
if (depType === 'replace') {
|
||||
if (upgrade.managerData.multiLine) {
|
||||
updateLineExp = regEx(
|
||||
/^(?<depPart>\s+[^\s]+[\s]+[=][>]+\s+)(?<divider>[^\s]+\s+)[^\s]+/,
|
||||
/^(?<depPart>\s+[^\s]+[\s]+[=][>]+\s+)(?<depName>[^\s]+)(?<divider>\s+)[^\s]+/,
|
||||
);
|
||||
} else {
|
||||
updateLineExp = regEx(
|
||||
/^(?<depPart>replace\s+[^\s]+[\s]+[=][>]+\s+)(?<divider>[^\s]+\s+)[^\s]+/,
|
||||
/^(?<depPart>replace\s+[^\s]+[\s]+[=][>]+\s+)(?<depName>[^\s]+)(?<divider>\s+)[^\s]+/,
|
||||
);
|
||||
}
|
||||
} else if (depType === 'require' || depType === 'indirect') {
|
||||
if (upgrade.managerData.multiLine) {
|
||||
updateLineExp = regEx(/^(?<depPart>\s+[^\s]+)(?<divider>\s+)[^\s]+/);
|
||||
updateLineExp = regEx(
|
||||
/^(?<depPart>\s+)(?<depName>[^\s]+)(?<divider>\s+)[^\s]+/,
|
||||
);
|
||||
} else {
|
||||
updateLineExp = regEx(
|
||||
/^(?<depPart>require\s+[^\s]+)(?<divider>\s+)[^\s]+/,
|
||||
/^(?<depPart>require\s+)(?<depName>[^\s]+)(?<divider>\s+)[^\s]+/,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +75,27 @@ export function updateDependency({
|
|||
return null;
|
||||
}
|
||||
let newLine: string;
|
||||
if (upgrade.updateType === 'digest') {
|
||||
let quote = '';
|
||||
|
||||
if (updateLineExp) {
|
||||
const groups = lineToChange.match(updateLineExp)?.groups;
|
||||
// istanbul ignore if: should never happen
|
||||
if (!groups) {
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
if (`${groups.depName}`.startsWith('"')) {
|
||||
quote = '"';
|
||||
}
|
||||
}
|
||||
|
||||
// newName will be available for replacement
|
||||
const newName = upgrade.newName ?? currentName;
|
||||
|
||||
if (
|
||||
upgrade.updateType === 'digest' ||
|
||||
(upgrade.updateType === 'replacement' && upgrade.newDigest)
|
||||
) {
|
||||
const newDigestRightSized = upgrade.newDigest!.substring(
|
||||
0,
|
||||
upgrade.currentDigest!.length,
|
||||
|
@ -92,13 +110,13 @@ export function updateDependency({
|
|||
newLine = lineToChange.replace(
|
||||
// TODO: can be undefined? (#22198)
|
||||
updateLineExp!,
|
||||
`$<depPart>$<divider>${newDigestRightSized}`,
|
||||
`$<depPart>${quote}${newName}${quote}$<divider>${newDigestRightSized}`,
|
||||
);
|
||||
} else {
|
||||
newLine = lineToChange.replace(
|
||||
// TODO: can be undefined? (#22198)
|
||||
updateLineExp!,
|
||||
`$<depPart>$<divider>${upgrade.newValue}`,
|
||||
`$<depPart>${quote}${newName}${quote}$<divider>${upgrade.newValue}`,
|
||||
);
|
||||
}
|
||||
if (upgrade.updateType === 'major') {
|
||||
|
|
Loading…
Reference in a new issue