feat: add build and upload scripts for Forgejo PyPI, update version management
This commit is contained in:
parent
462c8aeac9
commit
64ea445ec3
12 changed files with 1288 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -25,6 +25,9 @@ dmypy.json
|
||||||
# Environment files
|
# Environment files
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# PyPI credentials
|
||||||
|
.pypirc
|
||||||
|
|
||||||
# pytest
|
# pytest
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.coverage
|
.coverage
|
||||||
|
|
|
||||||
25
.pypirc.example
Normal file
25
.pypirc.example
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# .pypirc.example
|
||||||
|
# Configuration file for uploading packages to Forgejo PyPI
|
||||||
|
#
|
||||||
|
# This file is a template - copy it to .pypirc and fill in your credentials:
|
||||||
|
# cp .pypirc.example .pypirc
|
||||||
|
#
|
||||||
|
# IMPORTANT: Never commit .pypirc to version control!
|
||||||
|
# It should already be in .gitignore
|
||||||
|
|
||||||
|
[distutils]
|
||||||
|
index-servers =
|
||||||
|
forgejo
|
||||||
|
|
||||||
|
[forgejo]
|
||||||
|
repository = https://git.him-tools.de/api/packages/HIM-public/pypi
|
||||||
|
username = __token__
|
||||||
|
password = YOUR_FORGEJO_ACCESS_TOKEN_HERE
|
||||||
|
|
||||||
|
# How to get your Forgejo access token:
|
||||||
|
# 1. Log in to your Forgejo instance: https://git.him-tools.de
|
||||||
|
# 2. Go to Settings > Applications > Generate New Token
|
||||||
|
# 3. Select 'write:package' scope
|
||||||
|
# 4. Copy the token and paste it above (replace YOUR_FORGEJO_ACCESS_TOKEN_HERE)
|
||||||
|
#
|
||||||
|
# Note: The username should always be "__token__" when using an access token
|
||||||
58
README.md
58
README.md
|
|
@ -136,6 +136,64 @@ pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Building & Publishing
|
||||||
|
|
||||||
|
### Update Version
|
||||||
|
|
||||||
|
Update the version number across all project files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PowerShell
|
||||||
|
.\update_version.ps1 0.2.0
|
||||||
|
|
||||||
|
# Python
|
||||||
|
python update_version.py 0.2.0
|
||||||
|
|
||||||
|
# Bash
|
||||||
|
./update_version.sh 0.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Wheel
|
||||||
|
|
||||||
|
Build distribution packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PowerShell
|
||||||
|
.\build_wheel.ps1
|
||||||
|
|
||||||
|
# Python
|
||||||
|
python build_wheel.py
|
||||||
|
|
||||||
|
# Bash
|
||||||
|
./build_wheel.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upload to Forgejo PyPI
|
||||||
|
|
||||||
|
First, create your `.pypirc` configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .pypirc.example .pypirc
|
||||||
|
# Edit .pypirc with your Forgejo access token
|
||||||
|
```
|
||||||
|
|
||||||
|
Then upload:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PowerShell
|
||||||
|
.\upload_wheel_to_forgejo_pypi.ps1
|
||||||
|
|
||||||
|
# Bash
|
||||||
|
./upload_wheel_to_forgejo_pypi.sh
|
||||||
|
|
||||||
|
# Windows Batch
|
||||||
|
upload_wheel_to_forgejo_pypi.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
The package will be available at:
|
||||||
|
`https://git.him-tools.de/HIM-public/-/packages/pypi/agravity-client`
|
||||||
|
|
||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
|
|
|
||||||
188
build_wheel.ps1
Normal file
188
build_wheel.ps1
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
# build_wheel.ps1
|
||||||
|
# Build wheel distribution for Agravity Client (PowerShell)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# .\build_wheel.ps1
|
||||||
|
#
|
||||||
|
# Requires:
|
||||||
|
# - Python 3.9+
|
||||||
|
# - setuptools>=65.0
|
||||||
|
# - wheel
|
||||||
|
# - build (recommended)
|
||||||
|
|
||||||
|
param(
|
||||||
|
[switch]$Clean = $false,
|
||||||
|
[switch]$Upload = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define symbols as variables to avoid encoding issues
|
||||||
|
$symSuccess = "[OK]"
|
||||||
|
$symError = "[!]"
|
||||||
|
$symBullet = "[*]"
|
||||||
|
|
||||||
|
# Color functions for output
|
||||||
|
function Write-Success {
|
||||||
|
Write-Host "$symSuccess $args" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Error-Custom {
|
||||||
|
Write-Host "$symError $args" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Header {
|
||||||
|
Write-Host ("=" * 70)
|
||||||
|
Write-Host $args
|
||||||
|
Write-Host ("=" * 70)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-SubHeader {
|
||||||
|
Write-Host ("-" * 70)
|
||||||
|
Write-Host $args
|
||||||
|
Write-Host ("-" * 70)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main script
|
||||||
|
$projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$distDir = Join-Path $projectRoot "dist"
|
||||||
|
$buildDir = Join-Path $projectRoot "build"
|
||||||
|
$eggInfoDir = Join-Path $projectRoot "agravity_client.egg-info"
|
||||||
|
|
||||||
|
Write-Header "Agravity Client - Wheel Builder (PowerShell)"
|
||||||
|
|
||||||
|
# Clean if requested
|
||||||
|
if ($Clean) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Cleaning previous builds..."
|
||||||
|
|
||||||
|
@($distDir, $buildDir, $eggInfoDir) | ForEach-Object {
|
||||||
|
if (Test-Path $_) {
|
||||||
|
Remove-Item $_ -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Write-Success "Removed $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if build directory exists from previous build
|
||||||
|
if (Test-Path $distDir) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Cleaning dist directory..."
|
||||||
|
Remove-Item $distDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Write-Success "Removed old distributions"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install build requirements if needed
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Checking build dependencies..."
|
||||||
|
$buildCheck = python -m pip list 2>$null | Select-String "build"
|
||||||
|
if (-not $buildCheck) {
|
||||||
|
Write-Host "Installing build tools..."
|
||||||
|
python -m pip install -q build setuptools wheel
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Write-Success "Build tools installed"
|
||||||
|
} else {
|
||||||
|
Write-Error-Custom "Failed to install build tools"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build
|
||||||
|
Write-SubHeader "Building distributions..."
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
Push-Location $projectRoot
|
||||||
|
try {
|
||||||
|
python -m build
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Error-Custom "Build failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verify output
|
||||||
|
Write-SubHeader "Build Results"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
if (!(Test-Path $distDir)) {
|
||||||
|
Write-Error-Custom "dist directory not created"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$wheels = @(Get-ChildItem -Path $distDir -Filter "*.whl" -ErrorAction SilentlyContinue)
|
||||||
|
$sdists = @(Get-ChildItem -Path $distDir -Filter "*.tar.gz" -ErrorAction SilentlyContinue)
|
||||||
|
|
||||||
|
if ($wheels.Count -eq 0 -and $sdists.Count -eq 0) {
|
||||||
|
Write-Error-Custom "No distributions created"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "Build successful!"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
if ($wheels.Count -gt 0) {
|
||||||
|
Write-Host "Wheels:"
|
||||||
|
$wheels | ForEach-Object {
|
||||||
|
$sizeMB = [Math]::Round($_.Length / 1MB, 2)
|
||||||
|
Write-Host " $symBullet $($_.Name) ($sizeMB MB)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sdists.Count -gt 0) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Source Distributions:"
|
||||||
|
$sdists | ForEach-Object {
|
||||||
|
$sizeMB = [Math]::Round($_.Length / 1MB, 2)
|
||||||
|
Write-Host " $symBullet $($_.Name) ($sizeMB MB)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Success "Distributions saved to: $distDir"
|
||||||
|
|
||||||
|
# Installation instructions
|
||||||
|
Write-SubHeader "Installation Instructions"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
if ($wheels.Count -gt 0) {
|
||||||
|
$wheel = $wheels[0]
|
||||||
|
Write-Host "Install the wheel locally:"
|
||||||
|
Write-Host " pip install `"$($wheel.FullName)`""
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
Write-Host "Or upload to PyPI:"
|
||||||
|
Write-Host " pip install twine"
|
||||||
|
Write-Host " twine upload dist/*"
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional upload
|
||||||
|
if ($Upload) {
|
||||||
|
Write-SubHeader "Uploading to PyPI..."
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
$twineCheck = python -m pip list 2>$null | Select-String "twine"
|
||||||
|
if (-not $twineCheck) {
|
||||||
|
Write-Host "Installing twine..."
|
||||||
|
python -m pip install -q twine
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Running twine upload..."
|
||||||
|
Push-Location $projectRoot
|
||||||
|
try {
|
||||||
|
python -m twine upload dist/*
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Write-Success "Upload complete!"
|
||||||
|
} else {
|
||||||
|
Write-Error-Custom "Upload failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Done!"
|
||||||
|
Write-Host ""
|
||||||
|
exit 0
|
||||||
152
build_wheel.py
Normal file
152
build_wheel.py
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Build wheel distribution for Agravity Client.
|
||||||
|
|
||||||
|
This script builds wheel and source distributions for the Agravity Client package.
|
||||||
|
It requires setuptools and wheel to be installed.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python build_wheel.py
|
||||||
|
|
||||||
|
Output:
|
||||||
|
- Wheels saved to dist/ directory
|
||||||
|
- Source distribution (sdist) also created for reference
|
||||||
|
"""
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
"""Build wheel distribution.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Exit code (0 for success, 1 for failure)
|
||||||
|
"""
|
||||||
|
project_root = Path(__file__).parent
|
||||||
|
dist_dir = project_root / "dist"
|
||||||
|
|
||||||
|
print("=" * 70)
|
||||||
|
print("Agravity Client - Wheel Builder")
|
||||||
|
print("=" * 70)
|
||||||
|
|
||||||
|
# Clean previous builds
|
||||||
|
print("\nCleaning previous builds...")
|
||||||
|
if dist_dir.exists():
|
||||||
|
try:
|
||||||
|
shutil.rmtree(dist_dir)
|
||||||
|
print(f"✓ Removed {dist_dir}")
|
||||||
|
except OSError as e:
|
||||||
|
print(f"✗ Failed to remove {dist_dir}: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
build_dir = project_root / "build"
|
||||||
|
if build_dir.exists():
|
||||||
|
try:
|
||||||
|
shutil.rmtree(build_dir)
|
||||||
|
print(f"✓ Removed {build_dir}")
|
||||||
|
except OSError as e:
|
||||||
|
print(f"✗ Failed to remove {build_dir}: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
egg_info_dir = project_root / "agravity_client.egg-info"
|
||||||
|
if egg_info_dir.exists():
|
||||||
|
try:
|
||||||
|
shutil.rmtree(egg_info_dir)
|
||||||
|
print(f"✓ Removed {egg_info_dir}")
|
||||||
|
except OSError as e:
|
||||||
|
print(f"✗ Failed to remove {egg_info_dir}: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Build wheel and sdist
|
||||||
|
print("\n" + "-" * 70)
|
||||||
|
print("Building distributions...")
|
||||||
|
print("-" * 70 + "\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Use python -m build for modern approach
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, "-m", "build"],
|
||||||
|
cwd=project_root,
|
||||||
|
check=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print("\n✗ Build failed")
|
||||||
|
print("\nTrying alternative build method...")
|
||||||
|
|
||||||
|
# Fallback to direct setuptools invocation
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, "setup.py", "sdist", "bdist_wheel"],
|
||||||
|
cwd=project_root,
|
||||||
|
check=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print("\n✗ Build failed with fallback method")
|
||||||
|
return 1
|
||||||
|
except FileNotFoundError:
|
||||||
|
# If 'build' module not available, use setup.py
|
||||||
|
print("Using setuptools directly...\n")
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, "setup.py", "sdist", "bdist_wheel"],
|
||||||
|
cwd=project_root,
|
||||||
|
check=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print("\n✗ Build failed")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Verify build output
|
||||||
|
print("\n" + "-" * 70)
|
||||||
|
print("Build Results")
|
||||||
|
print("-" * 70 + "\n")
|
||||||
|
|
||||||
|
if not dist_dir.exists():
|
||||||
|
print("✗ dist directory not created")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
wheels = list(dist_dir.glob("*.whl"))
|
||||||
|
sdists = list(dist_dir.glob("*.tar.gz"))
|
||||||
|
|
||||||
|
if not wheels and not sdists:
|
||||||
|
print("✗ No distributions created")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("✓ Build successful!\n")
|
||||||
|
|
||||||
|
if wheels:
|
||||||
|
print("Wheels:")
|
||||||
|
for wheel in wheels:
|
||||||
|
size_mb = wheel.stat().st_size / (1024 * 1024)
|
||||||
|
print(f" • {wheel.name} ({size_mb:.2f} MB)")
|
||||||
|
|
||||||
|
if sdists:
|
||||||
|
print("\nSource Distributions:")
|
||||||
|
for sdist in sdists:
|
||||||
|
size_mb = sdist.stat().st_size / (1024 * 1024)
|
||||||
|
print(f" • {sdist.name} ({size_mb:.2f} MB)")
|
||||||
|
|
||||||
|
print(f"\n✓ Distributions saved to: {dist_dir}")
|
||||||
|
|
||||||
|
# Installation instructions
|
||||||
|
print("\n" + "-" * 70)
|
||||||
|
print("Installation Instructions")
|
||||||
|
print("-" * 70 + "\n")
|
||||||
|
|
||||||
|
if wheels:
|
||||||
|
wheel = wheels[0]
|
||||||
|
print(f"Install the wheel locally:\n")
|
||||||
|
print(f" pip install {dist_dir / wheel.name}\n")
|
||||||
|
|
||||||
|
print(f"Or upload to PyPI:\n")
|
||||||
|
print(f" pip install twine")
|
||||||
|
print(f" twine upload dist/*\n")
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
197
build_wheel.sh
Normal file
197
build_wheel.sh
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# build_wheel.sh - Build wheel distribution for Agravity Client
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./build_wheel.sh [--clean] [--upload]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --clean Clean previous builds before building
|
||||||
|
# --upload Upload to PyPI after building
|
||||||
|
#
|
||||||
|
# Requires:
|
||||||
|
# - Python 3.9+
|
||||||
|
# - setuptools>=65.0
|
||||||
|
# - wheel
|
||||||
|
# - build (recommended)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
print_success() {
|
||||||
|
echo -e "${GREEN}✓ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}✗ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_header() {
|
||||||
|
echo "========================================================================"
|
||||||
|
echo "$1"
|
||||||
|
echo "========================================================================"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_subheader() {
|
||||||
|
echo "------------------------------------------------------------------------"
|
||||||
|
echo "$1"
|
||||||
|
echo "------------------------------------------------------------------------"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
CLEAN=false
|
||||||
|
UPLOAD=false
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--clean)
|
||||||
|
CLEAN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--upload)
|
||||||
|
UPLOAD=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Usage: $0 [--clean] [--upload]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Get project root
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
DIST_DIR="$PROJECT_ROOT/dist"
|
||||||
|
BUILD_DIR="$PROJECT_ROOT/build"
|
||||||
|
EGG_INFO_DIR="$PROJECT_ROOT/agravity_client.egg-info"
|
||||||
|
|
||||||
|
print_header "Agravity Client - Wheel Builder"
|
||||||
|
|
||||||
|
# Clean if requested
|
||||||
|
if [ "$CLEAN" = true ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Cleaning previous builds..."
|
||||||
|
for dir in "$DIST_DIR" "$BUILD_DIR" "$EGG_INFO_DIR"; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
rm -rf "$dir"
|
||||||
|
print_success "Removed $dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean dist directory for fresh build
|
||||||
|
if [ -d "$DIST_DIR" ]; then
|
||||||
|
rm -rf "$DIST_DIR"
|
||||||
|
print_success "Removed old distributions"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check build dependencies
|
||||||
|
echo ""
|
||||||
|
echo "Checking build dependencies..."
|
||||||
|
if ! python3 -m pip list 2>/dev/null | grep -q "^build "; then
|
||||||
|
echo "Installing build tools..."
|
||||||
|
python3 -m pip install -q build setuptools wheel
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
print_success "Build tools installed"
|
||||||
|
else
|
||||||
|
print_error "Failed to install build tools"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build
|
||||||
|
print_subheader "Building distributions..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
if ! python3 -m build; then
|
||||||
|
print_error "Build failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify output
|
||||||
|
print_subheader "Build Results"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ ! -d "$DIST_DIR" ]; then
|
||||||
|
print_error "dist directory not created"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count wheels and sdists
|
||||||
|
WHEEL_COUNT=$(find "$DIST_DIR" -maxdepth 1 -name "*.whl" 2>/dev/null | wc -l)
|
||||||
|
SDIST_COUNT=$(find "$DIST_DIR" -maxdepth 1 -name "*.tar.gz" 2>/dev/null | wc -l)
|
||||||
|
|
||||||
|
if [ $WHEEL_COUNT -eq 0 ] && [ $SDIST_COUNT -eq 0 ]; then
|
||||||
|
print_error "No distributions created"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_success "Build successful!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $WHEEL_COUNT -gt 0 ]; then
|
||||||
|
echo "Wheels:"
|
||||||
|
for wheel in "$DIST_DIR"/*.whl; do
|
||||||
|
SIZE=$(du -h "$wheel" | cut -f1)
|
||||||
|
echo " • $(basename "$wheel") ($SIZE)"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $SDIST_COUNT -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Source Distributions:"
|
||||||
|
for sdist in "$DIST_DIR"/*.tar.gz; do
|
||||||
|
SIZE=$(du -h "$sdist" | cut -f1)
|
||||||
|
echo " • $(basename "$sdist") ($SIZE)"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
print_success "Distributions saved to: $DIST_DIR"
|
||||||
|
|
||||||
|
# Installation instructions
|
||||||
|
print_subheader "Installation Instructions"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $WHEEL_COUNT -gt 0 ]; then
|
||||||
|
WHEEL=$(ls "$DIST_DIR"/*.whl | head -1)
|
||||||
|
echo "Install the wheel locally:"
|
||||||
|
echo " pip install \"$WHEEL\""
|
||||||
|
echo ""
|
||||||
|
echo "Or upload to PyPI:"
|
||||||
|
echo " pip install twine"
|
||||||
|
echo " twine upload dist/*"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Optional upload
|
||||||
|
if [ "$UPLOAD" = true ]; then
|
||||||
|
print_subheader "Uploading to PyPI..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if ! python3 -m pip list 2>/dev/null | grep -q "^twine "; then
|
||||||
|
echo "Installing twine..."
|
||||||
|
python3 -m pip install -q twine
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running twine upload..."
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
if python3 -m twine upload dist/*; then
|
||||||
|
print_success "Upload complete!"
|
||||||
|
else
|
||||||
|
print_error "Upload failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Done!"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
82
update_version.ps1
Normal file
82
update_version.ps1
Normal file
|
|
@ -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 "agravity_client") "__init__.py"
|
||||||
|
|
||||||
|
Write-Host "======================================================================"
|
||||||
|
Write-Host "Updating Agravity 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
|
||||||
|
}
|
||||||
127
update_version.py
Normal file
127
update_version.py
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Update version across Agravity Client project files.
|
||||||
|
|
||||||
|
This script updates the version in:
|
||||||
|
- pyproject.toml
|
||||||
|
- agravity_client/__init__.py
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python update_version.py <version>
|
||||||
|
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]} <version>")
|
||||||
|
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 / "agravity_client" / "__init__.py"
|
||||||
|
|
||||||
|
print("=" * 70)
|
||||||
|
print(f"Updating Agravity 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())
|
||||||
123
update_version.sh
Normal file
123
update_version.sh
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Update version across Agravity Client project files.
|
||||||
|
#
|
||||||
|
# This script updates the version in:
|
||||||
|
# - pyproject.toml
|
||||||
|
# - agravity_client/__init__.py
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./update_version.sh <version>
|
||||||
|
# ./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 <version>"
|
||||||
|
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/agravity_client/__init__.py"
|
||||||
|
|
||||||
|
echo "======================================================================"
|
||||||
|
echo "Updating Agravity 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 "$@"
|
||||||
103
upload_wheel_to_forgejo_pypi.bat
Normal file
103
upload_wheel_to_forgejo_pypi.bat
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
@echo off
|
||||||
|
REM Upload wheel to Forgejo PyPI for Agravity Client
|
||||||
|
REM
|
||||||
|
REM Prerequisites:
|
||||||
|
REM 1. Create .pypirc file in project root
|
||||||
|
REM 2. Copy from .pypirc.example and add your credentials
|
||||||
|
REM
|
||||||
|
REM Usage:
|
||||||
|
REM upload_wheel_to_forgejo_pypi.bat [--build]
|
||||||
|
REM Options: --build Force rebuild before upload
|
||||||
|
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
set PYPIRC_SRC=%CD%\.pypirc
|
||||||
|
set PYPIRC_DEST=%USERPROFILE%\.pypirc
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================================================
|
||||||
|
echo Agravity Client - Upload to Forgejo PyPI
|
||||||
|
echo ========================================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM Check for .pypirc
|
||||||
|
if not exist ".pypirc" (
|
||||||
|
echo [!] .pypirc not found in project root!
|
||||||
|
echo.
|
||||||
|
echo Setup instructions:
|
||||||
|
echo 1. cp .pypirc.example .pypirc
|
||||||
|
echo 2. Edit .pypirc with your Forgejo credentials
|
||||||
|
echo 3. Run this script again
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM Copy .pypirc to user profile
|
||||||
|
echo Configuring credentials...
|
||||||
|
copy /Y "%PYPIRC_SRC%" "%PYPIRC_DEST%" > nul
|
||||||
|
|
||||||
|
REM Activate virtual environment (if exists)
|
||||||
|
if exist .venv\Scripts\activate.bat (
|
||||||
|
call .venv\Scripts\activate.bat
|
||||||
|
)
|
||||||
|
|
||||||
|
REM Install twine if needed
|
||||||
|
python -m pip list | find /I "twine" > nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo Installing twine...
|
||||||
|
python -m pip install -q twine
|
||||||
|
)
|
||||||
|
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
REM Check for --build flag
|
||||||
|
if "%~1"=="--build" (
|
||||||
|
echo Building wheel (forced)...
|
||||||
|
rmdir /s /q dist > nul 2>&1
|
||||||
|
python build_wheel.py
|
||||||
|
if errorlevel 1 (
|
||||||
|
del "%PYPIRC_DEST%"
|
||||||
|
if exist .venv\Scripts\deactivate.bat call .venv\Scripts\deactivate.bat
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
REM Build wheel if not present
|
||||||
|
if not exist dist\*.whl (
|
||||||
|
echo Building wheel...
|
||||||
|
python build_wheel.py
|
||||||
|
if errorlevel 1 (
|
||||||
|
del "%PYPIRC_DEST%"
|
||||||
|
if exist .venv\Scripts\deactivate.bat call .venv\Scripts\deactivate.bat
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
REM Upload to Forgejo PyPI
|
||||||
|
echo.
|
||||||
|
echo ========================================================================
|
||||||
|
echo Uploading to Forgejo PyPI...
|
||||||
|
echo ========================================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
twine upload -r forgejo dist\*.whl
|
||||||
|
set UPLOAD_RESULT=%errorlevel%
|
||||||
|
|
||||||
|
REM Cleanup
|
||||||
|
del "%PYPIRC_DEST%"
|
||||||
|
if exist .venv\Scripts\deactivate.bat call .venv\Scripts\deactivate.bat
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================================================
|
||||||
|
if %UPLOAD_RESULT% equ 0 (
|
||||||
|
echo Upload successful!
|
||||||
|
) else (
|
||||||
|
echo Upload failed
|
||||||
|
)
|
||||||
|
echo ========================================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
endlocal
|
||||||
|
pause
|
||||||
|
exit /b %UPLOAD_RESULT%
|
||||||
130
upload_wheel_to_forgejo_pypi.ps1
Normal file
130
upload_wheel_to_forgejo_pypi.ps1
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
# upload_wheel_to_forgejo_pypi.ps1
|
||||||
|
# Upload wheel to Forgejo PyPI for Agravity Client
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# 1. Create .pypirc file with your Forgejo credentials
|
||||||
|
# 2. Copy from .pypirc.example and add your credentials
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# .\upload_wheel_to_forgejo_pypi.ps1
|
||||||
|
|
||||||
|
param(
|
||||||
|
[switch]$Build = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host @"
|
||||||
|
Upload wheel to Forgejo PyPI for Agravity Client
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
.\upload_wheel_to_forgejo_pypi.ps1 [-Build]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-Build Force rebuild wheel before uploading
|
||||||
|
-Help Display this help message
|
||||||
|
|
||||||
|
SETUP:
|
||||||
|
1. Create .pypirc in project root
|
||||||
|
2. Copy from .pypirc.example as template
|
||||||
|
3. Add your Forgejo repository URL and credentials:
|
||||||
|
[distutils]
|
||||||
|
index-servers = forgejo
|
||||||
|
|
||||||
|
[forgejo]
|
||||||
|
repository = https://git.him-tools.de/api/packages/HIM-public/pypi
|
||||||
|
username = __token__
|
||||||
|
password = YOUR_ACCESS_TOKEN
|
||||||
|
|
||||||
|
4. Keep .pypirc in .gitignore (already added)
|
||||||
|
|
||||||
|
EXAMPLE:
|
||||||
|
.\upload_wheel_to_forgejo_pypi.ps1 # Upload existing wheel
|
||||||
|
.\upload_wheel_to_forgejo_pypi.ps1 -Build # Rebuild and upload
|
||||||
|
"@
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$pypiRcSrc = Join-Path $projectRoot ".pypirc"
|
||||||
|
$pypiRcDest = Join-Path $env:USERPROFILE ".pypirc"
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "========================================================================"
|
||||||
|
Write-Host "Agravity Client - Upload to Forgejo PyPI"
|
||||||
|
Write-Host "========================================================================"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Check for .pypirc
|
||||||
|
if (!(Test-Path $pypiRcSrc)) {
|
||||||
|
Write-Host "[!] .pypirc not found in project root!" -ForegroundColor Red
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Setup instructions:"
|
||||||
|
Write-Host " 1. cp .pypirc.example .pypirc"
|
||||||
|
Write-Host " 2. Edit .pypirc with your Forgejo credentials"
|
||||||
|
Write-Host " 3. Run this script again"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "For help: .\upload_wheel_to_forgejo_pypi.ps1 -Help"
|
||||||
|
Write-Host ""
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy .pypirc to user profile
|
||||||
|
Write-Host "Configuring credentials..."
|
||||||
|
Copy-Item -Path $pypiRcSrc -Destination $pypiRcDest -Force
|
||||||
|
|
||||||
|
# Activate virtual environment
|
||||||
|
$activateScript = Join-Path $projectRoot ".venv\Scripts\Activate.ps1"
|
||||||
|
if (Test-Path $activateScript) {
|
||||||
|
& $activateScript
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install/upgrade twine if needed
|
||||||
|
python -m pip list | Select-String "^twine " > $null
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "Installing twine..."
|
||||||
|
python -m pip install -q twine
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build wheel if requested or not present
|
||||||
|
Push-Location $projectRoot
|
||||||
|
if ($Build -or !(Get-ChildItem -Path "dist" -Filter "*.whl" -ErrorAction SilentlyContinue)) {
|
||||||
|
if ($Build) {
|
||||||
|
Write-Host "Building wheel (forced)..."
|
||||||
|
Remove-Item "dist" -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
} else {
|
||||||
|
Write-Host "Building wheel..."
|
||||||
|
}
|
||||||
|
python build_wheel.py
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Remove-Item $pypiRcDest -Force
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Upload to Forgejo PyPI
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "========================================================================"
|
||||||
|
Write-Host "Uploading to Forgejo PyPI..."
|
||||||
|
Write-Host "========================================================================"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
twine upload -r forgejo dist/*.whl
|
||||||
|
$uploadResult = $LASTEXITCODE
|
||||||
|
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
# Cleanup credentials
|
||||||
|
Remove-Item $pypiRcDest -Force
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "========================================================================"
|
||||||
|
if ($uploadResult -eq 0) {
|
||||||
|
Write-Host "Upload successful!" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Upload failed" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
Write-Host "========================================================================"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
exit $uploadResult
|
||||||
100
upload_wheel_to_forgejo_pypi.sh
Normal file
100
upload_wheel_to_forgejo_pypi.sh
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# upload_wheel_to_forgejo_pypi.sh
|
||||||
|
# Upload wheel to Forgejo PyPI for Agravity Client
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# 1. Create .pypirc file in project root
|
||||||
|
# 2. Copy from .pypirc.example and add your credentials
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./upload_wheel_to_forgejo_pypi.sh [--build]
|
||||||
|
# Options: --build Force rebuild before upload
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PYPIRC_SRC="$PROJECT_ROOT/.pypirc"
|
||||||
|
PYPIRC_DEST="$HOME/.pypirc"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================================================"
|
||||||
|
echo "Agravity Client - Upload to Forgejo PyPI"
|
||||||
|
echo "========================================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for .pypirc
|
||||||
|
if [ ! -f "$PYPIRC_SRC" ]; then
|
||||||
|
echo "[!] .pypirc not found in project root!"
|
||||||
|
echo ""
|
||||||
|
echo "Setup instructions:"
|
||||||
|
echo " 1. cp .pypirc.example .pypirc"
|
||||||
|
echo " 2. Edit .pypirc with your Forgejo credentials"
|
||||||
|
echo " 3. Run this script again"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy .pypirc to user home
|
||||||
|
echo "Configuring credentials..."
|
||||||
|
cp "$PYPIRC_SRC" "$PYPIRC_DEST"
|
||||||
|
chmod 600 "$PYPIRC_DEST"
|
||||||
|
|
||||||
|
# Activate virtual environment (if exists)
|
||||||
|
if [ -f "$PROJECT_ROOT/.venv/bin/activate" ]; then
|
||||||
|
source "$PROJECT_ROOT/.venv/bin/activate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install twine if needed
|
||||||
|
if ! pip list 2>/dev/null | grep -q "^twine "; then
|
||||||
|
echo "Installing twine..."
|
||||||
|
pip install -q twine
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for --build flag
|
||||||
|
if [ "$1" = "--build" ]; then
|
||||||
|
echo "Building wheel (forced)..."
|
||||||
|
rm -rf "$PROJECT_ROOT/dist"
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
python build_wheel.py
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
rm -f "$PYPIRC_DEST"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Build wheel if not present
|
||||||
|
if ! ls "$PROJECT_ROOT/dist"/*.whl > /dev/null 2>&1; then
|
||||||
|
echo "Building wheel..."
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
python build_wheel.py
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
rm -f "$PYPIRC_DEST"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Upload to Forgejo PyPI
|
||||||
|
echo ""
|
||||||
|
echo "========================================================================"
|
||||||
|
echo "Uploading to Forgejo PyPI..."
|
||||||
|
echo "========================================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
twine upload -r forgejo dist/*.whl
|
||||||
|
UPLOAD_RESULT=$?
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -f "$PYPIRC_DEST"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================================================"
|
||||||
|
if [ $UPLOAD_RESULT -eq 0 ]; then
|
||||||
|
echo "Upload successful!"
|
||||||
|
else
|
||||||
|
echo "Upload failed"
|
||||||
|
fi
|
||||||
|
echo "========================================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
exit $UPLOAD_RESULT
|
||||||
Loading…
Add table
Add a link
Reference in a new issue