github-actionsgit-ls-remote

Is git ls-remote able to use GITHUB variables? Error: Process completed with exit code 2


Actions code:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout codes
        uses: actions/checkout@v2
      - name: Test git for actions
        shell: bash
        run: |
          ## use GitHub variables, such as: GITHUB_REF,GITHUB_HEAD_REF..
          BRANCH=${GITHUB_REF##*/}
          branch=$BRANCH
          git ls-remote --heads --exit-code repo_url "$branch" >/dev/null
          if [ "$?" == "1" ]
          then 
            echo "Branch doesn't exist"
          else
            echo "Branch exist"
          fi

It will occur the following error:

  BRANCH=${GITHUB_REF##*/}
  branch=${BRANCH}
  echo $branch
  git ls-remote --heads --exit-code repo_url "$branch" >/dev/null
  if [ "$?" == "1" ]
  then 
    echo "Branch doesn't exist"
  else
    echo "Branch exist"
  fi

  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
main
Error: Process completed with exit code 2.

When I replace ${GITHUB_REF} with main, it works fine.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Test git for actions
        shell: bash
        run: |
          ## use GitHub variables, such as: GITHUB_REF,GITHUB_HEAD_REF..
          BRANCH=${GITHUB_REF##*/}
          branch=main
          git ls-remote --heads --exit-code repo_url "$branch" >/dev/null
          if [ "$?" == "1" ]
          then 
            echo "Branch doesn't exist"
          else
            echo "Branch exist"
          fi

Output:

  BRANCH=${GITHUB_REF##*/}
  branch=main
  echo $branch
  git ls-remote --heads --exit-code repo_url "$branch" >/dev/null
  if [ "$?" == "1" ]
  then 
    echo "Branch doesn't exist"
  else
    echo "Branch exist"
  fi
main
Branch exist

Is the git ls-remote command not able to use variables?

I want to check whether a certain branch exists in the remote warehouse in GitHub Actions.


Solution

  • According to jobs.<job_id>.steps[*].shell, the default Bash invocation is:

    bash --noprofile --norc -eo pipefail {0}
    

    which makes it to fail fast as described under Exit codes and error action preference, for bash:

    Fail-fast behavior using set -eo pipefail: This option is set when shell: bash is explicitly specified.

    And, according to Bash manual, under The Set Builtin:

    -e: Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists of Commands), or a compound command (see Compound Commands) returns a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits.

    and,

    -o pipefail: If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.


    In your case, the possible solution could be to directly handle the exit status of the command in an if:

    if command; then
      # succes
    else
      # failure
    end
    

    i.e.

    if ! git ls-remote --heads --exit-code repo_url "$branch" >/dev/null
    then 
      echo "Branch doesn't exist"
    else
      echo "Branch exist"
    fi
    

    or,

    if git ls-remote --heads --exit-code repo_url "$branch" >/dev/null
    then 
      echo "Branch exist"
    else
      echo "Branch doesn't exist"
    fi