spring-petclinic/infra/scripts/release-patch.sh
Jesse Houldsworth 00ed61ebb5 tf
2025-10-09 06:46:44 -07:00

264 lines
8.3 KiB
Bash
Executable file

#!/usr/bin/env bash
set -eo pipefail
usage()
{
echo "usage: release-patch.sh
This script is used to release a patch release. It is untested on major/minor releases and for those, some modification may be necessary.
-v, --version version to release, example: 0.10.6
-t, --github-token personal GitHub token
-r, --remote git remote server name for the feast-dev/feast repo (e.g. origin, upstream, etc.)
"
}
while [ "$1" != "" ]; do
case "$1" in
-v | --version ) VERSION="$2"; shift;;
-t | --github-token ) GH_TOKEN="$2"; shift;;
-r | --remote ) REMOTE="$2"; shift;;
-h | --help ) usage; exit;;
* ) usage; exit 1
esac
shift
done
if [ -z $VERSION ]; then usage; exit 1; fi
if [ -z $GH_TOKEN ]; then usage; exit 1; fi
if [ -z $REMOTE ]; then usage; exit 1; fi
regex="([0-9]+)\.([0-9]+)\.([0-9]+)"
if [[ $VERSION =~ $regex ]]
then
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
PATCH="${BASH_REMATCH[3]}"
else
usage
exit 1
fi
if ! which gh ; then echo "Please install the GitHub CLI to use this script"; exit 1; fi
echo "This script is mostly idempotent; check git status for temp files before restarting. It will always prompt you before making any non-local change."
# Go to infra/scripts directory
cd $(dirname "$0")
# Login to GitHub CLI
echo $GH_TOKEN | gh auth login --with-token
echo "Step 1: rebase new commits onto release branch"
git fetch $REMOTE
git checkout $REMOTE/master
STARTING_COMMIT=$(git merge-base $REMOTE/master v$MAJOR.$MINOR-branch)
git checkout v$MAJOR.$MINOR-branch
push_rebased_commits()
{
echo "Pushing commits"
git push $REMOTE v$MAJOR.$MINOR-branch
echo "Commits pushed"
}
rebase_from_master()
{
echo "Rebasing commits"
git checkout $REMOTE/master
git rebase --interactive --onto v$MAJOR.$MINOR-branch $STARTING_COMMIT HEAD
git branch -f v$MAJOR.$MINOR-branch HEAD
git checkout v$MAJOR.$MINOR-branch
echo "Commits rebased"
echo "Step 1b: Push commits"
read -p "Commits are not pushed. Continue (y) or skip this sub-step (n)? " choice
case "$choice" in
y|Y ) push_rebased_commits ;;
* ) echo "Skipping this sub-step" ;;
esac ;
}
echo "Step 1a: rebase commits"
if git status | grep -q "is ahead of" ; then
read -p "Your local branch is ahead of its remote counterpart, indicating you may have already rebased. Skip this step (y) or run the rebase starting from commit $STARTING_COMMIT (n)? " choice
case "$choice" in
y|Y ) echo "Skipping this step" ;;
* ) rebase_from_master ;;
esac ;
else
read -p "Will rebase starting from commit $STARTING_COMMIT. Continue (y) or skip this step (n)? " choice
case "$choice" in
y|Y ) rebase_from_master ;;
* ) echo "Skipping this step" ;;
esac ;
fi
CHANGELOG=$(git rev-parse --show-toplevel)/CHANGELOG.md
commit_changelog()
{
echo "Committing CHANGELOG.md"
git add $CHANGELOG
git commit -m "Update CHANGELOG for Feast v$MAJOR.$MINOR.$PATCH"
}
update_changelog()
{
echo "Running changelog generator (will take up to a few minutes)"
echo -e "# Changelog\n" > temp \
&& docker run -it --rm ferrarimarco/github-changelog-generator \
--user feast-dev \
--project feast \
--release-branch master \
--future-release v$MAJOR.$MINOR.$PATCH \
--unreleased-only \
--no-issues \
--bug-labels kind/bug \
--enhancement-labels kind/feature \
--breaking-labels compat/breaking \
-t $GH_TOKEN \
--max-issues 1 -o \
| sed -n '/## \[v'"$MAJOR.$MINOR.$PATCH"'\]/,$p' \
| sed '$d' | sed '$d' | sed '$d' | tr -d '\r' >> temp \
&& sed '1d' $CHANGELOG >> temp && mv temp $CHANGELOG
git diff $CHANGELOG
echo "Check CHANGELOG.md carefully and fix any errors. In particular, make sure the new enhancements/PRs/bugfixes aren't already listed somewhere lower down in the file."
read -p "Once you're done checking, continue to commit the changelog (y) or exit (n)? " choice
case "$choice" in
y|Y ) commit_changelog ;;
* ) exit ;;
esac ;
}
echo "Step 2: Updating CHANGELOG.md"
if grep -q "https://github.com/feast-dev/feast/tree/v$MAJOR.$MINOR.$PATCH" $CHANGELOG ; then
read -p "CHANGELOG.md appears updated. Skip this step (y/n)? " choice
case "$choice" in
y|Y ) echo "Skipping this step" ;;
* ) update_changelog ;;
esac ;
else
update_changelog ;
fi
tag_commit()
{
echo "Tagging commit"
git tag v$MAJOR.$MINOR.$PATCH
echo "Commit tagged"
}
echo "Step 3: Tag commit"
if git tag | grep -q "v$MAJOR.$MINOR.$PATCH" ; then
read -p "The tag already exists. Skip this step (y/n)? " choice
case "$choice" in
y|Y ) echo "Skipping this step" ;;
* ) tag_commit ;;
esac ;
else
tag_commit ;
fi
echo "Step 4: Push commits and tags"
push_commits()
{
echo "Pushing commits"
git push $REMOTE v$MAJOR.$MINOR-branch
echo "Commits pushed"
}
echo "Step 4a: Push commits"
if git status | grep -q "nothing to commit" ; then
echo "The commits appear pushed. Skipping this sub-step"
else
read -p "Commits are not pushed. Continue (y) or skip this sub-step (n)? " choice
case "$choice" in
y|Y ) push_commits ;;
* ) echo "Skipping this sub-step" ;;
esac ;
fi
push_tag()
{
echo "Pushing tag"
git push $REMOTE v$MAJOR.$MINOR.$PATCH
echo "Tag pushed"
}
echo "Step 4b: Push tag"
if git ls-remote --tags $REMOTE | grep -q "v$MAJOR.$MINOR.$PATCH" ; then
read -p "The tag appears pushed. Skip this sub-step (y/n)? " choice
case "$choice" in
y|Y ) echo "Skipping this sub-step" ;;
* ) push_tag ;;
esac ;
else
read -p "The tag is not pushed. Continue (y) or skip this sub-step (n)? " choice
case "$choice" in
y|Y ) push_tag ;;
* ) echo "Skipping this sub-step" ;;
esac ;
fi
read -p "Now wait for the CI to pass. Continue (y) or exit and fix the problem (n)? " choice
case "$choice" in
y|Y ) echo "Moving on to the next step" ;;
* ) exit ;;
esac ;
echo "Step 6: Add changelog to master"
changelog_hash=$(git rev-parse HEAD)
git checkout master
cp_changelog()
{
echo "Cherry-picking"
git cherry-pick $changelog_hash
echo "Cherry-pick done"
}
echo "Step 6a: Cherry-pick changelog to master"
if grep -q "https://github.com/feast-dev/feast/tree/v$MAJOR.$MINOR.$PATCH" $CHANGELOG ; then
read -p "The changelog appears to be cherry-picked onto master. Skip this sub-step (y/n)? " choice
case "$choice" in
y|Y ) echo "Skipping this sub-step" ;;
* ) cp_changelog ;;
esac ;
else
read -p "The changelog does not appear to be cherry-picked onto master. Continue (y) or skip this sub-step (n)? " choice
case "$choice" in
y|Y ) cp_changelog ;;
* ) echo "Skipping this sub-step" ;;
esac ;
fi
push_cp()
{
echo "Pushing cherry-pick"
git push $REMOTE master
echo "Commit pushed"
}
echo "Step 6b: Push changelog to master"
if git status | grep -q "nothing to commit" ; then
echo "The commit appears pushed. Skipping this sub-step"
else
read -p "The commit is not pushed. Continue (y) or skip this sub-step (n)? " choice
case "$choice" in
y|Y ) push_cp ;;
* ) echo "Skipping this sub-step" ;;
esac ;
fi
create_release()
{
echo "Creating GitHub release"
cat $CHANGELOG | sed -n '/## \[v'"$MAJOR.$MINOR.$PATCH"'\]/,/## \[v'"$MAJOR.$MINOR.$(($PATCH-1))"'\]/p' | sed -n '/**Implemented enhancements/,$p' | sed '$d' > temp2 \
&& gh release create v$MAJOR.$MINOR.$PATCH -t "Feast v$MAJOR.$MINOR.$PATCH" --repo feast-dev/feast --notes-file temp2 \
&& rm temp2
echo "GitHub release created"
}
echo "Step 7: Create a GitHub release"
if gh release list --repo feast-dev/feast | grep -q "v$MAJOR.$MINOR.$PATCH" ; then
read -p "GitHub release appears created. Skip this step (y/n)? " choice
case "$choice" in
y|Y ) echo "Skipping this step" ;;
* ) create_release ;;
esac ;
else
read -p "A GitHub release has not been created. Continue (y) or skip this step (n)? " choice
case "$choice" in
y|Y ) create_release ;;
* ) echo "Skipping this step" ;;
esac ;
fi
echo "Step 8: Update the Upgrade Guide manually (docs/advanced/upgrading.md)"