Add secrets and environments task groups#173
Merged
Merged
Conversation
A reviewer hash with neither :team nor :user previously fell through to a nil user lookup at runtime. Also cover destroy continuing past a fully absent secret.
There was a problem hiding this comment.
Pull request overview
This PR adds two new provisioning task groups—secrets and environments—so rake_github can manage GitHub repository secrets (Actions + Dependabot) and deployment environments (including protection rules/reviewers) as part of the CircleCI → GitHub Actions migration.
Changes:
- Introduces
secretstasks (provision/destroy/ensure) with client-side encryption usingrbnaclsealed boxes and writes secrets to both Actions and Dependabot stores. - Introduces
environmentstasks (provision/destroy/ensure) that create/update environments and resolve team/user reviewers to numeric IDs with per-run caching. - Updates repository task set + public entrypoints/docs/changelog; bumps dependencies (
octokit >= 7.0, addsrbnacl ~> 7.1).
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/rake_github/tasks/secrets/provision_spec.rb | Adds specs covering encryption and Actions/Dependabot secret provisioning behavior. |
| spec/rake_github/tasks/secrets/ensure_spec.rb | Adds specs for secrets ensure task orchestration (destroy then provision). |
| spec/rake_github/tasks/secrets/destroy_spec.rb | Adds specs for secrets deletion and idempotent NotFound handling. |
| spec/rake_github/tasks/environments/provision_spec.rb | Adds specs for environment provisioning, reviewer resolution, and optional payload shaping. |
| spec/rake_github/tasks/environments/ensure_spec.rb | Adds specs for environments ensure task orchestration. |
| spec/rake_github/tasks/environments/destroy_spec.rb | Adds specs for environment deletion and idempotent NotFound handling. |
| spec/rake_github/task_sets/secrets_spec.rb | Adds task set specs for secrets namespaceing and parameter wiring. |
| spec/rake_github/task_sets/environments_spec.rb | Adds task set specs for environments namespaceing and parameter wiring. |
| spec/rake_github/task_sets/repository_spec.rb | Ensures repository task set includes secrets + environments groups and wiring options. |
| spec/rake_github_spec.rb | Adds coverage for new define_secrets_tasks and define_environments_tasks entrypoints. |
| README.md | Documents new task groups, parameters, and CLI task exposure. |
| rake_github.gemspec | Adds rbnacl dependency and raises octokit lower bound for Dependabot secrets APIs. |
| Gemfile.lock | Locks updated dependency set including rbnacl and uri bump. |
| CHANGELOG.md | Notes newly added secrets/environments task groups and repository integration. |
| lib/rake_github/tasks/secrets/provision.rb | Implements provisioning to Actions + Dependabot with sealed-box encryption. |
| lib/rake_github/tasks/secrets/ensure.rb | Implements ensure orchestration for secrets tasks. |
| lib/rake_github/tasks/secrets/destroy.rb | Implements deletion from both stores with NotFound tolerance. |
| lib/rake_github/tasks/secrets.rb | Registers secrets task group requires. |
| lib/rake_github/tasks/environments/provision.rb | Implements environment create/update with optional payload + reviewer resolution. |
| lib/rake_github/tasks/environments/ensure.rb | Implements ensure orchestration for environments tasks. |
| lib/rake_github/tasks/environments/destroy.rb | Implements environment deletion with NotFound tolerance. |
| lib/rake_github/tasks/environments.rb | Registers environments task group requires. |
| lib/rake_github/tasks.rb | Adds secrets/environments to the overall tasks registry. |
| lib/rake_github/task_sets/secrets.rb | Adds secrets task set wrapper with namespaceing and naming overrides. |
| lib/rake_github/task_sets/environments.rb | Adds environments task set wrapper with namespaceing and naming overrides. |
| lib/rake_github/task_sets/repository.rb | Integrates secrets/environments tasks into repository task set and namespace routing. |
| lib/rake_github/task_sets.rb | Registers new task sets. |
| lib/rake_github.rb | Exposes define_secrets_tasks and define_environments_tasks public APIs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def encrypt(base64_public_key, value) | ||
| require 'rbnacl' | ||
|
|
||
| decoded_key = Base64.decode64(base64_public_key) |
| | environments | array | N | Environments to provision on the repository | { name: string, reviewers: array } | [ ] | | ||
| | environments_namespace | symbol | N | Namespace to contain environments tasks | :repository_environments | :environments | | ||
| | environments_destroy_task_name | symbol | N | Option to change the environments destroy task name | :obliterate | :destroy | | ||
| | environments_provision_task_name| symbol | N | Option to change the environments provision task name | :add | :provision | |
| | Parameter | Type | Required | Description | Example | Default | | ||
| |----------------------|--------|----------|------------------------------------------------------------|---------------------------------------------|------------| | ||
| | repository | string | Y | Repository to perform tasks upon | 'organisation/repository_name' | N/A | | ||
| | access_token | string | Y | Github token for authorisation | 'ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' | N/A | |
| | Parameter | Type | Required | Description | Example | Default | | ||
| |----------------------|--------|----------|------------------------------------------------------------|---------------------------------------------|----------------| | ||
| | repository | string | Y | Repository to perform tasks upon | 'organisation/repository_name' | N/A | | ||
| | access_token | string | Y | Github token for authorisation | 'ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' | N/A | |
Previously every secret was written to both the Actions and Dependabot secret stores. Write to Actions by default and only to Dependabot when a secret sets `dependabot: true`, so Actions-only credentials are not exposed to the Dependabot attack surface. Skip fetching the Dependabot public key when no secret opts in.
An explicit empty `reviewers: []` was sent to the API, clearing any existing required reviewers on an already-provisioned environment. Treat an empty array like an absent key and omit it from the payload.
Record the raised octokit lower bound and the new rbnacl/libsodium runtime requirement in the changelog and README, document the per-secret Dependabot opt-in, and note that destroying an environment is irreversible.
Comment on lines
+31
to
+33
| def provision_actions_secrets(client, task) | ||
| public_key = client.get_actions_public_key(task.repository) | ||
| task.secrets.each do |secret| |
Comment on lines
+44
to
+46
| def provision_dependabot_secrets(client, task) | ||
| secrets = task.secrets.select { |secret| secret[:dependabot] } | ||
| return if secrets.empty? |
| end | ||
|
|
||
| # rubocop:disable RSpec/MultipleExpectations | ||
| it 'seals each store value against that store own public key' do |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The CircleCI → GHA migration needs
rake_githubto take overrake_circle_ci's provisioning role: a repo's Rakefile declares its secrets and itsreleaseenvironment, and./go-style tasks push them to GitHub.What
Two new task groups, each following the
deploy_keysconventions (provision/destroy/ensure tasks, namespaceable task set,define_<group>_tasksentry point, embedded indefine_repository_tasks):secretsdestroyrescuesOctokit::NotFoundper store per secret, so re-runs against clean state succeed.environments{team: 'slug'}/{user: 'login'}and resolved to the numeric-id shape the API requires (team viateam_by_nameagainst the org parsed from the repository, each principal resolved once per run).wait_timer,prevent_self_review,deployment_branch_policy) are omitted from the payload when not supplied; falsy values likewait_timer: 0are retained.destroyrescuesOctokit::NotFoundper environment.Both provision tasks use PUT create-or-update semantics, so re-running against already-provisioned state succeeds.
Dependencies
rbnacl ~> 7.1(needs the native libsodium library — installed in CI by Fix CI base image and add libsodium #172;require 'rbnacl'is lazy so merely loading the gem doesn't demand it).octokitlower bound raised>= 4.16→>= 7.0(Dependabot secret methods landed in 7.0; lockfile already resolves 10.0.0).uri1.0.3 → 1.1.1 lockfile bump (needed to run the suite under a local Ruby whose patched defaulturipre-empts the lock).Testing
TDD throughout; 246 examples, 0 failures; rubocop clean. Encryption is tested for real: specs generate keypairs, decrypt the captured
encrypted_valuewith the private key, and assert each store received ciphertext sealed against its own key. Team/user reviewer resolution asserts the exact reviewers payload. Idempotency covered for provisioned and clean state.Merging auto-prereleases; approving the hold then cuts the release (the remaining acceptance criterion).