Passing Environment Variables to Reusable Workflow

It’s my understanding that the environment from main workflow does not extend to the reusable workflow it calls. When I dump the env from both jobs to the stdout, indeed, the env variables I set in the main job do not appear in the env of the reusable workflow I have called.

When I pass a variable other than an ‘env’ variable from the main workflow to the reusable workflow with the following syntax (an expression), it works:

  with:
    my-variable: ${{ needs.MyJobId.outputs.MyVariable }}
    ref: ${{ github.GITHUB_REF_NAME }}

When I attempt to do this with an environment variable I get an error:
Unrecognized named-value: 'env’
Here is the offending syntax:

  with:
    my-variable: ${{ env.MY_VARIABLE }}

So ‘with’ doesn’t like to evaluate the ‘env’ context in an expression.

I’ve tried bash (I’m on an ubuntu runner) notation which doesn’t work, either:

  with:
    $MY_VARIABLE

I’ve tried about everything I can think of including stupid things like quotes, using github context, etc. What is the magic cookie I need here?

3 Likes

I don’t think you can use env, the problem is that env is set for stages based on the nested thing and that’s firewalled off in this case. (It needs to know what kind of runner to live in amongst other things.)

You could have a step that converts an env item into an output and then use the step output was input to the reusable workflow.

There are other similar restrictions, I tripped on not being able to use env at the job level (in an if). It’s the same restriction/problem. I could either replicate the if for each step, or I could make a step with it and somehow use that step.

1 Like

Yeah, I’ve dealt with the env scope problem and used outputs to get around it. I just thought this was within scope since I set the env value at the workflow level and the “With” is down in a step. Unless someone has an official position on it, I’m going to submit a feature request and see if it goes anywhere.

I think the problem is specific to reusable workflows, but I’ll test.

Can you please provide an example how did you do this? I cannot figure it out for hours already.
I tried creating a separate job setting its output to needed value - but apparently I cannot reference ‘jobs’ as well when calling reusable workflow…

https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability

sorry, it’s job not jobs.

It seems like there may be a typo in their documentation.

name: Project Specific Workflow
on:
  push:
    branches: [<which branches to run on>]
  pull_request:
    branches: [<which branches to run on>]
  workflow_dispatch:
    # Defaults here are for worflow_dispatch only, all other events are set in EnvSetup.setup-output-defaults:
    inputs:
      build-and-verify:
        description: 'Do a build and verify'
        required: true
        default: 'true'    
jobs:
  EnvSetup:
    name: Setup Dynamic Environment Variables
    runs-on: <your-awesome-runner>
    outputs:
      build-and-verify: ${{ steps.set-output-defaults.outputs.build-and-verify }}
    steps:
      - name: set outputs with default values
        id: set-output-defaults
        run: |    
          # If workflow_dispatch, use inputs (left), if other trigger, use default env (right)
          echo "::set-output name=build-and-verify::${{ github.event.inputs.build-and-verify || 'true' }}"
  invoke-workflow:
    needs: [EnvSetup]
    uses: <my-awesome-org>/<my-awesome-repo>/.github/workflows/<my-resuable-workflow>@<the-branch-to-invoke>
    with:
      build-and-verify: ${{needs.EnvSetup.outputs.build-and-verify}}
    secrets:
      token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"

Some important things to note about this code snippet that calls a reusable workflow:

  1. The “uses” statement that calls the reusable workflow can’t evaluate expressions yet. That means the repo name, branch, etc. must be hardcoded.
  2. The “with” statement that supplies arguments can only take elements from the github context and the “needs” object, so you MUST have a line that “needs” the job where you set the values and return the outputs.
  3. the echo "::set-output name=::${{}} syntax is where the variable is set and exposed as a step output, then it is returned with the job output that references it. Pay attention to the names of each object to see how they fit together.
  4. Because you can’t pass ENV variables to the reusable workflow, they are almost useless in this pattern.
  5. I’m hoping GitHub comes up with a better way to assign values inline or pass them into reusable workflows, because handling each parameter three or more times just to pass it into a reusable workflow is cumbersome.
  6. I included some extra trimmings to show how to pass secrets to the reusable workflow and evaluate the default vs. an input inline during variable assignment. The problem is that your default from the “inputs” section of “workflow_dispatch” only gets assigned on workflow_dispatch, and not on any other trigger. So the ${{ $var || value }} syntax lets you assign the value on the right if the one on the left is empty.
1 Like