How to set env vars for many deployment environments while using github actions

Viewed 112

I need to use github actions for deploying my stack to many environments, e.g., development and production. My prior implementation won't work anymore, and whilst I have a new working workflow, setting env vars for multiple envs seems repetitive and makes me think there must be a better way.

What I had before:

jobs:
  build-and-deploy:
    name: Build Container and Deploy
    runs-on: ubuntu-latest
    steps:
      - name: Set env to development
        if: ${{ !endsWith(github.ref, '/main') }}
        run: |
          echo "GCP_PROJECT=my-project-dev" >> $GITHUB_ENV
          echo "NODE_ENV=development" >> $GITHUB_ENV

      - name: Set env to production
        if: ${{ endsWith(github.ref, '/main') }}
        run: |
          echo "GCP_PROJECT=my-project-prod" >> $GITHUB_ENV
          echo "NODE_ENV=production" >> $GITHUB_ENV
    ...

What I have now:

jobs:
  build-and-deploy:
    name: Build Container and Deploy
    runs-on: ubuntu-latest
    env:
      GCP_PROJECT: ${{ (!endsWith(github.ref, '/main') && 'my-project-dev') || 'my-project-prod' }}
      NODE_ENV: ${{ (!endsWith(github.ref, '/main') && 'development') || 'production' }}
    steps:
    ...

Obviously, it doesn't seem so bad in the example, but for many more env vars the ${{ (!endsWith(github.ref, '/main') && 'dev-value') || 'prod-value' }} seems noisy and dirty.

So, what would be the proper way for doing this?

1 Answers

I would structure your workflow differently and use one step for production and one step for development.

While this might seem repetitive, it makes it very clear what variables you're passing in the case of production and which ones for development.

This also means you only need one if and it's immediately clear to the reader what happens only on the main branch.

NB: you're condition endsWith(/main) would also trigger on a branch named feature/main. As I have shown below, I'd recommend using the entire reference.

steps:
  - name: Deploy to Development
    if: github.ref != 'refs/head/main'
    uses: my-action-to-deploy
    env:
      GCP_PROJECT: my-dev-project
      NODE_ENV: development

  - name: Deploy to Production
    if: github.ref == 'refs/head/main'
    uses: my-action-to-deploy
    env:
      GCP_PROJECT: my-prod-project
      NODE_ENV: production
Related