Skip to content

Commit

Permalink
Merge branch 'main' into remove-remaining-hardcoded-master-references
Browse files Browse the repository at this point in the history
  • Loading branch information
abdulapopoola authored Mar 5, 2024
2 parents fe9dba6 + 795dafe commit 4849c7b
Show file tree
Hide file tree
Showing 15 changed files with 290 additions and 41 deletions.
2 changes: 2 additions & 0 deletions common/lib/dependabot/file_updaters/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
# frozen_string_literal: true

require "sorbet-runtime"

require "dependabot/credential"

module Dependabot
module FileUpdaters
class Base
extend T::Sig
extend T::Helpers

abstract!

sig { returns(T::Array[Dependabot::Dependency]) }
Expand Down
33 changes: 26 additions & 7 deletions github_actions/lib/dependabot/github_actions/file_fetcher.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"

require "dependabot/file_fetchers"
require "dependabot/file_fetchers/base"

Expand All @@ -13,14 +14,31 @@ class FileFetcher < Dependabot::FileFetchers::Base

FILENAME_PATTERN = /\.ya?ml$/

sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
def self.required_files_in?(filenames)
filenames.any? { |f| f.match?(FILENAME_PATTERN) }
end

sig { override.returns(String) }
def self.required_files_message
"Repo must contain a .github/workflows directory with YAML files or an action.yml file"
end

sig do
override
.params(
source: Dependabot::Source,
credentials: T::Array[Dependabot::Credential],
repo_contents_path: T.nilable(String),
options: T::Hash[String, String]
)
.void
end
def initialize(source:, credentials:, repo_contents_path: nil, options: {})
@workflow_files = T.let([], T::Array[DependencyFile])
super(source: source, credentials: credentials, repo_contents_path: repo_contents_path, options: options)
end

sig { override.returns(T::Array[DependencyFile]) }
def fetch_files
fetched_files = []
Expand All @@ -43,17 +61,16 @@ def fetch_files
else
raise(
Dependabot::DependencyFileNotParseable,
incorrectly_encoded_workflow_files.first.path
T.must(incorrectly_encoded_workflow_files.first).path
)
end
end

private

sig { returns(T::Array[DependencyFile]) }
def workflow_files
return @workflow_files if defined? @workflow_files

@workflow_files = []
return @workflow_files unless @workflow_files.empty?

# In the special case where the root directory is defined we also scan
# the .github/workflows/ folder.
Expand All @@ -71,12 +88,14 @@ def workflow_files
.map { |f| fetch_file_from_host("#{workflows_dir}/#{f.name}") }
end

sig { returns(T::Array[DependencyFile]) }
def correctly_encoded_workflow_files
workflow_files.select { |f| f.content.valid_encoding? }
workflow_files.select { |f| f.content&.valid_encoding? }
end

sig { returns(T::Array[DependencyFile]) }
def incorrectly_encoded_workflow_files
workflow_files.reject { |f| f.content.valid_encoding? }
workflow_files.reject { |f| f.content&.valid_encoding? }
end
end
end
Expand Down
20 changes: 16 additions & 4 deletions github_actions/lib/dependabot/github_actions/file_parser.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"
require "yaml"

require "dependabot/dependency"
require "dependabot/errors"
require "dependabot/file_parsers"
require "dependabot/file_parsers/base"
require "dependabot/errors"
require "dependabot/github_actions/version"

# For docs, see
Expand All @@ -15,6 +16,8 @@
module Dependabot
module GithubActions
class FileParser < Dependabot::FileParsers::Base
extend T::Set

require "dependabot/file_parsers/base/dependency_set"

GITHUB_REPO_REFERENCE = %r{
Expand All @@ -24,6 +27,7 @@ class FileParser < Dependabot::FileParsers::Base
@(?<ref>.+)
}x

sig { override.returns(T::Array[Dependabot::Dependency]) }
def parse
dependency_set = DependencySet.new

Expand All @@ -36,10 +40,11 @@ def parse

private

sig { params(file: Dependabot::DependencyFile).returns(Dependabot::FileParsers::Base::DependencySet) }
def workfile_file_dependencies(file)
dependency_set = DependencySet.new

json = YAML.safe_load(file.content, aliases: true, permitted_classes: [Date, Time, Symbol])
json = YAML.safe_load(T.must(file.content), aliases: true, permitted_classes: [Date, Time, Symbol])
return dependency_set if json.nil?

uses_strings = deep_fetch_uses(json.fetch("jobs", json.fetch("runs", nil))).uniq
Expand Down Expand Up @@ -81,6 +86,7 @@ def workfile_file_dependencies(file)
raise Dependabot::DependencyFileNotParseable, file.path
end

sig { params(file: Dependabot::DependencyFile, string: String).returns(Dependabot::Dependency) }
def build_github_dependency(file, string)
unless source&.hostname == "github.com"
dep = github_dependency(file, string, T.must(source).hostname)
Expand All @@ -91,8 +97,9 @@ def build_github_dependency(file, string)
github_dependency(file, string, "github.com")
end

sig { params(file: Dependabot::DependencyFile, string: String, hostname: String).returns(Dependabot::Dependency) }
def github_dependency(file, string, hostname)
details = string.match(GITHUB_REPO_REFERENCE).named_captures
details = T.must(string.match(GITHUB_REPO_REFERENCE)).named_captures
name = "#{details.fetch('owner')}/#{details.fetch('repo')}"
ref = details.fetch("ref")
version = version_class.new(ref).to_s if version_class.correct?(ref)
Expand All @@ -115,6 +122,7 @@ def github_dependency(file, string, hostname)
)
end

sig { params(json_obj: T.untyped, found_uses: T::Array[String]).returns(T::Array[String]) }
def deep_fetch_uses(json_obj, found_uses = [])
case json_obj
when Hash then deep_fetch_uses_from_hash(json_obj, found_uses)
Expand All @@ -123,6 +131,7 @@ def deep_fetch_uses(json_obj, found_uses = [])
end
end

sig { params(json_object: T::Hash[String, T.untyped], found_uses: T::Array[String]).returns(T::Array[String]) }
def deep_fetch_uses_from_hash(json_object, found_uses)
if json_object.key?("uses")
found_uses << json_object["uses"]
Expand All @@ -136,19 +145,22 @@ def deep_fetch_uses_from_hash(json_object, found_uses)
found_uses
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def workflow_files
# The file fetcher only fetches workflow files, so no need to
# filter here
dependency_files
end

sig { override.void }
def check_required_files
# Just check if there are any files at all.
return if dependency_files.any?

raise "No workflow files!"
end

sig { returns(T.class_of(Dependabot::GithubActions::Version)) }
def version_class
GithubActions::Version
end
Expand Down
29 changes: 21 additions & 8 deletions github_actions/lib/dependabot/github_actions/file_updater.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"

require "dependabot/errors"
require "dependabot/file_updaters"
require "dependabot/file_updaters/base"
require "dependabot/errors"

module Dependabot
module GithubActions
class FileUpdater < Dependabot::FileUpdaters::Base
extend T::Sig

sig { override.returns(T::Array[Regexp]) }
def self.updated_files_regex
[%r{\.github/workflows/.+\.ya?ml$}]
end

sig { override.returns(T::Array[Dependabot::DependencyFile]) }
def updated_dependency_files
updated_files = []

Expand All @@ -33,37 +39,41 @@ def updated_dependency_files

private

sig { returns(Dependabot::Dependency) }
def dependency
# GitHub Actions will only ever be updating a single dependency
dependencies.first
T.must(dependencies.first)
end

sig { override.void }
def check_required_files
# Just check if there are any files at all.
return if dependency_files.any?

raise "No workflow files!"
end

# rubocop:disable Metrics/AbcSize
sig { params(file: Dependabot::DependencyFile).returns(String) }
def updated_workflow_file_content(file)
updated_requirement_pairs =
dependency.requirements.zip(dependency.previous_requirements)
dependency.requirements.zip(T.must(dependency.previous_requirements))
.reject do |new_req, old_req|
next true if new_req[:file] != file.name

new_req[:source] == old_req[:source]
new_req[:source] == T.must(old_req)[:source]
end

updated_content = file.content
updated_content = T.must(file.content)

updated_requirement_pairs.each do |new_req, old_req|
# TODO: Support updating Docker sources
next unless new_req.fetch(:source).fetch(:type) == "git"

old_ref = old_req.fetch(:source).fetch(:ref)
old_ref = T.must(old_req).fetch(:source).fetch(:ref)
new_ref = new_req.fetch(:source).fetch(:ref)

old_declaration = old_req.fetch(:metadata).fetch(:declaration_string)
old_declaration = T.must(old_req).fetch(:metadata).fetch(:declaration_string)
new_declaration =
old_declaration
.gsub(/@.*+/, "@#{new_ref}")
Expand Down Expand Up @@ -91,7 +101,9 @@ def updated_workflow_file_content(file)

updated_content
end
# rubocop:enable Metrics/AbcSize

sig { params(comment: T.nilable(String), old_ref: String, new_ref: String).returns(T.nilable(String)) }
def updated_version_comment(comment, old_ref, new_ref)
raise "No comment!" unless comment

Expand All @@ -110,6 +122,7 @@ def updated_version_comment(comment, old_ref, new_ref)
comment.gsub(previous_version, new_version)
end

sig { returns(T.class_of(Dependabot::GithubActions::Version)) }
def version_class
GithubActions::Version
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"

require "dependabot/metadata_finders"
require "dependabot/metadata_finders/base"

module Dependabot
module GithubActions
class MetadataFinder < Dependabot::MetadataFinders::Base
extend T::Sig

private

sig { override.returns(T.nilable(Dependabot::Source)) }
def look_up_source
info = dependency.requirements.filter_map { |r| r[:source] }.first

Expand Down
9 changes: 6 additions & 3 deletions github_actions/lib/dependabot/github_actions/requirement.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# typed: true
# typed: strong
# frozen_string_literal: true

require "sorbet-runtime"

require "dependabot/github_actions/version"
require "dependabot/requirement"
require "dependabot/utils"
require "dependabot/github_actions/version"

module Dependabot
module GithubActions
# Lifted from the bundler package manager
class Requirement < Dependabot::Requirement
extend T:: Sig

# For consistency with other languages, we define a requirements array.
# Ruby doesn't have an `OR` separator for requirements, so it always
# contains a single element.
Expand All @@ -21,9 +23,10 @@ def self.requirements_array(requirement_string)

# Patches Gem::Requirement to make it accept requirement strings like
# "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
sig { params(requirements: T.any(T.nilable(String), T::Array[T.nilable(String)])).void }
def initialize(*requirements)
requirements = requirements.flatten.flat_map do |req_string|
req_string.split(",").map(&:strip)
req_string&.split(",")&.map(&:strip)
end

super(requirements)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
# frozen_string_literal: true

require "sorbet-runtime"

require "dependabot/errors"
require "dependabot/github_actions/requirement"
require "dependabot/github_actions/version"
require "dependabot/update_checkers"
require "dependabot/update_checkers/base"
require "dependabot/update_checkers/version_filters"
require "dependabot/errors"
require "dependabot/github_actions/version"
require "dependabot/github_actions/requirement"

module Dependabot
module GithubActions
Expand Down
Loading

0 comments on commit 4849c7b

Please sign in to comment.