Release Publishing¶
This page documents the staged proxbox-api package-release workflow. The
workflow validates release candidates on TestPyPI first, then promotes the
final release to PyPI and publishes Docker images only after PyPI installation
succeeds.
For the broader CI job map and NetBox-backed E2E matrix, see CI and E2E Workflows.
Release State Machine¶
flowchart TD
Start([Choose target release\nX.Y.Z])
Bump[Bump package version\npyproject.toml + uv.lock]
RCTag[Create release-candidate tag\nvX.Y.ZrcN]
RCCI[CI builds dist\nvalidates tag/version/lockfile]
RCUpload[Upload vX.Y.ZrcN to TestPyPI\nwithout --skip-existing]
RCValidate[Install rcN from TestPyPI\non Python 3.11, 3.12, 3.13]
RCChecks[Run lint, type, compile,\nimport, schema, pytest checks]
RCE2E[E2E Docker\nproxbox-api rcN from TestPyPI]
RCFailed{Any TestPyPI\nvalidation failed?}
NextRC[Bump to vX.Y.ZrcN+1]
FinalTag[Create or dispatch final tag\nvX.Y.Z]
FinalUpload[Upload vX.Y.Z to PyPI]
FinalValidate[Install final from PyPI\non Python 3.11, 3.12, 3.13]
Docker[Publish Docker images\nraw, nginx, granian]
FinalE2E[Run post-publish E2E\npublished package + Docker image]
FinalFailed{Post-release fix needed?}
Post[Bump to vX.Y.Z.postN\npublish .postN to PyPI]
Done([Release is green])
Start --> Bump --> RCTag --> RCCI --> RCUpload --> RCValidate --> RCChecks --> RCE2E --> RCFailed
RCFailed -- yes --> NextRC --> RCTag
RCFailed -- no --> FinalTag --> FinalUpload --> FinalValidate --> Docker --> FinalE2E --> FinalFailed
FinalFailed -- yes --> Post --> FinalTag
FinalFailed -- no --> Done
Workflow Lanes¶
sequenceDiagram
participant Tag as Version tag
participant WF as publish-testpypi.yml
participant TP as TestPyPI
participant PY as PyPI
participant DH as Docker Hub
participant E2E as E2E stack
Tag->>WF: vX.Y.ZrcN
WF->>WF: Validate pyproject + uv.lock + tag
WF->>TP: Upload package
WF->>TP: Reinstall exact rcN version
WF->>WF: Run local checks from TestPyPI install
Tag->>WF: vX.Y.Z, vX.Y.Z.postN, release event, or publish_target=pypi
WF->>WF: Run candidate checks and pre-publish E2E
WF->>E2E: Wait for NetBox migrations and /api/status/ readiness
WF->>PY: Upload package
WF->>PY: Reinstall exact package version
WF->>DH: Publish raw, nginx, and granian images
WF->>E2E: Verify published PyPI package and Docker image
Workflow Rules¶
pyproject.toml,uv.lock, and the Git tag must describe the same version.rcNtag pushes publish to TestPyPI for release-candidate validation.- Non-rc tag pushes (
vX.Y.Z,vX.Y.Z.postN), GitHub releases, or manual dispatch withpublish_target=pypipublish to PyPI. - Package uploads intentionally omit
twine --skip-existing; if a version was consumed by any package index, fix forward with the next.postNorrcN. - PyPI publication must pass package reinstall validation before Docker images are published.
- Docker image tags use the same version as the PyPI package that passed validation.
- Pre-publish and post-publish E2E jobs allow NetBox up to 20 minutes to finish
migrations/search indexing and require
/api/status/readiness before configuring tokens or backend endpoints.
Operator Checklist¶
- Bump
pyproject.tomland refreshuv.lock. - Tag
vX.Y.Zrc1for TestPyPI release-candidate validation. If validation fails after upload, continue withrc2,rc3, and so on. - Publish the final
vX.Y.Zto PyPI only after an rc lane is green. - Use
vX.Y.Z.postNfor any code or packaging fix discovered after final PyPI publication.