Release & Hot-Fix Workflow¶
This document explains how to cut a new feature release, data release, or hot-fix in the OpenAI Model Registry project.
Table of Contents¶
- Branching Model
- Release Types
- Library Release Workflow
- Data Release Workflow
- Hot-Fix Workflow
- Do's and Don'ts
- Troubleshooting
Branching Model¶
main
– the only long-lived branch. All daily work happens here.- Tags – every published version (
v1.0.0
,v1.0.1
,data-v1.0.0
) is an annotated git tag onmain
. - Hot-fix branch – created only if you must fix the current release without pulling in unreleased work that is already on
main
. Delete it right after the tag is pushed.
Release Types¶
1. Library Releases¶
Library releases contain the Python package code and are published to PyPI.
- Tag Format:
v1.0.0
,v1.0.1
,v1.1.0
- RC Format:
v1.0.0-rc1
,v1.0.0-rc2
- Publishing:
- RC → TestPyPI
- Final → PyPI
2. Data Releases¶
Data releases contain model configuration files and are published as GitHub releases.
- Tag Format:
data-v1.0.0
,data-v1.0.1
- RC Format:
data-v1.0.0-rc1
,data-v1.0.0-rc2
- Publishing: GitHub Releases with data packages
Library Release Workflow¶
Before Writing Code¶
- Make sure you are on
main
and up-to-date:
git switch main
git pull --ff-only origin main
- Create a short feature branch (optional but recommended):
git switch -c feature/<short-name>
-
Implement the feature, update tests, update
CHANGELOG.md
incrementally. -
Open a PR (even if you merge it yourself) – CI must be green.
Creating a Release Candidate¶
-
Merge your PR into
main
. -
Verify
CHANGELOG.md
and docs are ready. -
Run pre-release validation:
./scripts/release/create-rc.sh
- Create RC tag:
./scripts/release/create-rc.sh 1.0.0 1
-
CI automatically:
-
Builds the package
- Runs tests
- Publishes to TestPyPI
-
Creates GitHub release (marked as prerelease)
-
Test the RC:
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
"openai-model-registry==1.0.0rc1"
- Verify functionality:
python -c "import openai_model_registry; print('✅ Import works')"
python -c "from openai_model_registry import ModelRegistry, RegistryConfig; registry = ModelRegistry(RegistryConfig(auto_update=False)); print('✅ Registry works')"
Creating the Final Release¶
- After RC testing is complete and successful:
./scripts/release/create-final.sh 1.0.0
-
CI automatically:
-
Builds the package
- Runs tests
- Publishes to PyPI
-
Creates GitHub release (production)
-
Verify PyPI publication:
pip install openai-model-registry==1.0.0
python -c "import openai_model_registry; print('✅ PyPI install works')"
Data Release Workflow¶
Automatic Data Releases¶
Data releases are automatically triggered when configuration files change:
-
Edit data files in
data/
: -
models.yaml
- Model definitions -
overrides.yaml
- Provider-specific overrides -
Commit and push to
main
:
git add data/
git commit -m "feat: add new model definitions"
git push origin main
-
CI automatically:
-
Detects config changes
- Validates YAML files
- Creates data package
- Increments version
- Creates GitHub release
Contributor Data Release Playbook¶
Use this checklist when publishing a new data release (or RC):
- Update files:
data/models.yaml
-
data/overrides.yaml
-
Update
data/data-changelog.md
(summarize changes, breaking notes) - Tag and publish:
- RC:
data-vX.Y.Z-rcN
- Final:
data-vX.Y.Z
- Attach assets:
models.yaml
,overrides.yaml
- Provide clear Release notes and link to changelog
- Verify client awareness:
- Run
omr --format json update check
→ exit code10
indicates an available update - In code:
ModelRegistry.check_for_updates()
/get_update_info()
returns latest - Optionally notify via GitHub Releases (watch → releases)
- Respect environments:
- Clients may pin via
OMR_DATA_VERSION_PIN
- Clients may disable updates via
OMR_DISABLE_DATA_UPDATES
- Confirm integrity:
- Assets properly attached and downloadable
- Fallback raw URLs (only if needed) should be tag-pinned for immutability
Manual Data Releases¶
For manual data releases or RCs:
- Create RC:
./scripts/release/create-rc.sh 1.0.0 1 --data
- Create final release:
./scripts/release/create-final.sh 1.0.0 --data
- Test data release:
# Download and verify
curl -L https://github.com/yaniv-golan/openai-model-registry/releases/download/data-v1.0.0/openai-model-registry-data-1.0.0.tar.gz -o data.tar.gz
tar -xzf data.tar.gz
cd data-package
# Verify files are present
ls -la models.yaml overrides.yaml
Hot-Fix Workflow¶
Scenario A – Fix is already on main
and safe to release¶
-
Ensure
CHANGELOG.md
has a Hot-fix entry. -
Tag and push directly from
main
:
git switch main && git pull --ff-only
./scripts/release/create-final.sh 1.1.1
Scenario B – Fix must not include unreleased work on main
¶
- Create a throw-away branch from the last tag:
git switch -c hotfix/v1.1.1 v1.1.0
-
Cherry-pick or implement just the necessary commits.
-
Update
CHANGELOG.md
in that branch. -
Tag & push:
git tag -a v1.1.1 -m "v1.1.1: security hot-fix"
git push origin hotfix/v1.1.1 v1.1.1
- After CI turns green, delete the branch:
git push origin --delete hotfix/v1.1.1
git branch -D hotfix/v1.1.1
Do's and Don'ts¶
Do ✓¶
- Keep
main
in a releasable state; let CI protect you. - Use annotated tags (
-a
) for every version. - Update the CHANGELOG steadily while you code.
- Delete merged or obsolete branches immediately.
- Test release candidates thoroughly before final release.
- Use the provided scripts for consistent release process.
- Run validation before creating releases.
Don't ✗¶
- ✗ Don't create long-lived
release/x.y
branches – history gets messy. - ✗ Don't manually publish to PyPI – CI handles this automatically.
- ✗ Don't force-push to shared branches or tags.
- ✗ Don't skip RC testing for significant releases.
- ✗ Don't forget to update CHANGELOG.md.
Troubleshooting¶
Common Issues¶
Release Script Fails¶
# Check if you're on main branch
git branch --show-current
# Ensure you're up to date
git pull --ff-only origin main
# Check for existing tags
git tag -l | grep v1.0.0
CI Build Fails¶
-
Check GitHub Actions logs for detailed error messages
-
Run validation locally:
./scripts/release/create-final.sh
- Test locally:
poetry run pytest -v
poetry build
python -m twine check dist/*
TestPyPI Installation Fails¶
# Try with verbose output
pip install -v --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
"openai-model-registry==1.0.0rc1"
# Check if dependencies are available
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
--dry-run "openai-model-registry==1.0.0rc1"
Version Mismatch¶
# Check current versions
poetry version --short
python -c "import openai_model_registry; print(openai_model_registry.__version__)"
# Update if needed
poetry version 1.0.0
Getting Help¶
- Check CI logs in GitHub Actions
- Review validation output from CI workflows (build/tests/docs) triggered by the release tag
- Test in clean environment to isolate issues
- Check existing tags to avoid conflicts
Automation Overview¶
GitHub Actions Workflows¶
-
release.yml - Library releases
-
Triggered by
v*
andv*-rc*
tags - Builds package, runs tests, publishes to PyPI/TestPyPI
-
Creates GitHub releases
-
data-release-enhanced.yml - Data releases
-
Triggered by config file changes or
data-v*
tags - Validates YAML, creates data packages
-
Creates GitHub releases
-
cross-platform-test.yml - Cross-platform testing
-
Tests installation across OS and Python versions
- Validates package quality and performance
Scripts¶
- create-rc.sh - Create release candidates
- create-final.sh - Create final releases
- Use GitHub Actions logs for validation (build/tests/docs) instead of local
validate-release.py
Related Documentation¶
- RELEASE_CHECKLIST.md - Pre-release validation checklist
- CHANGELOG.md - Version history and changes
- CONTRIBUTING.md - General contribution guidelines
- ostruct pricing automation - Detector and per-model pricing extraction templates used by CI