configure_trusted_publisher 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/configure_trusted_publisher/cli.rb +90 -100
- data/lib/configure_trusted_publisher/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62e88e6f8fe2b2d276cb12750fa89c2197510a32c2c0f173f8d1fb0882c48195
|
4
|
+
data.tar.gz: 1aca9105419c282a2e007f9d0289425bfddbdca0508a008d9142fddb79aa7072
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 593966c8a3b809875c88151be176f7e6c62feeb934f337cf1e54479668fd24dbc4e763fb3bb1eb579292b9f1b4e758fef4c9b9e3db8f59c9677446df9eca974a
|
7
|
+
data.tar.gz: 9ea13772ac9bd771cdf766cdfed92e906aaf05498744172a225c055d5e71a1fd5b2f598ba86e4c5700b78c3c3b42c4d61aab8c1b29b3c52325dd3c0f797032f5
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ConfigureTrustedPublisher
|
2
2
|
|
3
|
-
A small CLI to automate the process of configuring a trusted publisher for a gem.
|
3
|
+
A small CLI to automate the process of configuring a [trusted publisher](https://guides.rubygems.org/trusted-publishing/) for a gem and [automating gem releases](https://guides.rubygems.org/trusted-publishing/releasing-gems/) with GitHub Actions!.
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
@@ -9,6 +9,7 @@ To configure a trusted publisher for a gem, run the following command:
|
|
9
9
|
```console
|
10
10
|
$ gem exec configure_trusted_publisher rubygem
|
11
11
|
Configuring trusted publisher for rubygem0 in /Users/segiddins/Development/github.com/rubygems/configure_trusted_publisher for rubygems/configure_trusted_publisher
|
12
|
+
|
12
13
|
Enter your https://rubygems.org credentials.
|
13
14
|
Don't have an account yet? Create one at https://rubygems.org/sign_up
|
14
15
|
Username/email: : gem-author
|
@@ -9,6 +9,7 @@ require "bundler"
|
|
9
9
|
require "json"
|
10
10
|
require "open3"
|
11
11
|
require "rubygems/gemcutter_utilities"
|
12
|
+
require "yaml"
|
12
13
|
|
13
14
|
Gem.configuration.verbose = true
|
14
15
|
|
@@ -153,17 +154,26 @@ module ConfigureTrustedPublisher
|
|
153
154
|
puts "Configuring trusted publisher for #{rubygem_name} in #{File.expand_path(repository)} for " \
|
154
155
|
"#{github_repository.join('/')}"
|
155
156
|
|
157
|
+
write_release_action(repository, rubygem_name, environment: add_environment)
|
158
|
+
|
156
159
|
gc = GemcutterUtilities.new(
|
157
160
|
say: ->(msg) { puts msg },
|
158
|
-
ask:
|
159
|
-
|
160
|
-
|
161
|
+
ask: lambda { |msg|
|
162
|
+
puts
|
163
|
+
ask msg.chomp(":")
|
164
|
+
},
|
165
|
+
ask_for_password: lambda { |msg|
|
166
|
+
puts
|
167
|
+
ask_secret msg.chomp(":")
|
168
|
+
},
|
169
|
+
terminate_interaction: lambda { |msg|
|
170
|
+
puts
|
171
|
+
exit msg
|
172
|
+
},
|
161
173
|
otp: options[:otp]
|
162
174
|
)
|
163
175
|
gc.sign_in(scope: "configure_trusted_publishers") unless gc.api_key
|
164
176
|
|
165
|
-
write_release_action(repository, rubygem_name)
|
166
|
-
|
167
177
|
owner, name = github_repository
|
168
178
|
config = {
|
169
179
|
"trusted_publisher" => {
|
@@ -235,13 +245,46 @@ module ConfigureTrustedPublisher
|
|
235
245
|
raise "No GitHub repository found for #{gemspec.name}"
|
236
246
|
end
|
237
247
|
|
248
|
+
def add_environment
|
249
|
+
puts
|
250
|
+
return unless ask_yes_or_no("Would you like to add a github environment to allow customizing " \
|
251
|
+
"prerequisites for the action?")
|
252
|
+
|
253
|
+
env_name = "rubygems.org"
|
254
|
+
|
255
|
+
owner, name = github_repository
|
256
|
+
puts "Adding GitHub environment to #{owner}/#{name} to protect the action"
|
257
|
+
if (env = Open3.capture2e("gh", "api", "repos/#{owner}/#{name}/environments").then do |output, status|
|
258
|
+
exit "Failed to list environments for #{owner}/#{name} using `gh api`:\n#{output}" unless status.success?
|
259
|
+
|
260
|
+
JSON.parse(output)["environments"].find { |e| e["name"] == env_name }
|
261
|
+
end)
|
262
|
+
|
263
|
+
puts
|
264
|
+
puts "Environment 'rubygems.org' already exists for #{owner}/#{name}:\n #{env['html_url']}"
|
265
|
+
else
|
266
|
+
Open3.capture2e("gh", "api", "--method", "PUT",
|
267
|
+
"repos/#{owner}/#{name}/environments/#{env_name}").then do |output, status|
|
268
|
+
unless status.success?
|
269
|
+
exit "Failed to create rubygems.org environment for #{owner}/#{name} using `gh api`:\n#{output}"
|
270
|
+
end
|
271
|
+
|
272
|
+
env = JSON.parse(output)
|
273
|
+
puts
|
274
|
+
puts "Created environment 'rubygems.org' for #{owner}/#{name}:\n #{env['html_url']}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
env_name
|
279
|
+
end
|
280
|
+
|
238
281
|
attr_reader :gemspec_source
|
239
282
|
|
240
283
|
def gemspec
|
241
284
|
gemspec_source.specs.first
|
242
285
|
end
|
243
286
|
|
244
|
-
def write_release_action(repository, rubygem_name)
|
287
|
+
def write_release_action(repository, rubygem_name, environment: nil)
|
245
288
|
tag = "Automatically when a new tag matching v* is pushed"
|
246
289
|
manual = "Manually by running a GitHub Action"
|
247
290
|
puts
|
@@ -252,103 +295,50 @@ module ConfigureTrustedPublisher
|
|
252
295
|
],
|
253
296
|
default: "2"
|
254
297
|
)
|
255
|
-
case response
|
256
|
-
when tag
|
257
|
-
write_tag_action(repository)
|
258
|
-
when manual
|
259
|
-
write_manual_action(repository)
|
260
|
-
end
|
261
|
-
end
|
262
298
|
|
263
|
-
def write_tag_action(repository)
|
264
299
|
action_file = File.expand_path(".github/workflows/push_gem.yml", repository)
|
265
300
|
return unless check_action(action_file)
|
266
301
|
|
267
302
|
File.write(
|
268
303
|
action_file,
|
269
|
-
|
270
|
-
name: Push Gem
|
271
|
-
|
272
|
-
on:
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
puts "Created #{action_file}"
|
308
|
-
end
|
309
|
-
|
310
|
-
def write_manual_action(repository)
|
311
|
-
action_file = File.expand_path(".github/workflows/push_gem.yml", repository)
|
312
|
-
return unless check_action(action_file)
|
313
|
-
|
314
|
-
File.write(
|
315
|
-
action_file,
|
316
|
-
<<~YAML
|
317
|
-
name: Push Gem
|
318
|
-
|
319
|
-
on:
|
320
|
-
workflow_dispatch:
|
321
|
-
|
322
|
-
permissions:
|
323
|
-
contents: read
|
324
|
-
|
325
|
-
jobs:
|
326
|
-
push:
|
327
|
-
if: github.repository == '#{github_repository.join('/')}'
|
328
|
-
runs-on: ubuntu-latest
|
329
|
-
|
330
|
-
permissions:
|
331
|
-
contents: write
|
332
|
-
id-token: write
|
333
|
-
|
334
|
-
steps:
|
335
|
-
# Set up
|
336
|
-
- name: Harden Runner
|
337
|
-
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
|
338
|
-
with:
|
339
|
-
egress-policy: audit
|
340
|
-
|
341
|
-
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
342
|
-
- name: Set up Ruby
|
343
|
-
uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # v1.176.0
|
344
|
-
with:
|
345
|
-
bundler-cache: true
|
346
|
-
ruby-version: ruby
|
347
|
-
|
348
|
-
# Release
|
349
|
-
- uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1
|
350
|
-
YAML
|
351
|
-
|
304
|
+
[
|
305
|
+
"name: Push Gem",
|
306
|
+
nil,
|
307
|
+
"on:",
|
308
|
+
" #{response == tag ? "push:\n tags:\n - 'v*'" : 'workflow_dispatch:'}",
|
309
|
+
nil,
|
310
|
+
"permissions:",
|
311
|
+
" contents: read",
|
312
|
+
nil,
|
313
|
+
"jobs:",
|
314
|
+
" push:",
|
315
|
+
" if: github.repository == '#{github_repository.join('/')}'",
|
316
|
+
" runs-on: ubuntu-latest",
|
317
|
+
if environment
|
318
|
+
"\n environment:\n name: #{environment}\n url: https://rubygems.org/gems/#{rubygem_name}\n"
|
319
|
+
end,
|
320
|
+
" permissions:",
|
321
|
+
" contents: write",
|
322
|
+
" id-token: write",
|
323
|
+
nil,
|
324
|
+
" steps:",
|
325
|
+
" # Set up",
|
326
|
+
" - name: Harden Runner",
|
327
|
+
" uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1",
|
328
|
+
" with:",
|
329
|
+
" egress-policy: audit",
|
330
|
+
nil,
|
331
|
+
" - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4",
|
332
|
+
" - name: Set up Ruby",
|
333
|
+
" uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # v1.176.0",
|
334
|
+
" with:",
|
335
|
+
" bundler-cache: true",
|
336
|
+
" ruby-version: ruby",
|
337
|
+
nil,
|
338
|
+
" # Release",
|
339
|
+
" - uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1",
|
340
|
+
nil
|
341
|
+
].join("\n")
|
352
342
|
)
|
353
343
|
puts "Created #{action_file}"
|
354
344
|
end
|
@@ -357,9 +347,9 @@ module ConfigureTrustedPublisher
|
|
357
347
|
return FileUtils.mkdir_p(File.dirname(action_file)) || true unless File.exist?(action_file)
|
358
348
|
|
359
349
|
puts
|
360
|
-
response =
|
361
|
-
"#{action_file} already exists, overwrite?",
|
362
|
-
default:
|
350
|
+
response = ask_yes_or_no(
|
351
|
+
"#{action_file} already exists, overwrite?",
|
352
|
+
default: false
|
363
353
|
)
|
364
354
|
return if response == "No"
|
365
355
|
|