How to pass GITHUB_TOKEN to reusable workflows?

I’m trying to avoid duplication across repos by reusing workflows, but workflow runs are failing because GITHUB_TOKEN is missing.

Here’s my called workflow :

name: Automatically merge Dependabot PRs
on:
  workflow_call:

jobs:
  label:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - name: Fetch metadata
        id: metadata
        uses: dependabot/fetch-metadata@v1.1.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
      - name: Rename production dependencies
        if: ${{ steps.metadata.outputs.dependency-type == 'direct:production' }}
        run: gh pr edit "$PR_URL" --title "${OLD_TITLE/chore/fix}"
        env:
          OLD_TITLE: ${{ github.event.pull_request.title }}
          PR_URL: ${{ github.event.pull_request.html_url }}
      - name: Add automerge label
        run: gh pr edit "$PR_URL" --add-label "automerge"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

And here’s my caller workflow:

name: Automerge Dependabot PRs

on:
  pull_request:
    types:
      - opened
      - assigned

jobs:
  dependabot-automerge:
    uses: relaycorp/shared-workflows/.github/workflows/dependabot-automerge.yml@main

However, when the workflow runs, it fails with the following error:

Run dependabot/fetch-metadata@v1.1.1
Error: github-token is not set! Please add 'github-token: "${{ secrets.GITHUB_TOKEN }}"' to your workflow file.

The documentation on reusable workflows doesn’t say anything about GITHUB_TOKEN. What am I missing?

Thanks.

Hi @gnarea,

Secrets have to be passed in explicitly. See the example from the docs.

 on:
  workflow_call:
    inputs:
      ring:
        description: 'Identifier for the target deployment ring'
        default: 'ring-0'
        required: false
        type: string
      environment:
        required: false
        type: string
    secrets:
      token:
        required: false

You’ll need to explicitly pass in the GitHub token as a secret to your called workflow.

The explicit mapping is to prevent unintended secret usage by any callers of your workflow

1 Like

The secrets didn’t work for me either (including explicitly passing them in), however I could reference ${{ github.token }}

2 Likes

yep good call @purplebooth. That’ll work too.

Thanks @luketomlinson and @purplebooth!

Unfortunately, I’ve made the changes above to the caller and called workflows, but I must be doing something else wrong because the called workflow is still not getting GITHUB_TOKEN.

Here’s the called workflow now:

name: Process pull requests
on:
  workflow_call:
    secrets:
      GITHUB_TOKEN:
        required: true

jobs:
  dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' && github.event.action == 'opened' }}
    steps:
      - name: Report number of chars in GITHUB_TOKEN
        run: echo -n "${GITHUB_TOKEN}" | wc -c
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Fetch metadata
        id: metadata
        uses: dependabot/fetch-metadata@v1.1.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
      - name: Trigger release if dependency is used in production
        if: ${{ steps.metadata.outputs.dependency-type == 'direct:production' }}
        run: gh pr edit "$PR_URL" --title "${OLD_TITLE/chore/fix}"
        env:
          OLD_TITLE: ${{ github.event.pull_request.title }}
          PR_URL: ${{ github.event.pull_request.html_url }}
      - name: Add automerge label
        run: gh pr edit "$PR_URL" --add-label "automerge"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

And the caller:

name: Process PRs

on:
  pull_request:
    types:
      - opened

jobs:
  dependabot-automerge:
    uses: relaycorp/shared-workflows/.github/workflows/prs.yml@main
    secrets:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

The error I get:

Error: github-token is not set! Please add 'github-token: "${{ secrets.GITHUB_TOKEN }}"' to your workflow file.

Which makes sense, because the step Report number of chars in GITHUB_TOKEN is reporting that this env var is empty.

Any idea what’s wrong?

I’m experiencing the same issue and I think it’s a bug. I can pass any secret into my reusable workflow except GITHUB_TOKEN.

Reusable Workflow:

name: test
on:
  workflow_call:
    secrets:
      token:
        required: true
      litmus_test:
        required: true

jobs:
  show-token:
    name: "show-token"
    runs-on: ubuntu-latest
    steps:
      - name: show token
        run: |
          token="${{ secrets.token }}"
          litmus_test="${{ secrets.litmus_test }}"
          echo "token is: $token"
          echo "token length: ${#token}"
          echo "litmus_test: $litmus_test"
          echo "litmust_test length: ${#litmus_test}"

Calling Workflow:

name: test-workflow-caller
on:
  pull_request:

jobs:
  call-workflow:
    uses: <redacted>/<redacted>/.github/workflows/test-github-token.yml@branchName
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}
      litmus_test: ${{ secrets.LITMUS_TEST }}

Results:

And I did confirm that GITHUB_TOKEN is not empty in the parent workflow, only in the reusable workflow. Using github.token has the same broken behavior.

Would be nice to have ${{ secrets.GITHUB_TOKEN }} working, but fortunately ${{ github.token }} worked for me! :raised_hands:

Thanks @purplebooth!

2 Likes

I didn’t realise you’re using github.token… My brain interpreted it as GITHUB_TOKEN :laughing:

But where exactly are you using it? Are you passing it from the caller workflow or are you using it directly in the called workflow? I’ve just tried both but neither is working for me (as @Josh-Schmitter-A1587448_bestbuy also reported).

I’ve got exactly same issue since yesterday, thanks for rasing it here, as I found a solution thanks to it.

@gnarea I am not passing github.token as it was not working for me as well, I just reference github.token in called workflow.

1 Like

It seems strange that some people are able to use github.token and others aren’t. For those of you able to use github.token, what virtual environment are you using? It’s failing for me on ubuntu-latest.

(I opened up a support ticket with github and they acknowledged the issue and said their engineers are investigating it.)

It turns out using github.token directly in the reusable workflow (not passed in as a secret) does work for me. @gnarea Note that there’s no secret-related syntax with this method, just ${{ github.token }} directly in your reusable workflow.

${{ secrets.GITHUB_TOKEN }} is now working as well!

1 Like

Using github.token in the called workflow is now working for me! :tada: I didn’t change the code so I guess they fixed the bug

@gnarea I’m using it in he called (reused) workflow

@wechuli Nice! Does it need to be passed as a secret, or can it just be access directly without being passed?

1 Like

Hi everyone, I’m the product manager for reusable workflows. We deployed a fix for this issue last Tuesday. Now, both of these should “just work,” without having to explicitly pass the token to the called workflow:

(1) github.token
(2) secrets.github_token

3 Likes

There are some cases when I need to explicitly pass the secrets.GITHUB_TOKEN to the workflow call, could it be changed to also allow the token to be passed through secrets rather than having to explicitly write it inside the reusable file?

Main workflow:

jobs:
  urls:
    name: URLs
    uses: Katsute/Workflows/.github/workflows/npm.run.commit.yml@main
    with:
      commit-files: "'links.json'"
      commit-message: Update links
    secrets:
      command: node dist/index.js ${{ secrets.GITHUB_TOKEN }}

Workflow call:

jobs:
  Commit:
    name: Run & Commit (${{ inputs.os }} / Node ${{ inputs.node-version }})
    runs-on: ${{ inputs.os }}
    timeout-minutes: ${{ inputs.timeout }}
    steps:
      - name: 📤 Checkout Repository
        uses: actions/checkout@v2.3.4

      - name: 📚 Install npm
        uses: actions/setup-node@v2.4.1
        with:
          node-version: ${{ inputs.node-version }}
          architecture: x64
          cache: npm

      - name: ✔ Run Command
        if: inputs.command
        run: |
          ${{ inputs.command }}

      - name: ✔ Run Command (secrets)
        if: ${{ !inputs.command }}
        run: |
          ${{ secrets.command }}

      - name: 📥 Commit Changes
        run: |
          git config --global user.name "${{ inputs.git-name }}"
          git config --global user.email "${{ inputs.git-email }}"
          git add "${{ join(fromJSON(format('[{0}]', inputs.commit-files)), '" "') }}"
          git diff-index --quiet HEAD || git commit -m "${{ inputs.commit-message }}"
          git push

Hi @katsute, we deployed some fixes today, including the ability to explicitly pass secrets.GITHUB_TOKEN to the workflow. You’ll need to do it through secrets and not inputs, just as you have shown. Try it out :slight_smile:

2 Likes