docs icon indicating copy to clipboard operation
docs copied to clipboard

GITHUB_REF and GITHUB_REF_NAME examples in Actions docs unclear

Open oofnikj opened this issue 3 years ago • 14 comments

Code of Conduct

What article on docs.github.com is affected?

https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables

What part(s) of the article would you like to see updated?

GITHUB_REF and GITHUB_REF_NAME show example values of refs/heads/feature-branch-1 and feature-branch-1 respectively. However this is inconsistent with the values populated in the case of a PR-triggered workflow.

Given the description and example, one would expect to see the branch that triggered the workflow when running a PR-triggered workflow. Instead these variables are populated by values like refs/pull/26/merge and 26/merge respectively. The variable that contains the desired data in this case is actually GITHUB_HEAD_REF.

The documentation should be updated to more accurately describe the content of GitHub Actions predefined variables.

Additional information

No response

oofnikj avatar Feb 10 '22 09:02 oofnikj

Thanks for opening this issue. A GitHub docs team member should be by to give feedback soon. In the meantime, please check out the contributing guidelines.

welcome[bot] avatar Feb 10 '22 09:02 welcome[bot]

@oofnikj Thanks so much for opening an issue! I'll triage this for the team to take a look :eyes:

ramyaparimi avatar Feb 10 '22 13:02 ramyaparimi

Thanks for opening this issue! You proposal to add/clarify this information sounds good. You or anyone else is welcome to open a PR to address this. (Note that this was partially addressed in https://github.com/github/docs/pull/15304)

skedwards88 avatar Feb 18 '22 00:02 skedwards88

What's next... 411 please

Princeprince559 avatar Feb 23 '22 22:02 Princeprince559

Why should GITHUB_REF_NAME be different for a PR? If it's supposed to return the source branch (a very useful thing) then it should do so regardless of the context. To me this seems more like a bug than bad documentation.

wickkidd avatar Mar 31 '22 21:03 wickkidd

It would certainly be more helpful for our use case to have a simpler way to get the branch name regardless of context. Here is the snippet of Python code we are using to get the branch name now.

Kurt-von-Laven avatar Apr 20 '22 20:04 Kurt-von-Laven

I think this has been covered and updated in a previous PR. I'm going to go ahead and close this now 💛

cmwilson21 avatar Sep 12 '22 22:09 cmwilson21

@cmwilson21 in what PR?

airtonix avatar Oct 30 '22 10:10 airtonix

@airtonix Sorry, I may have been mistaken. I thought it was covered here. I'll reopen the issue.

My apologies! 🙈

cmwilson21 avatar Nov 08 '22 21:11 cmwilson21

Disclaimer: I'm the author of the following action

In this action https://github.com/rlespinasse/github-slug-action, the behavior, described by @wickkidd, is possible with ${{ env.GITHUB_REF_NAME }} (read more).

- name: Inject slug/short variables
  uses: rlespinasse/github-slug-action@v4
  
- run:|
    echo "$GITHUB_REF_NAME will serve the internal behavior of GitHub Action"
    echo "${{ env.GITHUB_REF_NAME }} will serve the behavior of the GitHub Slug action"
  shell: bash

rlespinasse avatar Feb 28 '23 08:02 rlespinasse

This would be extremely useful to my team as we currently have to maintain hardcoded environment and terraform workspace names in our workflows, this forces us to have a different workflow for each environment. We could create some custom expression logic that only run on a Push or PR to export ref_name when event_name == push and github_base_ref when event_name == workflow_dispatch. I would highly prefer there to be some way to consistently get the ref_name regardless of event_name.

  terraform:
    runs-on: ubuntu-latest
    environment:
      name: ${{ github.ref_name }}
    env:
      working-directory: terraform
      TF_WORKSPACE: ${{ github.ref_name }}
      ARM_USE_OIDC: true

Edit: this is usable as a workaround that does not require an action.

jobs:
get_ref_name:
  runs-on: ubuntu-latest
  outputs:
    ref_name: ${{ steps.get_ref_name.outputs.ref_name }}
  steps:
    - name: Get ref_name
      id: get_ref_name
      run: |
        if [ "${{ github.event_name }}" == "pull_request" ]; then
          echo "ref_name=${{ github.base_ref }}"
          echo "ref_name=${{ github.base_ref }}" >> $GITHUB_OUTPUT || exit 1
        else
          echo "ref_name=${{ github.ref_name }}"
          echo "ref_name=${{ github.ref_name }}" >> $GITHUB_OUTPUT || exit 1
        fi  
 
terraform:
  needs: get_ref_name
  runs-on: ubuntu-latest
  environment:
    name: ${{ needs.get_ref_name.outputs.ref_name }}
  env:
    working-directory: terraform
    TF_WORKSPACE: ${{ needs.get_ref_name.outputs.ref_name }}
    

walkerk1980 avatar Mar 20 '23 18:03 walkerk1980

Can you please just add ${{ github.branch_name }}. Why is getting something I can do on my console with git branch so hard in a GHA environment?

Getting something as basic as the current branch name shouldn't require custom bash scripting depending on the context. Github, please make this easy for us.

danielricecodes avatar May 31 '23 22:05 danielricecodes

https://docs.github.com/en/actions/learn-github-actions/variables is really unclear. Please get better WORKING examples. It shouldn't be that hard. If you can't do this just tell people to write their own logic in bash or pwsh or use gitlab.

I asked chatgpt and that got it right. Maybe you should have it write the docs.

works ${{ github.event_name == 'pull_request' && github.ref.name == 'dev' }}

doesn't work if: | github.ref.name == 'dev' && github.event_name == 'pull request'

or maybe these both don't work.

Asked ChatGPT again more specifically and got something like this.

if: ${{ github.event.pull_request.base.ref == 'dev' && github.event.pull_request.merged }}

But still not working it really shouldn't be this hard. Please tell us if we should just use bash but please give some examples

jeremybusk avatar Jun 15 '23 15:06 jeremybusk

It is even more weird with pull_request event. I'm using this code to pass env vars to an action :

  env:
    COMMIT_INFO_BRANCH: ${{ github.ref_name }}
    COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title }}
    COMMIT_INFO_SHA: ${{ github.sha }}  

Branch name for PR is chore/ci-setup. In logs I get this:

  env:
    COMMIT_INFO_BRANCH: 3/merge
    COMMIT_INFO_MESSAGE: chore(ci): setup
    COMMIT_INFO_SHA: fbf88412867d6d0475da156e1ad3deb2d02c43e9

Who would ever want 3/merge to be returned for ref name?!

I know I should probably use github.event.pull_request.head.ref but then I need to do some condition if same job is running also for push trigger. This is just PITA.

piotrekkr avatar Jun 16 '23 11:06 piotrekkr

Just wanted to add support for this issue. I was very confused as to why a GHA was skipping my branch and it was because the github.ref_name wasn't accurate, which isn't something the documentation warns about. It makes it really sound like it's the way to get the branch name in all cases, and it's confusing that I need to use head_ref for PRs, but ref_name for non-PRs.

I think there'd be beneficial to have a github.branch_name that works universally, and gives you the branch name irrespective of how it's ran or triggered, but I also think the docs are a little misleading as-is.

VioletHynes avatar Jul 04 '23 18:07 VioletHynes

👋 Hey folks! Thanks for all the great feedback in this issue. We had this as an open issue for anyone to work on, but after reviewing it, we are going to remove it from the help wanted board and discuss it a bit further.

Thanks again for all your input! 💖

cmwilson21 avatar Jul 10 '23 18:07 cmwilson21

I have a step like this at the start of most workflows:

- run: echo "REF=${{ github.event.pull_request && github.head_ref || github.ref_name }}" >> $GITHUB_ENV

which lets me reference $REF in subsequent steps, to abstract over this head_ref/ref_name inconsistency.

ryan-williams avatar Aug 02 '23 13:08 ryan-williams

@ryan-williams Thanks for your example. I did not know there was ternary available in expression until I saw your example. Must have missed it in docs. Super handy to know about this.

//EDIT

Missed it probably because this was just one sentence with one example. There should be whole section just for ternary. I mostly used bash to make some stuff conditional and with ternary I don't have to do this any more. Such useful feature and it is not emphasized enough in docs...

// EDIT 2

Just checked git blame for docs and ternary operator docs were added 2 months ago... So that is why I missed it.

piotrekkr avatar Aug 03 '23 07:08 piotrekkr

👋 Hey folks! Thanks for all the great feedback in this issue. We had this as an open issue for anyone to work on, but after reviewing it, we are going to remove it from the help wanted board and discuss it a bit further.

Thanks again for all your input! 💖

Does it mean you're on it, or that we're going to wait another year or two for this simple feature? By then, nearly everyone got a workaround in place...

igiona avatar Aug 19 '23 22:08 igiona

A stale label has been added to this issue because it has been open for 60 days with no activity. To keep this issue open, add a comment within 3 days.

github-actions[bot] avatar Oct 20 '23 16:10 github-actions[bot]

3 days pass quickly nowadays...

mering avatar Oct 20 '23 16:10 mering

A simple and generic way to get the current branch name is still required and would be much appreciated. Thanks for considering this issue.

igiona avatar Oct 20 '23 17:10 igiona

I recently learned that even using some bash condition can fail to figure out the ref name for current workflow run. Idk how GitHub runners work but this workflow step fails randomly (like 10% of times). I have already sent an issue about this to GitHub support.

I have a workflow that is run on release and workflow_dispatch events. When this workflow is triggered by publishing new release it is randomly failing because GITHUB_REF and github.ref is not set. I use some bash logic to handle both release and workflows_dispatch GIT ref like this:

name: 01 - Deploy To Staging

concurrency: staging

on:
  release:
    types:
      - published
  workflow_dispatch:
    inputs:
      release_ref:
        description: "Release TAG"
        required: true

jobs:
  initialize:
    name: "Initialize deploy"
    runs-on: ubuntu-22.04
    timeout-minutes: 2
    outputs:
      ref: "${{ steps.version.outputs.ref }}"
    steps:
      - name: Get git ref
        id: git_ref
        run: |
          if [[ "${{ github.event_name }}" = "release" ]]; then
            echo "value=${{ github.ref }}" >> $GITHUB_OUTPUT
          else
            echo "value=${{ github.event.inputs.release_ref }}" >> $GITHUB_OUTPUT
          fi

# next steps are failing because they expect `steps.git_ref.outputs.value` or `GITHUB_REF` to be set

90% of times this works fine:

image

but in 10% of cases it fails:

image

Based on GitHub docs about github.ref it should be always set for both of those events:

The fully-formed ref of the branch or tag that triggered the workflow run. For workflows triggered by push, this is the branch or tag ref that was pushed. For workflows triggered by pull_request, this is the pull request merge branch. For workflows triggered by release, this is the release tag created. For other triggers, this is the branch or tag ref that triggered the workflow run. This is only set if a branch or tag is available for the event type. The ref given is fully-formed, meaning that for branches the format is refs/heads/<branch_name>, for pull requests it is refs/pull/<pr_number>/merge, and for tags it is refs/tags/<tag_name>. For example, refs/heads/feature-branch-1.

Also this randomness is not just happening inside one repository workflow runs. When it happens it happens for multiple repositories at similar time.

Really weird stuff going on.

piotrekkr avatar Oct 21 '23 07:10 piotrekkr

If anyone is interested about my issue with getting current ref with release event, I got response from GitHub support:

Hello Piotr,

Thank you for reaching out to GitHub Support! I apologize for the delay here.

The behavior you're seeing is due to a known issue at this time affecting release event triggered runs. Our engineering team is tracking this behavior internally, and have confirmed that it has a fairly low repro rate - explaining the 90/10 split of times you noted seeing this issue.

Fix work will be planned and prioritized for this, but there is currently no concrete ETA. In the meantime, you can leverage data from the release payload to get the tag name (through github.event.release.tag_name) and set this up as a fallback value where you're calling github.ref.

In your provided snippet, this would look like the following:

if [[ "${{ github.event_name }}" = "release" ]]; then

echo "value=${{ github.ref || format('{0}{1}', 'refs/tags/', github.event.release.tag_name) }}" >> $GITHUB_OUTPUT

else

echo "value=${{ github.event.inputs.release_ref }}" >> $GITHUB_OUTPUT

fi

Since github.event.release.tag_name only returns the name of the tag minus the ref prefix, we're using the format function to add the prefix manually.

It seems for now this is low prio for them and as a workaround I should use

echo "value=${{ github.ref || format('{0}{1}', 'refs/tags/', github.event.release.tag_name) }}" >> $GITHUB_OUTPUT

to get release ref without random problems.

piotrekkr avatar Oct 30 '23 12:10 piotrekkr

@piotrekkr Thanks for coming back and reporting the convo with support! 👍

cmwilson21 avatar Oct 30 '23 17:10 cmwilson21