Add hash-suffixed versioning and git-based reinstall command
This commit is contained in:
@@ -1,15 +1,6 @@
|
|||||||
# Reinstall tensors
|
---
|
||||||
|
description: Reinstall tensors - update version with git hash, install locally and on junkpile
|
||||||
Bump version, reinstall locally and on junkpile.
|
---
|
||||||
|
|
||||||
Run the reinstall script:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/reinstall.py
|
${CLAUDE_PROJECT_ROOT}/.claude/commands/reinstall.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This will:
|
|
||||||
1. Bump the patch version in pyproject.toml
|
|
||||||
2. Install locally with `uv pip install -e .`
|
|
||||||
3. Sync the project to junkpile via rsync
|
|
||||||
4. Install on junkpile with `pip install -e '.[server]'`
|
|
||||||
|
|||||||
Executable
+73
@@ -0,0 +1,73 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Tensors Reinstall Script
|
||||||
|
# Updates version with git hash, reinstalls locally and on junkpile
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TENSORS_ROOT="/Users/chi/Projects/tensors"
|
||||||
|
JUNKPILE_HOST="chi@junkpile"
|
||||||
|
JUNKPILE_PATH="/opt/tensors/app"
|
||||||
|
|
||||||
|
cd "$TENSORS_ROOT"
|
||||||
|
|
||||||
|
# Get current version from __init__.py
|
||||||
|
CURRENT_VERSION=$(sed -n 's/^__version__ = "\([^"]*\)"/\1/p' tensors/__init__.py)
|
||||||
|
BASE_VERSION=$(echo "$CURRENT_VERSION" | sed 's/+.*//')
|
||||||
|
|
||||||
|
# Get the LAST commit hash BEFORE we make any changes
|
||||||
|
LAST_HASH=$(git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
# New version with hash
|
||||||
|
NEW_VERSION="${BASE_VERSION}+${LAST_HASH}"
|
||||||
|
|
||||||
|
echo "=== Tensors Reinstall ==="
|
||||||
|
echo "Current version: $CURRENT_VERSION"
|
||||||
|
echo "Base version: $BASE_VERSION"
|
||||||
|
echo "Last commit: $LAST_HASH"
|
||||||
|
echo "New version: $NEW_VERSION"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if version already matches (avoid loop)
|
||||||
|
if [[ "$CURRENT_VERSION" == "$NEW_VERSION" ]]; then
|
||||||
|
echo "[1/5] Version already at $NEW_VERSION, skipping version bump"
|
||||||
|
else
|
||||||
|
echo "[1/5] Updating version to $NEW_VERSION..."
|
||||||
|
sed -i '' "s/__version__ = \".*\"/__version__ = \"$NEW_VERSION\"/" tensors/__init__.py
|
||||||
|
echo " Updated tensors/__init__.py"
|
||||||
|
|
||||||
|
# Commit version change if there are changes
|
||||||
|
if ! git diff --quiet; then
|
||||||
|
echo ""
|
||||||
|
echo "[2/5] Committing version update..."
|
||||||
|
git add tensors/__init__.py
|
||||||
|
git commit -m "Version $NEW_VERSION"
|
||||||
|
echo " Committed."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Push if ahead of remote
|
||||||
|
if git status | grep -q "Your branch is ahead"; then
|
||||||
|
echo ""
|
||||||
|
echo "Pushing to remote..."
|
||||||
|
git push
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[3/5] Installing locally via uv..."
|
||||||
|
uv pip install -e .
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[4/5] Pulling on junkpile..."
|
||||||
|
ssh "$JUNKPILE_HOST" "cd $JUNKPILE_PATH && sudo -u tensors git checkout . && sudo -u tensors git pull"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[5/5] Installing on junkpile..."
|
||||||
|
ssh "$JUNKPILE_HOST" "cd $JUNKPILE_PATH && sudo -u tensors uv sync && sudo systemctl restart tensors"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Verification ==="
|
||||||
|
uv run tsr --version
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Done ==="
|
||||||
|
echo "Version: $NEW_VERSION"
|
||||||
|
echo "Installed locally and on junkpile."
|
||||||
+5
-2
@@ -1,9 +1,9 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "tensors"
|
name = "tensors"
|
||||||
version = "0.1.18"
|
dynamic = ["version"]
|
||||||
description = "Read safetensor metadata and fetch CivitAI model information"
|
description = "Read safetensor metadata and fetch CivitAI model information"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.14"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"safetensors>=0.4.0",
|
"safetensors>=0.4.0",
|
||||||
"httpx>=0.27.0",
|
"httpx>=0.27.0",
|
||||||
@@ -24,6 +24,9 @@ tsr = "tensors:main"
|
|||||||
requires = ["hatchling"]
|
requires = ["hatchling"]
|
||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.hatch.version]
|
||||||
|
path = "tensors/__init__.py"
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["tensors"]
|
packages = ["tensors"]
|
||||||
|
|
||||||
|
|||||||
+77
-25
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Reinstall tensors locally and on junkpile."""
|
"""Reinstall tensors locally and on junkpile with hash-suffixed versioning."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -9,51 +9,81 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
PROJECT_ROOT = Path(__file__).parent.parent
|
PROJECT_ROOT = Path(__file__).parent.parent
|
||||||
PYPROJECT = PROJECT_ROOT / "pyproject.toml"
|
INIT_FILE = PROJECT_ROOT / "tensors" / "__init__.py"
|
||||||
JUNKPILE_HOST = "chi@junkpile"
|
JUNKPILE_HOST = "chi@junkpile"
|
||||||
JUNKPILE_PATH = "~/Projects/tensors"
|
JUNKPILE_PATH = "/opt/tensors"
|
||||||
|
|
||||||
|
|
||||||
def get_version() -> str:
|
def get_version() -> str:
|
||||||
"""Get current version from pyproject.toml."""
|
"""Get current version from __init__.py."""
|
||||||
content = PYPROJECT.read_text()
|
content = INIT_FILE.read_text()
|
||||||
match = re.search(r'version\s*=\s*"([^"]+)"', content)
|
match = re.search(r'__version__\s*=\s*"([^"]+)"', content)
|
||||||
if not match:
|
if not match:
|
||||||
raise ValueError("Could not find version in pyproject.toml")
|
raise ValueError("Could not find __version__ in tensors/__init__.py")
|
||||||
return match.group(1)
|
return match.group(1)
|
||||||
|
|
||||||
|
|
||||||
def bump_version(current: str) -> str:
|
def get_base_version(version: str) -> str:
|
||||||
"""Bump patch version."""
|
"""Strip any +hash suffix from version."""
|
||||||
parts = current.split(".")
|
return version.split("+")[0]
|
||||||
parts[-1] = str(int(parts[-1]) + 1)
|
|
||||||
return ".".join(parts)
|
|
||||||
|
def get_git_hash() -> str:
|
||||||
|
"""Get short git hash of HEAD."""
|
||||||
|
result = subprocess.run(
|
||||||
|
["git", "rev-parse", "--short", "HEAD"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
cwd=PROJECT_ROOT,
|
||||||
|
)
|
||||||
|
return result.stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
def set_version(new_version: str) -> None:
|
def set_version(new_version: str) -> None:
|
||||||
"""Update version in pyproject.toml."""
|
"""Update version in __init__.py."""
|
||||||
content = PYPROJECT.read_text()
|
content = INIT_FILE.read_text()
|
||||||
# Only replace the project version (line starts with 'version')
|
content = re.sub(r'__version__\s*=\s*"[^"]+"', f'__version__ = "{new_version}"', content)
|
||||||
content = re.sub(r'^version\s*=\s*"[^"]+"', f'version = "{new_version}"', content, count=1, flags=re.MULTILINE)
|
INIT_FILE.write_text(content)
|
||||||
PYPROJECT.write_text(content)
|
print(f" Updated tensors/__init__.py to {new_version}")
|
||||||
print(f" Updated pyproject.toml to {new_version}")
|
|
||||||
|
|
||||||
|
|
||||||
def run(cmd: list[str], *, check: bool = True, capture: bool = False) -> subprocess.CompletedProcess[str]:
|
def run(cmd: list[str], *, check: bool = True, capture: bool = False, cwd: Path | None = None) -> subprocess.CompletedProcess[str]:
|
||||||
"""Run a command."""
|
"""Run a command."""
|
||||||
print(f" $ {' '.join(cmd)}")
|
print(f" $ {' '.join(cmd)}")
|
||||||
return subprocess.run(cmd, check=check, capture_output=capture, text=True)
|
return subprocess.run(cmd, check=check, capture_output=capture, text=True, cwd=cwd or PROJECT_ROOT)
|
||||||
|
|
||||||
|
|
||||||
|
def git_commit_version(version: str) -> bool:
|
||||||
|
"""Commit version change if there are changes."""
|
||||||
|
# Check if there are changes
|
||||||
|
result = run(["git", "diff", "--quiet", "tensors/__init__.py"], check=False, capture=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
return False # No changes
|
||||||
|
|
||||||
|
run(["git", "add", "tensors/__init__.py"])
|
||||||
|
run(["git", "commit", "-m", f"Version {version}"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def git_push_if_ahead() -> bool:
|
||||||
|
"""Push to remote if ahead."""
|
||||||
|
result = run(["git", "status", "--porcelain", "-b"], capture=True)
|
||||||
|
if "ahead" in result.stdout:
|
||||||
|
run(["git", "push"])
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def install_local() -> None:
|
def install_local() -> None:
|
||||||
"""Install locally with uv."""
|
"""Install locally with uv."""
|
||||||
print("\n[2/4] Installing locally...")
|
print("\n[3/5] Installing locally...")
|
||||||
run(["uv", "pip", "install", "-e", "."], check=True)
|
run(["uv", "pip", "install", "-e", "."], check=True)
|
||||||
|
|
||||||
|
|
||||||
def sync_to_junkpile() -> None:
|
def sync_to_junkpile() -> None:
|
||||||
"""Sync project to junkpile."""
|
"""Sync project to junkpile."""
|
||||||
print("\n[3/4] Syncing to junkpile...")
|
print("\n[4/5] Syncing to junkpile...")
|
||||||
excludes = [
|
excludes = [
|
||||||
".git",
|
".git",
|
||||||
".venv",
|
".venv",
|
||||||
@@ -76,18 +106,36 @@ def sync_to_junkpile() -> None:
|
|||||||
|
|
||||||
def install_junkpile() -> None:
|
def install_junkpile() -> None:
|
||||||
"""Install on junkpile."""
|
"""Install on junkpile."""
|
||||||
print("\n[4/4] Installing on junkpile...")
|
print("\n[5/5] Installing on junkpile...")
|
||||||
run(["ssh", JUNKPILE_HOST, f"cd {JUNKPILE_PATH} && pip install -e '.[server]'"])
|
run(["ssh", JUNKPILE_HOST, f"cd {JUNKPILE_PATH} && pip install -e '.[server]'"])
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
"""Main entry point."""
|
"""Main entry point."""
|
||||||
current = get_version()
|
current = get_version()
|
||||||
new_version = bump_version(current)
|
base_version = get_base_version(current)
|
||||||
|
git_hash = get_git_hash()
|
||||||
|
new_version = f"{base_version}+{git_hash}"
|
||||||
|
|
||||||
print(f"\n[1/4] Bumping version {current} -> {new_version}...")
|
print("\n=== Tensors Reinstall ===")
|
||||||
|
print(f" Current version: {current}")
|
||||||
|
print(f" Base version: {base_version}")
|
||||||
|
print(f" Git hash: {git_hash}")
|
||||||
|
print(f" New version: {new_version}")
|
||||||
|
|
||||||
|
if current == new_version:
|
||||||
|
print("\n[1/5] Version already current, skipping update")
|
||||||
|
else:
|
||||||
|
print(f"\n[1/5] Updating version to {new_version}...")
|
||||||
set_version(new_version)
|
set_version(new_version)
|
||||||
|
|
||||||
|
print("\n[2/5] Committing version change...")
|
||||||
|
if git_commit_version(new_version):
|
||||||
|
print(" Committed.")
|
||||||
|
git_push_if_ahead()
|
||||||
|
else:
|
||||||
|
print(" No changes to commit.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
install_local()
|
install_local()
|
||||||
sync_to_junkpile()
|
sync_to_junkpile()
|
||||||
@@ -96,6 +144,10 @@ def main() -> int:
|
|||||||
print(f"\nError: Command failed with exit code {e.returncode}")
|
print(f"\nError: Command failed with exit code {e.returncode}")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
print("\n=== Verification ===")
|
||||||
|
run(["uv", "run", "tsr", "--version"])
|
||||||
|
|
||||||
print(f"\n Done! tensors {new_version} installed locally and on junkpile")
|
print(f"\n Done! tensors {new_version} installed locally and on junkpile")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user