Checkout a commit created during the same workflow

I have a workflow that runs a script to update a template and pushes that template back to Github (Job 1), then tries to check it out and use it with another action (Job 2). Because actions/checkout@v2 only uses the reference that calls it, this means that in the second job, I end up checking out an older version of the template (because the updated template technically occurred in the future).

jobs:
  prepare:
    name: Update the template
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      # do things
      - name: Commit changes to repo
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git commit -m "Template updated!" -a
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

  trystable:
    needs: prepare
    name: Build from the updated template
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      # do things with the updated template from the first job

I’m going to experiment, but wanted to post 1) in case someone else has the same issue and 2) in case I don’t figure it out, since I’m not super comfortable with git.

Is this what checking out the HEAD is for? I really only need one commit, the issue is that the commit occurs after the workflow starts.

I also understand that Github doesn’t want to be able to trigger workflows from Github Actions to prevent recursion, but I’m not trying to do that. The user triggers the workflow, but checkout needs to be able to access a later commit than the one that triggered the workflow. No future knowledge is required because the current commit at the time of the second job is the one I want to work on.

This is the result of adding the HEAD checkout:

Run actions/checkout@v2
    attempting to correct wrong ref checkout
Run actions/checkout@v2
Syncing repository: b*ner-cmd/CrepeMC
Getting Git version info
Deleting the contents of '/home/runner/work/CrepeMC/CrepeMC'
Initializing the repository
Disabling automatic garbage collection
Setting up auth
Fetching the repository
Determining the checkout info
Checking out the ref
/usr/bin/git log -1
commit 0881a425a4d76a35aa274e130a1bc69963d825da
Author: Dimelo Waterson <54084132+b*ner-cmd@users.noreply.github.com>
Date:   Sat Jun 27 16:48:38 2020 -0500

    attempting to correct wrong ref checkout
  Run git checkout HEAD^
HEAD is now at f1db0f6 Template updated!
Run git checkout HEAD^
Note: switching to 'HEAD^'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at f1db0f6 Template updated!

So checkout initially grabbed the “wrong” ref (“Attempting to correct”), then the HEAD checkout pointed to the correct subsequent ref (“Template Updated”). Unfortunately I’m not sure if it did what I wanted because the template didn’t have a functional change. But it looks like it worked? Is this the answer?

If there are no other team members or workflow which push new changes at the time gap after job1 pushed the changes and before job2 checkout operation, you could use checkout HEAD to get the commit pushed in job1.
The ref for actions/checkout action defaults to the reference or SHA for that event which triggered the workflow. As those two jobs are in the same workflow, so in defaults, the reference or SHA for checkout steps in two jobs are the same. You need to add some other settings to checkout what you need.

This is essentially the basis of my question. I’m reassured to hear that checkout HEAD is a solution. However, I’m still trying to reach the best solution. As you said, that would preferably be to checkout the correct reference (the one pushed by job 1).

My next step would be to grab that reference somehow and then store it, then somehow reference it when using actions/checkout, but I don’t see a way to checkout a specific reference. Two ways I’ll probably try next:

  1. Use git checkout <commit> instead of git checkout HEAD^ after storing the correct commit ref or SHA

  2. Set the environmental variable GITHUB_SHA, GITHUB_REF, or both if necessary at the beginning of Job 2 to make it appear that the reference that triggered the workflow was the one created in Job 1, not before Job 1.

As always, I’m open to more elegant, less hacky, solutions

You could store the SHA ref in a file, upload the file as an artifact, and grab it in the next job. According to the documentation you can check out a specific commit using the ref parameter for actions/checkout.

1 Like

The commit id could be got using git command:

git rev-parse HEAD

You could set an output variable in job “prepare” with the commit id. Then you could get its value through job needs output.
As what @airtower-luna suggested, In job “trystable” , you could specify the commit id as ref input value in checkout step .
Please see my example :

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      commitid: ${{ steps.commit.outputs.commitid }}
      
    steps:
    - uses: actions/checkout@v2
    - name: Create local changes
      run: |
        echo "hello" >> sales663.txt
    - name: Commit files
      id: commit
      run: |
        git config --local user.email "action@github.com"
        git config --local user.name "github-actions"
        git add --all
        git commit -m "Add changes" -a
        git push -u origin $GITHUB_REF 
        SHA=$(git rev-parse HEAD)
        echo "::set-output name=commitid::$SHA"
         
  trystable:
    needs: prepare
    name: Build from the updated template
    runs-on: ubuntu-latest
    steps:
      - run : echo ${{ needs.prepare.outputs.commitid }}
      - uses: actions/checkout@v2
        with:
          ref: ${{ needs.prepare.outputs.commitid }}

1 Like

I marked the post with a complete example as the solution, but the answer to my question required both halves:

  1. Use with: ref: to pass the correct SHA directly to actions/checkout
  2. Use job needs output instead of environment variables to pass the value between jobs

Thank you both for the help. I also found the job needs output page, but was trying to use it with git checkout, which was messy and error-prone. Returning to read your answers resolved the issue perfectly.

Edit: For completeness, I forgot to mention that I used git log -1 --format="%H" in testing instead of git rev-parse HEAD, with no ill effects, although the latter is probably superior for automation.

1 Like

Thanks for the nod in the issue/commit comments! :slightly_smiling_face: