githubgithub-actions

How to share a calculated value between job steps?


Is there a DRY way to calculate and share a value in multiple job steps with GitHub Actions?

In the below workflow, echo ${GITHUB_REF} | cut -d'/' -f3-${GITHUB_SHA}` is repeated in multiple steps.

name: Test, Build and Deploy
on:
  push:
    branches:
      - master
jobs:
  build_and_push:
    name: Build and Push
    runs-on: ubuntu-latest
    steps:
      - name: Docker Build
        uses: "actions/docker/cli@master"
        with:
          args: build . --file Dockerfile -t cflynnus/blog:`echo ${GITHUB_REF} | cut -d'/' -f3`-${GITHUB_SHA}
      - name: Docker Tag Latest
        uses: "actions/docker/cli@master"
        with:
          args: tag cflynnus/blog:`echo ${GITHUB_REF} | cut -d'/' -f3`-${GITHUB_SHA} cflynnus/blog:latest

Solution

  • set-output can be used to define outputs for steps. The outputs can then be used in later steps and evaluated in with and env input sections. Also, the step returning outputs should have an id, which is referred to by the step consuming the outputs.

    The following is what that would look like for your example.

    name: Test, Build and Deploy
    on:
      push:
        branches:
          - master
    jobs:
      build_and_push:
        name: Build and Push
        runs-on: ubuntu-latest
        steps:
          - name: Set tag var
            id: vars
            run: echo "docker_tag=$(echo ${GITHUB_REF} | cut -d'/' -f3)-${GITHUB_SHA}" >> $GITHUB_OUTPUT
          - name: Docker Build
            uses: "actions/docker/cli@master"
            with:
              args: build . --file Dockerfile -t cflynnus/blog:${{ steps.vars.outputs.docker_tag }}
          - name: Docker Tag Latest
            uses: "actions/docker/cli@master"
            with:
              args: tag cflynnus/blog:${{ steps.vars.outputs.docker_tag }} cflynnus/blog:latest
    

    Here is another example showing how to dynamically set multiple variables to be used by an action.

          - name: Set output variables
            id: vars
            run: |
              pr_title="[Test] Add report file $(date +%d-%m-%Y)"
              pr_body="This PR was auto-generated on $(date +%d-%m-%Y) \
                by [create-pull-request](https://github.com/peter-evans/create-pull-request)."
              echo "pr_title=$pr_title" >> $GITHUB_OUTPUT
              echo "pr_body=$pr_body" >> $GITHUB_OUTPUT
          - name: Create Pull Request
            uses: peter-evans/create-pull-request@v4
            with:
              title: ${{ steps.vars.outputs.pr_title }}
              body: ${{ steps.vars.outputs.pr_body }}
    

    Alternatively you can create environment variables.

          - name: Set environment variables
            run: |
              echo "PR_TITLE=[Test] Add report file $(date +%d-%m-%Y)" >> $GITHUB_ENV
              echo "PR_BODY=This PR was auto-generated on $(date +%d-%m-%Y) by [create-pull-request](https://github.com/peter-evans/create-pull-request)." >> $GITHUB_ENV
          - name: Create Pull Request
            uses: peter-evans/create-pull-request@v4
            with:
              title: ${{ env.PR_TITLE }}
              body: ${{ env.PR_BODY }}
    

    Update: The docker actions in the first example are deprecated. Please see this answer for the latest way to work with docker in GitHub Actions.

    Note: For sharing values between different jobs, see this question.