Our organization has a bunch of repos on GitHub using GitHub Actions to deploy, some of which need access to the same secrets (token for our code coverage tool as one example). Organization-level secrets work great for this.
Individual repos also require secrets which differ based whether they are deploying to staging or production. Environment secrets work great for this by allowing the action to be generic and just reference AWS_KEY
rather than conditionally use PROD_AWS_KEY
or STAGING_AWS_KEY
, for instance.
But I can't seem to find a way to use both features together. If two repos want to use environment secrets to change the value of the secret they are accessing, but have that underlying secret be shared to the repos from the organization level.
CircleCI had a feature called contexts which allowed us to share a prod and staging context to any repo that needed them but I can't seem to get analogous behaviour out of GitHub Actions. Does anyone know if this is possible, and if so how?
So after some messing around I found an answer to this that works, at least in my particular use case.
It is possible to use a variable/secret value to access an organization secret. If I store the name of the organization secret in the value of an environment variable then I can use it to access the correct org secret at action runtime.
Lets assume the repo has two environments setup; production and staging. Also assume the organization has a secret to access an AWS key for each of there corresponding AWS accounts, named AWS_KEY_PROD
and AWS_KEY_STAGE
for instance.
In each GitHub Action environment lets create an environment variable named AWS_KEY
where the value is the name of the org secret that makes sense for the environment we are working with. So the value of AWS_KEY
for the production environment is AWS_KEY_PROD
and for the staging environment its AWS_KEY_STAGE
. Then we can use the value to access the corresponding org secret.
jobs:
staging-job:
name: example staging job
runs-on: ubuntu-latest
environment: staging
steps:
#Should print 'AWS_KEY_STAGE'
- name: get secret name from environment vars
run: echo "${{ vars.AWS_KEY }}"
- name: get secret value using secret name
run: someCommand "${{ secrets[vars.AWS_KEY] }}"
production-job:
name: example production job
runs-on: ubuntu-latest
environment: production
steps:
#Should print 'AWS_KEY_PROD'
- name: get secret name from environment vars
run: echo "${{ vars.AWS_KEY }}"
- name: get secret value using secret name
run: someCommand "${{ secrets[vars.AWS_KEY] }}"
As you can see the two different jobs use the exact same steps definition (except for the comment added here for clarity) to access the different secrets based on the environment.