Skip to content

Add secrets and environments task groups#173

Merged
phelma merged 18 commits into
mainfrom
secrets-and-environments-tasks
Jul 8, 2026
Merged

Add secrets and environments task groups#173
phelma merged 18 commits into
mainfrom
secrets-and-environments-tasks

Conversation

@phelma

@phelma phelma commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Why

The CircleCI → GHA migration needs rake_github to take over rake_circle_ci's provisioning role: a repo's Rakefile declares its secrets and its release environment, and ./go-style tasks push them to GitHub.

What

Two new task groups, each following the deploy_keys conventions (provision/destroy/ensure tasks, namespaceable task set, define_<group>_tasks entry point, embedded in define_repository_tasks):

secrets

  • Writes each secret to both the Actions and Dependabot stores (dependabot-triggered runs cannot read Actions secrets).
  • Values are encrypted client-side with a libsodium sealed box (rbnacl) against each store's own public key, fetched once per run.
  • destroy rescues Octokit::NotFound per store per secret, so re-runs against clean state succeed.

environments

  • Creates/updates deployment environments including protection rules; reviewers are declared as {team: 'slug'} / {user: 'login'} and resolved to the numeric-id shape the API requires (team via team_by_name against the org parsed from the repository, each principal resolved once per run).
  • Optional keys (wait_timer, prevent_self_review, deployment_branch_policy) are omitted from the payload when not supplied; falsy values like wait_timer: 0 are retained.
  • destroy rescues Octokit::NotFound per environment.

Both provision tasks use PUT create-or-update semantics, so re-running against already-provisioned state succeeds.

Dependencies

  • New runtime dependency 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).
  • octokit lower bound raised >= 4.16>= 7.0 (Dependabot secret methods landed in 7.0; lockfile already resolves 10.0.0).
  • Incidental uri 1.0.3 → 1.1.1 lockfile bump (needed to run the suite under a local Ruby whose patched default uri pre-empts the lock).

Testing

TDD throughout; 246 examples, 0 failures; rubocop clean. Encryption is tested for real: specs generate keypairs, decrypt the captured encrypted_value with 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).

Copilot AI review requested due to automatic review settings July 8, 2026 14:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 secrets tasks (provision/destroy/ensure) with client-side encryption using rbnacl sealed boxes and writes secrets to both Actions and Dependabot stores.
  • Introduces environments tasks (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, adds rbnacl ~> 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)
Comment thread README.md
| 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 |
Comment thread README.md
| 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 |
Comment thread README.md
| 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 |
phelma added 3 commits July 8, 2026 15:47
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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 3 comments.

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
@phelma phelma merged commit 586426f into main Jul 8, 2026
1 check passed
@phelma phelma deleted the secrets-and-environments-tasks branch July 8, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants