diff --git a/infra/scripts/release-patch.sh b/infra/scripts/release-patch.sh new file mode 100755 index 0000000000..8b7973185e --- /dev/null +++ b/infra/scripts/release-patch.sh @@ -0,0 +1,264 @@ +#!/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)"