Skip to content

(Optionally) Ref to a branch and if it doesn't exist, use default #512

Open
@obedparla

Description

@obedparla

Hey!

Is there a way to get a ref to work like an optional OR? For example:

// GITHUB_HEAD_REF being the name of the branch if my google-foo didn't fail me
ref: ${GITHUB_HEAD_REF} || master

My use-case: I have multiple repos that depend on each other sometimes. If they do, they all share the same branch name for a feature (e.g feature/add-tests). I want to pull the repos with those branches when they exist, but if they don't (as it's not always necessary to change code in all repos), it'll pull master.

Thanks!

Activity

obedparla

obedparla commented on May 24, 2021

@obedparla
Author

Thinking about this further, I guess I can just run a bash command before this to define the branch name and export a variable to use in the checkout action. But if I have multiple repos this would become a lot of copy paste code for each repo 😄

I'm just wondering wether there's built-in way, or maybe a potential feature?

vicmassy

vicmassy commented on Nov 4, 2021

@vicmassy

Looking for the same feature here!

Any updates on this?

iBotPeaches

iBotPeaches commented on Dec 6, 2021

@iBotPeaches

Just hit this, this would be so handy. Now I'm thinking I'll also take a route of checking if the branch is available in the other repo.

vinayakkulkarni

vinayakkulkarni commented on Aug 4, 2022

@vinayakkulkarni

Is there a workaround for this?

tristan957

tristan957 commented on Aug 4, 2022

@tristan957

@vinayakkulkarni here is a pattern that I have been using.

https://github.com/hse-project/hse/blob/master/.github/workflows/builds.yaml#L99

Determine if branch exists using git ls-remote.

chingc

chingc commented on Oct 2, 2022

@chingc

I have a similar use case and was hoping actions/checkout would have something like a fallback-to-default boolean option. For the longest time I've been copy/pasting some ugly bash I wrote, but I recently got tired of it and wrote a composite action. I've included it below. The options you see are all the ones I need for my use case, so I didn't bother adding anything else. Feel free to modify it. Hope you find it useful.

# .github/actions/checkout/action.yml

# This is essentially the same as actions/checkout, but will
# fallback to the default branch if the ref does not exist.
# https://github.com/actions/checkout

name: Checkout

inputs:
  fetch-depth:
    default: 1
    required: false
    type: number
  path:
    default: ''
    required: false
    type: string
  repository:
    default: ${{ github.repository }}
    required: false
    type: string
  ref:
    default: ''
    required: false
    type: string
  token:
    default: ${{ github.token }}
    required: false
    type: string

runs:
  using: composite

  steps:
  - id: repo
    shell: bash
    env:
      GH_TOKEN: ${{ inputs.token }}
    run: |
      if [[ -z "${{ inputs.ref }}" ]]
      then
        if [[ "${{ inputs.repository }}" != "${{ github.repository }}" ]]
        then
          USING="default branch"
        else
          USING="$(gh api /repos/${{ inputs.repository }}/commits/${{ github.sha }}/branches-where-head --jq '.[0].name')"
        fi
        echo "::notice::Checkout: ${{ inputs.repository }} using ${USING}"
        echo "::set-output name=ref-exists::true"
      else
        if git ls-remote --heads --quiet --exit-code https://${{ inputs.token }}@github.com/${{ inputs.repository }}.git ${{ inputs.ref }}
        then
          echo "::notice::Checkout: ${{ inputs.repository }} using ${{ inputs.ref }}"
          echo "::set-output name=ref-exists::true"
        else
          USING="$(gh api /repos/${{ inputs.repository }} --jq '.default_branch')"
          echo "::notice::Checkout: ${{ inputs.repository }} does not have ref ${{ inputs.ref }} (fallback to ${USING})"
          echo "::set-output name=ref-exists::false"
          echo "::set-output name=default-branch::${USING}"
        fi
      fi

  - if: steps.repo.outputs.ref-exists == 'true'
    uses: actions/checkout@v3
    with:
      fetch-depth: ${{ inputs.fetch-depth }}
      path: ${{ inputs.path }}
      repository: ${{ inputs.repository }}
      ref: ${{ inputs.ref }}
      token: ${{ inputs.token }}

  - if: steps.repo.outputs.ref-exists == 'false'
    uses: actions/checkout@v3
    with:
      fetch-depth: ${{ inputs.fetch-depth }}
      path: ${{ inputs.path }}
      repository: ${{ inputs.repository }}
      ref: ${{ steps.repo.outputs.default-branch }}
      token: ${{ inputs.token }}
linked a pull request that will close this issue on Feb 19, 2024
YBadiss

YBadiss commented on Apr 4, 2024

@YBadiss

For anyone looking for other simple options, you can use continue-on-error and steps.<step_id>.outcome to achieve this fallback pretty easily:

steps:
  - name: Try checkout on first branch
    uses: actions/checkout@v4
    id: bad-checkout
    continue-on-error: true
    with:
      repository: actions/checkout
      ref: some-bad-branch
  # If the first checkout fails, we checkout the `main` branch by default
  - name: Fallback to main branch
    if: steps.bad-checkout.outcome == 'failure'
    uses: actions/checkout@v4
    with:
      repository: actions/checkout
      ref: main
acoulton

acoulton commented on Apr 23, 2025

@acoulton

It's a shame this isn't directly supported. The solution in #512 (comment) works but it takes a while to run because actions/checkout attempts 2 retries at 12 second intervals before the bad-checkout step fails and the job continues to create the new branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @acoulton@chingc@iBotPeaches@YBadiss@obedparla

      Issue actions

        (Optionally) Ref to a branch and if it doesn't exist, use default · Issue #512 · actions/checkout