diff --git a/UPDATE_VERSION.md b/UPDATE_VERSION.md new file mode 100644 index 0000000..4931d9e --- /dev/null +++ b/UPDATE_VERSION.md @@ -0,0 +1,164 @@ +# Version Update Scripts + +This directory contains scripts to update the version across the Elytra PIM Client project before building a wheel distribution. + +## Quick Start + +Update version and build: +```bash +# Python (cross-platform) +python update_version.py 1.0.0 +python build_wheel.py + +# PowerShell (Windows) +.\update_version.ps1 1.0.0 +.\build_wheel.ps1 + +# Bash (Linux/macOS) +./update_version.sh 1.0.0 +./build_wheel.sh +``` + +## Files Updated + +The version update scripts modify the following files: +- `pyproject.toml` - Project configuration (line 7) +- `elytra_client/__init__.py` - Package version (line 3) + +## Available Scripts + +### Python Version +```bash +python update_version.py 0.2.0 +``` + +**Usage:** +```bash +python update_version.py +``` + +**Example:** +```bash +python update_version.py 1.0.0 +``` + +### PowerShell Version +```powershell +.\update_version.ps1 -Version 0.2.0 +``` + +**Usage:** +```powershell +.\update_version.ps1 -Version +# or +.\update_version.ps1 +``` + +**Examples:** +```powershell +.\update_version.ps1 0.2.0 +.\update_version.ps1 -Version 1.0.0 +``` + +### Bash Version +```bash +./update_version.sh 0.2.0 +``` + +**Usage:** +```bash +./update_version.sh +``` + +**Example:** +```bash +./update_version.sh 1.0.0 +``` + +## Version Format + +The version must follow semantic versioning format: `major.minor.patch` + +Valid examples: +- `0.1.0` +- `1.0.0` +- `0.2.1` +- `1.0.0-beta` (with pre-release identifier) + +Invalid examples: +- `1.0` (missing patch version) +- `v1.0.0` (invalid prefix) + +## Workflow + +### Before Building a Wheel + +1. **Update the version:** + ```bash + # On Windows + .\update_version.ps1 0.2.0 + + # On Linux/macOS + ./update_version.sh 0.2.0 + ``` + +2. **Build the wheel:** + ```bash + # Using Python + python build_wheel.py + + # Or PowerShell + .\build_wheel.ps1 + + # Or Bash + ./build_wheel.sh + ``` + +3. **Upload (optional):** + ```bash + .\upload_wheel_to_forgejo_pypi.ps1 + ``` + +### Verification + +After running the update script, verify the changes: + +**Check pyproject.toml:** +```bash +grep "version = " pyproject.toml +``` + +**Check __init__.py:** +```bash +grep "__version__ = " elytra_client/__init__.py +``` + +## Error Messages + +### Invalid Version Format +``` +✗ Invalid version format: 1.0 +Version must follow semantic versioning (major.minor.patch) +Examples: 1.0.0, 0.2.0, 1.0.0-beta +``` + +**Solution:** Use the format `major.minor.patch` (e.g., `1.0.0`) + +### File Not Found +``` +✗ /path/to/file not found +``` + +**Solution:** Ensure you're running the script from the project root directory + +## Return Codes + +- `0` - Success (version updated) +- `1` - Error (see error message) + +## Notes + +- Run from the project root directory +- The scripts will show which files were updated +- All scripts support semantic versioning with optional pre-release identifiers +- Use consistent versions across all files to avoid build issues diff --git a/elytra_client/__init__.py b/elytra_client/__init__.py index 231df6b..7c93921 100644 --- a/elytra_client/__init__.py +++ b/elytra_client/__init__.py @@ -6,13 +6,13 @@ __author__ = "Your Name" from .client import ElytraClient from .exceptions import ElytraAPIError, ElytraAuthenticationError from .models import ( - SingleProductResponse, - SingleProductGroupResponse, - SingleNewProductRequestBody, - SingleUpdateProductRequestBody, - SingleNewProductGroupRequestBody, - SingleUpdateProductGroupRequestBody, ProductAttributeResponse, + SingleNewProductGroupRequestBody, + SingleNewProductRequestBody, + SingleProductGroupResponse, + SingleProductResponse, + SingleUpdateProductGroupRequestBody, + SingleUpdateProductRequestBody, ) __all__ = [ diff --git a/pyproject.toml b/pyproject.toml index 839336f..c41a630 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "elytra-pim-client" -version = "0.1.0" +version = "0.2.0" description = "A Pythonic client for the Elytra PIM API" readme = "README.md" requires-python = ">=3.9" @@ -56,7 +56,7 @@ profile = "black" line_length = 100 [tool.mypy] -python_version = "3.9" +python_version = "0.2.0" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = false diff --git a/update_version.ps1 b/update_version.ps1 new file mode 100644 index 0000000..1d4d190 --- /dev/null +++ b/update_version.ps1 @@ -0,0 +1,82 @@ +param( + [Parameter(Mandatory = $true, Position = 0)] + [string]$Version +) + +function Test-VersionFormat { + param([string]$Ver) + $pattern = '^\d+\.\d+\.\d+(?:-[a-zA-Z0-9]+)?$' + return $Ver -match $pattern +} + +function Update-FileVersion { + param( + [string]$FilePath, + [string]$Pattern, + [string]$NewVersion + ) + try { + $content = Get-Content -Path $FilePath -Raw + $newContent = $content -replace $Pattern, $NewVersion + if ($content -eq $newContent) { + Write-Host "[OK] $(Split-Path -Leaf $FilePath) already up-to-date" -ForegroundColor Green + return $true + } + Set-Content -Path $FilePath -Value $newContent -NoNewline + Write-Host "[OK] Updated $(Split-Path -Leaf $FilePath)" -ForegroundColor Green + return $true + } + catch { + Write-Host "[ERROR] Error: $_" -ForegroundColor Red + return $false + } +} + +if (-not (Test-VersionFormat $Version)) { + Write-Host "[ERROR] Invalid version format: $Version" -ForegroundColor Red + exit 1 +} + +$projectRoot = Split-Path -Parent $PSCommandPath +$pyprojectPath = Join-Path $projectRoot "pyproject.toml" +$initPath = Join-Path (Join-Path $projectRoot "elytra_client") "__init__.py" + +Write-Host "======================================================================" +Write-Host "Updating Elytra PIM Client to version $Version" +Write-Host "======================================================================" + +$success = $true + +if (Test-Path $pyprojectPath) { + $pattern = 'version = "[^"]+"' + $newVersion = "version = `"$Version`"" + if (-not (Update-FileVersion $pyprojectPath $pattern $newVersion)) { + $success = $false + } +} +else { + Write-Host "[ERROR] pyproject.toml not found" -ForegroundColor Red + $success = $false +} + +if (Test-Path $initPath) { + $pattern = '__version__ = "[^"]+"' + $newVersion = "__version__ = `"$Version`"" + if (-not (Update-FileVersion $initPath $pattern $newVersion)) { + $success = $false + } +} +else { + Write-Host "[ERROR] init file not found" -ForegroundColor Red + $success = $false +} + +Write-Host "======================================================================" +if ($success) { + Write-Host "[OK] Version successfully updated to $Version" -ForegroundColor Green + exit 0 +} +else { + Write-Host "[ERROR] Update completed with errors" -ForegroundColor Red + exit 1 +} diff --git a/update_version.py b/update_version.py new file mode 100644 index 0000000..9e05bc4 --- /dev/null +++ b/update_version.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +"""Update version across Elytra PIM Client project files. + +This script updates the version in: +- pyproject.toml +- elytra_client/__init__.py + +Usage: + python update_version.py + python update_version.py 0.2.0 + python update_version.py 1.0.0 + +The version must follow semantic versioning (major.minor.patch). +""" + +import re +import sys +from pathlib import Path + + +def validate_version(version: str) -> bool: + """Validate semantic version format. + + Args: + version: Version string to validate + + Returns: + True if valid, False otherwise + """ + pattern = r'^\d+\.\d+\.\d+(?:-[a-zA-Z0-9]+)?$' + return bool(re.match(pattern, version)) + + +def update_file(file_path: Path, old_pattern: str, new_version: str) -> bool: + """Update version in a file. + + Args: + file_path: Path to file to update + old_pattern: Regex pattern to find version + new_version: New version string + + Returns: + True if successful, False otherwise + """ + try: + content = file_path.read_text() + updated_content = re.sub(old_pattern, new_version, content) + + if content == updated_content: + print(f"✓ {file_path.name} already up-to-date") + return True + + file_path.write_text(updated_content) + print(f"✓ Updated {file_path.name}") + return True + except Exception as e: + print(f"✗ Error updating {file_path.name}: {e}") + return False + + +def main() -> int: + """Update version in project files. + + Returns: + Exit code (0 for success, 1 for failure) + """ + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ") + print(f"Example: {sys.argv[0]} 0.2.0") + return 1 + + new_version = sys.argv[1] + + if not validate_version(new_version): + print(f"✗ Invalid version format: {new_version}") + print("Version must follow semantic versioning (major.minor.patch)") + print("Examples: 1.0.0, 0.2.0, 1.0.0-beta") + return 1 + + project_root = Path(__file__).parent + pyproject_path = project_root / "pyproject.toml" + init_path = project_root / "elytra_client" / "__init__.py" + + print("=" * 70) + print(f"Updating Elytra PIM Client to version {new_version}") + print("=" * 70) + + success = True + + # Update pyproject.toml + if pyproject_path.exists(): + pattern = r'version = "[^"]+"' + success &= update_file( + pyproject_path, + pattern, + f'version = "{new_version}"' + ) + else: + print(f"✗ {pyproject_path} not found") + success = False + + # Update __init__.py + if init_path.exists(): + pattern = r'__version__ = "[^"]+"' + success &= update_file( + init_path, + pattern, + f'__version__ = "{new_version}"' + ) + else: + print(f"✗ {init_path} not found") + success = False + + if success: + print("=" * 70) + print(f"✓ Version successfully updated to {new_version}") + print("=" * 70) + return 0 + else: + print("=" * 70) + print("✗ Version update completed with errors") + print("=" * 70) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/update_version.sh b/update_version.sh new file mode 100644 index 0000000..be188b2 --- /dev/null +++ b/update_version.sh @@ -0,0 +1,123 @@ +#!/bin/bash +# Update version across Elytra PIM Client project files. +# +# This script updates the version in: +# - pyproject.toml +# - elytra_client/__init__.py +# +# Usage: +# ./update_version.sh +# ./update_version.sh 0.2.0 +# +# The version must follow semantic versioning (major.minor.patch). + +set -euo pipefail + +# Color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +validate_version() { + local version=$1 + if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then + return 1 + fi + return 0 +} + +update_file() { + local file_path=$1 + local pattern=$2 + local new_version=$3 + + if [[ ! -f "$file_path" ]]; then + echo -e "${RED}✗ File not found: $file_path${NC}" + return 1 + fi + + # Check if content would change + local content + content=$(cat "$file_path") + + # Use sed to update the file (handles both macOS and Linux) + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS requires -i '' for in-place editing + sed -i '' "$pattern" "$file_path" + else + # Linux + sed -i "$pattern" "$file_path" + fi + + local new_content + new_content=$(cat "$file_path") + + if [[ "$content" == "$new_content" ]]; then + echo -e "${GREEN}✓ $(basename "$file_path") already up-to-date${NC}" + else + echo -e "${GREEN}✓ Updated $(basename "$file_path")${NC}" + fi + return 0 +} + +main() { + if [[ $# -ne 1 ]]; then + echo "Usage: $0 " + echo "Example: $0 0.2.0" + exit 1 + fi + + local new_version=$1 + + if ! validate_version "$new_version"; then + echo -e "${RED}✗ Invalid version format: $new_version${NC}" + echo -e "${YELLOW}Version must follow semantic versioning (major.minor.patch)${NC}" + echo -e "${YELLOW}Examples: 1.0.0, 0.2.0, 1.0.0-beta${NC}" + exit 1 + fi + + local project_root + project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local pyproject_path="$project_root/pyproject.toml" + local init_path="$project_root/elytra_client/__init__.py" + + echo "======================================================================" + echo "Updating Elytra PIM Client to version $new_version" + echo "======================================================================" + + local success=true + + # Update pyproject.toml + if [[ -f "$pyproject_path" ]]; then + local pattern_pyproject="s|version = \"[^\"]*\"|version = \"$new_version\"|g" + if ! update_file "$pyproject_path" "$pattern_pyproject"; then + success=false + fi + else + echo -e "${RED}✗ $pyproject_path not found${NC}" + success=false + fi + + # Update __init__.py + if [[ -f "$init_path" ]]; then + local pattern_init="s|__version__ = \"[^\"]*\"|__version__ = \"$new_version\"|g" + if ! update_file "$init_path" "$pattern_init"; then + success=false + fi + else + echo -e "${RED}✗ $init_path not found${NC}" + success=false + fi + + echo "======================================================================" + if [[ "$success" == true ]]; then + echo -e "${GREEN}✓ Version successfully updated to $new_version${NC}" + exit 0 + else + echo -e "${RED}✗ Version update completed with errors${NC}" + exit 1 + fi +} + +main "$@"