Releasing Victor¶
Guide for maintainers on creating and publishing Victor releases.
Table of Contents¶
- Release Process Overview
- Pre-Release Checklist
- Creating a Release
- Automated Release Pipeline
- Manual Release Steps
- Distribution Channels
- Post-Release Tasks
- Hotfix Releases
- Troubleshooting
Release Process Overview¶
The release-train diagram separates dependency readiness from tag-triggered publication.
Victor depends directly on Sandhi and optionally on ProximaDB; there is no automatic
Sandhi → ProximaDB → Victor trigger. Victor AI and contracts have independent version trains.
Use the promotion procedure for branch and tag placement:
---
title: Independent release trains and promotion
---
%%{init: {"theme":"base","themeVariables":{"primaryColor":"#E8EFF7","primaryTextColor":"#17324D","primaryBorderColor":"#456987","lineColor":"#456987","fontFamily":"Arial"}}}%%
flowchart TB
S["sandhi-gateway release availability"]
P["ProximaDB release availability"]
READY["Verify Victor dependency pins"]
DEV["develop<br/>version sync and validation"]
PR["Promotion PR<br/>develop → main"]
MAIN["main promotion merge commit"]
TAG["vX.Y.Z tag"]
AI["release.yml"]
PY["PyPI<br/>victor-ai and native distributions"]
GH["GitHub Release<br/>checksums and built artifacts"]
DOCKER["Docker publication"]
SDK["Independent contracts version"]
SDKTAG["sdk-vX.Y.Z tag"]
SDKWF["release-contracts.yml"]
SDKPY["PyPI · victor-contracts"]
S -->|"required dependency"| READY
P -->|"optional extra dependency"| READY
READY -.->|"release readiness"| DEV
DEV -->|"open reviewed promotion"| PR
PR -->|"merge after promotion battery"| MAIN
MAIN -->|"tag release commit"| TAG
TAG -->|"trigger"| AI
AI -->|"build, verify and publish"| PY
AI -->|"assemble release assets"| GH
AI -->|"publish image"| DOCKER
SDK -->|"tag SDK release"| SDKTAG
SDKTAG -->|"trigger"| SDKWF
SDKWF -->|"test, build and publish"| SDKPY
Pre-Release Checklist¶
Before creating a release, ensure:
- All tests pass:
make test - Linting passes:
make lint - Documentation is updated
- CHANGELOG.md is updated (if applicable)
- Deprecation inventory is updated for any new or removed compatibility surfaces
- Release notes/changelog include replacement path, target removal version/date, and shim status for every deprecation touched in the release
- If the release changes first-party vertical packaging, the authoritative package, bundled-shim status, and earliest removal milestone are called out explicitly
- If the release publishes or updates an extracted first-party vertical, package versions remain aligned with the Victor suite version for that release
- Clean-environment install/discovery smoke tests pass for every extracted vertical touched by the release
- Version in
pyproject.tomlis correct - All PRs for this release are merged
- Dependencies are up to date
Version Numbering¶
We follow Semantic Versioning:
- MAJOR.MINOR.PATCH (e.g.,
1.2.3) - Pre-release:
1.0.0-alpha,1.0.0-beta,1.0.0-rc.1
| Change Type | Version Bump | Example |
|---|---|---|
| Breaking changes | MAJOR | 0.1.0 → 1.0.0 |
| New features (backward compatible) | MINOR | 0.1.0 → 0.2.0 |
| Bug fixes | PATCH | 0.1.0 → 0.1.1 |
| Pre-release | Suffix | 0.2.0-beta |
Extracted Vertical Release Rules¶
When a release touches first-party extracted vertical packages:
- use the canonical package identities from
docs/development/vertical-package-naming-ownership-versioning-policy-2026-03-12.md - treat extracted first-party vertical packages as lockstep-versioned with the
Victor suite for that release - treat bundled contrib copies as compatibility shims only once a vertical flips
- do not remove bundled shims until the retirement policy in
docs/development/bundled-vertical-shim-retirement-milestones-2026-03-12.md
is satisfied
Release notes should always state:
- which package is authoritative
- whether a bundled shim still exists
- the earliest removal version/date for that shim
- the install/upgrade command users should follow
Creating a Release¶
Using Make (Recommended)¶
# 1. Ensure you're on main branch with latest changes
git checkout main
git pull origin main
# 2. Run tests
make test
make lint
# 3. Create the release (updates version, commits, tags)
make release VERSION=0.2.0
# 4. Push to trigger automated release
git push origin main
git push origin --tags
Manual Steps¶
# 1. Update version in pyproject.toml
sed -i 's/version = ".*"/version = "0.2.0"/' pyproject.toml
# 2. Commit the version change
git add pyproject.toml
git commit -m "Release v0.2.0"
# 3. Create annotated tag
git tag -a "v0.2.0" -m "Release v0.2.0"
# 4. Push changes and tag
git push origin main
git push origin v0.2.0
Automated Release Pipeline¶
When a tag matching v* is pushed, GitHub Actions automatically:
1. Runs Tests¶
- Unit tests on Python 3.12 and 3.13
- Linting with ruff and black
- Type checking with mypy
2. Builds Artifacts¶
Python Package:
- Source distribution (.tar.gz)
- Wheel (.whl)
Standalone Binaries:
- victor-macos-arm64.tar.gz
- victor-linux-x64.tar.gz
- (victor-linux-arm64.tar.gz — pending sandhi-gateway publishing a
manylinux-aarch64 wheel; the pinned exact version cannot install there yet)
- victor-windows-x64.zip
Each artifact is smoke-tested in CI (cold/warm --version, --help, size
tripwire) before it reaches the release.
Docker Images:
- vjsingh1984/victor-ai:<version>
- vjsingh1984/victor-ai:latest
3. Publishes to Distribution Channels¶
- PyPI: Automatic via trusted publishing (OIDC, no token needed)
- uv:
uv tool install --python 3.12 victor-ai(recommended CLI path;
resolves straight from PyPI — no separate channel) - GitHub Releases: Creates release with artifacts and checksums
- Docker Hub: Pushes images to
vjsingh1984/victor-ai - Homebrew: Auto-updates via PyPI polling (every 6 hours)
Release-engineering checklist addition: verify the uv path against the
TestPyPI rehearsal before a stable tag
(uv tool install --python 3.12 --index-url https://test.pypi.org/simple/
--extra-index-url https://pypi.org/simple/ victor-ai==<version> && victor
--version).
Required Secrets¶
Configure these in GitHub repository settings:
| Secret | Purpose |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub username (vjsingh1984) |
DOCKERHUB_TOKEN |
Docker Hub access token |
Notes:
- PyPI uses trusted publishing (OIDC, no token needed)
- Homebrew tap uses PyPI polling (no cross-repo token needed)
Manual Release Steps¶
If automated release fails, follow these manual steps:
Publish to PyPI¶
# Build packages
pip install build twine
python -m build
# Check packages
twine check dist/*
# Upload to PyPI
twine upload dist/*
Build Binaries¶
# Install build dependencies
pip install -e ./victor-contracts -e ".[build]"
# Build for current platform
python scripts/build_binary.py --onefile
# Output in dist/
ls dist/
Build and Push Docker¶
# Build
docker build -t vjsingh1984/victor-ai:0.2.3 .
docker tag vjsingh1984/victor-ai:0.2.3 vjsingh1984/victor-ai:latest
# Push
docker push vjsingh1984/victor-ai:0.2.3
docker push vjsingh1984/victor-ai:latest
Create GitHub Release¶
- Go to GitHub Releases
- Click "Draft a new release"
- Select the tag (e.g.,
v0.2.0) - Title: "Victor v0.2.0"
- Description: Include changelog
- Upload binary artifacts
- Check "Pre-release" if applicable
- Publish
Distribution Channels¶
PyPI¶
- URL: https://pypi.org/project/victor/
- Install:
pip install victor - Publishing: Automated via GitHub Actions
GitHub Releases¶
- URL: https://github.com/vijayksingh/victor/releases
- Contains: Source code, binaries, changelog
Docker Hub¶
- URL: https://hub.docker.com/r/vjsingh1984/victor-ai
- Pull:
docker pull vjsingh1984/victor-ai:latest
Homebrew¶
- Tap:
vjsingh1984/tap - Install:
brew install vjsingh1984/tap/victor - Formula: Auto-updates every 6 hours via PyPI polling
Post-Release Tasks¶
After a successful release:
-
Verify Installation
-
Test Docker Image
-
Update Documentation
- Update version references in docs
- Update changelog -
Announce Release
- GitHub Discussions
- Social media (if applicable) -
Monitor for Issues
- Watch GitHub Issues for reports
- Check PyPI download stats
Hotfix Releases¶
For critical bug fixes:
# 1. Create hotfix branch from tag
git checkout -b hotfix/0.2.1 v0.2.0
# 2. Apply fixes
# ... make changes ...
git commit -m "Fix critical bug"
# 3. Update version
make release VERSION=0.2.1
# 4. Merge to main
git checkout main
git merge hotfix/0.2.1
# 5. Push
git push origin main
git push origin --tags
# 6. Clean up
git branch -d hotfix/0.2.1
Troubleshooting¶
PyPI Upload Fails¶
"Invalid distribution":
"Version exists":
- Version already published to PyPI
- Increment version number
Docker Build Fails¶
"No space left on device":
"Permission denied":
Binary Build Fails¶
Missing dependencies:
PyInstaller errors:
- Check scripts/build_binary.py for missing hidden imports
- Add imports to get_hidden_imports()
GitHub Actions Fails¶
- Check workflow logs in Actions tab
- Verify secrets are configured
- Check for rate limiting
- Re-run failed jobs
Homebrew Formula Not Updated¶
- Check
vjsingh1984/homebrew-tapworkflow ran successfully - Formula auto-updates via PyPI polling (every 6 hours)
- Manually trigger: Go to Actions → "Update Formula" → Run workflow
- Run:
brew update && brew upgrade victor
Release Artifacts Reference¶
| Artifact | Location | Purpose |
|---|---|---|
victor_ai-0.2.3.tar.gz |
PyPI, GitHub | Source distribution |
victor_ai-0.2.3-py3-none-any.whl |
PyPI, GitHub | Python wheel |
victor-macos-arm64.tar.gz |
GitHub | macOS Apple Silicon binary |
victor-macos-x64.tar.gz |
GitHub | macOS Intel binary |
victor-windows-x64.zip |
GitHub | Windows binary |
vjsingh1984/victor-ai:0.2.3 |
Docker Hub | Docker image |
checksums.txt |
GitHub | SHA256 checksums |