Skip to content

Commit 586426f

Browse files
authored
Merge pull request #173 from infrablocks/secrets-and-environments-tasks
Add secrets and environments task groups
2 parents 14eaedd + ea855a8 commit 586426f

28 files changed

Lines changed: 2962 additions & 3 deletions

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,46 @@ and this project adheres to
88

99
## Unreleased
1010

11+
### Added
12+
13+
* New `secrets` task group, defined via `RakeGithub.define_secrets_tasks`, for
14+
managing GitHub repository secrets. It exposes `provision`, `destroy` and
15+
`ensure` tasks. Each secret is written to the Actions secret store, and
16+
additionally to the Dependabot secret store when it sets `dependabot: true`,
17+
so that Dependabot-triggered workflow runs can read the secrets they need.
18+
19+
Secrets are supplied as an array of hashes, e.g.
20+
`[{ name: 'SOME_SECRET', value: 'plaintext' }]`, and are encrypted
21+
client-side before being sent to GitHub.
22+
23+
* The `secrets` task group is also included in the tasks defined by
24+
`RakeGithub.define_repository_tasks`.
25+
26+
* New `environments` task group, defined via
27+
`RakeGithub.define_environments_tasks`, for managing GitHub deployment
28+
environments. It exposes `provision`, `destroy` and `ensure` tasks, and
29+
supports protection rules including required reviewers.
30+
31+
Environments are supplied as an array of hashes, e.g.
32+
`[{ name: 'release', reviewers: [{ team: 'maintainers' }] }]`. Only `name`
33+
is required; team and user reviewers are resolved to their numeric ids
34+
before being sent to GitHub.
35+
36+
* The `environments` task group is also included in the tasks defined by
37+
`RakeGithub.define_repository_tasks`.
38+
1139
### Changed
1240

1341
* The `pull_requests:merge` task no longer requires setting the branch name and
1442
commit message provide via arguments as parameters within the task definition.
43+
* The `octokit` dependency lower bound has been raised from `>= 4.16` to
44+
`>= 7.0`, as the Dependabot secret methods used by the `secrets` task group
45+
were introduced in octokit 7.0. Consumers pinning octokit below 7.0 will need
46+
to relax that constraint.
47+
* Added a new runtime dependency on `rbnacl` (`~> 7.1`), used to encrypt
48+
secrets client-side. `rbnacl` requires the native libsodium library to be
49+
installed on the host (see the Installation section of the README); this is
50+
only needed when using the `secrets` task group.
1551

1652
## [0.9.0] 2022-01-28
1753

Gemfile.lock

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ PATH
33
specs:
44
rake_github (0.16.0.pre.3)
55
colored2 (~> 3.1)
6-
octokit (>= 4.16, < 11.0)
6+
octokit (>= 7.0, < 11.0)
77
rake_factory (~> 0.33)
8+
rbnacl (~> 7.1)
89
sshkey (~> 2.0)
910

1011
GEM
@@ -42,6 +43,7 @@ GEM
4243
logger
4344
faraday-net_http (3.4.0)
4445
net-http (>= 0.5.0)
46+
ffi (1.17.4)
4547
gem-release (2.2.4)
4648
git (1.19.1)
4749
addressable (~> 2.8)
@@ -100,6 +102,8 @@ GEM
100102
colored2 (~> 3.1)
101103
rake_factory (~> 0.33)
102104
sshkey (~> 2.0)
105+
rbnacl (7.1.2)
106+
ffi (~> 1)
103107
rchardet (1.8.0)
104108
regexp_parser (2.10.0)
105109
rspec (3.13.1)
@@ -157,7 +161,7 @@ GEM
157161
unicode-display_width (3.1.4)
158162
unicode-emoji (~> 4.0, >= 4.0.4)
159163
unicode-emoji (4.0.4)
160-
uri (1.0.3)
164+
uri (1.1.1)
161165

162166
PLATFORMS
163167
ruby

README.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ Or install it yourself as:
1818

1919
$ gem install rake_github
2020

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+
2136
## Usage
2237

2338
### define_deploy_keys_tasks
@@ -52,6 +67,16 @@ end
5267
| deploy_keys_destroy_task_name | symbol | N | Option to change the destroy task name | :obliterate | :destroy |
5368
| deploy_keys_provision_task_name | symbol | N | Option to change the provision task name | :add | :provision |
5469
| 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 |
5580
| namespace | symbol | N | Namespace for tasks to live in, defaults to root namespace | :rake_github | N/A |
5681

5782
Exposes tasks:
@@ -62,6 +87,12 @@ $ rake -T
6287
rake github:deploy_keys:destroy
6388
rake github:deploy_keys:ensure
6489
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
6596
rake github:pull_requests:merge[branch_name,commit_message]
6697
```
6798

@@ -84,6 +115,145 @@ Merges the PR associated with the `branch_name`. Branch name is required.
84115
`commit_message` is optional, and can contain the original commit message with
85116
the `%s` placeholder, e.g. `pull_requests:merge[new_feature,"%s [skip ci]"]`.
86117

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+
87257
### define_release_task
88258

89259
## Development

lib/rake_github.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ def self.define_deploy_keys_tasks(opts = {}, &)
1010
RakeGithub::TaskSets::DeployKeys.define(opts, &)
1111
end
1212

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+
1321
def self.define_repository_tasks(opts = {}, &)
1422
RakeGithub::TaskSets::Repository.define(opts, &)
1523
end

lib/rake_github/task_sets.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# frozen_string_literal: true
22

33
require_relative 'task_sets/deploy_keys'
4+
require_relative 'task_sets/secrets'
5+
require_relative 'task_sets/environments'
46
require_relative 'task_sets/repository'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)