rake_github 0.16.0.pre.3 → 0.16.0.pre.4

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: 6ce3d495a40896a827bc5d040bc9d04c9c8d0a04034797e1588694e66f88ef4a
4
- data.tar.gz: 6a5077f3d2c3d57f0cc6a0bb3eb7f5545a3d0cfd0704484e671708efe4cf93c7
3
+ metadata.gz: f120b956192eb362519228ff9729bb5a0f7dbe55f2c1778140d818fa5b9d9596
4
+ data.tar.gz: 527b937b23abfaf85ec50d4789cb16273aa2ff45c5288256a611d98071e93028
5
5
  SHA512:
6
- metadata.gz: 964e0c598270de1d9d670410d86624af377820dc6e094bcc9b2b7a2def6104956030f30e051fd10e89a147750091509a688c1176385516cbabbbd1f2e60b9c8c
7
- data.tar.gz: 8810f89d5c5720be6c67f83302f038949e54f4d05251897426daface8240bb800ba28a43c0623dbb0fb0cd7a91461172e04bba38c5cded803b9aef832c4598a2
6
+ metadata.gz: 1cc3b0768de864672330930dfb61f51b37c3d7ccf57c3eae2b737b79136f142fd0ae899a26f01149c51c1f02ab09c0bc8dfe811c73996db12e2480d9e04e5c9c
7
+ data.tar.gz: 9bed9380255dc0e0c0f4e5258fe25a18ad981094ac27919d33d6daf17c6ed95e8fcbe1e6e9f5df354885fb9ca57137b78bc1cd1963f123292b2416edce267485
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rake_github (0.16.0.pre.3)
4
+ rake_github (0.16.0.pre.4)
5
5
  colored2 (~> 3.1)
6
- octokit (>= 4.16, < 11.0)
6
+ octokit (>= 7.0, < 11.0)
7
7
  rake_factory (~> 0.33)
8
+ rbnacl (~> 7.1)
8
9
  sshkey (~> 2.0)
9
10
 
10
11
  GEM
@@ -42,6 +43,7 @@ GEM
42
43
  logger
43
44
  faraday-net_http (3.4.0)
44
45
  net-http (>= 0.5.0)
46
+ ffi (1.17.4)
45
47
  gem-release (2.2.4)
46
48
  git (1.19.1)
47
49
  addressable (~> 2.8)
@@ -100,6 +102,8 @@ GEM
100
102
  colored2 (~> 3.1)
101
103
  rake_factory (~> 0.33)
102
104
  sshkey (~> 2.0)
105
+ rbnacl (7.1.2)
106
+ ffi (~> 1)
103
107
  rchardet (1.8.0)
104
108
  regexp_parser (2.10.0)
105
109
  rspec (3.13.1)
@@ -157,7 +161,7 @@ GEM
157
161
  unicode-display_width (3.1.4)
158
162
  unicode-emoji (~> 4.0, >= 4.0.4)
159
163
  unicode-emoji (4.0.4)
160
- uri (1.0.3)
164
+ uri (1.1.1)
161
165
 
162
166
  PLATFORMS
163
167
  ruby
data/README.md CHANGED
@@ -18,6 +18,21 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install rake_github
20
20
 
21
+ ### System dependencies
22
+
23
+ The `secrets` task group encrypts secrets client-side using `rbnacl`, which
24
+ requires the native [libsodium](https://libsodium.org) library to be present on
25
+ the host. Install it before running any `secrets` task:
26
+
27
+ # macOS
28
+ $ brew install libsodium
29
+
30
+ # Debian/Ubuntu
31
+ $ apt-get install libsodium23
32
+
33
+ libsodium is only required when using the `secrets` tasks; the other task groups
34
+ have no additional system dependencies.
35
+
21
36
  ## Usage
22
37
 
23
38
  ### define_deploy_keys_tasks
@@ -52,6 +67,16 @@ end
52
67
  | deploy_keys_destroy_task_name | symbol | N | Option to change the destroy task name | :obliterate | :destroy |
53
68
  | deploy_keys_provision_task_name | symbol | N | Option to change the provision task name | :add | :provision |
54
69
  | deploy_keys_ensure_task_name | symbol | N | Option to change the ensure task name | :destroy_and_provision | :ensure |
70
+ | secrets | array | N | Secrets to provision on the repository | { name: string, value: string, dependabot: bool } | [ ] |
71
+ | secrets_namespace | symbol | N | Namespace to contain secrets tasks | :repository_secrets | :secrets |
72
+ | secrets_destroy_task_name | symbol | N | Option to change the secrets destroy task name | :obliterate | :destroy |
73
+ | secrets_provision_task_name | symbol | N | Option to change the secrets provision task name | :add | :provision |
74
+ | secrets_ensure_task_name | symbol | N | Option to change the secrets ensure task name | :destroy_and_provision | :ensure |
75
+ | environments | array | N | Environments to provision on the repository | { name: string, reviewers: array } | [ ] |
76
+ | environments_namespace | symbol | N | Namespace to contain environments tasks | :repository_environments | :environments |
77
+ | environments_destroy_task_name | symbol | N | Option to change the environments destroy task name | :obliterate | :destroy |
78
+ | environments_provision_task_name| symbol | N | Option to change the environments provision task name | :add | :provision |
79
+ | environments_ensure_task_name | symbol | N | Option to change the environments ensure task name | :destroy_and_provision | :ensure |
55
80
  | namespace | symbol | N | Namespace for tasks to live in, defaults to root namespace | :rake_github | N/A |
56
81
 
57
82
  Exposes tasks:
@@ -62,6 +87,12 @@ $ rake -T
62
87
  rake github:deploy_keys:destroy
63
88
  rake github:deploy_keys:ensure
64
89
  rake github:deploy_keys:provision
90
+ rake github:secrets:destroy
91
+ rake github:secrets:ensure
92
+ rake github:secrets:provision
93
+ rake github:environments:destroy
94
+ rake github:environments:ensure
95
+ rake github:environments:provision
65
96
  rake github:pull_requests:merge[branch_name,commit_message]
66
97
  ```
67
98
 
@@ -84,6 +115,145 @@ Merges the PR associated with the `branch_name`. Branch name is required.
84
115
  `commit_message` is optional, and can contain the original commit message with
85
116
  the `%s` placeholder, e.g. `pull_requests:merge[new_feature,"%s [skip ci]"]`.
86
117
 
118
+ ### define_secrets_tasks
119
+
120
+ Sets up rake tasks for managing repository secrets. Each secret is written to
121
+ the Actions secret store by default. A secret can additionally be written to the
122
+ Dependabot secret store by setting `dependabot: true`, so that
123
+ Dependabot-triggered workflow runs can read the secrets they need. Secrets are
124
+ encrypted client-side before being sent to GitHub.
125
+
126
+ These tasks require the native libsodium library to be installed on the host —
127
+ see [System dependencies](#system-dependencies) above.
128
+
129
+ ```ruby
130
+ require 'rake_github'
131
+
132
+ RakeGithub.define_secrets_tasks(
133
+ namespace: :secrets,
134
+ repository: 'org/repo', # required
135
+ ) do |t|
136
+ t.access_token = "your_github_access_token" # required
137
+ t.secrets = [
138
+ {
139
+ name: 'SOME_SECRET',
140
+ value: 'some-plaintext-value'
141
+ },
142
+ {
143
+ name: 'SHARED_SECRET',
144
+ value: 'another-plaintext-value',
145
+ dependabot: true # also write to the Dependabot store
146
+ }
147
+ ]
148
+ end
149
+ ```
150
+
151
+ | Parameter | Type | Required | Description | Example | Default |
152
+ |----------------------|--------|----------|------------------------------------------------------------|---------------------------------------------|------------|
153
+ | repository | string | Y | Repository to perform tasks upon | 'organisation/repository_name' | N/A |
154
+ | access_token | string | Y | Github token for authorisation | 'ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' | N/A |
155
+ | secrets | array | N | Secrets to provision on the repository | { name: string, value: string, dependabot: bool } | [ ] |
156
+ | destroy_task_name | symbol | N | Option to change the destroy task name | :obliterate | :destroy |
157
+ | provision_task_name | symbol | N | Option to change the provision task name | :add | :provision |
158
+ | ensure_task_name | symbol | N | Option to change the ensure task name | :destroy_and_provision | :ensure |
159
+ | namespace | symbol | N | Namespace for tasks to live in, defaults to root namespace | :secrets | N/A |
160
+
161
+ Exposes tasks:
162
+
163
+ ```shell
164
+ $ rake -T
165
+
166
+ rake secrets:destroy
167
+ rake secrets:ensure
168
+ rake secrets:provision
169
+ ```
170
+
171
+ #### secrets:provision
172
+
173
+ Provisions the specified secrets to the repository, writing each one to the
174
+ Actions secret store and, for secrets marked `dependabot: true`, also to the
175
+ Dependabot secret store.
176
+
177
+ #### secrets:destroy
178
+
179
+ Destroys the specified secrets from the repository, removing each one from both
180
+ the Actions and Dependabot secret stores.
181
+
182
+ #### secrets:ensure
183
+
184
+ Destroys and then provisions the specified secrets on the repository.
185
+
186
+ ### define_environments_tasks
187
+
188
+ Sets up rake tasks for managing GitHub deployment environments, including
189
+ protection rules such as required reviewers. Team and user reviewers are
190
+ resolved to their numeric ids before being sent to GitHub.
191
+
192
+ ```ruby
193
+ require 'rake_github'
194
+
195
+ RakeGithub.define_environments_tasks(
196
+ namespace: :environments,
197
+ repository: 'org/repo', # required
198
+ ) do |t|
199
+ t.access_token = "your_github_access_token" # required
200
+ t.environments = [
201
+ {
202
+ name: 'release',
203
+ wait_timer: 0,
204
+ prevent_self_review: false,
205
+ reviewers: [
206
+ { team: 'maintainers' },
207
+ { user: 'someone' }
208
+ ],
209
+ deployment_branch_policy: {
210
+ protected_branches: true,
211
+ custom_branch_policies: false
212
+ }
213
+ }
214
+ ]
215
+ end
216
+ ```
217
+
218
+ Only `name` is required for each environment; every other key is optional and
219
+ is omitted from the GitHub API payload when absent.
220
+
221
+ | Parameter | Type | Required | Description | Example | Default |
222
+ |----------------------|--------|----------|------------------------------------------------------------|---------------------------------------------|----------------|
223
+ | repository | string | Y | Repository to perform tasks upon | 'organisation/repository_name' | N/A |
224
+ | access_token | string | Y | Github token for authorisation | 'ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' | N/A |
225
+ | environments | array | N | Environments to provision on the repository | { name: string, reviewers: array } | [ ] |
226
+ | destroy_task_name | symbol | N | Option to change the destroy task name | :obliterate | :destroy |
227
+ | provision_task_name | symbol | N | Option to change the provision task name | :add | :provision |
228
+ | ensure_task_name | symbol | N | Option to change the ensure task name | :destroy_and_provision | :ensure |
229
+ | namespace | symbol | N | Namespace for tasks to live in, defaults to root namespace | :environments | N/A |
230
+
231
+ Exposes tasks:
232
+
233
+ ```shell
234
+ $ rake -T
235
+
236
+ rake environments:destroy
237
+ rake environments:ensure
238
+ rake environments:provision
239
+ ```
240
+
241
+ #### environments:provision
242
+
243
+ Provisions the specified environments on the repository, resolving any team
244
+ and user reviewers to their numeric ids.
245
+
246
+ #### environments:destroy
247
+
248
+ Destroys the specified environments from the repository. This is irreversible
249
+ and also discards each environment's protection rules, environment secrets and
250
+ deployment history. `environments:ensure` therefore fully recreates each
251
+ environment rather than patching it in place.
252
+
253
+ #### environments:ensure
254
+
255
+ Destroys and then provisions the specified environments on the repository.
256
+
87
257
  ### define_release_task
88
258
 
89
259
  ## Development
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+
5
+ require_relative '../tasks'
6
+
7
+ module RakeGithub
8
+ module TaskSets
9
+ class Environments < RakeFactory::TaskSet
10
+ prepend RakeFactory::Namespaceable
11
+
12
+ parameter :repository, required: true
13
+ parameter :access_token, required: true
14
+ parameter :environments, default: []
15
+
16
+ parameter :destroy_task_name, default: :destroy
17
+ parameter :provision_task_name, default: :provision
18
+ parameter :ensure_task_name, default: :ensure
19
+
20
+ task Tasks::Environments::Provision,
21
+ name: RakeFactory::DynamicValue.new { |ts|
22
+ ts.provision_task_name
23
+ }
24
+ task Tasks::Environments::Destroy,
25
+ name: RakeFactory::DynamicValue.new { |ts|
26
+ ts.destroy_task_name
27
+ }
28
+ task Tasks::Environments::Ensure,
29
+ name: RakeFactory::DynamicValue.new { |ts|
30
+ ts.ensure_task_name
31
+ }
32
+ end
33
+ end
34
+ end
@@ -12,12 +12,24 @@ module RakeGithub
12
12
  parameter :repository, required: true
13
13
  parameter :access_token, required: true
14
14
  parameter :deploy_keys, default: []
15
+ parameter :secrets, default: []
16
+ parameter :environments, default: []
15
17
 
16
18
  parameter :deploy_keys_namespace, default: :deploy_keys
17
19
  parameter :deploy_keys_destroy_task_name, default: :destroy
18
20
  parameter :deploy_keys_provision_task_name, default: :provision
19
21
  parameter :deploy_keys_ensure_task_name, default: :ensure
20
22
 
23
+ parameter :secrets_namespace, default: :secrets
24
+ parameter :secrets_destroy_task_name, default: :destroy
25
+ parameter :secrets_provision_task_name, default: :provision
26
+ parameter :secrets_ensure_task_name, default: :ensure
27
+
28
+ parameter :environments_namespace, default: :environments
29
+ parameter :environments_destroy_task_name, default: :destroy
30
+ parameter :environments_provision_task_name, default: :provision
31
+ parameter :environments_ensure_task_name, default: :ensure
32
+
21
33
  task Tasks::DeployKeys::Provision,
22
34
  name: RakeFactory::DynamicValue.new { |ts|
23
35
  ts.deploy_keys_provision_task_name
@@ -36,6 +48,42 @@ module RakeGithub
36
48
  destroy_task_name: RakeFactory::DynamicValue.new { |ts|
37
49
  ts.deploy_keys_destroy_task_name
38
50
  }
51
+ task Tasks::Secrets::Provision,
52
+ name: RakeFactory::DynamicValue.new { |ts|
53
+ ts.secrets_provision_task_name
54
+ }
55
+ task Tasks::Secrets::Destroy,
56
+ name: RakeFactory::DynamicValue.new { |ts|
57
+ ts.secrets_destroy_task_name
58
+ }
59
+ task Tasks::Secrets::Ensure,
60
+ name: RakeFactory::DynamicValue.new { |ts|
61
+ ts.secrets_ensure_task_name
62
+ },
63
+ provision_task_name: RakeFactory::DynamicValue.new { |ts|
64
+ ts.secrets_provision_task_name
65
+ },
66
+ destroy_task_name: RakeFactory::DynamicValue.new { |ts|
67
+ ts.secrets_destroy_task_name
68
+ }
69
+ task Tasks::Environments::Provision,
70
+ name: RakeFactory::DynamicValue.new { |ts|
71
+ ts.environments_provision_task_name
72
+ }
73
+ task Tasks::Environments::Destroy,
74
+ name: RakeFactory::DynamicValue.new { |ts|
75
+ ts.environments_destroy_task_name
76
+ }
77
+ task Tasks::Environments::Ensure,
78
+ name: RakeFactory::DynamicValue.new { |ts|
79
+ ts.environments_ensure_task_name
80
+ },
81
+ provision_task_name: RakeFactory::DynamicValue.new { |ts|
82
+ ts.environments_provision_task_name
83
+ },
84
+ destroy_task_name: RakeFactory::DynamicValue.new { |ts|
85
+ ts.environments_destroy_task_name
86
+ }
39
87
  task Tasks::PullRequests::Merge
40
88
 
41
89
  def define_on(application)
@@ -57,6 +105,8 @@ module RakeGithub
57
105
  def resolve_namespace(task_definition)
58
106
  case task_definition.klass.to_s
59
107
  when /DeployKeys/ then deploy_keys_namespace
108
+ when /Secrets/ then secrets_namespace
109
+ when /Environments/ then environments_namespace
60
110
  when /PullRequests/ then :pull_requests
61
111
  end
62
112
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+
5
+ require_relative '../tasks'
6
+
7
+ module RakeGithub
8
+ module TaskSets
9
+ class Secrets < RakeFactory::TaskSet
10
+ prepend RakeFactory::Namespaceable
11
+
12
+ parameter :repository, required: true
13
+ parameter :access_token, required: true
14
+ parameter :secrets, default: []
15
+
16
+ parameter :destroy_task_name, default: :destroy
17
+ parameter :provision_task_name, default: :provision
18
+ parameter :ensure_task_name, default: :ensure
19
+
20
+ task Tasks::Secrets::Provision,
21
+ name: RakeFactory::DynamicValue.new { |ts|
22
+ ts.provision_task_name
23
+ }
24
+ task Tasks::Secrets::Destroy,
25
+ name: RakeFactory::DynamicValue.new { |ts|
26
+ ts.destroy_task_name
27
+ }
28
+ task Tasks::Secrets::Ensure,
29
+ name: RakeFactory::DynamicValue.new { |ts|
30
+ ts.ensure_task_name
31
+ }
32
+ end
33
+ end
34
+ end
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'task_sets/deploy_keys'
4
+ require_relative 'task_sets/secrets'
5
+ require_relative 'task_sets/environments'
4
6
  require_relative 'task_sets/repository'
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+ require 'octokit'
5
+
6
+ module RakeGithub
7
+ module Tasks
8
+ module Environments
9
+ class Destroy < RakeFactory::Task
10
+ default_name :destroy
11
+ default_description(RakeFactory::DynamicValue.new do |t|
12
+ "Destroys environments from the #{t.repository} repository"
13
+ end)
14
+
15
+ parameter :repository, required: true
16
+ parameter :access_token, required: true
17
+ parameter :environments, default: []
18
+
19
+ action do |t|
20
+ client = Octokit::Client.new(access_token:)
21
+
22
+ $stdout.puts 'Removing specified environments from the ' \
23
+ "'#{t.repository}' repository... "
24
+ t.environments.each do |environment|
25
+ $stdout.print "Removing '#{environment[:name]}'... "
26
+ delete_environment(client, t.repository, environment[:name])
27
+ $stdout.puts 'Done.'
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def delete_environment(client, repository, name)
34
+ client.delete_environment(repository, name)
35
+ rescue Octokit::NotFound
36
+ nil
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+
5
+ module RakeGithub
6
+ module Tasks
7
+ module Environments
8
+ class Ensure < RakeFactory::Task
9
+ default_name :ensure
10
+ default_description(RakeFactory::DynamicValue.new do |t|
11
+ 'Ensure environments are configured on the ' \
12
+ "#{t.repository} repository"
13
+ end)
14
+
15
+ parameter :repository, required: true
16
+
17
+ parameter :provision_task_name, default: :provision
18
+ parameter :destroy_task_name, default: :destroy
19
+
20
+ action do |t, args|
21
+ t.application[t.destroy_task_name, t.scope].invoke(*args)
22
+ t.application[t.provision_task_name, t.scope].invoke(*args)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+ require 'octokit'
5
+
6
+ module RakeGithub
7
+ module Tasks
8
+ module Environments
9
+ class Provision < RakeFactory::Task
10
+ default_name :provision
11
+ default_description(RakeFactory::DynamicValue.new do |t|
12
+ "Provision environments to the #{t.repository} repository"
13
+ end)
14
+
15
+ parameter :repository, required: true
16
+ parameter :access_token, required: true
17
+ parameter :environments, default: []
18
+
19
+ action do |t|
20
+ client = Octokit::Client.new(access_token:)
21
+ org = t.repository.split('/').first
22
+
23
+ $stdout.puts 'Provisioning specified environments on the ' \
24
+ "'#{t.repository}' repository... "
25
+ t.environments.each do |environment|
26
+ $stdout.print "Adding '#{environment[:name]}'... "
27
+ client.create_or_update_environment(
28
+ t.repository,
29
+ environment[:name],
30
+ environment_options(client, org, environment)
31
+ )
32
+ $stdout.puts 'Done.'
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def environment_options(client, org, environment)
39
+ {
40
+ wait_timer: environment[:wait_timer],
41
+ prevent_self_review: environment[:prevent_self_review],
42
+ reviewers: resolve_reviewers(client, org, environment[:reviewers]),
43
+ deployment_branch_policy: environment[:deployment_branch_policy]
44
+ }.compact
45
+ end
46
+
47
+ def resolve_reviewers(client, org, reviewers)
48
+ return nil if reviewers.nil? || reviewers.empty?
49
+
50
+ reviewers.map { |reviewer| resolve_reviewer(client, org, reviewer) }
51
+ end
52
+
53
+ def resolve_reviewer(client, org, reviewer)
54
+ if reviewer[:team]
55
+ { type: 'Team', id: resolve_team_id(client, org, reviewer[:team]) }
56
+ elsif reviewer[:user]
57
+ { type: 'User', id: resolve_user_id(client, reviewer[:user]) }
58
+ else
59
+ raise(ArgumentError,
60
+ "invalid reviewer: #{reviewer.inspect} " \
61
+ '(must have :team or :user)')
62
+ end
63
+ end
64
+
65
+ def resolve_team_id(client, org, slug)
66
+ team_ids[slug] ||= client.team_by_name(org, slug).id
67
+ end
68
+
69
+ def resolve_user_id(client, login)
70
+ user_ids[login] ||= client.user(login).id
71
+ end
72
+
73
+ def team_ids
74
+ @team_ids ||= {}
75
+ end
76
+
77
+ def user_ids
78
+ @user_ids ||= {}
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'environments/provision'
4
+ require_relative 'environments/destroy'
5
+ require_relative 'environments/ensure'
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+ require 'octokit'
5
+
6
+ module RakeGithub
7
+ module Tasks
8
+ module Secrets
9
+ class Destroy < RakeFactory::Task
10
+ default_name :destroy
11
+ default_description(RakeFactory::DynamicValue.new do |t|
12
+ "Destroys secrets from the #{t.repository} repository"
13
+ end)
14
+
15
+ parameter :repository, required: true
16
+ parameter :access_token, required: true
17
+ parameter :secrets, default: []
18
+
19
+ action do |t|
20
+ client = Octokit::Client.new(access_token:)
21
+
22
+ $stdout.puts 'Removing specified secrets from the ' \
23
+ "'#{t.repository}' repository... "
24
+ t.secrets.each do |secret|
25
+ $stdout.print "Removing '#{secret[:name]}'... "
26
+ delete_actions_secret(client, t.repository, secret[:name])
27
+ delete_dependabot_secret(client, t.repository, secret[:name])
28
+ $stdout.puts 'Done.'
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def delete_actions_secret(client, repository, name)
35
+ client.delete_actions_secret(repository, name)
36
+ rescue Octokit::NotFound
37
+ nil
38
+ end
39
+
40
+ def delete_dependabot_secret(client, repository, name)
41
+ client.delete_dependabot_secret(repository, name)
42
+ rescue Octokit::NotFound
43
+ nil
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake_factory'
4
+
5
+ module RakeGithub
6
+ module Tasks
7
+ module Secrets
8
+ class Ensure < RakeFactory::Task
9
+ default_name :ensure
10
+ default_description(RakeFactory::DynamicValue.new do |t|
11
+ 'Ensure secrets are configured on the ' \
12
+ "#{t.repository} repository"
13
+ end)
14
+
15
+ parameter :repository, required: true
16
+
17
+ parameter :provision_task_name, default: :provision
18
+ parameter :destroy_task_name, default: :destroy
19
+
20
+ action do |t, args|
21
+ t.application[t.destroy_task_name, t.scope].invoke(*args)
22
+ t.application[t.provision_task_name, t.scope].invoke(*args)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'rake_factory'
5
+ require 'octokit'
6
+
7
+ module RakeGithub
8
+ module Tasks
9
+ module Secrets
10
+ class Provision < RakeFactory::Task
11
+ default_name :provision
12
+ default_description(RakeFactory::DynamicValue.new do |t|
13
+ "Provision secrets to the #{t.repository} repository"
14
+ end)
15
+
16
+ parameter :repository, required: true
17
+ parameter :access_token, required: true
18
+ parameter :secrets, default: []
19
+
20
+ action do |t|
21
+ client = Octokit::Client.new(access_token:)
22
+
23
+ $stdout.puts 'Provisioning specified secrets on the ' \
24
+ "'#{t.repository}' repository... "
25
+ provision_actions_secrets(client, t)
26
+ provision_dependabot_secrets(client, t)
27
+ end
28
+
29
+ private
30
+
31
+ def provision_actions_secrets(client, task)
32
+ public_key = client.get_actions_public_key(task.repository)
33
+ task.secrets.each do |secret|
34
+ $stdout.print "Adding '#{secret[:name]}' to Actions... "
35
+ client.create_or_update_actions_secret(
36
+ task.repository,
37
+ secret[:name],
38
+ secret_options(public_key, secret[:value])
39
+ )
40
+ $stdout.puts 'Done.'
41
+ end
42
+ end
43
+
44
+ def provision_dependabot_secrets(client, task)
45
+ secrets = task.secrets.select { |secret| secret[:dependabot] }
46
+ return if secrets.empty?
47
+
48
+ public_key = client.get_dependabot_public_key(task.repository)
49
+ secrets.each do |secret|
50
+ write_dependabot_secret(client, task, public_key, secret)
51
+ end
52
+ end
53
+
54
+ def write_dependabot_secret(client, task, public_key, secret)
55
+ $stdout.print "Adding '#{secret[:name]}' to Dependabot... "
56
+ client.create_or_update_dependabot_secret(
57
+ task.repository,
58
+ secret[:name],
59
+ secret_options(public_key, secret[:value])
60
+ )
61
+ $stdout.puts 'Done.'
62
+ end
63
+
64
+ def secret_options(public_key, value)
65
+ {
66
+ key_id: public_key.key_id,
67
+ encrypted_value: encrypt(public_key.key, value)
68
+ }
69
+ end
70
+
71
+ def encrypt(base64_public_key, value)
72
+ require 'rbnacl'
73
+
74
+ decoded_key = Base64.decode64(base64_public_key)
75
+ box = RbNaCl::Boxes::Sealed.from_public_key(
76
+ RbNaCl::PublicKey.new(decoded_key)
77
+ )
78
+ Base64.strict_encode64(box.encrypt(value))
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'secrets/provision'
4
+ require_relative 'secrets/destroy'
5
+ require_relative 'secrets/ensure'
@@ -3,3 +3,5 @@
3
3
  require_relative 'tasks/deploy_keys'
4
4
  require_relative 'tasks/releases'
5
5
  require_relative 'tasks/pull_requests'
6
+ require_relative 'tasks/secrets'
7
+ require_relative 'tasks/environments'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RakeGithub
4
- VERSION = '0.16.0.pre.3'
4
+ VERSION = '0.16.0.pre.4'
5
5
  end
data/lib/rake_github.rb CHANGED
@@ -10,6 +10,14 @@ module RakeGithub
10
10
  RakeGithub::TaskSets::DeployKeys.define(opts, &)
11
11
  end
12
12
 
13
+ def self.define_secrets_tasks(opts = {}, &)
14
+ RakeGithub::TaskSets::Secrets.define(opts, &)
15
+ end
16
+
17
+ def self.define_environments_tasks(opts = {}, &)
18
+ RakeGithub::TaskSets::Environments.define(opts, &)
19
+ end
20
+
13
21
  def self.define_repository_tasks(opts = {}, &)
14
22
  RakeGithub::TaskSets::Repository.define(opts, &)
15
23
  end
data/rake_github.gemspec CHANGED
@@ -36,8 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.required_ruby_version = '>= 3.1'
37
37
 
38
38
  spec.add_dependency 'colored2', '~> 3.1'
39
- spec.add_dependency 'octokit', '>= 4.16', '< 11.0'
39
+ spec.add_dependency 'octokit', '>= 7.0', '< 11.0'
40
40
  spec.add_dependency 'rake_factory', '~> 0.33'
41
+ spec.add_dependency 'rbnacl', '~> 7.1'
41
42
  spec.add_dependency 'sshkey', '~> 2.0'
42
43
 
43
44
  spec.add_development_dependency 'activesupport'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rake_github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0.pre.3
4
+ version: 0.16.0.pre.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - InfraBlocks Maintainers
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4.16'
33
+ version: '7.0'
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
36
  version: '11.0'
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: '4.16'
43
+ version: '7.0'
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '11.0'
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0.33'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rbnacl
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '7.1'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '7.1'
61
75
  - !ruby/object:Gem::Dependency
62
76
  name: sshkey
63
77
  requirement: !ruby/object:Gem::Requirement
@@ -317,16 +331,26 @@ files:
317
331
  - lib/rake_github/exceptions/required_argument_unset.rb
318
332
  - lib/rake_github/task_sets.rb
319
333
  - lib/rake_github/task_sets/deploy_keys.rb
334
+ - lib/rake_github/task_sets/environments.rb
320
335
  - lib/rake_github/task_sets/repository.rb
336
+ - lib/rake_github/task_sets/secrets.rb
321
337
  - lib/rake_github/tasks.rb
322
338
  - lib/rake_github/tasks/deploy_keys.rb
323
339
  - lib/rake_github/tasks/deploy_keys/destroy.rb
324
340
  - lib/rake_github/tasks/deploy_keys/ensure.rb
325
341
  - lib/rake_github/tasks/deploy_keys/provision.rb
342
+ - lib/rake_github/tasks/environments.rb
343
+ - lib/rake_github/tasks/environments/destroy.rb
344
+ - lib/rake_github/tasks/environments/ensure.rb
345
+ - lib/rake_github/tasks/environments/provision.rb
326
346
  - lib/rake_github/tasks/pull_requests.rb
327
347
  - lib/rake_github/tasks/pull_requests/merge.rb
328
348
  - lib/rake_github/tasks/releases.rb
329
349
  - lib/rake_github/tasks/releases/create.rb
350
+ - lib/rake_github/tasks/secrets.rb
351
+ - lib/rake_github/tasks/secrets/destroy.rb
352
+ - lib/rake_github/tasks/secrets/ensure.rb
353
+ - lib/rake_github/tasks/secrets/provision.rb
330
354
  - lib/rake_github/version.rb
331
355
  - rake_github.gemspec
332
356
  homepage: https://github.com/infrablocks/rake_github