dependabot-nix 0.373.0 → 0.375.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53b61523c3b571914ab9f84f386c8ab456efb4f93db7681a1721811daa723003
4
- data.tar.gz: 99a851d470ab8258b980f08ac553546864d7e7d5a68375ee6d6793553f923b25
3
+ metadata.gz: fe9c75a30d41c44bb089dd18e28434137aaf7fce44c245ce8c264fffca4b4e58
4
+ data.tar.gz: 61b4d00c58b904848439a8d9e323bc3707518783e9319d6ea6843a0fac738b54
5
5
  SHA512:
6
- metadata.gz: b560b5794a2aedca3c16c62f47f14f56255d8cf64dcce450b4d01f3783adb304ad632597bccf2dc5bed7af77aa718f3fed0bd5bda8adcdaca24d103498afc27f
7
- data.tar.gz: 4c09eb9971fd0c5dc5d2b80185c41ba784edbd219bad03a3b51e4f99d2bfcdfb04261a43303f12dd7ebb392c8a2797b58112d304a5850edd9abd2c355c50e4e9
6
+ metadata.gz: 8e0054563b1d303456fdf277cc3b0e39fb86c2d8dde54f3dadc9719007686718cd91c18654836f946a47e69f13af28a65300b55620242f3dffb7d85c9d85fb4c
7
+ data.tar.gz: aef6100cb0225988b52c87dfdccaae3d507231af2b44518e96fbb3ddcc78899a7fb604ff21dcb23ba19331f7402284fb9847506171e1b28c9294979361538774
@@ -3,12 +3,14 @@
3
3
 
4
4
  require "json"
5
5
  require "time"
6
+ require "uri"
6
7
  require "sorbet-runtime"
7
8
  require "dependabot/nix"
8
9
  require "dependabot/package/package_release"
9
10
  require "dependabot/package/package_details"
10
11
  require "dependabot/git_commit_checker"
11
12
  require "dependabot/git_metadata_fetcher"
13
+ require "dependabot/clients/github_with_retries"
12
14
 
13
15
  module Dependabot
14
16
  module Nix
@@ -35,7 +37,7 @@ module Dependabot
35
37
 
36
38
  sig { returns(T.nilable(T::Array[Dependabot::Package::PackageRelease])) }
37
39
  def available_versions
38
- versions_metadata = fetch_tags_and_release_date
40
+ versions_metadata = fetch_branch_tip_history || fetch_tags_and_release_date
39
41
 
40
42
  versions_metadata = fetch_latest_tag_info if versions_metadata.empty?
41
43
 
@@ -62,7 +64,125 @@ module Dependabot
62
64
  private
63
65
 
64
66
  TARGET_COMMITS_TO_FETCH = 500
65
- private_constant :TARGET_COMMITS_TO_FETCH
67
+ ACTIVITY_TYPES = "push,force_push"
68
+ SHA_REGEX = /\A[0-9a-f]{40}\z/
69
+ # Heuristic for refs that look like a tag/version rather than a branch
70
+ # (e.g. `v1.2.3`, `1.2`, `2024.01`). Branch names like `nixos-25.05`
71
+ # don't match because they don't start with a digit or `v<digit>`.
72
+ TAG_LIKE_REF_REGEX = /\Av?\d+\./
73
+ private_constant :TARGET_COMMITS_TO_FETCH, :ACTIVITY_TYPES, :SHA_REGEX, :TAG_LIKE_REF_REGEX
74
+
75
+ # Fetch branch-tip history via GitHub's Repo Activity API. Each entry's
76
+ # `after` SHA was once the actual branch tip — for `nixpkgs` channels
77
+ # that means it was Hydra-evaluated and is cache-backed. The /commits
78
+ # endpoint, by contrast, returns intermediate commits that were never
79
+ # branch tips and may not be cached.
80
+ #
81
+ # Returns nil when the activity API isn't usable (non-GitHub host,
82
+ # SHA-pinned ref, missing ref, HTTP error). Callers should fall back to
83
+ # the existing /commits walker in that case.
84
+ sig { returns(T.nilable(T::Array[T::Hash[Symbol, T.untyped]])) }
85
+ def fetch_branch_tip_history
86
+ url = source_url
87
+ ref = branch_ref
88
+ return nil unless use_activity_api?(url, ref)
89
+
90
+ Dependabot.logger.info("Fetching branch-tip history for Nix flake input: #{dependency.name}")
91
+ entries = fetch_activity_entries(T.must(url), T.must(ref))
92
+ return nil unless entries.is_a?(Array) && entries.any?
93
+
94
+ trim_entries_to_locked_sha(entries)
95
+ rescue Octokit::Error => e
96
+ Dependabot.logger.info(
97
+ "Repo Activity API failed for #{dependency.name} (#{e.class}: #{e.message}), " \
98
+ "falling back to commits API"
99
+ )
100
+ nil
101
+ rescue StandardError => e
102
+ Dependabot.logger.error(
103
+ "Error fetching branch-tip history for #{dependency.name} " \
104
+ "(#{e.class}: #{e.message})"
105
+ )
106
+ nil
107
+ end
108
+
109
+ sig { params(url: String, ref: String).returns(T.untyped) }
110
+ def fetch_activity_entries(url, ref)
111
+ T.unsafe(github_client).get( # rubocop:disable Sorbet/ForbidTUnsafe
112
+ "/repos/#{github_repo_path(url)}/activity",
113
+ ref: "refs/heads/#{ref}",
114
+ activity_type: ACTIVITY_TYPES,
115
+ per_page: 100
116
+ )
117
+ end
118
+
119
+ # Trim to entries up to and including the currently locked SHA, stopping
120
+ # once that SHA is reached so we don't introduce candidates older than
121
+ # `dependency.version`.
122
+ sig { params(entries: T::Array[T.untyped]).returns(T::Array[T::Hash[Symbol, T.untyped]]) }
123
+ def trim_entries_to_locked_sha(entries)
124
+ locked = dependency.version
125
+ result = T.let([], T::Array[T::Hash[Symbol, T.untyped]])
126
+ entries.each do |e|
127
+ after_sha = e[:after]
128
+ result << { tag: after_sha, release_date: format_timestamp(e[:timestamp]) }
129
+
130
+ next unless locked
131
+ break if after_sha == locked
132
+
133
+ if e[:before] == locked
134
+ result << { tag: locked, release_date: nil } unless result.last&.fetch(:tag) == locked
135
+ break
136
+ end
137
+ end
138
+ result
139
+ end
140
+
141
+ sig { params(timestamp: T.untyped).returns(T.nilable(String)) }
142
+ def format_timestamp(timestamp)
143
+ return nil if timestamp.nil?
144
+ return timestamp.iso8601 if timestamp.respond_to?(:iso8601)
145
+
146
+ timestamp.to_s
147
+ end
148
+
149
+ sig { params(url: T.nilable(String), ref: T.nilable(String)).returns(T::Boolean) }
150
+ def use_activity_api?(url, ref)
151
+ return false unless url && ref
152
+ return false if ref.match?(SHA_REGEX)
153
+ return false if ref.match?(TAG_LIKE_REF_REGEX)
154
+
155
+ host = URI.parse(url).host
156
+ host == "github.com"
157
+ rescue URI::InvalidURIError
158
+ false
159
+ end
160
+
161
+ sig { params(url: String).returns(String) }
162
+ def github_repo_path(url)
163
+ T.must(URI.parse(url).path)
164
+ .delete_prefix("/")
165
+ .delete_suffix("/")
166
+ .delete_suffix(".git")
167
+ end
168
+
169
+ sig { returns(T.nilable(String)) }
170
+ def source_url
171
+ dependency.source_details(allowed_types: ["git"])&.fetch(:url, nil)
172
+ end
173
+
174
+ sig { returns(T.nilable(String)) }
175
+ def branch_ref
176
+ dependency.source_details(allowed_types: ["git"])&.fetch(:ref, nil)
177
+ end
178
+
179
+ sig { returns(Dependabot::Clients::GithubWithRetries) }
180
+ def github_client
181
+ @github_client ||= T.let(
182
+ Dependabot::Clients::GithubWithRetries.for_github_dot_com(credentials: credentials),
183
+ T.nilable(Dependabot::Clients::GithubWithRetries)
184
+ )
185
+ end
66
186
 
67
187
  sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
68
188
  def fetch_latest_tag_info
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-nix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.373.0
4
+ version: 0.375.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.373.0
18
+ version: 0.375.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.373.0
25
+ version: 0.375.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -259,7 +259,7 @@ licenses:
259
259
  - MIT
260
260
  metadata:
261
261
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
262
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.373.0
262
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.375.0
263
263
  rdoc_options: []
264
264
  require_paths:
265
265
  - lib