dependabot-devbox 0.1.1 → 0.2.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 +4 -4
- data/exe/dependabot-devbox-update +14 -76
- data/lib/dependabot/devbox/file_fetcher.rb +2 -2
- data/lib/dependabot/devbox/file_parser.rb +5 -5
- data/lib/dependabot/devbox/file_updater.rb +3 -3
- data/lib/dependabot/devbox/helpers.rb +2 -5
- data/lib/dependabot/devbox/metadata_finder.rb +1 -1
- data/lib/dependabot/devbox/package/package_details_fetcher.rb +1 -1
- data/lib/dependabot/devbox/update_checker.rb +1 -1
- data/lib/dependabot/devbox/update_runner.rb +121 -0
- data/lib/dependabot/devbox/version.rb +1 -1
- data/lib/dependabot/devbox.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35d218d66727572ab52df9c11c35b6869478d549cd15c5d9042833d0e94a7aad
|
|
4
|
+
data.tar.gz: 262ca126fac5c3083505dc7afd6ef41a285d9b0a2444e635ebbbe8d6acd95d2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0baa0a5ecfcc39ff64e8e5d546ca570349040f7087db824870f756e50812755d10c8504c35f5666e548c7a0e097b725196d435de65cf10f6f008ed5987d0cd73
|
|
7
|
+
data.tar.gz: 3e056cf0ae29dc2385a63947e2df367901b5aa26f98cb356d4a77310001c00541c79556d9054612cc69929be0cd81b3bf87e0b61eeda9fecf6e2501dbdc19d4e
|
|
@@ -7,12 +7,14 @@ require "dependabot/update_checkers"
|
|
|
7
7
|
require "dependabot/file_updaters"
|
|
8
8
|
require "dependabot/pull_request_creator"
|
|
9
9
|
require "dependabot/devbox"
|
|
10
|
+
require "dependabot/devbox/update_runner"
|
|
10
11
|
|
|
11
12
|
repo = ENV.fetch("GITHUB_REPOSITORY")
|
|
12
13
|
token = ENV["GITHUB_ACCESS_TOKEN"] || ENV.fetch("GITHUB_TOKEN")
|
|
13
14
|
directory = ENV.fetch("DIRECTORY_PATH", "/")
|
|
14
|
-
branch = ENV["BASE_BRANCH"].then { |b| b
|
|
15
|
+
branch = ENV["BASE_BRANCH"].then { |b| b.nil? || b.empty? ? nil : b }
|
|
15
16
|
group = ENV.fetch("GROUP_UPDATES", "false") == "true"
|
|
17
|
+
cooldown = Dependabot::Devbox::UpdateRunner.build_cooldown(ENV.fetch("COOLDOWN_DAYS", "0").to_i)
|
|
16
18
|
|
|
17
19
|
credentials = [
|
|
18
20
|
{
|
|
@@ -50,93 +52,29 @@ parser = Dependabot::FileParsers.for_package_manager("devbox").new(
|
|
|
50
52
|
dependencies = parser.parse
|
|
51
53
|
puts "Found #{dependencies.length} devbox package(s)"
|
|
52
54
|
|
|
53
|
-
def check_dep(dep, files, credentials)
|
|
54
|
-
puts "Checking #{dep.name} (#{dep.version})..."
|
|
55
|
-
|
|
56
|
-
checker = Dependabot::UpdateCheckers.for_package_manager("devbox").new(
|
|
57
|
-
dependency: dep,
|
|
58
|
-
dependency_files: files,
|
|
59
|
-
credentials: credentials
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
return nil if checker.up_to_date? && puts(" up to date")
|
|
63
|
-
|
|
64
|
-
requirements_to_unlock = checker.requirements_unlocked_or_can_be? ? :own : :none
|
|
65
|
-
|
|
66
|
-
begin
|
|
67
|
-
checker.updated_dependencies(requirements_to_unlock: requirements_to_unlock)
|
|
68
|
-
rescue Dependabot::AllVersionsIgnored
|
|
69
|
-
puts " all versions ignored"
|
|
70
|
-
nil
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
55
|
if group
|
|
75
|
-
all_updated_deps = dependencies.filter_map
|
|
56
|
+
all_updated_deps = dependencies.filter_map do |dep|
|
|
57
|
+
Dependabot::Devbox::UpdateRunner.check_dependency(dep, files, credentials, cooldown)
|
|
58
|
+
end.flatten
|
|
76
59
|
|
|
77
60
|
if all_updated_deps.empty?
|
|
78
61
|
puts "All packages up to date."
|
|
79
62
|
else
|
|
80
|
-
|
|
81
|
-
dependencies: all_updated_deps,
|
|
82
|
-
dependency_files: files,
|
|
83
|
-
credentials: credentials
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
updated_files = updater.updated_dependency_files
|
|
63
|
+
majors, rest = Dependabot::Devbox::UpdateRunner.partition_majors(all_updated_deps)
|
|
87
64
|
|
|
88
|
-
|
|
89
|
-
source: source,
|
|
90
|
-
base_commit: commit,
|
|
91
|
-
dependencies: all_updated_deps,
|
|
92
|
-
files: updated_files,
|
|
93
|
-
credentials: credentials,
|
|
94
|
-
label_language: true
|
|
95
|
-
)
|
|
65
|
+
Dependabot::Devbox::UpdateRunner.open_pr(source, commit, rest, files, credentials) unless rest.empty?
|
|
96
66
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
puts "PR created: #{pr.html_url}"
|
|
101
|
-
else
|
|
102
|
-
puts "PR already exists or no changes needed"
|
|
103
|
-
end
|
|
104
|
-
rescue Dependabot::PullRequestCreator::UnmergedPRExists => e
|
|
105
|
-
puts "Skipping: #{e.message} (closed but not merged — delete the branch to recreate)"
|
|
67
|
+
majors.each do |dep|
|
|
68
|
+
puts "Opening individual PR for major bump: #{dep.name}"
|
|
69
|
+
Dependabot::Devbox::UpdateRunner.open_pr(source, commit, [dep], files, credentials, indent: " ")
|
|
106
70
|
end
|
|
107
71
|
end
|
|
108
72
|
else
|
|
109
|
-
dependencies.each do |dep|
|
|
110
|
-
updated_deps =
|
|
73
|
+
dependencies.each do |dep|
|
|
74
|
+
updated_deps = Dependabot::Devbox::UpdateRunner.check_dependency(dep, files, credentials, cooldown)
|
|
111
75
|
next unless updated_deps
|
|
112
76
|
|
|
113
|
-
|
|
114
|
-
dependencies: updated_deps,
|
|
115
|
-
dependency_files: files,
|
|
116
|
-
credentials: credentials
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
updated_files = updater.updated_dependency_files
|
|
120
|
-
|
|
121
|
-
pr_creator = Dependabot::PullRequestCreator.new(
|
|
122
|
-
source: source,
|
|
123
|
-
base_commit: commit,
|
|
124
|
-
dependencies: updated_deps,
|
|
125
|
-
files: updated_files,
|
|
126
|
-
credentials: credentials,
|
|
127
|
-
label_language: true
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
begin
|
|
131
|
-
pr = pr_creator.create
|
|
132
|
-
if pr
|
|
133
|
-
puts " PR created: #{pr.html_url}"
|
|
134
|
-
else
|
|
135
|
-
puts " PR already exists or no changes needed"
|
|
136
|
-
end
|
|
137
|
-
rescue Dependabot::PullRequestCreator::UnmergedPRExists => e
|
|
138
|
-
puts " Skipping: #{e.message} (closed but not merged — delete the branch to recreate)"
|
|
139
|
-
end
|
|
77
|
+
Dependabot::Devbox::UpdateRunner.open_pr(source, commit, updated_deps, files, credentials, indent: " ")
|
|
140
78
|
end
|
|
141
79
|
end
|
|
142
80
|
|
|
@@ -9,8 +9,8 @@ module Dependabot
|
|
|
9
9
|
class FileFetcher < Dependabot::FileFetchers::Base
|
|
10
10
|
extend T::Sig
|
|
11
11
|
|
|
12
|
-
MANIFEST_FILENAME =
|
|
13
|
-
LOCKFILE_FILENAME =
|
|
12
|
+
MANIFEST_FILENAME = "devbox.json"
|
|
13
|
+
LOCKFILE_FILENAME = "devbox.lock"
|
|
14
14
|
|
|
15
15
|
sig { override.returns(String) }
|
|
16
16
|
def self.required_files_message
|
|
@@ -13,12 +13,12 @@ module Dependabot
|
|
|
13
13
|
class FileParser < Dependabot::FileParsers::Base
|
|
14
14
|
extend T::Sig
|
|
15
15
|
|
|
16
|
-
ECOSYSTEM =
|
|
17
|
-
MANIFEST_FILENAME =
|
|
18
|
-
LOCKFILE_FILENAME =
|
|
16
|
+
ECOSYSTEM = "devbox"
|
|
17
|
+
MANIFEST_FILENAME = "devbox.json"
|
|
18
|
+
LOCKFILE_FILENAME = "devbox.lock"
|
|
19
19
|
# An entry without an "@constraint" suffix tracks the newest release.
|
|
20
|
-
DEFAULT_CONSTRAINT =
|
|
21
|
-
SOURCE_TYPE =
|
|
20
|
+
DEFAULT_CONSTRAINT = "latest"
|
|
21
|
+
SOURCE_TYPE = "nixhub"
|
|
22
22
|
|
|
23
23
|
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
|
24
24
|
def parse
|
|
@@ -14,9 +14,9 @@ module Dependabot
|
|
|
14
14
|
class FileUpdater < Dependabot::FileUpdaters::Base
|
|
15
15
|
extend T::Sig
|
|
16
16
|
|
|
17
|
-
MANIFEST_FILENAME =
|
|
18
|
-
LOCKFILE_FILENAME =
|
|
19
|
-
LATEST =
|
|
17
|
+
MANIFEST_FILENAME = "devbox.json"
|
|
18
|
+
LOCKFILE_FILENAME = "devbox.lock"
|
|
19
|
+
LATEST = "latest"
|
|
20
20
|
|
|
21
21
|
sig { override.returns(T::Array[Dependabot::DependencyFile]) }
|
|
22
22
|
def updated_dependency_files
|
|
@@ -15,15 +15,12 @@ module Dependabot
|
|
|
15
15
|
# block comment, or a trailing comma. The alternation lets gsub preserve
|
|
16
16
|
# strings while stripping the JSONC-only constructs, so e.g. "//" inside a
|
|
17
17
|
# URL value is not mistaken for the start of a comment.
|
|
18
|
-
JSONC_TOKEN =
|
|
19
|
-
%r{
|
|
18
|
+
JSONC_TOKEN = %r{
|
|
20
19
|
("(?:\\.|[^"\\])*") # JSON string literal
|
|
21
20
|
| //[^\n]* # line comment
|
|
22
21
|
| /\*.*?\*/ # block comment
|
|
23
22
|
| ,(?=\s*[\}\]]) # trailing comma
|
|
24
|
-
}mx
|
|
25
|
-
Regexp
|
|
26
|
-
)
|
|
23
|
+
}mx
|
|
27
24
|
|
|
28
25
|
sig { params(content: T.nilable(String)).returns(T::Hash[String, Object]) }
|
|
29
26
|
def self.parse_json_or_jsonc(content)
|
|
@@ -15,7 +15,7 @@ module Dependabot
|
|
|
15
15
|
class PackageDetailsFetcher
|
|
16
16
|
extend T::Sig
|
|
17
17
|
|
|
18
|
-
SEARCH_URL =
|
|
18
|
+
SEARCH_URL = "https://search.devbox.sh/v1/search"
|
|
19
19
|
|
|
20
20
|
sig { params(dependency: Dependabot::Dependency).void }
|
|
21
21
|
def initialize(dependency:)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/dependency"
|
|
6
|
+
require "dependabot/update_checkers"
|
|
7
|
+
require "dependabot/file_updaters"
|
|
8
|
+
require "dependabot/pull_request_creator"
|
|
9
|
+
require "dependabot/package/release_cooldown_options"
|
|
10
|
+
|
|
11
|
+
module Dependabot
|
|
12
|
+
module Devbox
|
|
13
|
+
# Extracted from exe/dependabot-devbox-update so its per-dependency and
|
|
14
|
+
# per-PR logic can be unit tested without loading the executable itself
|
|
15
|
+
# (which RubyGems' bin stub runs via Kernel#load, under which the
|
|
16
|
+
# conventional `$PROGRAM_NAME == __FILE__` require-guard never matches).
|
|
17
|
+
module UpdateRunner
|
|
18
|
+
extend T::Sig
|
|
19
|
+
|
|
20
|
+
sig { params(days: Integer).returns(T.nilable(Dependabot::Package::ReleaseCooldownOptions)) }
|
|
21
|
+
def self.build_cooldown(days)
|
|
22
|
+
return nil unless days.positive?
|
|
23
|
+
|
|
24
|
+
Dependabot::Package::ReleaseCooldownOptions.new(default_days: days)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Classifies by comparing the major segment of the previous and new
|
|
28
|
+
# version strings, so it works for both semver ("24.11.1" -> "26.4.0")
|
|
29
|
+
# and nixpkgs' shorter version strings ("0.99.4" -> "1.0.4").
|
|
30
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
|
31
|
+
def self.major_bump?(dependency)
|
|
32
|
+
previous = dependency.previous_version
|
|
33
|
+
current = dependency.version
|
|
34
|
+
return false unless previous && current
|
|
35
|
+
|
|
36
|
+
previous.to_s.split(".").first != current.to_s.split(".").first
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
sig do
|
|
40
|
+
params(dependencies: T::Array[Dependabot::Dependency])
|
|
41
|
+
.returns([T::Array[Dependabot::Dependency], T::Array[Dependabot::Dependency]])
|
|
42
|
+
end
|
|
43
|
+
def self.partition_majors(dependencies)
|
|
44
|
+
dependencies.partition { |dep| major_bump?(dep) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
sig do
|
|
48
|
+
params(
|
|
49
|
+
dependency: Dependabot::Dependency,
|
|
50
|
+
files: T::Array[Dependabot::DependencyFile],
|
|
51
|
+
credentials: T::Array[T.untyped],
|
|
52
|
+
cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
|
|
53
|
+
).returns(T.nilable(T::Array[Dependabot::Dependency]))
|
|
54
|
+
end
|
|
55
|
+
def self.check_dependency(dependency, files, credentials, cooldown)
|
|
56
|
+
puts "Checking #{dependency.name} (#{dependency.version})..."
|
|
57
|
+
|
|
58
|
+
checker = Dependabot::UpdateCheckers.for_package_manager("devbox").new(
|
|
59
|
+
dependency: dependency,
|
|
60
|
+
dependency_files: files,
|
|
61
|
+
credentials: credentials,
|
|
62
|
+
update_cooldown: cooldown
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if checker.up_to_date?
|
|
66
|
+
puts " up to date"
|
|
67
|
+
return nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
requirements_to_unlock = checker.requirements_unlocked_or_can_be? ? :own : :none
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
checker.updated_dependencies(requirements_to_unlock: requirements_to_unlock)
|
|
74
|
+
rescue Dependabot::AllVersionsIgnored
|
|
75
|
+
puts " all versions ignored"
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
sig do
|
|
81
|
+
params(
|
|
82
|
+
source: T.untyped,
|
|
83
|
+
commit: String,
|
|
84
|
+
dependencies: T::Array[Dependabot::Dependency],
|
|
85
|
+
files: T::Array[Dependabot::DependencyFile],
|
|
86
|
+
credentials: T::Array[T.untyped],
|
|
87
|
+
indent: String
|
|
88
|
+
).void
|
|
89
|
+
end
|
|
90
|
+
def self.open_pr(source, commit, dependencies, files, credentials, indent: "")
|
|
91
|
+
updater = Dependabot::FileUpdaters.for_package_manager("devbox").new(
|
|
92
|
+
dependencies: dependencies,
|
|
93
|
+
dependency_files: files,
|
|
94
|
+
credentials: credentials
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
updated_files = updater.updated_dependency_files
|
|
98
|
+
|
|
99
|
+
pr_creator = Dependabot::PullRequestCreator.new(
|
|
100
|
+
source: source,
|
|
101
|
+
base_commit: commit,
|
|
102
|
+
dependencies: dependencies,
|
|
103
|
+
files: updated_files,
|
|
104
|
+
credentials: credentials,
|
|
105
|
+
label_language: true
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
pr = pr_creator.create
|
|
109
|
+
if pr
|
|
110
|
+
puts "#{indent}PR created: #{pr.html_url}"
|
|
111
|
+
else
|
|
112
|
+
puts "#{indent}PR already exists or no changes needed"
|
|
113
|
+
end
|
|
114
|
+
rescue Dependabot::PullRequestCreator::UnmergedPRExists => e
|
|
115
|
+
puts "#{indent}Skipping: #{e.message} (closed but not merged — delete the branch to recreate)"
|
|
116
|
+
rescue Dependabot::PullRequestCreator::BranchAlreadyExists => e
|
|
117
|
+
puts "#{indent}Skipping: #{e.message} (stale branch with no open PR — delete it to retry)"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -20,7 +20,7 @@ module Dependabot
|
|
|
20
20
|
# A value that sorts above any realistic nixpkgs version, used as the
|
|
21
21
|
# internal representation of the "latest" sentinel since Gem::Version
|
|
22
22
|
# cannot parse the word itself.
|
|
23
|
-
LATEST_SENTINEL =
|
|
23
|
+
LATEST_SENTINEL = "999999"
|
|
24
24
|
|
|
25
25
|
sig { override.params(version: VersionParameter).returns(T::Boolean) }
|
|
26
26
|
def self.correct?(version)
|
data/lib/dependabot/devbox.rb
CHANGED
|
@@ -32,6 +32,7 @@ require "dependabot/devbox/package/package_details_fetcher"
|
|
|
32
32
|
require "dependabot/devbox/helpers"
|
|
33
33
|
require "dependabot/devbox/version"
|
|
34
34
|
require "dependabot/devbox/requirement"
|
|
35
|
+
require "dependabot/devbox/update_runner"
|
|
35
36
|
|
|
36
37
|
require "dependabot/pull_request_creator/labeler"
|
|
37
38
|
Dependabot::PullRequestCreator::Labeler
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-devbox
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andoni A.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dependabot-common
|
|
@@ -44,6 +44,7 @@ files:
|
|
|
44
44
|
- lib/dependabot/devbox/requirement.rb
|
|
45
45
|
- lib/dependabot/devbox/update_checker.rb
|
|
46
46
|
- lib/dependabot/devbox/update_checker/latest_version_finder.rb
|
|
47
|
+
- lib/dependabot/devbox/update_runner.rb
|
|
47
48
|
- lib/dependabot/devbox/version.rb
|
|
48
49
|
homepage: https://github.com/andoniaf/dependabot-devbox
|
|
49
50
|
licenses:
|