Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Label Notification feature #19

Merged
merged 8 commits into from
Apr 24, 2019
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
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# PR Tag Release Script

This is a simple bash script to generate a tag on a merged PR. It also sets
relevent environment variables so that a Travis release is easy. See the
included `.travis.yml` for an example.
This is a simple bash script to generate a tag on a merged PR. A label is added
to the PR as well, the name, description, and color of which can be modified.
It also sets relevent environment variables so that a Travis release is easy.
See the included `.travis.yml` for an example.

The available configuration environment variables are shown below. Keep in mind
that the `PRERELEASE_REGEX` and `DRAFT_REGEX` are applied to the ***title*** of
the Pull Request, unlike the others, which apply to the body.

```bash
DEPLOY_BRANCH=${DEPOY_BRANCH-"^master$"}
MERGE_COMMIT_REGEX=${MERGE_COMMIT_REGEX-"Merge pull request #([0-9]+)"}
PATCH_CHANGE_REGEX=${PATCH_CHANGE_REGEX-"This (PR|release) is an?( small| tiny)? (update|bugfix|change)"}
MINOR_CHANGE_REGEX=${MINOR_CHANGE_REGEX-"This (PR|release) is a (feature( update| change)?|big (update|change))"}
Expand All @@ -18,6 +18,20 @@ PRERELEASE_REGEX=${PRERELEASE_REGEX-"\[(PRE|WIP|PRERELEASE)\]"}
DRAFT_REGEX=${DRAFT_REGEX-"\[(WIP|DRAFT)\]"}
```

```bash
PATCH_LABEL_COLOR=${PATCH_LABEL_COLOR-"14a3bc"}
PATCH_LABEL_NAME=${PATCH_LABEL_NAME-"patch"}
PATCH_LABEL_DESC=${PATCH_LABEL_DESC-"This PR updates the patch version: v0.0.X"}

MINOR_LABEL_COLOR=${MINOR_LABEL_COLOR-"23e059"}
MINOR_LABEL_NAME=${MINOR_LABEL_NAME-"minor"}
MINOR_LABEL_DESC=${MINOR_LABEL_DESC-"This PR updates the minor version: v0.X.0"}

MAJOR_LABEL_COLOR=${MAJOR_LABEL_COLOR-"c60f7a"}
MAJOR_LABEL_NAME=${MAJOR_LABEL_NAME-"major"}
MAJOR_LABEL_DESC=${MAJOR_LABEL_DESC-"This PR updates the major version: vX.0.0"}
```

Including the below `yaml` in your `.travis.yml` and providing the
`$GITHUB_OAUTH_TOKEN` enviroment variable will enable auto-generated releases.

Expand All @@ -30,6 +44,6 @@ deploy:
api_key: "$GITHUB_OAUTH_TOKEN"
skip_cleanup: true
on:
all_branches: true
branch: master
condition: $DO_GITHUB_RELEASE = true
```
179 changes: 160 additions & 19 deletions pr_tag_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

### Variable Setup ###

DEPLOY_BRANCH=${DEPOY_BRANCH-"^master$"}
MERGE_COMMIT_REGEX=${MERGE_COMMIT_REGEX-"Merge pull request #([0-9]+)"}
PATCH_CHANGE_REGEX=${PATCH_CHANGE_REGEX-"This (PR|release) is an?( small| tiny)? (update|bugfix|change)"}
MINOR_CHANGE_REGEX=${MINOR_CHANGE_REGEX-"This (PR|release) is a (feature( update| change)?|big (update|change))"}
Expand All @@ -24,9 +23,145 @@ PATCH=${VERSION_SPLIT[2]-0}
GIT_EMAIL="[email protected]"
GIT_USER="Travis CI"

PATCH_LABEL_COLOR=${PATCH_LABEL_COLOR-"14a3bc"}
PATCH_LABEL_NAME=${PATCH_LABEL_NAME-"patch"}
PATCH_LABEL_DESC=${PATCH_LABEL_DESC-"This PR updates the patch version: v0.0.X"}

MINOR_LABEL_COLOR=${MINOR_LABEL_COLOR-"23e059"}
MINOR_LABEL_NAME=${MINOR_LABEL_NAME-"minor"}
MINOR_LABEL_DESC=${MINOR_LABEL_DESC-"This PR updates the minor version: v0.X.0"}

### Functions ###
MAJOR_LABEL_COLOR=${MAJOR_LABEL_COLOR-"c60f7a"}
MAJOR_LABEL_NAME=${MAJOR_LABEL_NAME-"major"}
MAJOR_LABEL_DESC=${MAJOR_LABEL_DESC-"This PR updates the major version: vX.0.0"}


function does_label_exist() {
OUTPUT=$(curl -X "GET" -s --write-out "PR_TAG_CODE=%{http_code}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.github.symmetra-preview+json" \
-H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
"https://api.github.com/repos/${TRAVIS_REPO_SLUG}/labels/$1")

CODE=${OUTPUT##*PR_TAG_CODE=}

#shellcheck disable=SC2046
return $(test "$CODE" = "200")
}

function create_labels() {
for label_type in "MAJOR" "MINOR" "PATCH"; do
local color; local name; local desc
color="${label_type}_LABEL_COLOR"
color=${!color}
name="${label_type}_LABEL_NAME"
name=${!name}
name="${label_type}_LABEL_NAME"
name=${!name}
desc="${label_type}_LABEL_DESC"
desc=${!desc}

if does_label_exist "$name"; then
# label exists -- patch it/do nothing
echo -e "$name label already exists, doing nothing"
else
# shellcheck disable=SC2155
local data="$(cat <<-EOF
{"name": "$name",
"description": "$desc",
"color": "$color"}
EOF
)"

OUTPUT=$(curl -X "POST" -s --write-out "PR_TAG_CODE=%{http_code}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.github.symmetra-preview+json" \
-H "Authorization: token ${GITHUB_OAUTH_TOKEN}" -d "$data" \
"https://api.github.com/repos/${TRAVIS_REPO_SLUG}/labels")
CODE=${OUTPUT##*PR_TAG_CODE=}
OUTPUT=${OUTPUT%PR_TAG_CODE=*}
if [[ "$CODE" != "201" ]]; then
echo -e "Failed to create version labels!"
return 1
fi
echo -e "created $label label"
fi
done
}

function set_label_on() {
local issue="$1"
local label="$2"

# get all labels on issue
OUTPUT=$(curl -X "GET" -s --write-out "PR_TAG_CODE=%{http_code}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.github.symmetra-preview+json" \
-H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
"https://api.github.com/repos/${TRAVIS_REPO_SLUG}/issues/${issue}/labels")
CODE=${OUTPUT##*PR_TAG_CODE=}
OUTPUT=${OUTPUT%PR_TAG_CODE=*}
if [[ "$CODE" != "200" ]]; then
echo -e "Failed to retrieve current labels on issue $issue!"
return 1
fi

local labels_to_delete; local has_label
IFS=$'\n' read -ra labels_to_delete <<<"$(echo "$OUTPUT" | jq --raw-output ".[].name | select(test(\"$MAJOR_LABEL_NAME|$MINOR_LABEL_NAME|$PATCH_LABEL_NAME\")) | select(. != \"$label\")")"
has_label=$(echo "$OUTPUT" | jq "[.[].name] | any(. == \"$label\")")

if [[ ${#labels_to_delete[@]} -ne 0 ]]; then
# delete the labels
for to_delete in "${labels_to_delete[@]}"; do
OUTPUT=$(curl -X "DELETE" -s --write-out "PR_TAG_CODE=%{http_code}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.github.symmetra-preview+json" \
-H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
"https://api.github.com/repos/${TRAVIS_REPO_SLUG}/issues/${issue}/labels/$to_delete")
CODE=${OUTPUT##*PR_TAG_CODE=}
OUTPUT=${OUTPUT%PR_TAG_CODE=*}
if [[ "$CODE" != "200" ]]; then
echo -e "Failed to delete label $to_delete on issue $issue!"
return 1
fi
done
fi

if [[ "$has_label" = "false" ]]; then
# shellcheck disable=SC2155
local data="{\"labels\": [\"$label\"]}"
OUTPUT=$(curl -X "POST" -s --write-out "PR_TAG_CODE=%{http_code}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.github.symmetra-preview+json" \
-H "Authorization: token ${GITHUB_OAUTH_TOKEN}" -d "$data" \
"https://api.github.com/repos/${TRAVIS_REPO_SLUG}/issues/${issue}/labels")
CODE=${OUTPUT##*PR_TAG_CODE=}
OUTPUT=${OUTPUT%PR_TAG_CODE=*}
if [[ "$CODE" != "200" ]]; then
echo -e "Failed to add label $label on issue $issue!"
return 1
fi
echo -e "set version label to $label"
else
echo -e "current label is already correct, doing nothing"
fi
}

function update_label() {
echo -e "==> Create Labels"
create_labels || return 1
local label;
label="${UPDATE_TYPE^^}_LABEL_NAME"
label=${!label}
echo -e "==> Set Label"
set_label_on "$PR_NUM" "$label" || return 1
return 0
}

function is_pr() {
# shellcheck disable=SC2046
return $(test "$TRAVIS_PULL_REQUEST" != "false")
}

function escape_markdown() {
escaped=$(printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
Expand All @@ -49,8 +184,12 @@ function export_pr_num() {
echo -e "==> Detected merged pull request"
echo -e "PR #$PR_NUM"
return 0
elif is_pr; then
export PR_NUM=$TRAVIS_PULL_REQUEST
echo -e "==> Detected open pull request"
return 0
else
echo -e "Could not detect PR number from commit message, exiting"
echo -e "Could not detect PR number from commit message or PR build, exiting"
return 1
fi
}
Expand All @@ -60,14 +199,11 @@ function check_valid_state() {
echo -e "Current commit ($TRAVIS_COMMIT) already has a tag"
echo -e "Don't tag a PR merge commit manually, exiting"
return 1
elif [[ ! "$TRAVIS_BRANCH" =~ $DEPLOY_BRANCH ]]; then
echo -e "Not on deploy branch, exiting"
return 1
fi
return 0
}

# expects #1 to be a file name to write to
# expects $1 to be a file name to write to
function get_pr_info() {
if [[ -z "$GITHUB_OAUTH_TOKEN" ]]; then
curl "https://api.github.com/repos/${TRAVIS_REPO_SLUG}/pulls/${PR_NUM}" | jq '[.title, .body, .merged]' > "$1"
Expand All @@ -79,10 +215,6 @@ function get_pr_info() {
echo -e "PR request response empty"
return 1
fi
if [[ "$(jq '.[2]' < "$1")" != "true" ]]; then
echo -e "PR is not merged, exiting"
return 1
fi

return 0
}
Expand All @@ -92,7 +224,8 @@ function export_pr_info() {
get_pr_info "$json" || return 1
TITLE="$(jq '.[0]' < "$json")"
PR_BODY="$(jq '.[1]' < "$json")"

MERGED="$(jq '.[2]' < "$json")"

# trim quotes
PR_BODY="${PR_BODY%\"}"
PR_BODY="${PR_BODY#\"}"
Expand All @@ -114,28 +247,28 @@ function export_pr_info() {
export PRERELEASE
export TITLE
export PR_BODY
export MERGED

return 0
}

# must have access to $PR_BODY
function update_version() {
local update
if [[ "$PR_BODY" =~ $PATCH_CHANGE_REGEX ]]; then
# patch version
PATCH=$((PATCH+1))
update="Patch"
UPDATE_TYPE="patch"
elif [[ "$PR_BODY" =~ $MINOR_CHANGE_REGEX ]]; then
# minor version
PATCH="0"
MINOR=$((MINOR+1))
update="Minor"
UPDATE_TYPE="minor"
elif [[ "$PR_BODY" =~ $MAJOR_CHANGE_REGEX ]]; then
# major version
PATCH="0"
MINOR="0"
MAJOR=$((MAJOR+1))
update="Major"
UPDATE_TYPE="major"
else
# non-versioned
unset TRAVIS_TAG
Expand All @@ -144,8 +277,9 @@ function update_version() {
fi
TRAVIS_TAG="$MAJOR.$MINOR.$PATCH"
echo -e "==> Updated Semantic Version"
echo -e "$update version update to $TRAVIS_TAG"
echo -e "${UPDATE_TYPE^} version update to $TRAVIS_TAG"
export TRAVIS_TAG="v$TRAVIS_TAG"
export UPDATE_TYPE
return 0
}

Expand Down Expand Up @@ -229,9 +363,16 @@ status
export_pr_num || return 0
check_valid_state || return 0
export_pr_info || return 0

create_release_body
create_release_body || return 0
update_version || return 0
update_label || return 0

# If not merged, exit
if test "$MERGED" != "true"; then
unset TRAVIS_TAG
echo -e "PR is not merged yet, exiting"
return 0
fi

set_up_git
create_version_tag || return 0
Expand Down