open-vault/scripts/upgrade-packagespec

131 lines
3.5 KiB
Bash
Executable file

#!/usr/bin/env bash
# This script takes 2 positional args:
#
# 1: The version of packagespec to upgrade a branch to (e.g. 1.2.3)
# 2: The target branch to upgrade.
#
# It works in a temp directory, so does not interfere with your work tree
# or git index or config.
#
# It does this:
#
# 1. Inspects your remote config for URL remotes.
# 2. Clone this directory into a temp dir.
# 3. Sets the remotes in the clone to match the remotes you have configured.
# 4. Fetches everything from all remotes.
# 5. Determines which remote your target branch is on. If it's more than one
# remote, then exits with an error as there would be no way to choose.
# 6. Checks out a new branch named packagespec<version>/<target branch name>
# 7. Runs packagespec upgrade -version <version>
# 8. Commits the relevant paths with the message 'packagespec upgrade -version <version>'
# 9. Pushes the new branch to the same remote as the original branch.
# 0. Tells you to open a PR.
# VERSION is the packagespec version to upgrade to.
VERSION="$1"
BRANCH="$2"
FLAG="$3"
REPO_NAME="$4"
BINNAME="$0"
usage() { echo "usage: $BINNAME <packagespec version> <branch name> [-pr PRODUCT_NAME]"; }
if [ -z "$VERSION" ]; then
usage; exit 1
fi
if [ -z "$BRANCH" ]; then
usage; exit 1
fi
PR=false
if [ -n "$FLAG" ]; then
if [ "$FLAG" = "-pr" ]; then
if [ -z "$REPO_NAME" ]; then
usage; exit 1
fi
PR=true
else
usage; exit 1
fi
fi
set -euo pipefail
declare -A REMOTES
# url_remotes lists remotes along with their push URLs, where they are
# not filesystem paths (i.e. do not start with / or . ).
url_remotes() { git remote -v | grep -F "(push)" | sed -E 's/[[:space:]]+\(push\)//g' | grep -Ev "\t(/|\.)"; }
for R in $(url_remotes | cut -f1); do
REMOTES[$R]="$(url_remotes | grep -E "^$R\t" | cut -f2)"
done
for R in "${!REMOTES[@]}"; do
echo "Remote: $R = ${REMOTES[$R]}"
done
TEMP=".upgrade-packagespec"
mkdir -p "$TEMP"
echo "*" > "$TEMP/.gitignore"
CLONEDIR="$TEMP/product-repo"
if ! [ -d "$CLONEDIR/.git" ]; then
git clone . "$CLONEDIR"
fi
cd "$CLONEDIR"
echo "==> WORKING IN TEMP DIR: $CLONEDIR"
git reset --hard
# Remove existing remotes
for R in $(git remote); do git remote rm "$R"; done
# Add remotes from original checkout dir
for R in "${!REMOTES[@]}"; do
git remote add "$R" "${REMOTES[$R]}"
done
# Fetch everything from these remotes, ignore errors.
git remote update || true
BRANCH_ESCAPED="$(sed -E -e 's/\./\\./g' -e 's/\+/\\+/g' -e 's/\//\\\//g' <<< "$BRANCH")"
# Determine which remotes the branch is on.
declare -A BRANCH_REMOTES
for R in "${!REMOTES[@]}"; do
if git branch -a | grep -E "^[[:space:]]*remotes/$R/$BRANCH_ESCAPED\$"; then
TARGET_REMOTE="$R"
BRANCH_REMOTES[$R]=1
fi
done
COUNT="${#BRANCH_REMOTES[@]}"
if [ "$COUNT" -ne "1" ]; then
echo "==> ERROR: Branch $BRANCH found on $COUNT remotes; want exactly 1"
exit 1
fi
# Checkout the target update branch.
git checkout "$BRANCH"
git reset --hard "$TARGET_REMOTE/$BRANCH"
NEW_BRANCH="packagespec$VERSION/$BRANCH"
git checkout -B "$NEW_BRANCH" "$BRANCH"
COMMAND="packagespec upgrade -version $VERSION"
echo "==> Running $COMMAND"
$COMMAND
git add .circleci/ packages*.lock packagespec*
git commit -m "$COMMAND"
git push -u "$TARGET_REMOTE" "$NEW_BRANCH"
echo "==> All done: upgrade pushed to branch $NEW_BRANCH on ${REMOTES[$TARGET_REMOTE]}"
echo "==> ACTIONS FOR YOU: Open a PR with base: $BRANCH compare: $NEW_BRANCH"
if ! $PR; then
exit 0
fi
# Open browser with PR ready:
open https://github.com/hashicorp/$REPO_NAME/compare/$BRANCH...$NEW_BRANCH?expand=1