Class: Dependabot::GithubActions::Lockfile::Reader

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/github_actions/lockfile/reader.rb

Overview

Read-only parser for .github/workflows/actions.lock. Authoritative only for the workflow paths in its workflows: section, so onboarding is decided per path via #onboarded?, never repo-wide. Never writes: lockfile generation belongs to the gh-actions-lock engine.

Constant Summary collapse

ParsedObject =
T.type_alias { T::Hash[String, Object] }
ALGO_PREFIXES =

Every commit must carry an explicit hash-algorithm prefix.

T.let(%w(sha1- sha256-).freeze, T::Array[String])
REQUIRED_DEPENDENCY_KEYS =

Keys gh-actions-lock requires on every dependencies entry. A missing key makes the engine silently discard the whole lockfile in memory and report every workflow as un-onboarded.

T.let(%w(ref commit owner_id repo_id).freeze, T::Array[String])

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content) ⇒ Reader

Returns a new instance of Reader.



32
33
34
35
# File 'lib/dependabot/github_actions/lockfile/reader.rb', line 32

def initialize(content)
  @content = T.let(content, String)
  @data = T.let(parse, ParsedObject)
end

Class Method Details

.from_files(files) ⇒ Object



40
41
42
43
44
45
46
47
48
# File 'lib/dependabot/github_actions/lockfile/reader.rb', line 40

def self.from_files(files)
  file = files.find { |f| f.path.delete_prefix("/") == LOCKFILE_PATH }
  return nil unless file

  content = file.content
  return nil if content.nil? || content.strip.empty?

  new(content)
end

Instance Method Details

#onboarded?(path) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/dependabot/github_actions/lockfile/reader.rb', line 56

def onboarded?(path)
  workflows.key?(path)
end

#pins_action?(path, action_ref) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
67
68
# File 'lib/dependabot/github_actions/lockfile/reader.rb', line 64

def pins_action?(path, action_ref)
  return false if action_ref.empty?

  Array(workflows[path]).include?(action_ref)
end

#validate_dependency_entries!Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/dependabot/github_actions/lockfile/reader.rb', line 75

def validate_dependency_entries!
  dependencies.each do |key, entry|
    raise parse_error("dependency entry #{key.inspect} is not a mapping") unless entry.is_a?(Hash)

    missing = REQUIRED_DEPENDENCY_KEYS.reject { |field| entry.key?(field) }
    unless missing.empty?
      raise parse_error(
        "dependency entry #{key.inspect} is missing required field(s) #{missing.join(', ')}; " \
        "gh-actions-lock requires #{REQUIRED_DEPENDENCY_KEYS.join(', ')} on every entry or it " \
        "silently treats the whole lockfile as empty"
      )
    end

    commit = entry["commit"].to_s
    next if ALGO_PREFIXES.any? { |prefix| commit.start_with?(prefix) }

    raise parse_error(
      "dependency entry #{key.inspect} has commit #{commit.inspect} without a hash-algorithm prefix " \
      "(expected one of #{ALGO_PREFIXES.join(', ')})"
    )
  end
end

#versionObject



51
52
53
# File 'lib/dependabot/github_actions/lockfile/reader.rb', line 51

def version
  @data["version"].to_s
end