rake-gem-maintenance 0.1.7 → 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.
@@ -2,13 +2,13 @@
2
2
 
3
3
  require_relative "../maintenance"
4
4
 
5
- Rake::GemMaintenance::Repos.rubygems_api_key_env_var = "GEM_HOST_API_KEY"
6
- Rake::GemMaintenance::Repos.rubygems_otp_seed_env_var = "RUBYGEMS_OTP_SEED"
5
+ Rake::Gem::Maintenance::Repos.rubygems_api_key_env_var = "GEM_HOST_API_KEY"
6
+ Rake::Gem::Maintenance::Repos.rubygems_otp_seed_env_var = "RUBYGEMS_OTP_SEED"
7
7
 
8
- Rake::GemMaintenance::UpgradeTask.new
9
- Rake::GemMaintenance::VersionBumpTask.new
8
+ Rake::Gem::Maintenance::UpgradeTask.new
9
+ Rake::Gem::Maintenance::VersionBumpTask.new
10
10
 
11
- Rake::GemMaintenance::CredentialStore.new.apply_to_env(
11
+ Rake::Gem::Maintenance::CredentialStore.new.apply_to_env(
12
12
  username_env_var: "RUBYGEMS_USERNAME",
13
13
  api_key_env_var: "GEM_HOST_API_KEY"
14
14
  )
@@ -1,44 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rake
4
- module GemMaintenance
5
- # Resolves a 2FA OTP code for gem push, either from the environment or interactively.
6
- # Resolution order for otp_for:
7
- # 1. RUBYGEMS_OTP env var set → use raw code (works in CI and locally)
8
- # 2. otp_seed_env_var provided and env var set → generate TOTP code (works in CI and locally)
9
- # 3. CI environmentnil (gate only interactive prompt)
10
- # 4. Interactive prompt
11
- class OtpProvider
12
- def initialize(ci_environment: CIEnvironment, input: $stdin)
13
- @ci_environment = ci_environment
14
- @input = input
15
- end
4
+ module Gem
5
+ module Maintenance
6
+ # Resolves a 2FA OTP code for gem push, either from the environment or interactively.
7
+ # Resolution order for otp_for:
8
+ # 1. RUBYGEMS_OTP env var set → use raw code (works in CI and locally)
9
+ # 2. otp_seed_env_var provided and env var set generate TOTP code (works in CI and locally)
10
+ # 3. CI environment → nil (gate only interactive prompt)
11
+ # 4. Interactive prompt
12
+ class OtpProvider
13
+ def initialize(ci_environment: CIEnvironment, input: $stdin)
14
+ @ci_environment = ci_environment
15
+ @input = input
16
+ end
16
17
 
17
- def otp_for(repository_name, otp_seed_env_var: nil)
18
- env_otp = ENV.fetch("RUBYGEMS_OTP", nil)
19
- return env_otp if env_otp && !env_otp.empty?
18
+ def otp_for(repository_name, otp_seed_env_var: nil)
19
+ env_otp = ENV.fetch("RUBYGEMS_OTP", nil)
20
+ return env_otp if env_otp && !env_otp.empty?
20
21
 
21
- if otp_seed_env_var
22
- seed = ENV.fetch(otp_seed_env_var, nil)
23
- return generate_totp(seed) if seed && !seed.empty?
24
- end
22
+ if otp_seed_env_var
23
+ seed = ENV.fetch(otp_seed_env_var, nil)
24
+ return generate_totp(seed) if seed && !seed.empty?
25
+ end
25
26
 
26
- return nil if @ci_environment.ci?
27
+ return nil if @ci_environment.ci?
27
28
 
28
- prompt_for_otp(repository_name)
29
- end
29
+ prompt_for_otp(repository_name)
30
+ end
30
31
 
31
- private
32
+ private
32
33
 
33
- def generate_totp(seed)
34
- require "rotp"
35
- ::ROTP::TOTP.new(seed).now
36
- end
34
+ def generate_totp(seed)
35
+ require "rotp"
36
+ ::ROTP::TOTP.new(seed).now
37
+ end
37
38
 
38
- def prompt_for_otp(repository_name)
39
- print "Enter OTP for #{repository_name} (blank to skip): "
40
- value = @input.gets&.chomp
41
- value&.empty? ? nil : value
39
+ def prompt_for_otp(repository_name)
40
+ print "Enter OTP for #{repository_name} (blank to skip): "
41
+ value = @input.gets&.chomp
42
+ value&.empty? ? nil : value
43
+ end
42
44
  end
43
45
  end
44
46
  end
@@ -5,134 +5,136 @@ require "rake/tasklib"
5
5
  require_relative "credential_store"
6
6
 
7
7
  module Rake
8
- module GemMaintenance
9
- # Generates a new rubygems.org API key via the rubygems.org API and stores
10
- # it in a Woodpecker CI org-level secret. Intended for local developer use only.
11
- #
12
- # Creates: <namespace>:renew_api_key
13
- #
14
- # Reads WOODPECKER_SERVER and WOODPECKER_TOKEN (or ~/.config/woodpecker/token)
15
- # from the environment.
16
- class RenewApiKeyTask < ::Rake::TaskLib
17
- attr_accessor :namespace_name, :host, :api_key_env_var, :ci_environment,
18
- :woodpecker_server, :woodpecker_org, :woodpecker_secret_name,
19
- :username_env_var, :password_env_var, :credential_store
20
-
21
- def initialize(namespace_name = :upgrade)
22
- super()
23
- apply_defaults(namespace_name)
24
- define_tasks
25
- end
8
+ module Gem
9
+ module Maintenance
10
+ # Generates a new rubygems.org API key via the rubygems.org API and stores
11
+ # it in a Woodpecker CI org-level secret. Intended for local developer use only.
12
+ #
13
+ # Creates: <namespace>:renew_api_key
14
+ #
15
+ # Reads WOODPECKER_SERVER and WOODPECKER_TOKEN (or ~/.config/woodpecker/token)
16
+ # from the environment.
17
+ class RenewApiKeyTask < ::Rake::TaskLib
18
+ attr_accessor :namespace_name, :host, :api_key_env_var, :ci_environment,
19
+ :woodpecker_server, :woodpecker_org, :woodpecker_secret_name,
20
+ :username_env_var, :password_env_var, :credential_store
21
+
22
+ def initialize(namespace_name = :upgrade)
23
+ super()
24
+ apply_defaults(namespace_name)
25
+ define_tasks
26
+ end
26
27
 
27
- private
28
-
29
- def apply_defaults(namespace_name)
30
- @namespace_name = namespace_name
31
- @host = "https://rubygems.org"
32
- @api_key_env_var = "GEM_HOST_API_KEY"
33
- @ci_environment = CIEnvironment
34
- @woodpecker_server = ENV.fetch("WOODPECKER_SERVER", nil)
35
- @woodpecker_org = ENV.fetch("WOODPECKER_ORG", "cbp-org")
36
- @woodpecker_secret_name = "rubygems_api_key"
37
- @username_env_var = "RUBYGEMS_USERNAME"
38
- @password_env_var = "RUBYGEMS_PASSWORD"
39
- @credential_store = CredentialStore.new
40
- end
28
+ private
29
+
30
+ def apply_defaults(namespace_name)
31
+ @namespace_name = namespace_name
32
+ @host = "https://rubygems.org"
33
+ @api_key_env_var = "GEM_HOST_API_KEY"
34
+ @ci_environment = CIEnvironment
35
+ @woodpecker_server = ENV.fetch("WOODPECKER_SERVER", nil)
36
+ @woodpecker_org = ENV.fetch("WOODPECKER_ORG", "cbp-org")
37
+ @woodpecker_secret_name = "rubygems_api_key"
38
+ @username_env_var = "RUBYGEMS_USERNAME"
39
+ @password_env_var = "RUBYGEMS_PASSWORD"
40
+ @credential_store = CredentialStore.new
41
+ end
41
42
 
42
- def define_tasks
43
- task_instance = self
44
- namespace namespace_name do
45
- desc "Generate a new rubygems.org API key and store it in Woodpecker CI"
46
- task(:renew_api_key) { task_instance.send(:run_renewal) }
43
+ def define_tasks
44
+ task_instance = self
45
+ namespace namespace_name do
46
+ desc "Generate a new rubygems.org API key and store it in Woodpecker CI"
47
+ task(:renew_api_key) { task_instance.send(:run_renewal) }
48
+ end
47
49
  end
48
- end
49
50
 
50
- def run_renewal
51
- credential_store.apply_to_env(username_env_var: username_env_var, api_key_env_var: api_key_env_var)
52
- abort_if_ci
53
- username, password = prompt_credentials
54
- prompt_otp_seed_if_missing
55
- api_key = generate_api_key(username, password)
56
- save_and_distribute(username, api_key)
57
- end
51
+ def run_renewal
52
+ credential_store.apply_to_env(username_env_var: username_env_var, api_key_env_var: api_key_env_var)
53
+ abort_if_ci
54
+ username, password = prompt_credentials
55
+ prompt_otp_seed_if_missing
56
+ api_key = generate_api_key(username, password)
57
+ save_and_distribute(username, api_key)
58
+ end
58
59
 
59
- def generate_api_key(username, password)
60
- otp = OtpProvider.new.otp_for("rubygems", otp_seed_env_var: "RUBYGEMS_OTP_SEED")
61
- RubyGemsApiKeyCreator.new(host: host).create(username, password, otp: otp)
62
- end
60
+ def generate_api_key(username, password)
61
+ otp = OtpProvider.new.otp_for("rubygems", otp_seed_env_var: "RUBYGEMS_OTP_SEED")
62
+ RubyGemsApiKeyCreator.new(host: host).create(username, password, otp: otp)
63
+ end
63
64
 
64
- def save_and_distribute(username, api_key)
65
- puts "\n[INFO] New API key generated."
66
- credential_store.update(username: username, api_key: api_key, api_key_env_var: api_key_env_var)
67
- store_in_woodpecker(api_key)
68
- end
65
+ def save_and_distribute(username, api_key)
66
+ puts "\n[INFO] New API key generated."
67
+ credential_store.update(username: username, api_key: api_key, api_key_env_var: api_key_env_var)
68
+ store_in_woodpecker(api_key)
69
+ end
69
70
 
70
- def abort_if_ci
71
- return unless ci_environment.ci?
71
+ def abort_if_ci
72
+ return unless ci_environment.ci?
72
73
 
73
- missing = [username_env_var, password_env_var].select { |v| env_credential(v).nil? }
74
- return if missing.empty?
74
+ missing = [username_env_var, password_env_var].select { |v| env_credential(v).nil? }
75
+ return if missing.empty?
75
76
 
76
- abort "[ERROR] Set #{missing.join(' and ')} CI secrets to run renewal unattended."
77
- end
77
+ abort "[ERROR] Set #{missing.join(' and ')} CI secrets to run renewal unattended."
78
+ end
78
79
 
79
- def prompt_otp_seed_if_missing
80
- return if (seed = ENV.fetch("RUBYGEMS_OTP_SEED", nil)) && !seed.empty?
80
+ def prompt_otp_seed_if_missing
81
+ return if (seed = ENV.fetch("RUBYGEMS_OTP_SEED", nil)) && !seed.empty?
81
82
 
82
- print "rubygems.org OTP seed (TOTP secret, not a code): "
83
- seed = $stdin.gets&.chomp
84
- ENV["RUBYGEMS_OTP_SEED"] = seed if seed && !seed.empty?
85
- end
86
-
87
- def prompt_credentials
88
- username = env_credential(username_env_var) || prompt_username
89
- password = env_credential(password_env_var) || read_password("rubygems.org password: ")
90
- [username, password]
91
- end
83
+ print "rubygems.org OTP seed (TOTP secret, not a code): "
84
+ seed = $stdin.gets&.chomp
85
+ ENV["RUBYGEMS_OTP_SEED"] = seed if seed && !seed.empty?
86
+ end
92
87
 
93
- def env_credential(env_var)
94
- value = ENV.fetch(env_var, nil)
95
- value&.empty? ? nil : value
96
- end
88
+ def prompt_credentials
89
+ username = env_credential(username_env_var) || prompt_username
90
+ password = env_credential(password_env_var) || read_password("rubygems.org password: ")
91
+ [username, password]
92
+ end
97
93
 
98
- def prompt_username
99
- print "rubygems.org username: "
100
- value = $stdin.gets&.chomp
101
- abort "[ERROR] No username provided." if value.nil? || value.empty?
102
- value
103
- end
94
+ def env_credential(env_var)
95
+ value = ENV.fetch(env_var, nil)
96
+ value&.empty? ? nil : value
97
+ end
104
98
 
105
- def read_password(prompt)
106
- require "io/console"
107
- print prompt
108
- password = $stdin.noecho(&:gets)&.chomp
109
- puts
110
- password
111
- rescue LoadError
112
- print prompt
113
- $stdin.gets&.chomp
114
- end
99
+ def prompt_username
100
+ print "rubygems.org username: "
101
+ value = $stdin.gets&.chomp
102
+ abort "[ERROR] No username provided." if value.nil? || value.empty?
103
+ value
104
+ end
115
105
 
116
- def store_in_woodpecker(api_key)
117
- unless woodpecker_server
118
- puts "[INFO] Set WOODPECKER_SERVER to auto-store the key in Woodpecker CI."
119
- puts "[INFO] New API key (store as secret '#{woodpecker_secret_name}'): #{api_key}"
120
- return
106
+ def read_password(prompt)
107
+ require "io/console"
108
+ print prompt
109
+ password = $stdin.noecho(&:gets)&.chomp
110
+ puts
111
+ password
112
+ rescue LoadError
113
+ print prompt
114
+ $stdin.gets&.chomp
121
115
  end
122
116
 
123
- token = read_woodpecker_token
124
- abort "[ERROR] No Woodpecker token. Set WOODPECKER_TOKEN or run woodpecker-cli setup." unless token
117
+ def store_in_woodpecker(api_key)
118
+ unless woodpecker_server
119
+ puts "[INFO] Set WOODPECKER_SERVER to auto-store the key in Woodpecker CI."
120
+ puts "[INFO] New API key (store as secret '#{woodpecker_secret_name}'): #{api_key}"
121
+ return
122
+ end
125
123
 
126
- WoodpeckerSecretStore.new(server: woodpecker_server, org: woodpecker_org, token: token)
127
- .store(woodpecker_secret_name, api_key)
128
- puts "[SUCCESS] API key stored in Woodpecker secret '#{woodpecker_secret_name}'."
129
- end
124
+ token = read_woodpecker_token
125
+ abort "[ERROR] No Woodpecker token. Set WOODPECKER_TOKEN or run woodpecker-cli setup." unless token
130
126
 
131
- def read_woodpecker_token
132
- ENV.fetch("WOODPECKER_TOKEN", nil) ||
133
- File.read(File.expand_path("~/.config/woodpecker/token")).strip
134
- rescue Errno::ENOENT
135
- nil
127
+ WoodpeckerSecretStore.new(server: woodpecker_server, org: woodpecker_org, token: token)
128
+ .store(woodpecker_secret_name, api_key)
129
+ puts "[SUCCESS] API key stored in Woodpecker secret '#{woodpecker_secret_name}'."
130
+ end
131
+
132
+ def read_woodpecker_token
133
+ ENV.fetch("WOODPECKER_TOKEN", nil) ||
134
+ File.read(File.expand_path("~/.config/woodpecker/token")).strip
135
+ rescue Errno::ENOENT
136
+ nil
137
+ end
136
138
  end
137
139
  end
138
140
  end
@@ -1,93 +1,95 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rake
4
- module GemMaintenance
5
- # Pre-configured gem repository configurations for common setups.
6
- #
7
- # @example Use internal-only repos
8
- # Rake::GemMaintenance::UpgradeTask.new do |t|
9
- # t.gem_repositories = Rake::GemMaintenance::Repos.internal
10
- # end
11
- #
12
- # @example Use both rubygems.org and internal repos
13
- # Rake::GemMaintenance::UpgradeTask.new do |t|
14
- # t.gem_repositories = Rake::GemMaintenance::Repos.all
15
- # end
16
- #
17
- # @example Use local geminabox only
18
- # Rake::GemMaintenance::GeminaboxUpgradeTask.new
19
- #
20
- # @example Dual publishing: geminabox + rubygems.org
21
- # Rake::GemMaintenance::UpgradeTask.new do |t|
22
- # t.gem_repositories = Rake::GemMaintenance::Repos.geminabox +
23
- # Rake::GemMaintenance::Repos.rubygems
24
- # end
25
- #
26
- # @example Reconfigure internal URL
27
- # Rake::GemMaintenance::Repos.internal_url = "https://my-internal-gem.example.com"
28
- #
29
- # @example Configure API key and TOTP seed env vars
30
- # Rake::GemMaintenance::Repos.rubygems_api_key_env_var = "GEM_HOST_API_KEY"
31
- # Rake::GemMaintenance::Repos.rubygems_otp_seed_env_var = "RUBYGEMS_OTP_SEED"
32
- # Rake::GemMaintenance::Repos.geminabox_url = "http://localhost:9292"
33
- module Repos
34
- @internal_url = "https://gems.cbp-org.internal"
35
- @rubygems_url = "https://rubygems.org"
36
- @geminabox_url = "http://localhost:9292"
4
+ module Gem
5
+ module Maintenance
6
+ # Pre-configured gem repository configurations for common setups.
7
+ #
8
+ # @example Use internal-only repos
9
+ # Rake::Gem::Maintenance::UpgradeTask.new do |t|
10
+ # t.gem_repositories = Rake::Gem::Maintenance::Repos.internal
11
+ # end
12
+ #
13
+ # @example Use both rubygems.org and internal repos
14
+ # Rake::Gem::Maintenance::UpgradeTask.new do |t|
15
+ # t.gem_repositories = Rake::Gem::Maintenance::Repos.all
16
+ # end
17
+ #
18
+ # @example Use local geminabox only
19
+ # Rake::Gem::Maintenance::GeminaboxUpgradeTask.new
20
+ #
21
+ # @example Dual publishing: geminabox + rubygems.org
22
+ # Rake::Gem::Maintenance::UpgradeTask.new do |t|
23
+ # t.gem_repositories = Rake::Gem::Maintenance::Repos.geminabox +
24
+ # Rake::Gem::Maintenance::Repos.rubygems
25
+ # end
26
+ #
27
+ # @example Reconfigure internal URL
28
+ # Rake::Gem::Maintenance::Repos.internal_url = "https://my-internal-gem.example.com"
29
+ #
30
+ # @example Configure API key and TOTP seed env vars
31
+ # Rake::Gem::Maintenance::Repos.rubygems_api_key_env_var = "GEM_HOST_API_KEY"
32
+ # Rake::Gem::Maintenance::Repos.rubygems_otp_seed_env_var = "RUBYGEMS_OTP_SEED"
33
+ # Rake::Gem::Maintenance::Repos.geminabox_url = "http://localhost:9292"
34
+ module Repos
35
+ @internal_url = "https://gems.cbp-org.internal"
36
+ @rubygems_url = "https://rubygems.org"
37
+ @geminabox_url = "http://localhost:9292"
37
38
 
38
- @rubygems_api_key_env_var = nil
39
- @internal_api_key_env_var = nil
40
- @geminabox_api_key_env_var = nil
39
+ @rubygems_api_key_env_var = nil
40
+ @internal_api_key_env_var = nil
41
+ @geminabox_api_key_env_var = nil
41
42
 
42
- @rubygems_otp_seed_env_var = nil
43
- @internal_otp_seed_env_var = nil
44
- @geminabox_otp_seed_env_var = nil
43
+ @rubygems_otp_seed_env_var = nil
44
+ @internal_otp_seed_env_var = nil
45
+ @geminabox_otp_seed_env_var = nil
45
46
 
46
- class << self
47
- attr_accessor :internal_url, :rubygems_url, :geminabox_url,
48
- :rubygems_api_key_env_var, :internal_api_key_env_var,
49
- :geminabox_api_key_env_var,
50
- :rubygems_otp_seed_env_var, :internal_otp_seed_env_var,
51
- :geminabox_otp_seed_env_var
52
- end
47
+ class << self
48
+ attr_accessor :internal_url, :rubygems_url, :geminabox_url,
49
+ :rubygems_api_key_env_var, :internal_api_key_env_var,
50
+ :geminabox_api_key_env_var,
51
+ :rubygems_otp_seed_env_var, :internal_otp_seed_env_var,
52
+ :geminabox_otp_seed_env_var
53
+ end
53
54
 
54
- # Publish only to internal repository
55
- # @return [Array<Hash>] repository configuration
56
- def self.internal
57
- base = { name: "cbp-org", url: internal_url }
58
- base[:api_key_env_var] = internal_api_key_env_var if internal_api_key_env_var
59
- base[:otp_seed_env_var] = internal_otp_seed_env_var if internal_otp_seed_env_var
60
- [base]
61
- end
55
+ # Publish only to internal repository
56
+ # @return [Array<Hash>] repository configuration
57
+ def self.internal
58
+ base = { name: "cbp-org", url: internal_url }
59
+ base[:api_key_env_var] = internal_api_key_env_var if internal_api_key_env_var
60
+ base[:otp_seed_env_var] = internal_otp_seed_env_var if internal_otp_seed_env_var
61
+ [base]
62
+ end
62
63
 
63
- # Publish to both rubygems.org and internal repository
64
- # @return [Array<Hash>] repository configuration
65
- def self.all
66
- rubygems + internal
67
- end
64
+ # Publish to both rubygems.org and internal repository
65
+ # @return [Array<Hash>] repository configuration
66
+ def self.all
67
+ rubygems + internal
68
+ end
68
69
 
69
- # Publish only to rubygems.org (the default)
70
- # @return [Array<Hash>] repository configuration
71
- def self.rubygems
72
- base = { name: "rubygems", url: rubygems_url }
73
- base[:api_key_env_var] = rubygems_api_key_env_var if rubygems_api_key_env_var
74
- base[:otp_seed_env_var] = rubygems_otp_seed_env_var if rubygems_otp_seed_env_var
75
- [base]
76
- end
70
+ # Publish only to rubygems.org (the default)
71
+ # @return [Array<Hash>] repository configuration
72
+ def self.rubygems
73
+ base = { name: "rubygems", url: rubygems_url }
74
+ base[:api_key_env_var] = rubygems_api_key_env_var if rubygems_api_key_env_var
75
+ base[:otp_seed_env_var] = rubygems_otp_seed_env_var if rubygems_otp_seed_env_var
76
+ [base]
77
+ end
77
78
 
78
- # Publish only to a local geminabox instance
79
- # @return [Array<Hash>] repository configuration
80
- def self.geminabox
81
- base = { name: "geminabox", url: geminabox_url }
82
- base[:api_key_env_var] = geminabox_api_key_env_var if geminabox_api_key_env_var
83
- base[:otp_seed_env_var] = geminabox_otp_seed_env_var if geminabox_otp_seed_env_var
84
- [base]
85
- end
79
+ # Publish only to a local geminabox instance
80
+ # @return [Array<Hash>] repository configuration
81
+ def self.geminabox
82
+ base = { name: "geminabox", url: geminabox_url }
83
+ base[:api_key_env_var] = geminabox_api_key_env_var if geminabox_api_key_env_var
84
+ base[:otp_seed_env_var] = geminabox_otp_seed_env_var if geminabox_otp_seed_env_var
85
+ [base]
86
+ end
86
87
 
87
- # Default configuration: rubygems.org only
88
- # @return [Array<Hash>] repository configuration
89
- def self.default
90
- rubygems
88
+ # Default configuration: rubygems.org only
89
+ # @return [Array<Hash>] repository configuration
90
+ def self.default
91
+ rubygems
92
+ end
91
93
  end
92
94
  end
93
95
  end
@@ -1,49 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rake
4
- module GemMaintenance
5
- # Creates a new scoped API key on rubygems.org via the v2 API.
6
- # Handles OTP header injection and maps HTTP error codes to actionable messages.
7
- class RubyGemsApiKeyCreator
8
- def initialize(host: "https://rubygems.org")
9
- @host = host
10
- end
4
+ module Gem
5
+ module Maintenance
6
+ # Creates a new scoped API key on rubygems.org via the v2 API.
7
+ # Handles OTP header injection and maps HTTP error codes to actionable messages.
8
+ class RubyGemsApiKeyCreator
9
+ def initialize(host: "https://rubygems.org")
10
+ @host = host
11
+ end
11
12
 
12
- def create(username, password, otp: nil)
13
- require "net/http"
13
+ def create(username, password, otp: nil)
14
+ require "net/http"
14
15
 
15
- request = build_request(username, password, otp)
16
- response = http_client.request(request)
17
- parse_response(response)
18
- end
16
+ request = build_request(username, password, otp)
17
+ response = http_client.request(request)
18
+ parse_response(response)
19
+ end
19
20
 
20
- private
21
+ private
21
22
 
22
- def build_request(username, password, otp)
23
- uri = URI("#{@host}/api/v1/api_key")
24
- key_name = "rake-gem-maintenance-ci-#{Time.now.strftime('%Y%m%d')}"
25
- req = Net::HTTP::Post.new(uri)
26
- req.basic_auth(username, password)
27
- req["OTP"] = otp if otp
28
- req["Content-Type"] = "application/x-www-form-urlencoded"
29
- req.body = "name=#{key_name}&push_rubygem=true"
30
- req
31
- end
23
+ def build_request(username, password, otp)
24
+ uri = URI("#{@host}/api/v1/api_key")
25
+ key_name = "rake-gem-maintenance-ci-#{Time.now.strftime('%Y%m%d')}"
26
+ req = Net::HTTP::Post.new(uri)
27
+ req.basic_auth(username, password)
28
+ req["OTP"] = otp if otp
29
+ req["Content-Type"] = "application/x-www-form-urlencoded"
30
+ req.body = "name=#{key_name}&push_rubygem=true"
31
+ req
32
+ end
32
33
 
33
- def http_client
34
- uri = URI(@host)
35
- http = Net::HTTP.new(uri.hostname, uri.port)
36
- http.use_ssl = true
37
- http
38
- end
34
+ def http_client
35
+ uri = URI(@host)
36
+ http = Net::HTTP.new(uri.hostname, uri.port)
37
+ http.use_ssl = true
38
+ http
39
+ end
39
40
 
40
- def parse_response(response)
41
- case response.code.to_i
42
- when 200, 201 then response.body.strip
43
- when 401 then abort "[ERROR] Invalid credentials for #{@host}."
44
- when 403 then abort "[ERROR] Forbidden. Check your MFA settings on #{@host}."
45
- when 449 then abort "[ERROR] OTP required by #{@host}. Set RUBYGEMS_OTP_SEED and retry."
46
- else abort "[ERROR] #{@host} returned #{response.code}: #{response.body.strip}"
41
+ def parse_response(response)
42
+ case response.code.to_i
43
+ when 200, 201 then response.body.strip
44
+ when 401 then abort "[ERROR] Invalid credentials for #{@host}."
45
+ when 403 then abort "[ERROR] Forbidden. Check your MFA settings on #{@host}."
46
+ when 449 then abort "[ERROR] OTP required by #{@host}. Set RUBYGEMS_OTP_SEED and retry."
47
+ else abort "[ERROR] #{@host} returned #{response.code}: #{response.body.strip}"
48
+ end
47
49
  end
48
50
  end
49
51
  end