diff --git a/terraform/lib/dependabot/terraform/file_fetcher.rb b/terraform/lib/dependabot/terraform/file_fetcher.rb index d09116b4a9f..34910d853d8 100644 --- a/terraform/lib/dependabot/terraform/file_fetcher.rb +++ b/terraform/lib/dependabot/terraform/file_fetcher.rb @@ -1,7 +1,8 @@ -# typed: false +# typed: strict # frozen_string_literal: true require "sorbet-runtime" + require "dependabot/file_fetchers" require "dependabot/file_fetchers/base" require "dependabot/terraform/file_selector" @@ -12,15 +13,17 @@ class FileFetcher < Dependabot::FileFetchers::Base extend T::Sig extend T::Helpers - include FileSelector + include FileFilter # https://www.terraform.io/docs/language/modules/sources.html#local-paths LOCAL_PATH_SOURCE = %r{source\s*=\s*['"](?..?\/[^'"]+)} + sig { override.params(filenames: T::Array[String]).returns(T::Boolean) } def self.required_files_in?(filenames) filenames.any? { |f| f.end_with?(".tf", ".hcl") } end + sig { override.returns(String) } def self.required_files_message "Repo must contain a Terraform configuration file." end @@ -37,22 +40,35 @@ def fetch_files private + sig { returns(T::Array[Dependabot::DependencyFile]) } def terraform_files - @terraform_files ||= + @terraform_files ||= T.let( repo_contents(raise_errors: false) .select { |f| f.type == "file" && f.name.end_with?(".tf") } - .map { |f| fetch_file_from_host(f.name) } + .map { |f| fetch_file_from_host(f.name) }, + T.nilable(T::Array[Dependabot::DependencyFile]) + ) end + sig { returns(T::Array[Dependabot::DependencyFile]) } def terragrunt_files - @terragrunt_files ||= + @terragrunt_files ||= T.let( repo_contents(raise_errors: false) .select { |f| f.type == "file" && terragrunt_file?(f.name) } - .map { |f| fetch_file_from_host(f.name) } + .map { |f| fetch_file_from_host(f.name) }, + T.nilable(T::Array[Dependabot::DependencyFile]) + ) end + sig do + params( + files: T::Array[Dependabot::DependencyFile], + dir: String + ) + .returns(T::Array[Dependabot::DependencyFile]) + end def local_path_module_files(files, dir: ".") - terraform_files = [] + terraform_files = T.let([], T::Array[Dependabot::DependencyFile]) files.each do |file| terraform_file_local_module_details(file).each do |path| @@ -71,19 +87,22 @@ def local_path_module_files(files, dir: ".") terraform_files.tap { |fs| fs.each { |f| f.support_file = true } } end + sig { params(file: Dependabot::DependencyFile).returns(T::Array[String]) } def terraform_file_local_module_details(file) return [] unless file.name.end_with?(".tf") - return [] unless file.content.match?(LOCAL_PATH_SOURCE) + return [] unless file.content&.match?(LOCAL_PATH_SOURCE) - file.content.scan(LOCAL_PATH_SOURCE).flatten.map do |path| + T.must(file.content).scan(LOCAL_PATH_SOURCE).flatten.map do |path| Pathname.new(path).cleanpath.to_path end end + sig { returns(T.nilable(Dependabot::DependencyFile)) } def lockfile - return @lockfile if defined?(@lockfile) - - @lockfile = fetch_file_if_present(".terraform.lock.hcl") + @lockfile ||= T.let( + fetch_file_if_present(".terraform.lock.hcl"), + T.nilable(Dependabot::DependencyFile) + ) end end end diff --git a/terraform/lib/dependabot/terraform/file_filter.rb b/terraform/lib/dependabot/terraform/file_filter.rb new file mode 100644 index 00000000000..ac12e1db8e9 --- /dev/null +++ b/terraform/lib/dependabot/terraform/file_filter.rb @@ -0,0 +1,24 @@ +# typed: strong +# frozen_string_literal: true + +require "sorbet-runtime" + +module Dependabot + module Terraform + module FileFilter + extend T::Sig + + private + + sig { params(file_name: String).returns(T::Boolean) } + def terragrunt_file?(file_name) + !lockfile?(file_name) && file_name.end_with?(".hcl") + end + + sig { params(filename: String).returns(T::Boolean) } + def lockfile?(filename) + filename == ".terraform.lock.hcl" + end + end + end +end diff --git a/terraform/lib/dependabot/terraform/file_selector.rb b/terraform/lib/dependabot/terraform/file_selector.rb index f30936573dc..6b6431c47b1 100644 --- a/terraform/lib/dependabot/terraform/file_selector.rb +++ b/terraform/lib/dependabot/terraform/file_selector.rb @@ -1,26 +1,39 @@ -# typed: false +# typed: strong # frozen_string_literal: true -module FileSelector - private +require "sorbet-runtime" - def terraform_files - dependency_files.select { |f| f.name.end_with?(".tf") } - end +require "dependabot/terraform/file_filter" - def terragrunt_files - dependency_files.select { |f| terragrunt_file?(f.name) } - end +module Dependabot + module Terraform + module FileSelector + extend T::Sig + extend T::Helpers - def terragrunt_file?(file_name) - !lockfile?(file_name) && file_name.end_with?(".hcl") - end + abstract! - def lockfile?(filename) - filename == ".terraform.lock.hcl" - end + sig { abstract.returns(T::Array[Dependabot::DependencyFile]) } + def dependency_files; end + + private + + include FileFilter + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def terraform_files + dependency_files.select { |f| f.name.end_with?(".tf") } + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def terragrunt_files + dependency_files.select { |f| terragrunt_file?(f.name) } + end - def lockfile - dependency_files.find { |f| lockfile?(f.name) } + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def lockfile + dependency_files.find { |f| lockfile?(f.name) } + end + end end end