diff --git a/terraform/lib/dependabot/terraform/file_updater.rb b/terraform/lib/dependabot/terraform/file_updater.rb index cbeec8d8f4b..c2a81df7ab8 100644 --- a/terraform/lib/dependabot/terraform/file_updater.rb +++ b/terraform/lib/dependabot/terraform/file_updater.rb @@ -48,6 +48,30 @@ def updated_dependency_files private + # Terraform allows to use a module from the same source multiple times + # To detect any changes in dependencies we need to overwrite an implementation from the base class + # + # Example (for simplicity other parameters are skipped): + # previous_requirements = [{requirement: "0.9.1"}, {requirement: "0.11.0"}] + # requirements = [{requirement: "0.11.0"}, {requirement: "0.11.0"}] + # + # Simple difference between arrays gives: + # requirements - previous_requirements + # => [] + # which loses an information that one of our requirements has changed. + # + # By using symmetric difference: + # (requirements - previous_requirements) | (previous_requirements - requirements) + # => [{requirement: "0.9.1"}] + # we can detect that change. + def requirement_changed?(file, dependency) + changed_requirements = + (dependency.requirements - dependency.previous_requirements) | + (dependency.previous_requirements - dependency.requirements) + + changed_requirements.any? { |f| f[:file] == file.name } + end + def updated_terraform_file_content(file) content = file.content.dup @@ -89,7 +113,7 @@ def update_git_declaration(new_req, old_req, updated_content, filename) def update_registry_declaration(new_req, old_req, updated_content) regex = new_req[:source][:type] == "provider" ? provider_declaration_regex : registry_declaration_regex - updated_content.sub!(regex) do |regex_match| + updated_content.gsub!(regex) do |regex_match| regex_match.sub(/^\s*version\s*=.*/) do |req_line_match| req_line_match.sub(old_req[:requirement], new_req[:requirement]) end diff --git a/terraform/spec/dependabot/terraform/file_updater_spec.rb b/terraform/spec/dependabot/terraform/file_updater_spec.rb index 1d3b98e2945..c686052b1dc 100644 --- a/terraform/spec/dependabot/terraform/file_updater_spec.rb +++ b/terraform/spec/dependabot/terraform/file_updater_spec.rb @@ -122,6 +122,75 @@ module "s3-webapp" { end end + context "with private modules with different versions" do + let(:project_name) { "private_modules_with_different_versions" } + + let(:dependencies) do + [ + Dependabot::Dependency.new( + name: "example-org-5d3190/s3-webapp/aws", + version: "0.11.0", + previous_version: "0.9.1", + requirements: [{ + requirement: "0.11.0", + groups: [], + file: "main.tf", + source: { + type: "registry", + registry_hostname: "app.terraform.io", + module_identifier: "example-org-5d3190/s3-webapp/aws" + } + }, { + requirement: "0.11.0", + groups: [], + file: "main.tf", + source: { + type: "registry", + registry_hostname: "app.terraform.io", + module_identifier: "example-org-5d3190/s3-webapp/aws" + } + }], + previous_requirements: [{ + requirement: "0.9.1", + groups: [], + file: "main.tf", + source: { + type: "registry", + registry_hostname: "app.terraform.io", + module_identifier: "example-org-5d3190/s3-webapp/aws" + } + }, { + requirement: "0.11.0", + groups: [], + file: "main.tf", + source: { + type: "registry", + registry_hostname: "app.terraform.io", + module_identifier: "example-org-5d3190/s3-webapp/aws" + } + }], + package_manager: "terraform" + ) + ] + end + + it "updates all private modules versions" do + updated_file = subject.find { |file| file.name == "main.tf" } + + expect(updated_file.content).to include(<<~HCL) + module "s3-webapp-first" { + source = "app.terraform.io/example-org-5d3190/s3-webapp/aws" + version = "0.11.0" + } + + module "s3-webapp-second" { + source = "app.terraform.io/example-org-5d3190/s3-webapp/aws" + version = "0.11.0" + } + HCL + end + end + context "with a private provider" do let(:project_name) { "private_provider" } diff --git a/terraform/spec/fixtures/projects/private_modules_with_different_versions/main.tf b/terraform/spec/fixtures/projects/private_modules_with_different_versions/main.tf new file mode 100644 index 00000000000..7a04e89b4ec --- /dev/null +++ b/terraform/spec/fixtures/projects/private_modules_with_different_versions/main.tf @@ -0,0 +1,9 @@ +module "s3-webapp-first" { + source = "app.terraform.io/example-org-5d3190/s3-webapp/aws" + version = "0.11.0" +} + +module "s3-webapp-second" { + source = "app.terraform.io/example-org-5d3190/s3-webapp/aws" + version = "0.9.1" +}