Skip to content

Instantly share code, notes, and snippets.

@minademian
Created October 14, 2025 01:04
Show Gist options
  • Select an option

  • Save minademian/e33bf8e269d879d2cbb8b15cfb94d046 to your computer and use it in GitHub Desktop.

Select an option

Save minademian/e33bf8e269d879d2cbb8b15cfb94d046 to your computer and use it in GitHub Desktop.
bump-version for custom WordPress plugins and themes
#!/usr/bin/env bash
set -euo pipefail
# ------------------------------------------------------------------------------
# bump-version.sh
#
# Bumps the project version (major, minor, or patch) across:
# Up to three files, typically:
# 1. package.json (default)
# 2. plugin or theme file(s)
#
# Options:
# --dry-run Show what would happen, without changing files.
# --git Commit and tag the new version in Git.
# --file <path> Specify first file (default: package.json)
# --file1 <path> Specify additional file #1
# --file2 <path> Specify additional file #2
#
# Compatible with macOS and Linux.
# ------------------------------------------------------------------------------
# Usage:
# ./scripts/bump-version.sh [major|minor|patch]
# [--dry-run] [--git]
# [--file path] [--file1 path] [--file2 path]
# ------------------------------------------------------------------------------
if [[ $# -lt 1 ]]; then
echo "❌ Usage: $0 [major|minor|patch] [--dry-run] [--git] [--file path] [--file1 path] [--file2 path]"
exit 1
fi
BUMP_TYPE="$1"
shift
# --- Defaults -----------------------------------------------------------------
DRY_RUN=false
DO_GIT=false
FILE_MAIN="package.json"
FILE_1=""
FILE_2=""
# --- Parse optional flags -----------------------------------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run)
DRY_RUN=true
;;
--git)
DO_GIT=true
;;
--file)
shift
[[ $# -eq 0 ]] && { echo "❌ Missing argument after --file"; exit 1; }
FILE_MAIN="$1"
;;
--file1)
shift
[[ $# -eq 0 ]] && { echo "❌ Missing argument after --file1"; exit 1; }
FILE_1="$1"
;;
--file2)
shift
[[ $# -eq 0 ]] && { echo "❌ Missing argument after --file2"; exit 1; }
FILE_2="$1"
;;
*)
echo "❌ Unknown option: $1"
echo "Usage: $0 [major|minor|patch] [--dry-run] [--git] [--file path] [--file1 path] [--file2 path]"
exit 1
;;
esac
shift
done
# --- Validate bump type -------------------------------------------------------
if [[ "$BUMP_TYPE" != "major" && "$BUMP_TYPE" != "minor" && "$BUMP_TYPE" != "patch" ]]; then
echo "❌ Invalid bump type: $BUMP_TYPE"
echo " Must be one of: major, minor, patch"
exit 1
fi
# --- Build file list ----------------------------------------------------------
FILES_TO_UPDATE=("$FILE_MAIN")
[[ -n "$FILE_1" ]] && FILES_TO_UPDATE+=("$FILE_1")
[[ -n "$FILE_2" ]] && FILES_TO_UPDATE+=("$FILE_2")
# --- Ensure files exist -------------------------------------------------------
for file in "${FILES_TO_UPDATE[@]}"; do
if [[ ! -f "$file" ]]; then
echo "❌ $file not found."
exit 1
fi
done
# --- Extract current version --------------------------------------------------
# If main file is package.json, parse JSON; otherwise, fall back to regex.
if [[ "$FILE_MAIN" == "package.json" ]]; then
CURR_VERSION=$(grep -Eo '"version": *"[0-9]+\.[0-9]+\.[0-9]+"' "$FILE_MAIN" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
else
CURR_VERSION=$(grep -Eo 'Version: *[0-9]+\.[0-9]+\.[0-9]+' "$FILE_MAIN" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
fi
if [[ -z "$CURR_VERSION" ]]; then
echo "❌ Could not find valid version in $FILE_MAIN"
exit 1
fi
IFS='.' read -r MAJOR MINOR PATCH <<<"$CURR_VERSION"
# --- Compute new version ------------------------------------------------------
case "$BUMP_TYPE" in
major)
((MAJOR++))
MINOR=0
PATCH=0
;;
minor)
((MINOR++))
PATCH=0
;;
patch)
((PATCH++))
;;
esac
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
echo ""
echo "🔢 Bumping version: $CURR_VERSION → $NEW_VERSION"
$DRY_RUN && echo "🧪 Dry run mode (no changes will be made)"
echo ""
# --- Apply replacements -------------------------------------------------------
if ! $DRY_RUN; then
for file in "${FILES_TO_UPDATE[@]}"; do
if grep -q '"version":' "$file"; then
sed -i.bak "s/\"version\": *\"$CURR_VERSION\"/\"version\": \"$NEW_VERSION\"/" "$file"
else
sed -i.bak "s/Version: *$CURR_VERSION/Version: $NEW_VERSION/" "$file"
fi
rm -f "$file.bak"
done
fi
# --- Git commit and tag (optional) --------------------------------------------
if $DO_GIT; then
if $DRY_RUN; then
echo "💾 Would create Git commit and tag: v$NEW_VERSION"
else
echo "💾 Creating Git commit and tag..."
git add "${FILES_TO_UPDATE[@]}"
git commit -m "chore(release): bump version to v$NEW_VERSION"
git tag "v$NEW_VERSION"
echo "✅ Created commit and tag: v$NEW_VERSION"
fi
fi
echo ""
echo "✅ Done!"
echo " New version: $NEW_VERSION"
printf " Files updated:\n"
for f in "${FILES_TO_UPDATE[@]}"; do
echo " • $f"
done
$DRY_RUN && echo " (Dry run only — no changes applied)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment