#!/usr/bin/env bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Version bump script for Genkit Python packages.
# Bumps version in core package and all plugins simultaneously.
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Get the directory of this script and the py directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PY_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
cd "$PY_DIR"
# Get current version
CURRENT_VERSION=$(grep '^version' packages/genkit/pyproject.toml | head -1 | sed 's/.*= *"//' | sed 's/".*//')
usage() {
echo "Usage: $0 [OPTIONS] <new_version>"
echo ""
echo "Bump version for all Genkit Python packages."
echo ""
echo "Arguments:"
echo " new_version New version number (e.g., 0.5.0, 1.0.0)"
echo ""
echo "Options:"
echo " --major Bump major version (X.0.0)"
echo " --minor Bump minor version (x.Y.0)"
echo " --patch Bump patch version (x.y.Z)"
echo " --dry-run Show what would be changed without making changes"
echo " -h, --help Show this help message"
echo ""
echo "Current version: $CURRENT_VERSION"
echo ""
echo "Examples:"
echo " $0 0.5.0 # Set specific version"
echo " $0 --minor # Bump minor version (0.4.0 -> 0.5.0)"
echo " $0 --patch # Bump patch version (0.4.0 -> 0.4.1)"
echo " $0 --major # Bump major version (0.4.0 -> 1.0.0)"
}
# Parse current version
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
# Parse arguments
DRY_RUN=false
NEW_VERSION=""
while [[ $# -gt 0 ]]; do
case "$1" in
--major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
shift
;;
--minor)
MINOR=$((MINOR + 1))
PATCH=0
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
shift
;;
--patch)
PATCH=$((PATCH + 1))
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
usage
exit 0
;;
-*)
echo "Unknown option: $1"
usage
exit 1
;;
*)
if [ -z "$NEW_VERSION" ]; then
NEW_VERSION="$1"
else
echo "Error: Multiple versions specified"
usage
exit 1
fi
shift
;;
esac
done
if [ -z "$NEW_VERSION" ]; then
echo "Error: No version specified"
usage
exit 1
fi
# Validate version format
if ! [[ "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo -e "${RED}Error${NC}: Invalid version format '$NEW_VERSION'. Expected format: X.Y.Z"
exit 1
fi
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Genkit Python Version Bump ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "Current version: ${YELLOW}$CURRENT_VERSION${NC}"
echo -e "New version: ${GREEN}$NEW_VERSION${NC}"
echo ""
if $DRY_RUN; then
echo -e "${CYAN}[DRY RUN] The following files would be updated:${NC}"
echo ""
fi
# Function to update version in a file
update_version() {
local file="$1"
local pkg_name
pkg_name=$(grep '^name' "$file" | head -1 | sed 's/.*= *"//' | sed 's/".*//')
if $DRY_RUN; then
echo -e " Would update: $file ($pkg_name)"
else
# Use sed to replace version line
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS sed
sed -i '' "s/^version *= *\"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" "$file"
else
# GNU sed
sed -i "s/^version *= *\"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" "$file"
fi
echo -e " ${GREEN}✓${NC} Updated: $file ($pkg_name)"
fi
}
# Update core package
echo -e "${CYAN}Updating core package...${NC}"
update_version "packages/genkit/pyproject.toml"
# Update all plugins
echo -e "\n${CYAN}Updating plugins...${NC}"
for f in plugins/*/pyproject.toml; do
if [ -f "$f" ]; then
update_version "$f"
fi
done
echo ""
if $DRY_RUN; then
echo -e "${YELLOW}[DRY RUN] No changes were made.${NC}"
echo -e "Run without --dry-run to apply changes."
else
# Update lock file
echo -e "${CYAN}Updating lock file...${NC}"
uv lock > /dev/null 2>&1
echo -e " ${GREEN}✓${NC} uv.lock updated"
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✓ Version bumped to $NEW_VERSION ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "Next steps:"
echo -e " 1. Update CHANGELOG.md with release notes"
echo -e " 2. Run ${CYAN}py/bin/release_check${NC} to verify release readiness"
echo -e " 3. Commit changes: ${CYAN}git commit -am 'chore: bump version to $NEW_VERSION'${NC}"
echo -e " 4. Create release tag: ${CYAN}git tag -a py-v$NEW_VERSION -m 'Python SDK v$NEW_VERSION'${NC}"
fi