Last active
November 1, 2022 19:37
-
-
Save eculver/a690bf0ead818d98b9c4fddb84d715f5 to your computer and use it in GitHub Desktop.
Consul OSS→Enterprise Merge Shell Helpers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function ci-for-oss-ent-merge-branch { | |
local branch | |
local base | |
branch="${1:-}" | |
if [ -z "${branch}" ]; then | |
echo "branch name required" | |
echo "usage: ci-for-oss-ent-merge-branch <branch-name>" | |
return 1 | |
fi | |
# There are two forms of branch names currently, one for when the merge is | |
# clean and the other when there were conflicts: | |
# oss/merge-$BRANCH-$SHA | |
# and | |
# oss/$BRANCH-$SHA | |
# | |
# Eventually, we should make these consistent but for now, let's just handle | |
# them both. The only difference is which field to use after cutting by '-'. | |
if grep -q '^oss/merge' <<< "$branch"; then | |
cut_flags=( "-f2" ) | |
else | |
cut_flags=( "-f1" ) | |
fi | |
base=$(echo "${branch}" | cut -d '/' -f2- | cut -d '-' ${cut_flags[@]}) | |
if [ -z "${base}" ]; then | |
echo "could not parse base from ${branch}, bailing" | |
return 1 | |
fi | |
open "https://app.circleci.com/pipelines/github/hashicorp/consul-enterprise?branch=${branch}" | |
} | |
function ci-for-all-oss-ent-merge-prs { | |
local branch | |
local pull_numbers | |
branch="${1:=main}" | |
if [ -z "${BOB_GITHUB_TOKEN}" ]; then | |
echo "must set \$BOB_GITHUB_TOKEN" | |
return 1 | |
fi | |
echo "Fetching all open oss-merge PRs for ${branch} branch" | |
pull_numbers=$(_get_oss_ent_merge_pull_numbers "${branch}" || echo "failed") | |
num_pulls=$(echo "${pull_numbers}" | wc -l | awk '{print $1}') | |
echo -n "Found ${num_pulls} oss-merge PRs for ${branch}, continue? (y/n) " | |
read -q | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
return | |
fi | |
while read -r num; do | |
echo "Fetching PR info for #${num}" | |
merge_branch=$(curl -s \ | |
-H "Authorization: token ${BOB_GITHUB_TOKEN}" \ | |
-H "Accept: application/vnd.github+json" \ | |
https://api.github.com/repos/hashicorp/consul-enterprise/pulls/${num} | jq -r '.head.ref') | |
if [ -z ${merge_branch} ]; then | |
echo "Could not find merge branch for PR #${num}, bailing" | |
return 1 | |
fi | |
ci-for-oss-ent-merge-branch "${merge_branch}" | |
done <<< "${pull_numbers}" | |
} | |
function delete-oss-merge-branches { | |
echo "Delete branches with ^oss/ pattern? (y/n) " | |
read -q | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
return | |
fi | |
for b in $(git branch | awk '{$1=$1;print}' | egrep '^oss/'); do git branch -D "$b"; done | |
} | |
function rebase-oss-ent-merge-branch { | |
local branch | |
local pull_number | |
local base | |
branch="${1:-}" | |
pull_number="${2:-}" | |
if [ -z "${branch}" ]; then | |
echo "branch name required" | |
echo "usage: rebase-oss-ent-merge-branch <branch-name> <pull-number>" | |
return 1 | |
fi | |
if [ -z "${pull_number}" ]; then | |
echo "pull_number name required" | |
echo "usage: rebase-oss-ent-merge-branch <branch-name> <pull-number>" | |
return 1 | |
fi | |
# There are two forms of branch names currently, one for when the merge is | |
# clean and the other when there were conflicts: | |
# oss/merge-$BRANCH-$SHA | |
# and | |
# oss/$BRANCH-$SHA | |
# | |
# Eventually, we should make these consistent but for now, let's just handle | |
# them both. The only difference is which field to use after cutting by '-'. | |
if grep -q '^oss/merge' <<< "$branch"; then | |
cut_flags=( "-f2" ) | |
else | |
cut_flags=( "-f1" ) | |
fi | |
base=$(echo "${branch}" | cut -d '/' -f2- | cut -d '-' ${cut_flags[@]}) | |
if [ -z "${base}" ]; then | |
echo "could not parse base from ${branch}, bailing" | |
return 1 | |
fi | |
echo -n "fixing up ${branch} for ${base}, continue? (y/n) " | |
read -q | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
return | |
fi | |
git co "${base}" | |
git pull origin "${base}" | |
git co "${branch}" | |
if ! git merge "${base}"; then | |
echo | |
echo "Looks like there were conflicts, stopping here." | |
echo "When done resolving conflicts, run" | |
echo | |
echo " git push origin ${branch}" | |
echo | |
return 1 | |
fi | |
git push origin "${branch}" | |
if git --no-pager diff "origin/${base}"; then | |
echo | |
echo -n "There are no changes between this branch and ${base}, would you like to close this PR (${pull_number})? (y/n)" | |
read -q | |
echo | |
if [[ $REPLY =~ ^[Yy]$ ]]; then | |
_close_ent_pr_with_comment "${pull_number}" "Closing as this was included in a subsequent merge." | |
# ensure the the PR branch gets cleaned up | |
git push origin --delete "${branch}" | |
fi | |
fi | |
} | |
function rebase-all-oss-ent-merge-prs { | |
local branch | |
local pull_numbers | |
branch="${1:=main}" | |
if [ -z "${BOB_GITHUB_TOKEN}" ]; then | |
echo "must set \$BOB_GITHUB_TOKEN" | |
return 1 | |
fi | |
echo "Fetching all open oss-merge PRs for ${branch} branch" | |
pull_numbers=$(_get_oss_ent_merge_pull_numbers "${branch}" || echo "failed") | |
num_pulls=$(echo "${pull_numbers}" | wc -l | awk '{print $1}') | |
echo -n "Found ${num_pulls} oss-merge PRs for ${branch}, continue? (y/n) " | |
read -q | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
return | |
fi | |
while read -r num; do | |
echo "Fetching PR info for #${num}" | |
merge_branch=$(curl -s \ | |
-H "Authorization: token ${BOB_GITHUB_TOKEN}" \ | |
-H "Accept: application/vnd.github+json" \ | |
https://api.github.com/repos/hashicorp/consul-enterprise/pulls/${num} | jq -r '.head.ref') | |
if [ -z ${merge_branch} ]; then | |
echo "Could not find merge branch for PR #${num}, bailing" | |
return 1 | |
fi | |
rebase-oss-ent-merge-branch "${merge_branch}" "${num}" | |
done <<< "${pull_numbers}" | |
} | |
function _get_oss_ent_merge_pull_numbers { | |
local branch | |
branch="${1:=main}" | |
if [ -z "${BOB_GITHUB_TOKEN}" ]; then | |
echo "must set \$BOB_GITHUB_TOKEN" | |
return 1 | |
fi | |
curl -s \ | |
-H "Authorization: token ${BOB_GITHUB_TOKEN}" \ | |
-H 'Accept: application/vnd.github.text-match+json' \ | |
'https://api.github.com/search/issues?q=repo%3Ahashicorp/consul-enterprise+is%3Apr+label%3Aoss-merge+is%3Aopen+%5B'${branch}'%5D' | jq -r '.items[].number' | sort -n | |
} | |
function _close_ent_pr_with_comment { | |
local pull_number | |
local comment | |
local response | |
local exit_code | |
pull_number="${1:-}" | |
comment="${2:-}" | |
if [ -z "${pull_number}" ]; then | |
echo "pull_number required" | |
echo "usage: _close_ent_pr_with_comment <pull-number> <comment>" | |
return 1 | |
fi | |
if [ -z "${comment}" ]; then | |
echo "comment required" | |
echo "usage: _close_ent_pr_with_comment <pull-number> <comment>" | |
return 1 | |
fi | |
if [ -z "${BOB_GITHUB_TOKEN}" ]; then | |
echo "must set \$BOB_GITHUB_TOKEN" | |
return 1 | |
fi | |
# create the comment, note: this does not do any escaping of the comment string | |
response=$(curl -s \ | |
-H "Authorization: token ${BOB_GITHUB_TOKEN}" \ | |
-H 'Accept: application/vnd.github.full+json' \ | |
-X POST \ | |
-d '{"body": "'${comment}'"}' \ | |
'https://api.github.com/repos/hashicorp/consul-enterprise/issues/'${pull_number}'/comments') | |
exit_code=$? | |
if [ $exit_code -ne 0 ]; then | |
echo "API request to create a comment returned non-zero exit. Got: ${exit_code}." | |
echo | |
echo "Response:" | |
echo "${response}" | |
echo | |
exit 1 | |
fi | |
# close the pull request | |
response=$(curl -s \ | |
-H "Authorization: token ${BOB_GITHUB_TOKEN}" \ | |
-H 'Accept: application/vnd.github.full+json' \ | |
-X POST \ | |
-d '{"state": "closed"}' \ | |
'https://api.github.com/repos/hashicorp/consul-enterprise/pulls/'${pull_number}) | |
exit_code=$? | |
if [ $exit_code -ne 0 ]; then | |
echo "API request to close the pull request returned non-zero exit. Got: ${exit_code}." | |
echo | |
echo "Response:" | |
echo "${response}" | |
echo | |
exit 1 | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I added support to detect whether the PR has a diff against the base and if not, to prompt the user for closing of the PR. If the user accepts the prompt, a comment with "Closing as this was included in a subsequent merge." is added, the PR is closed and the PR branch is deleted.