Files
TwitchDropsMiner/.github/scripts/revert_release.sh
2025-10-27 16:02:40 +11:00

350 lines
11 KiB
Bash
Executable File

#!/bin/bash
# revert_release.sh - Revert a failed version release
# Usage: revert_release.sh <version>
#
# Arguments:
# version: The semver version to revert (e.g., 1.2.3 or 2.0.0-rc.1)
#
# This script:
# 1. Validates the version format
# 2. Checks what resources exist (tag, branch, GitHub release)
# 3. Extracts the previous version from git history
# 4. Shows a summary and asks for confirmation
# 5. Deletes the tag, branch, and GitHub release
# 6. Reverts version.py and pyproject.toml to the previous version
# 7. Commits and pushes the revert to main branch
#
# Requirements:
# - gh CLI installed and authenticated
# - Git repository with proper remotes configured
# - Write access to the repository
set -euo pipefail
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script directory for accessing sibling scripts
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Display usage information
usage() {
echo "Usage: $0 <version>"
echo ""
echo "Reverts a failed version release by:"
echo " - Deleting the GitHub release"
echo " - Deleting the git tag (local and remote)"
echo " - Deleting the release branch (local and remote)"
echo " - Reverting version files to the previous version"
echo " - Committing and pushing the revert to main branch"
echo ""
echo "Arguments:"
echo " version: The semver version to revert (e.g., 1.2.3 or 2.0.0-rc.1)"
echo ""
echo "Examples:"
echo " $0 1.2.3 # Revert version 1.2.3"
echo " $0 2.0.0-rc.1 # Revert pre-release 2.0.0-rc.1"
exit 1
}
# Check if version argument is provided
if [ "$#" -ne 1 ]; then
echo -e "${RED}Error: Version argument required${NC}"
usage
fi
VERSION="$1"
TAG_NAME="v$VERSION"
BRANCH_NAME="release/$VERSION"
echo -e "${BLUE}=====================================${NC}"
echo -e "${BLUE}Version Release Revert Tool${NC}"
echo -e "${BLUE}=====================================${NC}"
echo ""
# Step 1: Validate version format
echo -e "${YELLOW}[1/7] Validating version format...${NC}"
if ! "$SCRIPT_DIR/validate_semver.sh" "$VERSION" &>/dev/null; then
echo -e "${RED}Error: Invalid version format: $VERSION${NC}"
echo -e "${RED}Expected semver format (e.g., 1.2.3 or 2.0.0-rc.1)${NC}"
exit 1
fi
echo -e "${GREEN}✓ Version format is valid${NC}"
echo ""
# Step 2: Check if gh CLI is installed and authenticated
echo -e "${YELLOW}[2/7] Checking GitHub CLI...${NC}"
if ! command -v gh &> /dev/null; then
echo -e "${RED}Error: gh CLI is not installed${NC}"
echo -e "${RED}Please install it from: https://cli.github.com/${NC}"
exit 1
fi
if ! gh auth status &>/dev/null; then
echo -e "${RED}Error: Not authenticated with GitHub${NC}"
echo -e "${RED}Please run: gh auth login${NC}"
exit 1
fi
echo -e "${GREEN}✓ GitHub CLI is ready${NC}"
echo ""
# Step 3: Check what resources exist
echo -e "${YELLOW}[3/7] Checking existing resources...${NC}"
# Check if tag exists locally
TAG_EXISTS_LOCAL=false
if git rev-parse "$TAG_NAME" &>/dev/null; then
TAG_EXISTS_LOCAL=true
echo -e "${GREEN}✓ Found local tag: $TAG_NAME${NC}"
else
echo -e "${YELLOW} Local tag not found: $TAG_NAME${NC}"
fi
# Check if tag exists remotely
TAG_EXISTS_REMOTE=false
if git ls-remote --tags origin | grep -q "refs/tags/$TAG_NAME$"; then
TAG_EXISTS_REMOTE=true
echo -e "${GREEN}✓ Found remote tag: $TAG_NAME${NC}"
else
echo -e "${YELLOW} Remote tag not found: $TAG_NAME${NC}"
fi
# Check if branch exists locally
BRANCH_EXISTS_LOCAL=false
if git rev-parse --verify "$BRANCH_NAME" &>/dev/null; then
BRANCH_EXISTS_LOCAL=true
echo -e "${GREEN}✓ Found local branch: $BRANCH_NAME${NC}"
else
echo -e "${YELLOW} Local branch not found: $BRANCH_NAME${NC}"
fi
# Check if branch exists remotely
BRANCH_EXISTS_REMOTE=false
if git ls-remote --heads origin | grep -q "refs/heads/$BRANCH_NAME$"; then
BRANCH_EXISTS_REMOTE=true
echo -e "${GREEN}✓ Found remote branch: $BRANCH_NAME${NC}"
else
echo -e "${YELLOW} Remote branch not found: $BRANCH_NAME${NC}"
fi
# Check if GitHub release exists
RELEASE_EXISTS=false
if gh release view "$TAG_NAME" &>/dev/null; then
RELEASE_EXISTS=true
echo -e "${GREEN}✓ Found GitHub release: $TAG_NAME${NC}"
else
echo -e "${YELLOW} GitHub release not found: $TAG_NAME${NC}"
fi
echo ""
# If nothing exists, exit
if [ "$TAG_EXISTS_LOCAL" = false ] && [ "$TAG_EXISTS_REMOTE" = false ] && \
[ "$BRANCH_EXISTS_LOCAL" = false ] && [ "$BRANCH_EXISTS_REMOTE" = false ] && \
[ "$RELEASE_EXISTS" = false ]; then
echo -e "${RED}Error: No resources found for version $VERSION${NC}"
echo -e "${RED}Nothing to revert.${NC}"
exit 1
fi
# Step 4: Extract previous version from git history
echo -e "${YELLOW}[4/7] Extracting previous version from git history...${NC}"
# Use the get_previous_version.sh script to extract the previous version
if ! PREVIOUS_VERSION=$("$SCRIPT_DIR/get_previous_version.sh" "$VERSION" 2>&1); then
echo -e "${RED}Error: Failed to extract previous version${NC}"
echo -e "${RED}$PREVIOUS_VERSION${NC}"
exit 1
fi
echo -e "${GREEN}✓ Previous version: $PREVIOUS_VERSION${NC}"
echo ""
# Step 5: Show summary and ask for confirmation
echo -e "${BLUE}=====================================${NC}"
echo -e "${BLUE}Revert Summary${NC}"
echo -e "${BLUE}=====================================${NC}"
echo ""
echo -e "${YELLOW}Version to revert:${NC} $VERSION"
echo -e "${YELLOW}Previous version:${NC} $PREVIOUS_VERSION"
echo ""
echo -e "${YELLOW}The following actions will be performed:${NC}"
echo ""
ACTION_COUNT=0
if [ "$RELEASE_EXISTS" = true ]; then
echo " • Delete GitHub release: $TAG_NAME"
((ACTION_COUNT++))
fi
if [ "$TAG_EXISTS_REMOTE" = true ]; then
echo " • Delete remote tag: $TAG_NAME"
((ACTION_COUNT++))
fi
if [ "$TAG_EXISTS_LOCAL" = true ]; then
echo " • Delete local tag: $TAG_NAME"
((ACTION_COUNT++))
fi
if [ "$BRANCH_EXISTS_REMOTE" = true ]; then
echo " • Delete remote branch: $BRANCH_NAME"
((ACTION_COUNT++))
fi
if [ "$BRANCH_EXISTS_LOCAL" = true ]; then
echo " • Delete local branch: $BRANCH_NAME"
((ACTION_COUNT++))
fi
echo " • Update src/version.py: $VERSION$PREVIOUS_VERSION"
echo " • Update pyproject.toml: $VERSION$PREVIOUS_VERSION"
echo " • Commit changes to main branch with message:"
echo " 'chore: revert version from $VERSION to $PREVIOUS_VERSION'"
echo " • Push changes to origin/main"
((ACTION_COUNT+=3))
echo ""
echo -e "${RED}Total actions: $ACTION_COUNT${NC}"
echo ""
echo -e "${YELLOW}This operation cannot be easily undone.${NC}"
echo -n -e "${YELLOW}Type 'yes' to confirm: ${NC}"
read -r CONFIRMATION
if [ "$CONFIRMATION" != "yes" ]; then
echo -e "${RED}Aborted.${NC}"
exit 0
fi
echo ""
echo -e "${GREEN}Confirmed. Proceeding with revert...${NC}"
echo ""
# Step 6: Perform revert operations
echo -e "${YELLOW}[5/7] Deleting release resources...${NC}"
# Delete GitHub release
if [ "$RELEASE_EXISTS" = true ]; then
echo " Deleting GitHub release $TAG_NAME..."
if gh release delete "$TAG_NAME" --yes; then
echo -e "${GREEN}✓ Deleted GitHub release${NC}"
else
echo -e "${RED}✗ Failed to delete GitHub release${NC}"
fi
fi
# Delete remote tag
if [ "$TAG_EXISTS_REMOTE" = true ]; then
echo " Deleting remote tag $TAG_NAME..."
if git push --delete origin "$TAG_NAME" 2>/dev/null; then
echo -e "${GREEN}✓ Deleted remote tag${NC}"
else
echo -e "${RED}✗ Failed to delete remote tag (may have been deleted by release deletion)${NC}"
fi
fi
# Delete local tag
if [ "$TAG_EXISTS_LOCAL" = true ]; then
echo " Deleting local tag $TAG_NAME..."
if git tag -d "$TAG_NAME"; then
echo -e "${GREEN}✓ Deleted local tag${NC}"
else
echo -e "${RED}✗ Failed to delete local tag${NC}"
fi
fi
# Delete remote branch
if [ "$BRANCH_EXISTS_REMOTE" = true ]; then
echo " Deleting remote branch $BRANCH_NAME..."
if git push --delete origin "$BRANCH_NAME"; then
echo -e "${GREEN}✓ Deleted remote branch${NC}"
else
echo -e "${RED}✗ Failed to delete remote branch${NC}"
fi
fi
# Delete local branch (only if we're not on it)
if [ "$BRANCH_EXISTS_LOCAL" = true ]; then
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$CURRENT_BRANCH" = "$BRANCH_NAME" ]; then
echo " Switching from $BRANCH_NAME to main..."
git checkout main
fi
echo " Deleting local branch $BRANCH_NAME..."
if git branch -D "$BRANCH_NAME"; then
echo -e "${GREEN}✓ Deleted local branch${NC}"
else
echo -e "${RED}✗ Failed to delete local branch${NC}"
fi
fi
echo ""
# Step 7: Update version files and commit
echo -e "${YELLOW}[6/7] Updating version files...${NC}"
# Make sure we're on main branch
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$CURRENT_BRANCH" != "main" ]; then
echo " Switching to main branch..."
git checkout main
git pull origin main
fi
# Configure git
git config user.name "github-actions[bot]" || true
git config user.email "github-actions[bot]@users.noreply.github.com" || true
# Update version.py
echo " Updating src/version.py..."
echo "__version__ = \"$PREVIOUS_VERSION\"" > src/version.py
echo -e "${GREEN}✓ Updated src/version.py${NC}"
# Update pyproject.toml
echo " Updating pyproject.toml..."
sed -i "s/^version = \"[^\"]*\"\(.*\)/version = \"$PREVIOUS_VERSION\"\1/" pyproject.toml
echo -e "${GREEN}✓ Updated pyproject.toml${NC}"
echo ""
# Step 8: Commit and push
echo -e "${YELLOW}[7/7] Committing and pushing changes...${NC}"
git add src/version.py pyproject.toml
if git diff --cached --quiet; then
echo -e "${YELLOW} No changes to commit (version may already be reverted)${NC}"
else
echo " Creating commit..."
git commit -m "chore: revert version from $VERSION to $PREVIOUS_VERSION"
echo -e "${GREEN}✓ Created commit${NC}"
echo " Pushing to origin/main..."
git push origin main
echo -e "${GREEN}✓ Pushed changes${NC}"
fi
echo ""
echo -e "${BLUE}=====================================${NC}"
echo -e "${GREEN}✅ Revert Complete!${NC}"
echo -e "${BLUE}=====================================${NC}"
echo ""
echo -e "${GREEN}Successfully reverted version from $VERSION to $PREVIOUS_VERSION${NC}"
echo ""
echo "Summary:"
[ "$RELEASE_EXISTS" = true ] && echo " ✓ Deleted GitHub release"
[ "$TAG_EXISTS_REMOTE" = true ] && echo " ✓ Deleted remote tag"
[ "$TAG_EXISTS_LOCAL" = true ] && echo " ✓ Deleted local tag"
[ "$BRANCH_EXISTS_REMOTE" = true ] && echo " ✓ Deleted remote branch"
[ "$BRANCH_EXISTS_LOCAL" = true ] && echo " ✓ Deleted local branch"
echo " ✓ Reverted version files"
echo " ✓ Committed and pushed to main"
echo ""