Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Add logging, Support fetching existing PR #117

Merged
merged 4 commits into from
Dec 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ inputs:
description: GitHub token secret
required: true
default: ${{ github.token }}
debug:
description: Bash set -x debugging mode
required: false
outputs:
pr_url:
description: 'Pull request URL'
pr_number:
description: 'Pull request number'
pr_created:
description: 'Boolean string indicating if a pull request was created from the action run'
has_changed_files:
description: 'Boolean string indicating whether any file has been changed'
runs:
Expand Down
187 changes: 159 additions & 28 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,96 @@
set -e
set -o pipefail

###################
# Helper Functions
reset_color="\\e[0m"
color_red="\\e[31m"
color_green="\\e[32m"
color_yellow="\\e[33m"
color_blue="\\e[36m"
color_gray="\\e[37m"
function echo_blue {
printf "%b\n" "${color_blue}$(printf "%s\n" "$*")${reset_color}"
}
function echo_green {
printf "%b\n" "${color_green}$(printf "%s\n" "$*")${reset_color}"
}
function echo_red {
printf "%b\n" "${color_red}$(printf "%s\n" "$*")${reset_color}"
}
function echo_yellow {
printf "%b\n" "${color_yellow}$(printf "%s\n" "$*")${reset_color}"
}
function echo_gray {
printf "%b\n" "${color_gray}$(printf "%s\n" "$*")${reset_color}"
}
function echo_grey {
printf "%b\n" "${color_gray}$(printf "%s\n" "$*")${reset_color}"
}
function echo_info {
printf "%b\n" "${color_blue}ℹ $(printf "%s\n" "$*")${reset_color}"
}
function echo_error {
printf "%b\n" "${color_red}✖ $(printf "%s\n" "$*")${reset_color}"
}
function echo_warning {
printf "%b\n" "${color_yellow}✔ $(printf "%s\n" "$*")${reset_color}"
}
function echo_success {
printf "%b\n" "${color_green}✔ $(printf "%s\n" "$*")${reset_color}"
}
function echo_fail {
printf "%b\n" "${color_red}✖ $(printf "%s\n" "$*")${reset_color}"
}
function enable_debug {
if [[ "${INPUT_DEBUG}" == "true" ]]; then
echo_info "Enabling debug mode."
set -x
fi
}
function disable_debug {
if [[ "${INPUT_DEBUG}" == "true" ]]; then
set +x
fi
}

# Fix for the unsafe repo error: https://github.com/repo-sync/pull-request/issues/84
git config --global --add safe.directory $(pwd)

##############################
echo "::group::Gather Inputs"

if [[ -z "$GITHUB_TOKEN" ]]; then
if [[ ! -z "$INPUT_GITHUB_TOKEN" ]]; then
GITHUB_TOKEN="$INPUT_GITHUB_TOKEN"
echo "::add-mask::$INPUT_GITHUB_TOKEN"
echo_info "INPUT_GITHUB_TOKEN=$INPUT_GITHUB_TOKEN"
else
echo "Set the GITHUB_TOKEN environment variable."
echo_fail "Set the GITHUB_TOKEN environment variable."
exit 1
fi
fi

# enable debug after token handling
enable_debug

if [[ ! -z "$INPUT_SOURCE_BRANCH" ]]; then
SOURCE_BRANCH="$INPUT_SOURCE_BRANCH"
elif [[ ! -z "$GITHUB_REF" ]]; then
SOURCE_BRANCH=${GITHUB_REF/refs\/heads\//} # Remove branch prefix
else
echo "Set the INPUT_SOURCE_BRANCH environment variable or trigger from a branch."
echo_fail "Set the INPUT_SOURCE_BRANCH environment variable or trigger from a branch."
exit 1
fi
echo_info "SOURCE_BRANCH=$SOURCE_BRANCH"

DESTINATION_BRANCH="${INPUT_DESTINATION_BRANCH:-"master"}"
echo_info "DESTINATION_BRANCH=$DESTINATION_BRANCH"

# Determine repository url
if [[ -z "$INPUT_DESTINATION_REPOSITORY" ]]; then
# Try to query local repository's remote url if INPUT_DESTINATION_REPOSITORY is null
local_origin=$(git config --get remote.origin.url)
local_origin=$(git remote get-url origin)

if [[ "$local_origin" == *.git ]]; then
origin_no_suffix="${local_origin%.*}"
Expand All @@ -45,8 +111,15 @@ fi
# Fallback to GITHUB_REPOSITORY if both INPUT_DESTINATION_REPOSITORY and CHECKOUT_REPOSITORY are unavailable
DESTINATION_REPOSITORY="${INPUT_DESTINATION_REPOSITORY:-${CHECKOUT_REPOSITORY:-${GITHUB_REPOSITORY}}}"

# Fix for the unsafe repo error: https://github.com/repo-sync/pull-request/issues/84
git config --global --add safe.directory /github/workspace
echo_gray "INPUT_DESTINATION_REPOSITORY=$INPUT_DESTINATION_REPOSITORY"
echo_gray "CHECKOUT_REPOSITORY=$CHECKOUT_REPOSITORY"
echo_gray "GITHUB_REPOSITORY=$GITHUB_REPOSITORY"
echo_info "DESTINATION_REPOSITORY=$DESTINATION_REPOSITORY"

echo "::endgroup::"

##############################
echo "::group::Configure git"

# Github actions no longer auto set the username and GITHUB_TOKEN
git remote set-url origin "https://x-access-token:$GITHUB_TOKEN@${GITHUB_SERVER_URL#https://}/$DESTINATION_REPOSITORY"
Expand All @@ -57,73 +130,131 @@ git fetch origin '+refs/heads/*:refs/heads/*' --update-head-ok
# Print out all branches
git --no-pager branch -a -vv

echo "::endgroup::"

#########################################################
echo "::group::Ensure pull-request contains differences"

if [ "$(git rev-parse --revs-only "$SOURCE_BRANCH")" = "$(git rev-parse --revs-only "$DESTINATION_BRANCH")" ]; then
echo "Source and destination branches are the same."
echo_info "Source and destination branches are the same."
exit 0
fi

# Do not proceed if there are no file differences, this avoids PRs with just a merge commit and no content
LINES_CHANGED=$(git diff --name-only "$DESTINATION_BRANCH" "$SOURCE_BRANCH" -- | wc -l | awk '{print $1}')
if [[ "$LINES_CHANGED" = "0" ]] && [[ ! "$INPUT_PR_ALLOW_EMPTY" == "true" ]]; then
echo "No file changes detected between source and destination branches."
echo_info "No file changes detected between source and destination branches."
exit 0
fi

echo "::endgroup::"

#############################################
echo "::group::Assemble hub pr parameters"
# Workaround for `hub` auth error https://github.com/github/hub/issues/2149#issuecomment-513214342
export GITHUB_USER="$GITHUB_ACTOR"

PR_ARG="$INPUT_PR_TITLE"
if [[ ! -z "$PR_ARG" ]]; then
PR_ARG="-m \"$PR_ARG\""
PR_ARG=(-b "$DESTINATION_BRANCH" -h "$SOURCE_BRANCH" --no-edit)

if [[ ! -z "$INPUT_PR_TITLE" ]]; then
PR_ARG+=(-m "$INPUT_PR_TITLE")
if [[ ! -z "$INPUT_PR_TEMPLATE" ]]; then
sed -i 's/`/\\`/g; s/\$/\\\$/g' "$INPUT_PR_TEMPLATE"
PR_ARG="$PR_ARG -m \"$(echo -e "$(cat "$INPUT_PR_TEMPLATE")")\""
PR_ARG+=(-m "$(echo -e "$(cat "$INPUT_PR_TEMPLATE")")")
elif [[ ! -z "$INPUT_PR_BODY" ]]; then
PR_ARG="$PR_ARG -m \"$INPUT_PR_BODY\""
PR_ARG+=(-m "$INPUT_PR_BODY")
fi
fi

if [[ ! -z "$INPUT_PR_REVIEWER" ]]; then
PR_ARG="$PR_ARG -r \"$INPUT_PR_REVIEWER\""
PR_ARG+=(-r "$INPUT_PR_REVIEWER")
fi

if [[ ! -z "$INPUT_PR_ASSIGNEE" ]]; then
PR_ARG="$PR_ARG -a \"$INPUT_PR_ASSIGNEE\""
PR_ARG+=(-a "$INPUT_PR_ASSIGNEE")
fi

if [[ ! -z "$INPUT_PR_LABEL" ]]; then
PR_ARG="$PR_ARG -l \"$INPUT_PR_LABEL\""
PR_ARG+=(-l "$INPUT_PR_LABEL")
fi

if [[ ! -z "$INPUT_PR_MILESTONE" ]]; then
PR_ARG="$PR_ARG -M \"$INPUT_PR_MILESTONE\""
PR_ARG+=(-M "$INPUT_PR_MILESTONE")
fi

if [[ "$INPUT_PR_DRAFT" == "true" ]]; then
PR_ARG="$PR_ARG -d"
PR_ARG+=(-d)
fi

COMMAND="GITHUB_TOKEN=\"$GITHUB_TOKEN\" hub pull-request \
-b $DESTINATION_BRANCH \
-h $SOURCE_BRANCH \
--no-edit \
$PR_ARG \
|| true"
echo_info "${PR_ARG[@]}"
echo "::endgroup::"

echo "$COMMAND"
##########################################################################
echo "::group::Create pull request $SOURCE_BRANCH -> $DESTINATION_BRANCH"

PR_URL=$(sh -c "$COMMAND")
if [[ "$?" != "0" ]]; then
exit 1
COMMAND="hub pull-request "${PR_ARG[@]}" 2> /tmp/pull-request.stderr.log || true"
echo_info "$COMMAND"

PR_URL=$(hub pull-request "${PR_ARG[@]}" 2> /tmp/pull-request.stderr.log || true)
STD_ERROR="$(cat /tmp/pull-request.stderr.log || true)"
echo_error "STD_ERROR=$STD_ERROR"

echo "::endgroup::"


################################################
echo "::group::Retrieving pull request details"

PR_CREATED="true"
# determine success / failure
# since various things can go wrong such as bad user input or non-existant branches, there is a need to handle outputs to determine if the pr was successfully created or not.
if [[ -z "$PR_URL" ]]; then
PR_CREATED="false"
if echo "$STD_ERROR" | grep -q "already exists"; then
echo_yellow "Pull request already exists. This is the stderr output:"
echo_yellow "$STD_ERROR"
else
echo_fail "Pull request command failed. This is the stderr output:"
echo_red "$STD_ERROR"
exit 1
fi
else
echo_success "Pull request was successfully created"
echo_success "PR_URL=$PR_URL"
fi

# attempt to obtain the pull-request details - pr already exists.
if [[ -z "$PR_URL" ]]; then
PR_URL=$(\
hub pr list -h $SOURCE_BRANCH -b $DESTINATION_BRANCH -f %U \
2>"./get-pull-request.stderr.log" || true \
)
STD_ERROR="$(cat "./get-pull-request.stderr.log" || true)"

if [[ -z "$PR_URL" ]]; then
echo_fail "Pull Request Already Exists, but was unable to retrieve url. This is the stderr output:"
echo_red "$STD_ERROR"
else
echo_success "Pull request details successfully obtained"
echo_success "PR_URL=${PR_URL}"
fi
fi

echo ${PR_URL}
echo "::endgroup::"

############################
echo "::group::Set outputs"

echo "pr_url=${PR_URL}" >> $GITHUB_OUTPUT
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
echo "pr_created=${PR_CREATED}" >> $GITHUB_OUTPUT

if [[ "$LINES_CHANGED" = "0" ]]; then
echo "has_changed_files=false" >> $GITHUB_OUTPUT
else
echo "has_changed_files=true" >> $GITHUB_OUTPUT
fi

cat $GITHUB_OUTPUT

echo "::endgroup::"