Reusable Workflows, Secrets and Environments

Hi! I have been finding reusable workflows a great feature, but I cant manage the make them work with secrets and environment secrets. My workflows essentially has a single deployment.yml file that takes all args needed for a deployment and encapsulates the deployment workflow.

Unfortunately, I could not manage to make it work with Environment secrets. I have tried:

  • Using environment: ${{ input.environment }} in the reusable workflow file and while the environment is correctly detected, the secrets are not no matter what I try.
  • Using environment: this in the reusable workflow caller file. This is simply not supported, actions complains about it.
4 Likes

I noticed some issues with setting the env globally inside the reusable workflow. The values I set statically were there but the secrets were coming up empty

name: Reusable Workflow

on:
  workflow_call:
    secrets:
      TOKEN:
        required: true

env:
  STATIC_VALUE: true # populated in job log
  TOKEN: ${{ secrets.TOKEN}} # empty in job

jobs:
  some-job:
    run: echo $TOKEN #empty

I experimented with adding it to the job within the reusable workflow and that seems to work. Seems to be some issue with the available scope of the secret values.

name: Reusable Workflow

on:
  workflow_call:
    secrets:
      TOKEN:
        required: true

jobs:
  some-job:
    run: echo $TOKEN
    env:
      STATIC_VALUE: true # populated
      TOKEN: ${{ secrets.TOKEN}} # populated with secret

It means some duplication of values on jobs which isnt too nice but at least it work.s

3 Likes

. . . +1, same here!

1 Like

I am having this same issue. I can’t figure out how to get Environment secrets withing a reusable workflow.

Hi everyone. I’m the product manager for reusable workflows. We have a bug with passing environment secrets to reusable workflows. We should have it fixed up shortly! I’ll post here when its working.

3 Likes

Aaaand it’s fixed :tada:

Here’s what you need to do to reference an environment secret in a reusable workflow:

  • In your calling workflow, pass it with secrets
  • In your called workflow, define it in secrets at the top of the file
  • In your called workflow, and specifically the job where you want to access it, reference the environment (just like normal). Then it will be available as secrets.ENV_SECRET like normal
4 Likes

Wow that was fast! I’ll test this first thing Monday!

1 Like

@jenschelkopf - How does the calling workflow get access to the environment specific value without specifying it in the calling yaml? As @pecigonzalo pointed out, a job that uses a reusable workflow doesn’t seem to allow setting environment. So, when the workflow runs, the value of secret.MY_SECRET in the calling workflow is blank and therefore passes blank to the called workflow. Can you share a simple example of two yaml files that use the correct syntax to accomplish this?

I put together a simpler example and it works! Now to go figure out what’s wrong in my more complex yaml.

Hi Jen, really appreciating your reactivity re: this excellent new feature but alas, this isn’t working for me? I’ve defined a secret as per your docs in the called and caller workflows,
but i’m getting this error " workflow is invalid: secrets is not a valid event name" in the caller workflow

I would also suggest on a larger design level, it is very counter-intuitive that I have to pass a token at all in situations where both workflows are in the same repository and hence should by default have access to the exact same secrets.

1 Like

@finolacahill, can you post both your caller and called workflows? The screenshot isn’t rendering correctly for me, so if you could copy and paste that would help.

Also, thanks for the feedback about access to secrets when both are in the same repo.

Hi Jen,

Thank you so much for getting back to me, I really appreciate it. In the meantime I have realized my error and I’ll share here in case others fall into the same trap.

on:
    workflow_call:
        inputs:
            CI_UPSTREAM_CANDIDATE:
                required: true
                type: string
            CI_UPSTREAM_SHA:
                required: true
                type: string
        secrets:
            PAT:
                required: true

When defining the inputs/secrets in my called workflow I forgot to add “required: true” to the PAT secret. This resulted in the “secrets is not a valid event name” error when I ran my caller workflow.

This new feature is a great addition, and it’s fantastic to see Github Actions continue to evolve. But, if you have a feature request list anywhere, we at Intel would love the capacity to call or checkout reusable workflows from private repos using a personal access token!

All the best,
Finola

1 Like

Glad that’s working for you!

We do support reusable workflows in internal repositories, does that work for you? As opposed to private?

1 Like

Oh that’s good to know! But alas due to a variety of cross-enterprise privacy requirements we almost exclusively use private repositories as opposed to internal repositories, so we’ll be keeping the fingers crossed for future evolutions :slight_smile:

1 Like

Hey @jenschelkopf sorry it took me a while to test this, busy week :frowning:

I have created the following test:

name: Reusable workflow example

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

jobs:
  example_job:
    environment: ${{ inputs.environment }}
    name: Pass input and secrets to my-action
    runs-on: ubuntu-latest
    env:
      FOO: ${{ secrets.FOO }}
    steps:
      - run: |
          echo ${{ inputs.username }}
          echo "asd$FOO"

and the following caller

name: Test

on:
  workflow_dispatch:

jobs:
  reuse:
    uses: myOrg/myRepo/.github/workflows/reusable.yml@main
    with:
      username: mona
      environment: development

and while it does pick up the environment correctly and I can see a deployment, it does not seem to load/print (even masked) the secret.

I also tried directly with echo ${{ secret.FOO }} but it always seems to print blank as @devkeydet shared before. I was expecting to see the *** as a proof that it was actually seeing the secret.

Thanks!

Hi @pecigonzalo, you need to explicitly pass the environment secret. Here’s how it works:

Step (1), pass the environment secret to the called workflow:

  cd:
    needs: ci
    uses: wizard-whitebeard/automation/.github/workflows/release.yml@master
    secrets:
      PAT: ${{ secrets.PAT }}

Step (2), define the secret input in the called workflow:

on:
  workflow_call:
    secrets:
      PAT:
        required: true

Step (3), reference the environment where you want to use the secret (just like normal workflows):

  deploy_to_production:
    name: Deploy Production
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Checkout a private repo
        uses: actions/checkout@v2
        with:
          repository: wizard-whitebeard/private-repo
          ref: main
          token: ${{ secrets.PAT }}
1 Like

Got it, so the caller can send ${{ secrets.PAT }} despite it not existing in its environment?

Ah, no. Are you trying to reference an environment in the called repository? That’s not expected to work. When you reference a reusable workflow, Actions executes it in the context of the caller repository.

You mentioned before that the called workflow picked up the environment and you can see the deployment. I would expect that is created an environment in the caller’s repository, and didn’t actually use the environment in the called’s repository. That’s generally how environments work (they get created if they don’t already exist).

Not exactly, all this is within the same repository.