Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(terraform): Reduce constraints changes in lockfiles #25430

179 changes: 179 additions & 0 deletions lib/modules/manager/terraform/lockfile/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -910,4 +910,183 @@ describe('modules/manager/terraform/lockfile/index', () => {
});
expect(result).toBeNull();
});

it('preserves constraints when current value and new value are same', async () => {
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
provider "registry.terraform.io/hashicorp/aws" {
version = "3.0.0"
constraints = "~> 3.0.0"
hashes = [
"aaa",
"bbb",
"ccc",
]
}
`);
fs.findLocalSiblingOrParent.mockResolvedValueOnce('.terraform.lock.hcl');

mockHash.mockResolvedValueOnce([
'h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=',
'h1:6zB2hX7YIOW26OrKsLJn0uLMnjqbPNxcz9RhlWEuuSY=',
]);

const result = await updateArtifacts({
packageFileName: 'main.tf',
updatedDeps: [
{
depName: 'aws',
depType: 'provider',
packageName: 'hashicorp/aws',
registryUrls: ['https://registry.example.com'],
newVersion: '3.36.1',
currentValue: '~> 3.36',
newValue: '~> 3.36',
},
],
newPackageFileContent: '',
config,
});

expect(result).toEqual([
{
file: {
contents: codeBlock`
provider "registry.terraform.io/hashicorp/aws" {
version = "3.36.1"
constraints = "~> 3.0.0"
hashes = [
"h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=",
"h1:6zB2hX7YIOW26OrKsLJn0uLMnjqbPNxcz9RhlWEuuSY=",
]
}
`,
path: '.terraform.lock.hcl',
type: 'addition',
},
},
]);

expect(mockHash.mock.calls).toEqual([
['https://registry.example.com', 'hashicorp/aws', '3.36.1'],
]);
});

it('replaces current value to new version within a constraint', async () => {
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
provider "registry.terraform.io/hashicorp/aws" {
version = "3.0.0"
constraints = "~> 3.0.0"
hashes = [
"aaa",
"bbb",
"ccc",
]
}
`);
fs.findLocalSiblingOrParent.mockResolvedValueOnce('.terraform.lock.hcl');

mockHash.mockResolvedValueOnce([
'h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=',
'h1:6zB2hX7YIOW26OrKsLJn0uLMnjqbPNxcz9RhlWEuuSY=',
]);

const result = await updateArtifacts({
packageFileName: 'main.tf',
updatedDeps: [
{
depName: 'aws',
depType: 'provider',
packageName: 'hashicorp/aws',
registryUrls: ['https://registry.example.com'],
newVersion: '3.37.0',
currentValue: '~> 3.0.0',
newValue: '~> 3.37.0',
zharinov marked this conversation as resolved.
Show resolved Hide resolved
},
],
newPackageFileContent: '',
config,
});

expect(result).toEqual([
{
file: {
contents: codeBlock`
provider "registry.terraform.io/hashicorp/aws" {
version = "3.37.0"
constraints = "~> 3.37.0"
hashes = [
"h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=",
"h1:6zB2hX7YIOW26OrKsLJn0uLMnjqbPNxcz9RhlWEuuSY=",
]
}
`,
path: '.terraform.lock.hcl',
type: 'addition',
},
},
]);

expect(mockHash.mock.calls).toEqual([
['https://registry.example.com', 'hashicorp/aws', '3.37.0'],
]);
});

it('replaces current version to new version within a constraint', async () => {
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
provider "registry.terraform.io/hashicorp/aws" {
version = "3.0.0"
constraints = "~> 3.0.0"
hashes = [
"aaa",
"bbb",
"ccc",
]
}
`);
fs.findLocalSiblingOrParent.mockResolvedValueOnce('.terraform.lock.hcl');

mockHash.mockResolvedValueOnce([
'h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=',
'h1:6zB2hX7YIOW26OrKsLJn0uLMnjqbPNxcz9RhlWEuuSY=',
]);

const result = await updateArtifacts({
packageFileName: 'main.tf',
updatedDeps: [
{
depName: 'aws',
depType: 'provider',
packageName: 'hashicorp/aws',
registryUrls: ['https://registry.example.com'],
newVersion: '3.37.0',
currentVersion: '3.0.0',
},
],
newPackageFileContent: '',
config,
});

expect(result).toEqual([
{
file: {
contents: codeBlock`
provider "registry.terraform.io/hashicorp/aws" {
version = "3.37.0"
constraints = "~> 3.37.0"
hashes = [
"h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=",
"h1:6zB2hX7YIOW26OrKsLJn0uLMnjqbPNxcz9RhlWEuuSY=",
]
}
`,
path: '.terraform.lock.hcl',
type: 'addition',
},
},
]);

expect(mockHash.mock.calls).toEqual([
['https://registry.example.com', 'hashicorp/aws', '3.37.0'],
]);
});
});
51 changes: 49 additions & 2 deletions lib/modules/manager/terraform/lockfile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,66 @@ export async function updateArtifacts({
);
for (const dep of providerDeps) {
massageProviderLookupName(dep);
const { registryUrls, newVersion, newValue, packageName } = dep;
const {
registryUrls,
currentValue,
currentVersion,
newValue,
newVersion,
packageName,
} = dep;

const registryUrl = registryUrls
? registryUrls[0]
: TerraformProviderDatasource.defaultRegistryUrls[0];
const newConstraint = isPinnedVersion(newValue) ? newVersion : newValue;
const updateLock = locks.find(
(value) => value.packageName === packageName
);
// istanbul ignore if: needs test
if (!updateLock) {
continue;
}
let newConstraint: string | undefined = updateLock.constraints;
zharinov marked this conversation as resolved.
Show resolved Hide resolved
if (
newConstraint &&
currentValue &&
newValue &&
currentValue === newValue
) {
logger.debug(
`Leaving constraints "${newConstraint}" unchanged for "${packageName}" as current and new values are the same`
);
} else if (
newConstraint &&
currentValue &&
newValue &&
newConstraint.includes(currentValue)
) {
logger.debug(
`Updating constraint "${newConstraint}" to replace "${currentValue}" with "${newValue}" for "${packageName}"`
);
newConstraint = newConstraint.replace(currentValue, newValue);
} else if (
newConstraint &&
currentVersion &&
newVersion &&
newConstraint.includes(currentVersion)
) {
logger.debug(
`Updating constraint "${newConstraint}" to replace "${currentVersion}" with "${newVersion}" for "${packageName}"`
);
newConstraint = newConstraint.replace(currentVersion, newVersion);
} else if (isPinnedVersion(newValue)) {
newConstraint = newVersion;
logger.debug(
`Pinning constraint for "${packageName}" to "${newConstraint}"`
);
} else {
newConstraint = newValue;
logger.debug(
`Could not detect constraint to update for "${packageName}" so setting to newValue "${newConstraint}"`
);
}
const update: ProviderLockUpdate = {
// TODO #22198
newVersion: newVersion!,
Expand Down