Skip to content

fi is a reserved keyword #238

@MohammadBnei

Description

@MohammadBnei

I have a basic release script with sed and grep, but i cannot convert it to a go module because of the following error :

# generate gives the same error
bunster build release.sh -o release
Error:  syntax error: `fi` is a reserved keyword, cannot be used a command name. (line: 58, column: 5)

Here is the script :

#!/bin/bash
# Trap SIGINT for the whole script and define an exit handler
trap "gum style --foreground 196 'Process interrupted. Exiting...'; exit 130" SIGINT

# Check for a --no-commit flag
NO_COMMIT=false
if [[ "$1" == "--no-commit" ]]; then
    NO_COMMIT=true
    gum style --foreground 226 "Running in dry-run mode: changes will not be committed or pushed."
fi

gum style \
    --foreground 212 --border-foreground 212 --border double \
    --align center --width 50 --margin "1 2" --padding "2 4" \
    "$(curl -s https://v2.jokeapi.dev/joke/Programming?format=txt || 'let`s release')"

# First, check if gum is installed
if ! command -v gum &>/dev/null; then
    echo "Gum is not installed. Please install it first:"
    echo "brew install gum (macOS/Linux)"
    echo "Or visit https://github.com/charmbracelet/gum for other installation options"
    exit 1
fi

# Ensure the script is run from the 'main' branch and it's up-to-date
CURRENT_BRANCH=$(git symbolic-ref --short HEAD)
if [ "$CURRENT_BRANCH" != "main" ]; then
    gum style --foreground 196 --margin "1" "You are not on the main branch."
    if gum confirm "Would you like to switch to the 'main' branch?"; then
        git checkout main
    else
        gum style --foreground 196 --margin "1" "Please switch to 'main' branch and ensure it is up-to-date before running this script."
        exit 1
    fi
fi

# Ask if the user wants to pull the latest changes
if gum confirm "Do you want to pull the latest changes for the main branch?"; then
    if ! git pull origin main; then
        gum style --foreground 196 --margin "1" "Failed to pull the latest changes. Please resolve any issues and ensure branch 'main' is up-to-date."
        exit 1
    fi
fi

# Function to extract version from changelog and initialize the release process
extract_version_from_changelog() {
    local changelog_path="$1"
    if [ ! -f "$changelog_path" ]; then
        gum style --foreground 196 --margin "1" "Error: $changelog_path not found!"
        return 1
    fi

    local changelog_header=$(head -n 10 "$changelog_path")
    local version_line=$(echo "$changelog_header" | grep -E "## (.*?-)?[0-9]+\.[0-9]+\.[0-9]+ \((?:unreleased|Unreleased)\)")
    if [ -z "$version_line" ]; then
        gum style --foreground 196 --margin "1" "Error: Couldn't find unreleased version in the first 10 lines of $changelog_path"
        return 1
    fi

    local full_version=$(echo "$version_line" | sed -E 's/## (.*) \((unreleased|Unreleased)\)/\1/')
    local prefix=""
    local version=""

    if [[ "$full_version" == *-* ]]; then
        prefix="${full_version%-*}-"
        version="${full_version##*-}"
    else
        version="$full_version"
    fi
    echo "$version|$prefix"
    return 0
}

# Function to update changelog with new version
update_changelog() {
    local changelog_path="$1"
    local current_version="$2"
    local next_version="$3"
    local release_date="$4"
    local prefix="$5"
    gum style --foreground 212 "Updating changelog at $changelog_path"

    local next_version_header="## ${prefix}${next_version} (unreleased)"
    local current_version_header="## ${prefix}${current_version} (${release_date}"

    # Check if the "unreleased" pattern exists
    if grep -qE "## ${prefix}${current_version} \(unreleased|Unreleased\)" "$changelog_path"; then
        # If found, replace using sed
        sed -i'.bak' -E "s|## ${prefix}${current_version} \(unreleased\|Unreleased\)|${next_version_header}\n\n${current_version_header}|g" "$changelog_path"
        rm "${changelog_path}.bak" 2>/dev/null
        gum style --foreground 76 "Changelog updated successfully!"
    else
        # If not found, insert the new version headers after the topmost title
        gum style --foreground 196 "No unreleased section found. Adding new version entries under main title."
        
        # Use awk to process the file and writelines appropriately
        awk -v nvh="$next_version_header" -v cvh="$current_version_header" '
        /^#/ && !seen {
            print;
            print "";
            print nvh;
            print "";
            print cvh;
            print "";
            seen=1;
            next
        }
        {print}' "$changelog_path" > "${changelog_path}.new" && mv "${changelog_path}.new" "$changelog_path"
        
        gum style --foreground 76 "Changelog updated successfully by appending new version entry!"
    fi
    return 0
}

# Function to update properties file
update_properties() {
    local properties_file="$1"
    local new_version="$2"
    # Check if properties file exists
    if [ ! -f "$properties_file" ]; then
        gum style --foreground 196 --margin "1" "Error: $properties_file not found!"
        return 1
    fi
    gum style --foreground 212 "Updating $properties_file"

    # Update the Version property in the file
    if sed -i'.bak' "s/Version=.*/Version=${new_version}/" "$properties_file"; then
        # Remove the backup file
        rm "${properties_file}.bak" 2>/dev/null
        gum style --foreground 76 "Properties file updated successfully!"
    else
        gum style --foreground 196 --margin "1" "Failed to update properties. Please check the script and properties format."
        exit 1
    fi

    return 0
}

# Select which service to release
SERVICE=$(gum choose "batch" "connectivity" "lambda")

# Get current date in YYYY-MM-DD format
RELEASE_DATE=$(date +%Y-%m-%d)

# Set the changelog path based on the selected service
if [ "$SERVICE" == "batch" ]; then
    CHANGELOG_PATH="batch/CHANGELOG.md"
    PROPERTIES_PATH="_devops/batch"
    PREFIX_EXPECTED="batch-"
elif [ "$SERVICE" == "connectivity" ]; then
    CHANGELOG_PATH="connectivity/CHANGELOG.md"
    PROPERTIES_PATH="_devops/connectivity"
    PREFIX_EXPECTED="back-connectivity-"
elif [ "$SERVICE" == "lambda" ]; then
    CHANGELOG_PATH="lambda/CHANGELOG.md"
    PREFIX_EXPECTED="lambda-"
fi

# Extract version information from changelog
VERSION_INFO=$(extract_version_from_changelog "$CHANGELOG_PATH")
if [ $? -ne 0 ]; then
    # If extraction failed, ask the user to input the version manually
    gum style --foreground 196 --margin "1" "Could not extract version from changelog. Please enter manually:"
    CURRENT_VERSION=$(gum input --placeholder "Current version (e.g., 1.10.0)")
    PREFIX="${PREFIX_EXPECTED}"
else
    # Parse the returned version info (format: "version|prefix")
    IFS='|' read -r CURRENT_VERSION PREFIX <<< "$VERSION_INFO"

    # If the prefix doesn't match the expected one for the service, show a warning
    if [ "$PREFIX" != "$PREFIX_EXPECTED" ]; then
        gum style --foreground 220 "Warning: Extracted prefix ($PREFIX) doesn't match expected prefix for $SERVICE ($PREFIX_EXPECTED)"
        gum confirm "Continue anyway?" || exit 1
    fi
fi

# Parse major, minor, patch
IFS='.' read -r major minor patch <<< "$CURRENT_VERSION"
next_minor=$((minor + 1))
NEXT_VERSION="$major.$next_minor.0"

# Create branch name based on service
BRANCH_NAME="release/$SERVICE-$CURRENT_VERSION"
gum style --foreground 212 "Creating a release for $SERVICE:"
gum style --foreground 212 "  Current version: $CURRENT_VERSION"
gum style --foreground 212 "  Next version: $NEXT_VERSION"
gum style --foreground 212 "  Branch: $BRANCH_NAME"

# Confirm before proceeding
gum confirm "Do you want to proceed with this release?" || exit 0

# Check if the branch already exists
if git show-ref --quiet refs/heads/"$BRANCH_NAME"; then
    gum style --foreground 196 --margin "1" "Branch '$BRANCH_NAME' already exists."
    if gum confirm "Would you like to switch to the existing branch?"; then
        if git checkout "$BRANCH_NAME"; then
            gum style --foreground 76 "Checked out $BRANCH_NAME"
        else
            gum style --foreground 196 --margin "1" "Process aborted. Please resolve checkout conflicts."
            exit 1
        fi
    else
        gum style --foreground 196 --margin "1" "Process aborted. Please resolve branch conflicts."
        exit 1
    fi
else
    # Create and checkout the release branch
    git checkout -b "$BRANCH_NAME"
fi

# Update changelog and properties based on service
if [ "$SERVICE" == "batch" ]; then
    # Ask which environment to target
    ENV="live"
    PROPERTIES_FILE="$PROPERTIES_PATH/$ENV.properties"
    # Update changelog
    update_changelog "$CHANGELOG_PATH" "$CURRENT_VERSION" "$NEXT_VERSION" "$RELEASE_DATE" "$PREFIX"
    # Update properties file
    update_properties "$PROPERTIES_FILE" "$CURRENT_VERSION"
elif [ "$SERVICE" == "connectivity" ]; then
    # Ask which environment to target
    ENV="live"
    PROPERTIES_FILE="$PROPERTIES_PATH/env-$ENV.properties"
    # Update changelog
    update_changelog "$CHANGELOG_PATH" "$CURRENT_VERSION" "$NEXT_VERSION" "$RELEASE_DATE" "$PREFIX"
    # Update properties file
    update_properties "$PROPERTIES_FILE" "$CURRENT_VERSION"
elif [ "$SERVICE" == "lambda" ]; then
    # Update changelog
    update_changelog "$CHANGELOG_PATH" "$CURRENT_VERSION" "$NEXT_VERSION" "$RELEASE_DATE" "$PREFIX"
fi

# Show diff before committing
git diff --color $CHANGELOG_PATH $PROPERTIES_FILE | gum pager

if [ "$NO_COMMIT" = false ]; then
    # Confirm the changes
    if ! gum confirm "Commit these changes?"; then
        gum style --foreground 196 --margin "1" "Aborting release process. Changes are not committed."
        exit 1
    fi

    # Add only relevant files
    gum style --foreground 76 "Adding files to commit:"
    gum style --foreground 76 "  - $CHANGELOG_PATH"
    if [ -n "$PROPERTIES_FILE" ]; then
        gum style --foreground 76 "  - $PROPERTIES_FILE"
        git add "$PROPERTIES_FILE"
    fi
    git add "$CHANGELOG_PATH"
    COMMIT_MSG="release $SERVICE-$CURRENT_VERSION"
    git commit -m "$COMMIT_MSG"
    COMMIT_SHA=$(git rev-parse --short HEAD)
    TAG_NAME="$SERVICE-$CURRENT_VERSION"
    git tag -a -m "$COMMIT_MSG" "$TAG_NAME" "$COMMIT_SHA"
    gum style --foreground 76 "Created tag: $TAG_NAME on commit $COMMIT_SHA"
else
    gum style --foreground 226 "Dry-run mode: Skipping commit and tag creation."
fi

# Push changes and create a merge request automatically
if [ "$NO_COMMIT" = false ] && gum confirm "Push changes, tags, and create a merge request?"; then
    gum spin --spinner dot --title "Pushing changes to origin and creating a merge request..." -- \
    git push origin $BRANCH_NAME --follow-tags -o merge_request.create -o merge_request.target=main \
    -o merge_request.title="Release $SERVICE-$CURRENT_VERSION" \
    -o merge_request.description="This is an automated release of $SERVICE version $CURRENT_VERSION."

    gum style --foreground 76 "Changes, tags pushed, and merge request created successfully!"
    gum style --foreground 212 "You can find the created merge request at:"
    echo "https://gitlab.com/perfectstay/touroperating/back-connectivity/-/merge_requests/"
else
    gum style --foreground 226 " Skipping push and merge request creation."
fi

# In dry-run mode, ask if the user wants to undo changes
if [ "$NO_COMMIT" = true ]; then
    if gum confirm "Would you like to undo all changes to the files?"; then
        git checkout -- "$CHANGELOG_PATH"
        if [ -n "$PROPERTIES_FILE" ]; then
            git checkout -- "$PROPERTIES_FILE"
        fi
        gum style --foreground 76 "Changes undone."
    else
        gum style --foreground 220 "You chose to keep changes."
    fi
fi

 # Final prompt to checkout main branch
if gum confirm "Would you like to checkout the main branch now?"; then
    git checkout main
    gum style --foreground 76 "Checked out to the main branch."
fi

gum style --foreground 212 --border-foreground 57 --border double --padding "1 2" \
    "✨ Release process completed! ✨" \
    "" \
    "Next steps:" \
    "1. Merge the changes" \
    "2. The CI will handle the rest"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions