rake-gem-maintenance 0.1.6 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6dc9985cb348ee5f79a3170eb6ef534b5fe8bc1aad6361be15178f883ba22767
4
- data.tar.gz: e819c2d3f58a936c59fb8caf620f84e92dc68bf59cee8f592bb852c03d02de62
3
+ metadata.gz: 1025716123e134ab6db2ffcfc5655a59208dd038691b73e270c92c6bd35ea977
4
+ data.tar.gz: 1445566f68985cdd2b915c9958ec9daddaf07caa5002c62277481b72a122d561
5
5
  SHA512:
6
- metadata.gz: 43b4d7dec762bcefd6cd816f4c7a8c05a5e091929937f6e329801a6d4ff211fabdac4631f449d39501807b408f0f1411dc97637519857da49911cafa5bd108f6
7
- data.tar.gz: 81d529473f1404940f0cc45d1011af5d1930506f972b2485cbe190f184cd53a820cbfaa683201ec0b8ef85e63f2d50714cf337780087a94704071a5ef82d735c
6
+ metadata.gz: ba35f363319b323fe927da2cc3a9e8934d7b4310f5995b31d1cc91a759b34c8462262c449ef59fa1debe3c35615c733ef8f0dc96e6f270b592a76f1f6cc76153
7
+ data.tar.gz: 892b319be15819eb07cf5f254e9e7144e8387393a586442e9831585602600ade156e6d6c7c0b1dc41b6e60ee9e58b411c10a1bcebbff5e08f8510ec56f32ffad
data/CLAUDE.md CHANGED
@@ -22,7 +22,7 @@ rake rubocop
22
22
 
23
23
  ## Architecture
24
24
 
25
- ### Core Classes (lib/rake/gem_maintenance/)
25
+ ### Core Classes (lib/rake/gem/maintenance/)
26
26
 
27
27
  - **UpgradeTask** — Rake::TaskLib subclass defining upgrade:* tasks (branch, gems, commit, push, auto)
28
28
  - Default repositories: rubygems.org
@@ -36,21 +36,21 @@ rake rubocop
36
36
 
37
37
  ### Entry Points
38
38
 
39
- - `rake/gem_maintenance.rb` — requires all task classes
40
- - `rake/gem_maintenance/install_tasks.rb` — auto-instantiates UpgradeTask and VersionBumpTask with defaults
39
+ - `rake/gem/maintenance.rb` — requires all task classes
40
+ - `rake/gem/maintenance/install_tasks.rb` — auto-instantiates UpgradeTask and VersionBumpTask with defaults
41
41
 
42
42
  ### Quick Usage
43
43
 
44
44
  ```ruby
45
45
  # Internal gems only (cbp-org.internal)
46
- Rake::GemMaintenance::InternalUpgradeTask.new
46
+ Rake::Gem::Maintenance::InternalUpgradeTask.new
47
47
 
48
48
  # Both repositories
49
- Rake::GemMaintenance::DualUpgradeTask.new
49
+ Rake::Gem::Maintenance::DualUpgradeTask.new
50
50
 
51
51
  # Default (rubygems.org) - can also use Repos module
52
- Rake::GemMaintenance::UpgradeTask.new do |t|
53
- t.gem_repositories = Rake::GemMaintenance::Repos.internal # or Repos.all
52
+ Rake::Gem::Maintenance::UpgradeTask.new do |t|
53
+ t.gem_repositories = Rake::Gem::Maintenance::Repos.internal # or Repos.all
54
54
  end
55
55
  ```
56
56
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rake-gem-maintenance (0.1.6)
4
+ rake-gem-maintenance (0.2.0)
5
5
  bundler-audit
6
6
  gem-release
7
7
  rake
@@ -254,7 +254,7 @@ CHECKSUMS
254
254
  racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
255
255
  rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
256
256
  rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
257
- rake-gem-maintenance (0.1.6)
257
+ rake-gem-maintenance (0.2.0)
258
258
  rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
259
259
  rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
260
260
  rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Rake::GemMaintenance
1
+ # Rake::Gem::Maintenance
2
2
 
3
3
  [![Ruby](https://github.com/cbroult/rake-gem-maintenance/actions/workflows/main.yml/badge.svg)](https://github.com/cbroult/rake-gem-maintenance/actions/workflows/main.yml)
4
4
  [![Dependabot](https://img.shields.io/badge/dependabot-enabled-blue?logo=dependabot)](https://github.com/cbroult/rake-gem-maintenance/network/updates)
@@ -18,7 +18,7 @@ gem "rake-gem-maintenance"
18
18
  Add to your Rakefile for default behavior:
19
19
 
20
20
  ```ruby
21
- require "rake/gem_maintenance/install_tasks"
21
+ require "rake/gem/maintenance/install_tasks"
22
22
  ```
23
23
 
24
24
  This defines:
@@ -33,93 +33,87 @@ This defines:
33
33
  ## Customization
34
34
 
35
35
  ```ruby
36
- require "rake/gem_maintenance"
36
+ require "rake/gem/maintenance"
37
37
 
38
- Rake::GemMaintenance::UpgradeTask.new do |t|
38
+ Rake::Gem::Maintenance::UpgradeTask.new do |t|
39
39
  t.main_branch = "develop"
40
40
  t.upgrade_branch = "chore/upgrade-deps"
41
41
  t.commit_message = "chore: upgrade dependencies"
42
42
  end
43
43
 
44
- Rake::GemMaintenance::VersionBumpTask.new do |t|
44
+ Rake::Gem::Maintenance::VersionBumpTask.new do |t|
45
45
  t.default_type = "minor"
46
46
  end
47
47
  ```
48
48
 
49
49
  ## Automated Publishing to rubygems.org
50
50
 
51
- Set two environment variables and `gem push` runs fully unattended including TOTP 2FA code
52
- generation if your rubygems.org account has MFA enabled.
53
-
54
- | Env var | Purpose |
55
- |---|---|
56
- | `GEM_HOST_API_KEY` | rubygems.org API key (scoped to push) |
57
- | `RUBYGEMS_OTP_SEED` | Base32 TOTP seed — auto-generates the 2FA code; omit if MFA is disabled |
58
-
59
- ### Quick setup
60
-
61
- `require "rake/gem_maintenance/install_tasks"` pre-configures both env var names automatically —
62
- no extra Ruby needed. See [features/install_tasks.feature](features/install_tasks.feature) for
63
- the full workflow.
64
-
65
- ### Custom env var names
66
-
67
- ```ruby
68
- require "rake/gem/maintenance"
51
+ ### Step 1First-time setup (one-off, interactive)
69
52
 
70
- Rake::GemMaintenance::Repos.rubygems_api_key_env_var = "MY_RUBYGEMS_KEY"
71
- Rake::GemMaintenance::Repos.rubygems_otp_seed_env_var = "MY_OTP_SEED"
53
+ Run the renewal task once on your local machine:
72
54
 
73
- Rake::GemMaintenance::UpgradeTask.new
55
+ ```bash
56
+ rake upgrade:renew_api_key
74
57
  ```
75
58
 
76
- See [features/upgrade_task/repos_configuration.feature](features/upgrade_task/repos_configuration.feature)
77
- for all configuration options including geminabox and dual publishing.
59
+ It will prompt for three things:
78
60
 
79
- ### Local credential store
61
+ | Prompt | What to enter |
62
+ |---|---|
63
+ | username | Your rubygems.org username or email |
64
+ | password | Your rubygems.org password (never stored) |
65
+ | OTP seed | The **base32 secret** from your authenticator app setup — the long code shown when you first enabled MFA, *not* the rotating 6-digit code. Omit (press Enter) if MFA is disabled. |
80
66
 
81
- After the first successful `upgrade:renew_api_key` run, the API key and OTP seed are saved to:
67
+ After answering, the task generates a scoped API key and saves it locally alongside your
68
+ username and OTP seed:
82
69
 
83
70
  ```
84
71
  ~/.config/rake-gem-maintenance/credentials.yml # Linux / Mac (respects $XDG_CONFIG_HOME)
85
72
  %APPDATA%\rake-gem-maintenance\credentials.yml # Windows
86
73
  ```
87
74
 
88
- The file is created with `0600` permissions (owner-read-only on Unix). It stores `username`,
89
- `gem_host_api_key`, and `rubygems_otp_seed` — **never the password**. Any project using
90
- `require "rake/gem_maintenance/install_tasks"` automatically loads the key and OTP seed from
91
- this file at startup, so `gem push` works without any manual env-var setup.
75
+ The file is `0600` (owner-read-only on Unix). The **password is never written to disk**.
76
+
77
+ ### Step 2 All future local runs are automatic
78
+
79
+ Any project using `require "rake/gem/maintenance/install_tasks"` automatically reads the
80
+ credential file at startup and sets `GEM_HOST_API_KEY` and `RUBYGEMS_OTP_SEED` in the process
81
+ environment. Running `rake upgrade` needs no manual credential setup from this point on.
92
82
 
93
83
  See [features/upgrade_task/credential_store.feature](features/upgrade_task/credential_store.feature)
94
84
  for the full behaviour specification.
95
85
 
96
- ### API key renewal
86
+ ### Step 3 — CI setup (Woodpecker / GitHub Actions)
97
87
 
98
- API keys can be rotated in two ways:
88
+ Set the following as CI secrets:
99
89
 
100
- **Automatic** when `gem push` returns a 401/403, the publisher transparently obtains a new
101
- key using `RUBYGEMS_USERNAME` + `RUBYGEMS_PASSWORD` (+ TOTP from `RUBYGEMS_OTP_SEED` if MFA is
102
- enabled), then retries the push once. No intervention needed.
90
+ | Secret / env var | Purpose |
91
+ |---|---|
92
+ | `RUBYGEMS_USERNAME` | rubygems.org username |
93
+ | `RUBYGEMS_PASSWORD` | rubygems.org password |
94
+ | `RUBYGEMS_OTP_SEED` | Same base32 seed as above |
95
+ | `GEM_HOST_API_KEY` | The API key generated in Step 1 (for the initial push) |
103
96
 
104
- **On-demand** run the task explicitly to rotate ahead of expiry:
97
+ On subsequent runs the key is renewed automatically: when `gem push` returns 401/403, the
98
+ publisher transparently calls `upgrade:renew_api_key` and retries. The refreshed key is written
99
+ back to the `rubygems_api_key` CI secret (requires `WOODPECKER_TOKEN` + `WOODPECKER_SERVER`
100
+ when running under Woodpecker CI).
105
101
 
106
- ```bash
107
- rake upgrade:renew_api_key
108
- ```
102
+ See [features/upgrade_task/renew_api_key.feature](features/upgrade_task/renew_api_key.feature).
109
103
 
110
- Locally this prompts for credentials interactively. In CI, supply all three env vars for
111
- unattended operation:
104
+ ### Custom env var names
112
105
 
113
- | Env var | Purpose |
114
- |---|---|
115
- | `RUBYGEMS_USERNAME` | rubygems.org account username or email |
116
- | `RUBYGEMS_PASSWORD` | rubygems.org account password |
117
- | `RUBYGEMS_OTP_SEED` | Same TOTP seed as above — reused here to authenticate the key-creation request |
106
+ ```ruby
107
+ require "rake/gem/maintenance"
118
108
 
119
- The new key is written back to the `GEM_HOST_API_KEY` CI secret automatically (requires
120
- `WOODPECKER_TOKEN` and `WOODPECKER_SERVER` when running under Woodpecker CI).
109
+ Rake::Gem::Maintenance::Repos.rubygems_api_key_env_var = "MY_RUBYGEMS_KEY"
110
+ Rake::Gem::Maintenance::Repos.rubygems_otp_seed_env_var = "MY_OTP_SEED"
121
111
 
122
- See [features/upgrade_task/renew_api_key.feature](features/upgrade_task/renew_api_key.feature).
112
+ Rake::Gem::Maintenance::UpgradeTask.new
113
+ ```
114
+
115
+ See [features/upgrade_task/repos_configuration.feature](features/upgrade_task/repos_configuration.feature)
116
+ for all configuration options including geminabox and dual publishing.
123
117
 
124
118
  ## License
125
119
 
data/TODO.md CHANGED
@@ -1 +1,4 @@
1
- * Relocate to Rake::Gem::Maintenance so that `rake bump` works (it fails currently).
1
+ # Packwerk
2
+
3
+ Packwerk is Shopify's package enforcement tool designed for large Rails monoliths.
4
+ With ~15 files in this library gem, the overhead is not warranted — close without implementing.
@@ -1,47 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rake
4
- module GemMaintenance
5
- # Renews a rubygems.org API key using credentials from env vars and
6
- # persists the new key to Woodpecker CI when server details are available.
7
- class ApiKeyRenewer
8
- def initialize(otp_provider:,
9
- username_env_var: "RUBYGEMS_USERNAME",
10
- password_env_var: "RUBYGEMS_PASSWORD")
11
- @otp_provider = otp_provider
12
- @username_env_var = username_env_var
13
- @password_env_var = password_env_var
14
- end
4
+ module Gem
5
+ module Maintenance
6
+ # Renews a rubygems.org API key using credentials from env vars and
7
+ # persists the new key to Woodpecker CI when server details are available.
8
+ class ApiKeyRenewer
9
+ def initialize(otp_provider:,
10
+ username_env_var: "RUBYGEMS_USERNAME",
11
+ password_env_var: "RUBYGEMS_PASSWORD")
12
+ @otp_provider = otp_provider
13
+ @username_env_var = username_env_var
14
+ @password_env_var = password_env_var
15
+ end
15
16
 
16
- def renew(repository)
17
- username = env_credential(@username_env_var)
18
- password = env_credential(@password_env_var)
19
- return nil if username.nil? || password.nil?
17
+ def renew(repository)
18
+ username = env_credential(@username_env_var)
19
+ password = env_credential(@password_env_var)
20
+ return nil if username.nil? || password.nil?
20
21
 
21
- otp = @otp_provider.otp_for(repository[:name], otp_seed_env_var: repository[:otp_seed_env_var])
22
- new_key = RubyGemsApiKeyCreator.new(host: repository.fetch(:url, "https://rubygems.org"))
23
- .create(username, password, otp: otp)
24
- persist_to_woodpecker(new_key)
25
- new_key
26
- rescue StandardError
27
- nil
28
- end
22
+ otp = @otp_provider.otp_for(repository[:name], otp_seed_env_var: repository[:otp_seed_env_var])
23
+ new_key = RubyGemsApiKeyCreator.new(host: repository.fetch(:url, "https://rubygems.org"))
24
+ .create(username, password, otp: otp)
25
+ persist_to_woodpecker(new_key)
26
+ new_key
27
+ rescue StandardError
28
+ nil
29
+ end
29
30
 
30
- private
31
+ private
31
32
 
32
- def env_credential(var)
33
- value = ENV.fetch(var, nil)
34
- value&.empty? ? nil : value
35
- end
33
+ def env_credential(var)
34
+ value = ENV.fetch(var, nil)
35
+ value&.empty? ? nil : value
36
+ end
36
37
 
37
- def persist_to_woodpecker(new_key)
38
- server = ENV.fetch("WOODPECKER_SERVER", nil)
39
- token = ENV.fetch("WOODPECKER_TOKEN", nil)
40
- return unless server && token
38
+ def persist_to_woodpecker(new_key)
39
+ server = ENV.fetch("WOODPECKER_SERVER", nil)
40
+ token = ENV.fetch("WOODPECKER_TOKEN", nil)
41
+ return unless server && token
41
42
 
42
- org = ENV.fetch("WOODPECKER_ORG", "cbp-org")
43
- WoodpeckerSecretStore.new(server: server, org: org, token: token)
44
- .store("rubygems_api_key", new_key)
43
+ org = ENV.fetch("WOODPECKER_ORG", "cbp-org")
44
+ WoodpeckerSecretStore.new(server: server, org: org, token: token)
45
+ .store("rubygems_api_key", new_key)
46
+ end
45
47
  end
46
48
  end
47
49
  end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rake
4
- module GemMaintenance
5
- # Detects whether the current process is running inside a CI environment.
6
- module CIEnvironment
7
- def self.ci?
8
- ENV["CI"].to_s != ""
4
+ module Gem
5
+ module Maintenance
6
+ # Detects whether the current process is running inside a CI environment.
7
+ module CIEnvironment
8
+ def self.ci?
9
+ ENV["CI"].to_s != ""
10
+ end
9
11
  end
10
12
  end
11
13
  end
@@ -5,60 +5,62 @@ require "fileutils"
5
5
  require "rubygems"
6
6
 
7
7
  module Rake
8
- module GemMaintenance
9
- # Persists rubygems.org credentials (username, API key, OTP seed) to a local config file.
10
- class CredentialStore
11
- def self.default_path
12
- base = if Gem.win_platform?
13
- ENV.fetch("APPDATA", File.expand_path("~"))
14
- else
15
- ENV.fetch("XDG_CONFIG_HOME", File.join(Dir.home, ".config"))
16
- end
17
- File.join(base, "rake-gem-maintenance", "credentials.yml")
18
- end
8
+ module Gem
9
+ module Maintenance
10
+ # Persists rubygems.org credentials (username, API key, OTP seed) to a local config file.
11
+ class CredentialStore
12
+ def self.default_path
13
+ base = if ::Gem.win_platform?
14
+ ENV.fetch("APPDATA", File.expand_path("~"))
15
+ else
16
+ ENV.fetch("XDG_CONFIG_HOME", File.join(Dir.home, ".config"))
17
+ end
18
+ File.join(base, "rake-gem-maintenance", "credentials.yml")
19
+ end
19
20
 
20
- def initialize(path: self.class.default_path)
21
- @path = path
22
- end
21
+ def initialize(path: self.class.default_path)
22
+ @path = path
23
+ end
23
24
 
24
- attr_reader :path
25
+ attr_reader :path
25
26
 
26
- def read
27
- return {} unless File.exist?(@path)
27
+ def read
28
+ return {} unless File.exist?(@path)
28
29
 
29
- YAML.safe_load_file(@path, symbolize_names: true) || {}
30
- rescue StandardError
31
- {}
32
- end
30
+ YAML.safe_load_file(@path, symbolize_names: true) || {}
31
+ rescue StandardError
32
+ {}
33
+ end
33
34
 
34
- def write(credentials)
35
- FileUtils.mkdir_p(File.dirname(@path))
36
- File.write(@path, credentials.transform_keys(&:to_s).to_yaml)
37
- File.chmod(0o600, @path) unless Gem.win_platform?
38
- end
35
+ def write(credentials)
36
+ FileUtils.mkdir_p(File.dirname(@path))
37
+ File.write(@path, credentials.transform_keys(&:to_s).to_yaml)
38
+ File.chmod(0o600, @path) unless ::Gem.win_platform?
39
+ end
39
40
 
40
- def apply_to_env(username_env_var:, api_key_env_var:)
41
- creds = read
42
- set_env_if_absent(username_env_var, creds[:username])
43
- set_env_if_absent("RUBYGEMS_OTP_SEED", creds[:rubygems_otp_seed])
44
- set_env_if_absent(api_key_env_var, creds[:gem_host_api_key])
45
- end
41
+ def apply_to_env(username_env_var:, api_key_env_var:)
42
+ creds = read
43
+ set_env_if_absent(username_env_var, creds[:username])
44
+ set_env_if_absent("RUBYGEMS_OTP_SEED", creds[:rubygems_otp_seed])
45
+ set_env_if_absent(api_key_env_var, creds[:gem_host_api_key])
46
+ end
46
47
 
47
- def update(username:, api_key:, api_key_env_var:)
48
- otp_seed = ENV.fetch("RUBYGEMS_OTP_SEED", nil)
49
- updated = read.merge(username: username, gem_host_api_key: api_key)
50
- updated[:rubygems_otp_seed] = otp_seed if otp_seed && !otp_seed.empty?
51
- write(updated)
52
- ENV[api_key_env_var] = api_key
53
- end
48
+ def update(username:, api_key:, api_key_env_var:)
49
+ otp_seed = ENV.fetch("RUBYGEMS_OTP_SEED", nil)
50
+ updated = read.merge(username: username, gem_host_api_key: api_key)
51
+ updated[:rubygems_otp_seed] = otp_seed if otp_seed && !otp_seed.empty?
52
+ write(updated)
53
+ ENV[api_key_env_var] = api_key
54
+ end
54
55
 
55
- private
56
+ private
56
57
 
57
- def set_env_if_absent(env_var, value)
58
- return unless value && !value.empty?
59
- return if (existing = ENV.fetch(env_var, nil)) && !existing.empty?
58
+ def set_env_if_absent(env_var, value)
59
+ return unless value && !value.empty?
60
+ return if (existing = ENV.fetch(env_var, nil)) && !existing.empty?
60
61
 
61
- ENV[env_var] = value
62
+ ENV[env_var] = value
63
+ end
62
64
  end
63
65
  end
64
66
  end
@@ -4,113 +4,115 @@ require "json"
4
4
  require "open-uri"
5
5
 
6
6
  module Rake
7
- module GemMaintenance
8
- # Publishes gems to multiple gem repositories, with version checking and warning handling.
9
- class GemPublisher
10
- attr_reader :repositories, :warnings, :failed_repositories, :successful_repos
11
-
12
- def initialize(repositories = default_repositories,
13
- otp_provider: OtpProvider.new,
14
- ci_environment: CIEnvironment)
15
- @repositories = repositories
16
- @otp_provider = otp_provider
17
- @ci_environment = ci_environment
18
- @warnings = []
19
- @failed_pushes = []
20
- @failed_repositories = []
21
- @published_files = []
22
- @successful_repos = []
23
- end
7
+ module Gem
8
+ module Maintenance
9
+ # Publishes gems to multiple gem repositories, with version checking and warning handling.
10
+ class GemPublisher
11
+ attr_reader :repositories, :warnings, :failed_repositories, :successful_repos
12
+
13
+ def initialize(repositories = default_repositories,
14
+ otp_provider: OtpProvider.new,
15
+ ci_environment: CIEnvironment)
16
+ @repositories = repositories
17
+ @otp_provider = otp_provider
18
+ @ci_environment = ci_environment
19
+ @warnings = []
20
+ @failed_pushes = []
21
+ @failed_repositories = []
22
+ @published_files = []
23
+ @successful_repos = []
24
+ end
24
25
 
25
- def default_repositories
26
- [{ name: "rubygems", url: "https://rubygems.org" }]
27
- end
26
+ def default_repositories
27
+ [{ name: "rubygems", url: "https://rubygems.org" }]
28
+ end
28
29
 
29
- def publish(gem_file)
30
- @failed_pushes = []
31
- @published_files = []
32
- build_and_push(gem_file)
33
- print_warnings
34
- end
30
+ def publish(gem_file)
31
+ @failed_pushes = []
32
+ @published_files = []
33
+ build_and_push(gem_file)
34
+ print_warnings
35
+ end
35
36
 
36
- def check_all_repositories(gem_name)
37
- @failed_repositories = []
38
- repositories.each do |repo|
39
- versions_on_repository(gem_name, repo)
37
+ def check_all_repositories(gem_name)
38
+ @failed_repositories = []
39
+ repositories.each do |repo|
40
+ versions_on_repository(gem_name, repo)
41
+ end
40
42
  end
41
- end
42
43
 
43
- def versions_on_repository(gem_name, repository)
44
- url = "#{repository[:url]}/api/v1/gems/#{gem_name}.json"
45
- uri = URI.parse(url)
46
- response = uri.read(accept: "application/json")
47
- data = JSON.parse(response)
48
- data["versions"].map { |v| v["number"] }
49
- rescue StandardError => e
50
- @failed_repositories << repository[:name]
51
- @warnings << { repository: repository[:name], error: "Cannot fetch versions: #{e.message}" }
52
- []
53
- end
44
+ def versions_on_repository(gem_name, repository)
45
+ url = "#{repository[:url]}/api/v1/gems/#{gem_name}.json"
46
+ uri = URI.parse(url)
47
+ response = uri.read(accept: "application/json")
48
+ data = JSON.parse(response)
49
+ data["versions"].map { |v| v["number"] }
50
+ rescue StandardError => e
51
+ @failed_repositories << repository[:name]
52
+ @warnings << { repository: repository[:name], error: "Cannot fetch versions: #{e.message}" }
53
+ []
54
+ end
54
55
 
55
- def next_version(gem_name, current_version)
56
- return current_version unless current_version
56
+ def next_version(gem_name, current_version)
57
+ return current_version unless current_version
57
58
 
58
- ver = Gem::Version.new(current_version)
59
- loop do
60
- return ver.to_s unless version_exists_on_all_repos?(gem_name, ver)
59
+ ver = ::Gem::Version.new(current_version)
60
+ loop do
61
+ return ver.to_s unless version_exists_on_all_repos?(gem_name, ver)
61
62
 
62
- ver = ver.bump
63
+ ver = ver.bump
64
+ end
63
65
  end
64
- end
65
66
 
66
- def available_repositories
67
- repositories.map { |r| r[:name] } - @failed_repositories
68
- end
67
+ def available_repositories
68
+ repositories.map { |r| r[:name] } - @failed_repositories
69
+ end
69
70
 
70
- def any_available?
71
- @failed_repositories.size < repositories.size
72
- end
71
+ def any_available?
72
+ @failed_repositories.size < repositories.size
73
+ end
73
74
 
74
- private
75
+ private
75
76
 
76
- def build_and_push(gem_file)
77
- repositories.each do |repo|
78
- push(gem_file, repository: repo)
77
+ def build_and_push(gem_file)
78
+ repositories.each do |repo|
79
+ push(gem_file, repository: repo)
80
+ end
79
81
  end
80
- end
81
82
 
82
- def push(gem_file, repository:)
83
- result = GemPush.new(gem_file, repository, @otp_provider).attempt
84
- return record_success(gem_file, repository) if result.success
83
+ def push(gem_file, repository:)
84
+ result = GemPush.new(gem_file, repository, @otp_provider).attempt
85
+ return record_success(gem_file, repository) if result.success
85
86
 
86
- record_push_failure(repository, result.error)
87
- rescue StandardError => e
88
- @failed_pushes << { repository: repository[:name], error: e.message }
89
- end
87
+ record_push_failure(repository, result.error)
88
+ rescue StandardError => e
89
+ @failed_pushes << { repository: repository[:name], error: e.message }
90
+ end
90
91
 
91
- def record_success(gem_file, repository)
92
- @published_files << gem_file
93
- @successful_repos << repository[:name]
94
- end
92
+ def record_success(gem_file, repository)
93
+ @published_files << gem_file
94
+ @successful_repos << repository[:name]
95
+ end
95
96
 
96
- def record_push_failure(repository, message)
97
- @failed_pushes << { repository: repository[:name], error: message.strip }
98
- end
97
+ def record_push_failure(repository, message)
98
+ @failed_pushes << { repository: repository[:name], error: message.strip }
99
+ end
99
100
 
100
- def version_exists_on_all_repos?(gem_name, version)
101
- repositories.all? do |repo|
102
- versions_on_repository(gem_name, repo).include?(version.to_s)
101
+ def version_exists_on_all_repos?(gem_name, version)
102
+ repositories.all? do |repo|
103
+ versions_on_repository(gem_name, repo).include?(version.to_s)
104
+ end
103
105
  end
104
- end
105
106
 
106
- def print_warnings
107
- return if @failed_pushes.empty?
107
+ def print_warnings
108
+ return if @failed_pushes.empty?
108
109
 
109
- puts "[WARN] The following repositories were unavailable:"
110
- @failed_pushes.each do |failure|
111
- puts " - #{failure[:repository]}: #{failure[:error]}"
110
+ puts "[WARN] The following repositories were unavailable:"
111
+ @failed_pushes.each do |failure|
112
+ puts " - #{failure[:repository]}: #{failure[:error]}"
113
+ end
114
+ puts "[WARN] Warning: Published to #{@published_files.size} of #{repositories.size} repositories"
112
115
  end
113
- puts "[WARN] Warning: Published to #{@published_files.size} of #{repositories.size} repositories"
114
116
  end
115
117
  end
116
118
  end