#!/usr/bin/env bash shopt -s extglob ACTION_INPUT_TOKEN="${ACTION_INPUT_TOKEN:?}" ACTION_INPUT_REPOSITORY="${ACTION_INPUT_REPOSITORY:?}" ACTION_INPUT_PATH="${ACTION_INPUT_PATH:?}" ACTION_INPUT_REF="${ACTION_INPUT_REF:?}" error() { echo "$*" 1>&2 ; exit 1; } # ensure we are in the right place [[ -z "${GITHUB_WORKSPACE:-}" ]] || { cd "${GITHUB_WORKSPACE}" || error ; } git config --global --add protocol.version 2 git init -q "${ACTION_INPUT_PATH}" && { cd "${ACTION_INPUT_PATH}" || error ; } git config --local gc.auto 0 # the server url and uri are important for determining the default checkout url GITHUB_SERVER_URL="${GITHUB_SERVER_URL:?}" GITHUB_SERVER_URI="${GITHUB_SERVER_URL//http?(s):\/\//}" # use https instead of everything else git config --add url."${GITHUB_SERVER_URL}/".insteadOf "git@${GITHUB_SERVER_URI}:" git config --add url."${GITHUB_SERVER_URL}/".insteadOf "ssh://git@${GITHUB_SERVER_URI}/" git config --add url."${GITHUB_SERVER_URL}/".insteadOf "git://${GITHUB_SERVER_URI}/" # prepare git config extra header for https auth BASE64="base64 --wrap 0" echo "" | ${BASE64} >/dev/null 2>&1 || BASE64="base64" echo "" | ${BASE64} >/dev/null 2>&1 || BASE64="openssl base64 -A" echo "" | ${BASE64} >/dev/null 2>&1 GIT_HTTP_EXTRAHEADER="AUTHORIZATION: basic $(echo -n "x-access-token:${ACTION_INPUT_TOKEN}" | ${BASE64})" git config --local --add http."${GITHUB_SERVER_URL}".extraheader "${GIT_HTTP_EXTRAHEADER}" # add the repository as remote git remote add origin "${ACTION_INPUT_REPOSITORY}" git_default_refspec() { git ls-remote --symref origin HEAD | { read -r _ ref name ; echo "${ref}" ; } } git_resolve_refspec() { # shellcheck disable=SC2068 git ls-remote origin $@ | { read -r sha ref _ ; echo "${sha} ${ref}" ; } } fetch() { # shellcheck disable=SC2068 git fetch --no-tags --prune --no-recurse-submodules --depth=1 origin $@ } checkout() { # shellcheck disable=SC2068 git checkout --force $@ } # the checkout is based on a commit hash if [[ ${ACTION_INPUT_REF:-} =~ ^[0-9a-f]{5,40}$ ]] then fetch "${ACTION_INPUT_REF}" && checkout "${ACTION_INPUT_REF}" exit fi # update selected ref when no input is given to remote default branch : "${ACTION_INPUT_REF:=$( git_default_refspec )}" # TODO: check if repo is workflow repo, if so, use commit sha from env # like GITHUB_REF and GITHUB_SHA read -r GIT_SHA GIT_REF _ <<< "$( git_resolve_refspec "${ACTION_INPUT_REF}" )" : "${GIT_SHA:?}" "${GIT_REF:?}" # we always use the refspec with the commit sha as source to prevent # race conditions when running on a frequently used branch checkout_head() { local name="${GIT_REF#refs\/heads\/}" local remote="refs/remotes/origin/${name}" fetch "+${GIT_SHA}:${remote}" checkout -B "${name}" "${remote}" } checkout_pull() { local name="${GIT_REF#refs\/pull\/}" local remote="refs/remotes/pull/${name}" fetch "+${GIT_SHA}:${remote}" # pull requests have a special treatment for the branch name. The name # is determined by the branch the pull request is targeting. local branch="${GITHUB_BASE_REF:-$( git_default_refspec )}" checkout -B "${branch#refs\/heads\/}" "${remote}" } checkout_tag() { local name="${GIT_REF#refs\/tags\/}" local remote="refs/tags/${name}" fetch "+${GIT_SHA}:${remote}" checkout "${remote}" } case "${GIT_REF}" in # heads and pull are a branch based checkout refs/heads/*) checkout_head ;; refs/pull/* ) checkout_pull ;; # tags are a detached head checkout refs/tags/* ) checkout_tag ;; *) error "ref type '${GIT_REF}' is unknown" ;; esac