Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 583
amro4934 Avatar asked May 08 '26 19:05

amro4934


1 Answers

Use a reusable workflow and call it in the main workflow. For this you will need a workflow for each environment. In your case a master, release and dev workflows.

Example:

Reusable workflow file:

name: Reusable CI Workflow

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string

  job-name:
    name: Some job
    environment: ${{ inputs.environment}}
    runs-on: self-hosted
    needs: something-else

You will use the reusable workflow in the main workflow for each environment.

Main workflow(example for dev):

name: Dev CI/CD Workflow
jobs:
  some-job:
    name: run the job
    uses: ./.github/workflows/reusableWorkflow.yml
    with:
      environment: "development"

In the example I hardcode the values but in your case you will probably use GitHub secrets.

What do you think?

like image 52
Stoyan Grozdev Avatar answered May 11 '26 15:05

Stoyan Grozdev