Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Actions Environment Secret Management #1607

Merged
merged 2 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions lib/octokit/client/actions_secrets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,59 @@ def create_or_update_actions_secret(repo, name, options)
def delete_actions_secret(repo, name)
boolean_from_response :delete, "#{Repository.path repo}/actions/secrets/#{name}"
end

# Get environment public key for secrets encryption
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param environment [String] Name of environment
# @return [Hash] key_id and key
# @see https://docs.github.com/en/rest/actions/secrets#get-an-environment-public-key
def get_actions_environment_public_key(repo, environment)
get "#{Repository.path repo}/environments/#{environment}/secrets/public-key"
end

# List environment secrets
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param environment [String] Name of environment
# @return [Hash] total_count and list of secrets (each item is hash with name, created_at and updated_at)
# @see https://developer.github.com/v3/actions/secrets/#list-environment-secrets
def list_actions_environment_secrets(repo, environment)
paginate "#{Repository.path repo}/environments/#{environment}/secrets" do |data, last_response |
data.secrets.concat last_response.data.secrets
end
end

# Get an environment secret
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param environment [String] Name of environment
# @param name [String] Name of secret
# @return [Hash] name, created_at and updated_at
# @see https://docs.github.com/en/rest/actions/secrets#get-an-environment-secret
def get_actions_environment_secret(repo, environment, name)
get "#{Repository.path repo}/environments/#{environment}/secrets/#{name}"
end

# Create or update an environment secret
#
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param environment [String] Name of environment
# @param name [String] Name of secret
# @param options [Hash] encrypted_value and key_id
# @see https://docs.github.com/en/rest/actions/secrets#create-or-update-an-environment-secret
def create_or_update_actions_environment_secret(repo, environment, name, options)
put "#{Repository.path repo}/environments/#{environment}/secrets/#{name}", options
end

# Delete environment secret
# @param repo [Integer, String, Hash, Repository] A GitHub repository
# @param environment [String] Name of environment
# @param name [String] Name of secret
# @see https://docs.github.com/en/rest/actions/secrets#delete-an-environment-secret
def delete_actions_environment_secret(repo, environment, name)
boolean_from_response :delete, "#{Repository.path repo}/environments/#{environment}/secrets/#{name}"
end
end
end
end

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

102 changes: 102 additions & 0 deletions spec/octokit/client/actions_secrets_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ def create_box(public_key)
expect(box[:key_id]).not_to be_empty
end
end # .get_actions_public_key

# describe '.get_actions_environment_public_key', :vcr do
# it 'get environment specific public key for secrets encryption' do
# box = create_box(@client.get_actions_environment_public_key(@repo.id, 'production'))
# expect(box[:key_id]).not_to be_empty
# end
# end # .get_actions_environment_public_key
end

context 'with a repo without secrets' do
Expand All @@ -54,6 +61,14 @@ def create_box(public_key)
end
end # .list_actions_secrets

# describe '.list_actions_environment_secrets', :vcr do
# it 'returns empty list of secrets' do
# secrets = @client.list_actions_environment_secrets(@repo.id, 'production')
# expect(secrets.total_count).to eq(0)
# expect(secrets.secrets).to be_empty
# end
# end # .list_actions_environment_secrets

describe '.create_or_update_actions_secret', :vcr do
it 'creating secret returns 201' do
box = create_box(@client.get_actions_public_key(@repo.id))
Expand All @@ -65,6 +80,18 @@ def create_box(public_key)
expect(@client.last_response.status).to eq(201)
end
end # .create_or_update_actions_secret

# describe '.create_or_update_actions_environment_secret', :vcr do
# it 'creating secret returns 201' do
# box = create_box(@client.get_actions_environment_public_key(@repo.id, 'production'))
# encrypted = box[:box].encrypt(@secrets.first[:value])
# @client.create_or_update_actions_environment_secret(
# @repo.id, 'production', @secrets.first[:name],
# key_id: box[:key_id], encrypted_value: Base64.strict_encode64(encrypted)
# )
# expect(@client.last_response.status).to eq(201)
# end
# end # .create_or_update_actions_environment_secret
end

context 'with a repository with a secret' do
Expand Down Expand Up @@ -140,4 +167,79 @@ def create_box(public_key)
end
end
end

context 'with a repository environment with a secret' do
before(:each) do
@repo = @client.create_repository('secret-repo')
@client.create_or_update_environment(@repo.id, 'production')
@box = create_box(@client.get_actions_environment_public_key(@repo.id, 'production'))
@secrets.each do |secret|
encrypted = @box[:box].encrypt(secret[:value])
@client.create_or_update_actions_environment_secret(
@repo.id, 'production', secret[:name],
key_id: @box[:key_id], encrypted_value: Base64.strict_encode64(encrypted)
)
end
end

after(:each) do
@client.delete_repository(@repo.full_name) unless @repo.nil?
rescue Octokit::NotFound
end

describe '.list_actions_environment_secrets', :vcr do
it 'returns list of two secrets' do
secrets = @client.list_actions_environment_secrets(@repo.id, 'production')
expect(secrets.total_count).to eq(2)
expect(secrets.secrets[0].name).to eq(@secrets.first[:name].upcase)
end

it 'paginates the results' do
@client.per_page = 1
allow(@client).to receive(:paginate).and_call_original
secrets = @client.list_actions_environment_secrets(@repo.id, 'production')

expect(@client).to have_received(:paginate)
expect(secrets.total_count).to eq(2)
expect(secrets.secrets.count).to eq(1)
end

it 'auto-paginates the results' do
@client.auto_paginate = true
@client.per_page = 1
allow(@client).to receive(:paginate).and_call_original
secrets = @client.list_actions_environment_secrets(@repo.id, 'production')

expect(@client).to have_received(:paginate)
expect(secrets.total_count).to eq(2)
expect(secrets.secrets.count).to eq(2)
end
end # .list_actions_environment_secrets

describe '.get_actions_environment_secret', :vcr do
it 'return timestamps related to one secret' do
received = @client.get_actions_environment_secret(@repo.id, 'production', @secrets.first[:name])
expect(received.name).to eq(@secrets.first[:name].upcase)
end
end # .get_actions_environment_secret

describe '.create_or_update_actions_environment_secret', :vcr do
it 'updating existing secret returns 204' do
box = create_box(@client.get_actions_environment_public_key(@repo.id, 'production'))
encrypted = box[:box].encrypt('new value')
@client.create_or_update_actions_environment_secret(
@repo.id, 'production', @secrets.first[:name],
key_id: box[:key_id], encrypted_value: Base64.strict_encode64(encrypted)
)
expect(@client.last_response.status).to eq(204)
end
end # .create_or_update_actions_environment_secret

describe '.delete_actions_environment_secret', :vcr do
it 'delete existing secret' do
@client.delete_actions_environment_secret(@repo.id, 'production', @secrets.first[:name])
expect(@client.last_response.status).to eq(204)
end
end # .delete_actions_environment_secret
end
end