Environment check in Github Actions
In a project I’ve been working on we faced a problem. While using Github Actions to handle our CI/CD, we wanted to reuse our deployment scripts across all environments for each app. Thus giving us less code to maintain.
The plan was to set up identical secret keys (with different values though) in two different Github repo environments. The actions would trigger on changes to either the dev branch or the main branch. The source code from each branch would then be deployed to either the dev or production environment, using the dev or prod secrets accordingly.
But how do we make the action know when to get which secrets and where?
The following solution did the trick, but it’s a bit of a backyard hack. To follow along, you should have some basic knowledge of YAML and Github Actions.
Step 1
For this example I’ve added two environments in the repo from which I will build my app.
They both contain a secret named MY_PRETTY_SECRET. Although they have the same name/key, they contain different values. This could for instance be an API key, a password, a URL or such. Depending on if I want to deploy this application to my dev environment or my production environment, I want to retrieve the corresponding value for that environment using only one script. Instead of having two identical scripts, each specific for each environment.
Click here to read more about environments in Github.
Step 2
Add a YAML file under the .github/workflows folder in your project
name: My pretty YAML script #presentation name of your script
on:
workflow_dispatch: #run this script on manual trigger in Github
push: #or on push to branches named main or dev
branches:
- main
- dev
jobs: #collection of jobs
set-environment: #this is a job named 'set-environment'
runs-on: ubuntu-latest #your preferred OS
outputs: #the env value needs to be exposed as an output in order to be reached from other jobs
current_env: ${{ steps.set_env.outputs.current_env }} #output variable to store the relevant environment
steps:
- name: Check if prod
if: endsWith(github.ref, '/main') #if the triggering branch is 'main'
run: |
echo "ENVIRONMENT_NAME=prod" >> $GITHUB_ENV #retrieve secrets from 'prod' environment in Github
- name: Check if dev
if: endsWith(github.ref, '/dev') #if the triggering branch is 'dev'
run: |
echo "ENVIRONMENT_NAME=dev" >> $GITHUB_ENV #retrieve secrets from 'dev' environment in Github
- name: Set output
id: set_env
run: echo "::set-output name=current_env::${{ env.ENVIRONMENT_NAME }}" #assign the value of ENVIRONMENT_NAME to the output variable 'current_env'
build-and-deploy: #this is a job named 'build-and-deploy'
runs-on: ubuntu-latest #your preferred OS
needs: set-environment #this job won't be executed until the set-environment job is finished
environment: ${{ needs.set-environment.outputs.current_env }} #this job will now retrieve secret values stored in either 'dev' or 'prod' repo environments, depending on the value set in previous job
steps:
- name: Get secret from Github
- uses: MyPrettyGithubAction #example action
with:
creds: ${{ secrets.MY_PRETTY_SECRET }} #gets the value of MY_PRETTY_SECRET from the current repo environment
- run: echo "Deploying to ${{ needs.set-environment.outputs.current_env }} environment" #output: "Deploying to {environment name}"
In the example above I’ve separated the logic into multiple jobs. You can of course do this in a single job, eliminating the need for exposing the current_env value.
Happy coding!