github-actions

Using the same job to target different environments in Github Actions


I'm new to Github Actions and there's something I can't understand. Coming from Bamboo and GitLab, all environment variables are immediately linked to the CI's environment. Still, in GitHub Actions, you need to have 1 job per environment.

Here's a simple example. defined env variables in github actions for each env

And how my workflow starts:

name: Build & Deploy

on:
  push:
    branches:
    - master
    - release
    - dev

jobs:
  build: 
    [...]
  deploy:
    run: |
      echo ${{ vars.CLUSTER_URL }}

Now the vars.CLUSTER_URL does not resolve. I can make it work by adding to the deploy job this line:

environment: dev

But this means I have to duplicate this job for every environment.

  deploy-dev:
    environment: dev
    run: |
      echo ${{ vars.CLUSTER_URL }}
  deploy-release:
    environment: release
    run: |
      echo ${{ vars.CLUSTER_URL }}
  deploy-prod:
    environment: prod
    run: |
      echo ${{ vars.CLUSTER_URL }}

Any change will have to be made 3 times. The workflow will also be 3x longer... If I one day I decide to add a new environment I'd have to duplicate everything again. Or perhaps have 3 workflow files, one for each environment.

I found ways to do this more efficiently by adding this step:

    - name: Determine environment
      run: |
        if [[ $BRANCH_NAME == 'refs/heads/release'* ]]; then
          echo "Environment: release"
          echo "::set-env name=ENVIRONMENT::release"
        elif [[ $BRANCH_NAME == 'refs/heads/master' ]]; then
          echo "Environment: master"
          echo "::set-env name=ENVIRONMENT::master"
        else
          echo "Environment: dev"
          echo "::set-env name=ENVIRONMENT::dev"
        fi

But I still find it sooo dirty for such a standard use.

Is this how GithubActions is supposed to work?

I also have an additional problem related. I want to tag my docker image during the build with the environment name (or branch name, they're the same).

      - name: Build Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: (...):${{ github.ref }}-(...)

But this resolves to refs/heads/env instead of env. Since I cannot do any string manipulations, I'd have to let go of this action and write instead a docker build --tag XXX myself where I can run some bash to filter out the refs/heads.

There is something suggested here to solve this issue by using a reusable matrix: https://limeii.github.io/2022/11/deploy-on-multiple-environment-with-github-actions/ Is this the best solution?

Edit: The solution above using reusable matrices does not work. It starts both deployments and also does not resolve environment related secrets.


Solution

  • Finally, this did the trick elegantly. environment: ${{ github.ref == 'refs/heads/master' && 'prod' || github.ref == 'refs/heads/release' && 'release' || 'dev' }}

    It means master will use prod environment, release release and everything else (like dev, or PRs) will use 'dev' environment.