gitgithubgithub-actions

Why is second Github Action Workflow (called via “workflow_call”) failing?


I have a main.yml that calls other workflows via workflow_call. The name of the workflows that are called are named workflow1 and workflow2.

If workflow2 is called after workflow1 then workflow2 fails. If I switch them, then workflow1 fails.

Both workflows work okay when called via workflow_dispatch.

Both workflows push to the repo.

The code I use for this is identical in both workflows:

- name: Commit and push the changes
  run: |
    echo "Initial status:"
    git status

    git config --local user.email "action@github.com"
    git config --local user.name "GitHub Action"

    git add -A

    echo "Status after git add:"
    git status

    git diff --cached --exit-code && exit 0  # Exit if no changes in the staging area

    echo "Committing changes:"
    git commit -m "chore: fetch content from various external sources"

    echo "Pushing changes:"
    git push

    echo "Final status:"
    git status

The second workflow fails with:

Run echo "Initial status:"
Initial status:
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   xxx.md
    modified:   yyy.md
    modified:   zzz.md

no changes added to commit (use "git add" and/or "git commit -a")
Status after git add:
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   xxx.md
    modified:   yyy.md
    modified:   zzz.md

diff --git a/xxx.md b/xxx.md etc etc

From what I understand is that if I have a main workflow that calls two other workflows, they all run on a separate “runner” so after workflow1 is executed, and workflow2 gets its own runner, a checkout of the repo should work?

I tried various suggestions made by AI:

1: Run this at the beginning of the git part (I don't understand why that would help, but I tried it):

git fetch origin main
git reset --hard origin/main

2: Run this at the beginning of the git part (I don't understand why that would help, but I tried it):

git pull origin main

I also tried a sleep of several seconds between the workflow1 and workflow2 but that didn't help.

What am I missing? I have spent a few hours on this now and I am not getting any further.

===

Addition: Below the caller yml script and the callee script(s), edited for simplicity, where you see “***”, those stars are a replacement for something that I decided to hide, same for “xxx”:

main.yml:

name: Import all and Deploy to GitHub Pages

on:
  workflow_dispatch:

jobs:
  workflow1:
    uses: ./.github/workflows/workflow1.yml
    secrets:
      SECRET1: ${{ secrets.*** }}
      SECRET2: ${{ secrets.*** }}
      SECRET3: ${{ secrets.*** }}

  workflow2:
    needs: workflow1
    uses: ./.github/workflows/workflow2.yml
    secrets:
      SECRET1: ${{ secrets.*** }}
      SECRET2: ${{ secrets.*** }}
      SECRET3: ${{ secrets.*** }}

workflow 1 (and workflow 2, they are basically the same):

# Summary: This GitHub Actions workflow fetches content from various external sources, updates a glossary, and deploys changes to GitHub Pages.

name: workflow1
on:
  workflow_dispatch:

  workflow_call:
    secrets:
      SECRET1:
        required: true
      SECRET2:
        required: true
      SECRET3:
        required: true    

jobs:
  deploy:
    name: Import external glossaries
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 19
          cache: npm

      - name: Install dependencies
        run: npm ci
      


      ##############################
      - name: Import external glossaries
        env:
          SECRET1: ${{ secrets.*** }}
          SECRET2: ${{ secrets.*** }}
          SECRET3: ${{ secrets.*** }}
        run: sh xxx/xxx/xxx/main.sh
      ##############################



      ##############################
      - name: Commit and push the changes
        run: |
          echo "Initial status:"
          git status

          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"

          git add -A

          echo "Status after git add:"
          git status

          git diff --cached --exit-code && exit 0  # Exit if no changes in the staging area

          echo "Committing changes:"
          git commit -m "chore: fetch content from various external sources"

          echo "Pushing changes:"
          git push

          echo "Final status:"
          git status
      ##############################

Solution

  • I was able to reproduce this unintuitive behaviour and discovered two issues:

    1. The parent workflow does not have permission to push to the repo and therefore the invoked workflows receive the same read-only permission as the parent workflow. Write permission needs to be explicitly given.

    2. workflow2 is unable to push because the head of the underlying branch has progressed by the push of the workflow1. Even though workflow2 checks out the repo after workflow1 finishes it still gets the same branch head position as workflow1. Therefore, workflow2 has to pull the branch before making any changes.

    The following shortened workflows work as expected:

    Parent workflow:

    name: workflow_main
    
    on:
      workflow_dispatch:
    
    permissions:
      contents: write
    
    jobs:
      workflow1:
        uses: ./.github/workflows/workflow1.yaml
    
      workflow2:
        needs: workflow1
        uses: ./.github/workflows/workflow2.yaml
    

    Workflow2 (same as workflow1) - please see git pull:

    name: workflow2
    on:
      workflow_dispatch:
    
      workflow_call:
    
    jobs:
      deploy:
        name: Import external glossaries
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v3
    
          - name: Import external glossaries
            run: |
              git pull
              echo $RANDOM > workflow2.txt
    
          - name: Commit and push the changes
            run: |
              git config --local user.email "action@github.com"
              git config --local user.name "GitHub Action"
    
              git add .
              git commit -m "chore: fetch content from various external sources"
              git push
              git status