dependabot-apm 0.400.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.
@@ -0,0 +1,303 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ require "dependabot/git_commit_checker"
7
+ require "dependabot/git_metadata_fetcher"
8
+ require "dependabot/git_tag_details"
9
+ require "dependabot/update_checkers"
10
+ require "dependabot/update_checkers/base"
11
+ require "dependabot/apm/git_commit_checker"
12
+ require "dependabot/apm/requirement"
13
+ require "dependabot/apm/version"
14
+
15
+ module Dependabot
16
+ module Apm
17
+ class UpdateChecker < Dependabot::UpdateCheckers::Base
18
+ extend T::Sig
19
+
20
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
21
+ def latest_version
22
+ @latest_version ||= T.let(
23
+ fetch_latest_version,
24
+ T.nilable(T.any(String, Gem::Version))
25
+ )
26
+ end
27
+
28
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
29
+ def latest_resolvable_version
30
+ # APM dependencies have no resolution graph: each manifest ref is
31
+ # independent, so the latest version is always resolvable.
32
+ latest_version
33
+ end
34
+
35
+ sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
36
+ def latest_resolvable_version_with_no_unlock
37
+ # Updating an APM dependency always rewrites its manifest requirement,
38
+ # so there is no newer version reachable "without unlocking".
39
+ dependency.version
40
+ end
41
+
42
+ # APM packages have no GitHub Advisory Database coverage, so Dependabot
43
+ # never supplies security advisories for them and the security-update flow
44
+ # (gated on `vulnerable?`, which is false without advisories) never runs.
45
+ # We have no visibility into whether APM security updates will be offered
46
+ # in the future; if they are, this needs a real implementation. The base
47
+ # declares it abstract, so it is stubbed to nil to satisfy the contract
48
+ # rather than carrying unreachable resolution logic.
49
+ sig { override.returns(T.nilable(Gem::Version)) }
50
+ def lowest_security_fix_version
51
+ nil
52
+ end
53
+
54
+ sig { override.returns(T.nilable(Gem::Version)) }
55
+ def lowest_resolvable_security_fix_version
56
+ lowest_security_fix_version
57
+ end
58
+
59
+ sig { override.returns(T::Array[Dependabot::DependencyRequirement]) }
60
+ def updated_requirements
61
+ return dependency.requirements unless git_commit_checker.git_dependency?
62
+
63
+ dependency.requirements.map do |req|
64
+ source = req.source_hash
65
+ current_ref = req.source_string("ref")
66
+ # Only rewrite requirements pinned to a semver tag (plain or
67
+ # package-scoped, e.g. `review--v1.0.0`); branch- and SHA-pinned
68
+ # entries are left as-is. Normalise the ref to its SemVer core through
69
+ # the shared APM extractor so scoped tags are recognised and compared.
70
+ ref_version = current_ref && Version.semver_from_ref(current_ref, dependency_name: dependency.name)
71
+ next req unless source && ref_version
72
+
73
+ # DependencySet merges repeated declarations of the same package into a
74
+ # single dependency with several requirements whose refs need not share
75
+ # a tag family (e.g. `review--v1.0.0` and `review-v1.0.0`). Resolve each
76
+ # requirement independently -- within its own family and above its own
77
+ # pinned version -- so a declaration is only ever bumped within its own
78
+ # family, and a higher declaration is never rewritten down to a lower
79
+ # family's tag.
80
+ new_tag = resolved_tag_for_requirement(source, ref_version)&.tag
81
+ next req unless new_tag
82
+
83
+ new_source = source.merge(ref: new_tag)
84
+ Dependabot::DependencyRequirement.create(req.merge(source: new_source))
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ sig { override.returns(T::Boolean) }
91
+ def latest_version_resolvable_with_full_unlock?
92
+ # APM has no concept of a full unlock (no transitive resolution).
93
+ false
94
+ end
95
+
96
+ sig { override.returns(T::Array[Dependabot::Dependency]) }
97
+ def updated_dependencies_after_full_unlock
98
+ raise NotImplementedError
99
+ end
100
+
101
+ # `latest_version` deliberately reports the MAX tag reachable by ANY family
102
+ # so the base `can_update?` gate still fires when only a higher family can
103
+ # move. But `DependencySet` defines a merged dependency's version as its
104
+ # LOWEST pin, and `updated_requirements` can leave families on different
105
+ # tags (e.g. `review-v1.4.0` alongside `review--v1.5.0`). Deriving the
106
+ # resulting version from `preferred_resolvable_version` (the max) would
107
+ # report a `1.5.0` update while the merged dependency is really `1.4.0`,
108
+ # desyncing the reported version (and its update type / PR metadata) from
109
+ # the rewritten requirements. Derive it from the post-update refs with the
110
+ # same lowest-pin rule instead, keeping the update gate and the reported
111
+ # version separate.
112
+ sig { returns(Dependabot::Dependency) }
113
+ def updated_dependency_with_own_req_unlock
114
+ new_requirements = updated_requirements
115
+ new_version = pinned_versions(new_requirements).min
116
+
117
+ Dependabot::Dependency.new(
118
+ name: dependency.name,
119
+ version: new_version || dependency.version,
120
+ requirements: new_requirements,
121
+ previous_version: dependency.version,
122
+ previous_requirements: dependency.requirements,
123
+ package_manager: dependency.package_manager,
124
+ metadata: dependency.metadata,
125
+ subdependency_metadata: dependency.subdependency_metadata
126
+ )
127
+ end
128
+
129
+ sig { returns(T.nilable(T.any(String, Gem::Version))) }
130
+ def fetch_latest_version
131
+ return dependency.version unless git_commit_checker.git_dependency?
132
+
133
+ # Only entries pinned to a semver tag are bumped in the manifest.
134
+ # Branch- and SHA-pinned entries are resolved via the lockfile, which
135
+ # APM regenerates itself, so Dependabot leaves them untouched.
136
+ return dependency.version unless git_commit_checker.pinned_ref_looks_like_version?
137
+
138
+ # A merged dependency can hold several ref families (e.g. `review--v*`
139
+ # and `review-v*`). Report the highest tag reachable by ANY requirement,
140
+ # each resolved within its own family and above its own pinned version,
141
+ # so the base `can_update?` isn't short-circuited when only a non-first
142
+ # family has a newer tag.
143
+ semver_requirement_checkers.filter_map do |ref_version, checker|
144
+ tag_version = latest_version_tag(checker)&.version
145
+ tag_version if tag_version && Version.new(ref_version) < tag_version
146
+ end.max || dependency.version
147
+ end
148
+
149
+ # The tag a single requirement should move to: the latest tag resolved
150
+ # within that requirement's own ref family (via a checker scoped to its
151
+ # ref). Returns nil when there is no strictly-higher tag, so a requirement
152
+ # is never downgraded -- a latest capped by an ignore rule must leave an
153
+ # already-higher declaration untouched.
154
+ sig do
155
+ params(source: Dependabot::DependencyRequirement::ObjectHash, ref_version: String)
156
+ .returns(T.nilable(Dependabot::GitTagDetails))
157
+ end
158
+ def resolved_tag_for_requirement(source, ref_version)
159
+ checker = git_commit_checker_for(source, ref_version)
160
+ return unless checker.pinned_ref_looks_like_version?
161
+
162
+ parsed = Version.new(ref_version)
163
+ tag = latest_version_tag(checker)
164
+ tag_version = tag&.version
165
+ return unless tag_version
166
+ return if parsed >= tag_version
167
+
168
+ tag
169
+ end
170
+
171
+ # Each git-semver-pinned requirement paired with a checker scoped to its
172
+ # own ref (all sharing one remote fetch via shared_git_metadata_fetcher).
173
+ # Drives the cross-family latest-version reporting that gates can_update?,
174
+ # so the gate still fires when only a non-first family has a newer tag.
175
+ sig { returns(T::Array[[String, Dependabot::GitCommitChecker]]) }
176
+ def semver_requirement_checkers
177
+ dependency.requirements.filter_map do |req|
178
+ source = req.source_hash
179
+ current_ref = req.source_string("ref")
180
+ ref_version = current_ref && Version.semver_from_ref(current_ref, dependency_name: dependency.name)
181
+ next unless source && ref_version
182
+
183
+ [ref_version, git_commit_checker_for(source, ref_version)]
184
+ end
185
+ end
186
+
187
+ # The parsed SemVer core of every requirement pinned to a version tag
188
+ # (plain or package-scoped, e.g. `review--v1.0.0`). Branch- and SHA-pinned
189
+ # requirements carry no comparable version and are skipped. Used to derive
190
+ # the merged post-update version (its lowest pin).
191
+ sig { params(requirements: T::Array[Dependabot::DependencyRequirement]).returns(T::Array[Dependabot::Version]) }
192
+ def pinned_versions(requirements)
193
+ requirements.filter_map do |req|
194
+ current_ref = req.source_string("ref")
195
+ ref_version = current_ref && Version.semver_from_ref(current_ref, dependency_name: dependency.name)
196
+ ref_version && Version.new(ref_version)
197
+ end
198
+ end
199
+
200
+ sig { params(checker: Dependabot::GitCommitChecker).returns(T.nilable(Dependabot::GitTagDetails)) }
201
+ def latest_version_tag(checker = git_commit_checker)
202
+ return unless checker.git_dependency?
203
+ return unless checker.pinned_ref_looks_like_version?
204
+
205
+ checker.local_tag_for_latest_version(update_cooldown)
206
+ end
207
+
208
+ sig { returns(Dependabot::GitCommitChecker) }
209
+ def git_commit_checker
210
+ @git_commit_checker ||= T.let(
211
+ Dependabot::Apm::GitCommitChecker.new(
212
+ dependency: dependency,
213
+ credentials: credentials,
214
+ ignored_versions: ignored_versions,
215
+ raise_on_ignored: raise_on_ignored,
216
+ consider_version_branches_pinned: false,
217
+ git_metadata_fetcher: shared_git_metadata_fetcher
218
+ ),
219
+ T.nilable(Dependabot::GitCommitChecker)
220
+ )
221
+ end
222
+
223
+ # A checker scoped to a single requirement's source (its own ref), sharing
224
+ # one remote metadata fetch across every requirement so per-requirement
225
+ # resolution does not re-fetch the upload pack for each declaration. The
226
+ # scoped ref makes the parent's family filtering (`same_prefix?`) select
227
+ # tags in that declaration's own family. When `ref_version` is given the
228
+ # checker's dependency version is scoped to this requirement's own pinned
229
+ # ref, so GitCommitChecker#current_version (and therefore cooldown's
230
+ # SemVer-distance classification) reflects THIS declaration rather than the
231
+ # merged dependency's lowest pin -- e.g. a `v2.1.0` candidate for a `v2.0.0`
232
+ # pin stays a minor bump even when a sibling `v1.4.0` pin lowers the merged
233
+ # version to 1.4.0.
234
+ sig do
235
+ params(
236
+ source: Dependabot::DependencyRequirement::ObjectHash,
237
+ ref_version: T.nilable(String)
238
+ ).returns(Dependabot::GitCommitChecker)
239
+ end
240
+ def git_commit_checker_for(source, ref_version = nil)
241
+ scoped_dependency =
242
+ if ref_version
243
+ Dependabot::Dependency.new(
244
+ name: dependency.name,
245
+ version: ref_version,
246
+ requirements: dependency.requirements,
247
+ package_manager: dependency.package_manager,
248
+ metadata: dependency.metadata,
249
+ subdependency_metadata: dependency.subdependency_metadata
250
+ )
251
+ else
252
+ dependency
253
+ end
254
+
255
+ Dependabot::Apm::GitCommitChecker.new(
256
+ dependency: scoped_dependency,
257
+ credentials: credentials,
258
+ ignored_versions: ignored_versions,
259
+ raise_on_ignored: raise_on_ignored,
260
+ consider_version_branches_pinned: false,
261
+ dependency_source_details: symbolized_source_details(source),
262
+ git_metadata_fetcher: shared_git_metadata_fetcher
263
+ )
264
+ end
265
+
266
+ # One metadata fetcher for the dependency's git remote, shared by the main
267
+ # and per-requirement checkers so the upload pack is fetched once. All
268
+ # requirements of a merged dependency share the same clone URL (differing
269
+ # ports/paths keep them as separate dependencies), so a single fetcher is
270
+ # correct. Nil for non-git dependencies, where no fetch is needed.
271
+ sig { returns(T.nilable(Dependabot::GitMetadataFetcher)) }
272
+ def shared_git_metadata_fetcher
273
+ return @shared_git_metadata_fetcher if defined?(@shared_git_metadata_fetcher)
274
+
275
+ url = dependency.source_string("url", allowed_types: ["git"])
276
+ @shared_git_metadata_fetcher = T.let(
277
+ url && Dependabot::GitMetadataFetcher.new(url: url, credentials: credentials),
278
+ T.nilable(Dependabot::GitMetadataFetcher)
279
+ )
280
+ end
281
+
282
+ # A symbol-keyed source-details hash for GitCommitChecker, holding the git
283
+ # coordinate fields it reads (type/url/ref/branch). Rebuilt explicitly so a
284
+ # requirement's mixed-key source hash conforms to the checker's expected
285
+ # `{Symbol => Object}` shape.
286
+ sig do
287
+ params(source: Dependabot::DependencyRequirement::ObjectHash)
288
+ .returns(T::Hash[Symbol, Object])
289
+ end
290
+ def symbolized_source_details(source)
291
+ details = T.let({}, T::Hash[Symbol, Object])
292
+ %i(type url ref branch).each do |key|
293
+ value = source[key] || source[key.to_s]
294
+ details[key] = value if value.is_a?(String)
295
+ end
296
+ details
297
+ end
298
+ end
299
+ end
300
+ end
301
+
302
+ Dependabot::UpdateCheckers
303
+ .register("apm", Dependabot::Apm::UpdateChecker)
@@ -0,0 +1,228 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ require "dependabot/utils"
7
+ require "dependabot/version"
8
+
9
+ module Dependabot
10
+ module Apm
11
+ # APM pins dependencies to git refs. When that ref is a SemVer 2.0.0 tag
12
+ # (optionally `v`-prefixed, e.g. `v1.2.0`, `1.2.0-alpha.1` or `1.2.0+build.5`)
13
+ # we treat it as the dependency version.
14
+ #
15
+ # The parent class uses RubyGems semantics, which differ from SemVer in ways
16
+ # that matter for git tags, so this subclass enforces SemVer 2.0.0 instead:
17
+ # * validation requires MAJOR.MINOR.PATCH, so partial refs (`v1`, `1.2`) or
18
+ # branch names are never mistaken for versions;
19
+ # * `+build` metadata is accepted and ignored for precedence;
20
+ # * prerelease identifiers follow SemVer precedence (numeric identifiers
21
+ # rank below alphanumeric ones, so `1.0.0-alpha.1 < 1.0.0-alpha.beta` —
22
+ # the opposite of RubyGems, which compares them the other way around).
23
+ class Version < Dependabot::Version
24
+ extend T::Sig
25
+
26
+ # Official SemVer 2.0.0 grammar (https://semver.org), anchored end to end so
27
+ # partial or branch-like refs are rejected.
28
+ SEMVER_REGEX = /
29
+ \A
30
+ (?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)
31
+ (?:-(?<prerelease>
32
+ (?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
33
+ (?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*
34
+ ))?
35
+ (?:\+(?<build>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?
36
+ \z
37
+ /x
38
+
39
+ # The separators APM places between a package name and the SemVer core in
40
+ # package-scoped tags (`{name}_v1.2.3`, `{name}--v1.2.3`, `{name}-v1.2.3`).
41
+ # Each already ends in the `v` that precedes the version, so the remaining
42
+ # suffix is a bare SemVer string. None is a prefix of another for a given
43
+ # name (`foo--v1.2.3` does not start with `foo-v`), so match order is
44
+ # irrelevant.
45
+ SCOPED_TAG_SEPARATORS = %w(_v --v -v).freeze
46
+
47
+ sig { returns(Integer) }
48
+ attr_reader :major
49
+
50
+ sig { returns(Integer) }
51
+ attr_reader :minor
52
+
53
+ sig { returns(Integer) }
54
+ attr_reader :patch
55
+
56
+ sig { returns(T.nilable(String)) }
57
+ attr_reader :prerelease_info
58
+
59
+ sig { returns(T.nilable(String)) }
60
+ attr_reader :build_info
61
+
62
+ sig { override.params(version: VersionParameter).void }
63
+ def initialize(version)
64
+ normalized = Version.remove_leading_v(version).to_s
65
+ match = normalized.match(SEMVER_REGEX)
66
+ raise ArgumentError, "Malformed version string - #{version}" unless match
67
+
68
+ @version_string = T.let(normalized, String)
69
+ @major = T.let(T.must(match[:major]).to_i, Integer)
70
+ @minor = T.let(T.must(match[:minor]).to_i, Integer)
71
+ @patch = T.let(T.must(match[:patch]).to_i, Integer)
72
+ @prerelease_info = T.let(match[:prerelease], T.nilable(String))
73
+ @build_info = T.let(match[:build], T.nilable(String))
74
+
75
+ # Hand RubyGems the release (plus any prerelease) without the build
76
+ # metadata, which is not part of precedence, so requirement matching and
77
+ # the inherited helpers keep working.
78
+ super(T.must(normalized.split("+").first))
79
+ end
80
+
81
+ sig { override.params(version: VersionParameter).returns(Dependabot::Apm::Version) }
82
+ def self.new(version)
83
+ T.cast(super, Dependabot::Apm::Version)
84
+ end
85
+
86
+ sig { params(version: VersionParameter).returns(VersionParameter) }
87
+ def self.remove_leading_v(version)
88
+ return version unless version.to_s.match?(/\Av\d/)
89
+
90
+ version.to_s.delete_prefix("v")
91
+ end
92
+
93
+ sig { override.params(version: VersionParameter).returns(T::Boolean) }
94
+ def self.correct?(version)
95
+ return false if version.to_s.strip.empty?
96
+
97
+ Version.remove_leading_v(version).to_s.match?(SEMVER_REGEX)
98
+ end
99
+
100
+ # Extracts the SemVer core from a git ref for the package `dependency_name`,
101
+ # or nil when the ref is not a version tag for that package. A plain
102
+ # `v?<semver>` ref keeps any build metadata; a package-scoped ref
103
+ # (`{name}_v…`, `{name}--v…`, `{name}-v…`) is accepted only when `{name}`
104
+ # matches the package's own name -- the final `/`-separated segment of
105
+ # `dependency_name`, since a virtual package `org/mono/skills/review` is
106
+ # released as `review--v1.2.3`. Scoping to that name keeps a monorepo's
107
+ # `security--v2.0.0` from resolving against a `review` dependency. This is
108
+ # the single reader of APM's tag grammar, shared by the git commit checker,
109
+ # the file parser and the update checker so ref handling never diverges.
110
+ sig { params(ref: String, dependency_name: String).returns(T.nilable(String)) }
111
+ def self.semver_from_ref(ref, dependency_name:)
112
+ return remove_leading_v(ref).to_s if correct?(ref)
113
+
114
+ name = dependency_name.split("/").last.to_s
115
+ return nil if name.empty?
116
+
117
+ SCOPED_TAG_SEPARATORS.each do |separator|
118
+ prefix = "#{name}#{separator}"
119
+ next unless ref.start_with?(prefix)
120
+
121
+ candidate = ref[prefix.length..].to_s
122
+ return candidate if candidate.match?(SEMVER_REGEX)
123
+ end
124
+
125
+ nil
126
+ end
127
+
128
+ sig { override.returns(String) }
129
+ def to_s
130
+ @version_string
131
+ end
132
+
133
+ sig { override.returns(String) }
134
+ def inspect
135
+ "#<#{self.class} #{@version_string}>"
136
+ end
137
+
138
+ # `Gem::Requirement` evaluates a `~> x.y.z` bound by comparing candidates
139
+ # against this operand's `bump`. The inherited `Gem::Version#bump` drops
140
+ # the last segment (`1.2.3` -> `1.3`) and rebuilds `self.class` from it,
141
+ # but `Apm::Version` rejects that partial value and raises while filtering
142
+ # tags. Return the SemVer upper bound (`x.(y+1).0`) instead, so a
143
+ # pessimistic ignore rule such as `~> 1.2.3` evaluates as
144
+ # `>= 1.2.3, < 1.3.0` rather than crashing.
145
+ sig { returns(Dependabot::Apm::Version) }
146
+ def bump
147
+ Version.new("#{major}.#{minor + 1}.0")
148
+ end
149
+
150
+ sig { params(other: Object).returns(T.nilable(Integer)) }
151
+ def <=>(other)
152
+ other_version = Version.coerce(other)
153
+ return super unless other_version
154
+
155
+ release = compare_release(other_version)
156
+ return release unless release.zero?
157
+
158
+ Version.compare_prerelease(prerelease_info, other_version.prerelease_info)
159
+ end
160
+
161
+ # Compares the MAJOR.MINOR.PATCH triples numerically.
162
+ sig { params(other: Dependabot::Apm::Version).returns(Integer) }
163
+ def compare_release(other)
164
+ [[major, other.major], [minor, other.minor], [patch, other.patch]].each do |mine, theirs|
165
+ comparison = mine <=> theirs
166
+ return comparison unless comparison.zero?
167
+ end
168
+
169
+ 0
170
+ end
171
+
172
+ # Coerces a comparison operand into an Apm::Version when it is a strict
173
+ # SemVer value, or nil when it is not (so `<=>` can fall back to RubyGems
174
+ # semantics for e.g. a bare `Gem::Version` requirement bound).
175
+ sig { params(other: Object).returns(T.nilable(Dependabot::Apm::Version)) }
176
+ def self.coerce(other)
177
+ return other if other.is_a?(Dependabot::Apm::Version)
178
+ return unless other.is_a?(String) || other.is_a?(Gem::Version)
179
+ return unless correct?(other.to_s)
180
+
181
+ new(other.to_s)
182
+ end
183
+
184
+ # SemVer prerelease precedence (spec rule 11): a version WITH a prerelease
185
+ # ranks below the same version without one, and equal releases are ordered
186
+ # by their prerelease identifiers.
187
+ sig { params(left: T.nilable(String), right: T.nilable(String)).returns(Integer) }
188
+ def self.compare_prerelease(left, right)
189
+ return 0 if left == right
190
+ return 1 if left.nil? # a normal version outranks any prerelease
191
+ return -1 if right.nil?
192
+
193
+ compare_prerelease_identifiers(left.split("."), right.split("."))
194
+ end
195
+
196
+ # Compares dot-separated prerelease identifiers left to right; a longer set
197
+ # of identifiers wins when the shorter one is a prefix of it.
198
+ sig { params(left: T::Array[String], right: T::Array[String]).returns(Integer) }
199
+ def self.compare_prerelease_identifiers(left, right)
200
+ left.zip(right).each do |l, r|
201
+ return 1 if r.nil? # left carries an extra identifier
202
+
203
+ comparison = compare_identifier(l, r)
204
+ return comparison unless comparison.zero?
205
+ end
206
+
207
+ left.length <=> right.length
208
+ end
209
+
210
+ # A single prerelease identifier: numeric identifiers compare numerically
211
+ # and always rank below alphanumeric ones, which compare lexically (ASCII).
212
+ sig { params(left: String, right: String).returns(Integer) }
213
+ def self.compare_identifier(left, right)
214
+ left_numeric = left.match?(/\A\d+\z/)
215
+ right_numeric = right.match?(/\A\d+\z/)
216
+
217
+ return left.to_i <=> right.to_i if left_numeric && right_numeric
218
+ return -1 if left_numeric
219
+ return 1 if right_numeric
220
+
221
+ T.must(left <=> right)
222
+ end
223
+ end
224
+ end
225
+ end
226
+
227
+ Dependabot::Utils
228
+ .register_version_class("apm", Dependabot::Apm::Version)
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # These all need to be required so the various classes can be registered in a
5
+ # lookup table of package manager names to concrete classes.
6
+ require "dependabot/apm/file_fetcher"
7
+ require "dependabot/apm/file_parser"
8
+ require "dependabot/apm/update_checker"
9
+ require "dependabot/apm/file_updater"
10
+ require "dependabot/apm/metadata_finder"
11
+ require "dependabot/apm/requirement"
12
+ require "dependabot/apm/version"
13
+
14
+ require "dependabot/pull_request_creator/labeler"
15
+ Dependabot::PullRequestCreator::Labeler
16
+ .register_label_details("apm", name: "apm", colour: "0e8a16")
17
+
18
+ require "dependabot/dependency"
19
+ Dependabot::Dependency
20
+ .register_production_check(
21
+ "apm",
22
+ # Production when the explicit "dependencies" marker is present (or when a
23
+ # dependency carries no group information at all). Presence-based rather than
24
+ # "not development", so a package merged from both `dependencies.apm` and
25
+ # `devDependencies.apm` -- whose flattened groups include both markers --
26
+ # stays production, while a `devDependencies`-only entry does not.
27
+ ->(groups) { groups.empty? || groups.include?("dependencies") }
28
+ )