Release Publishing¶
This page documents the staged package-release workflow for netbox-proxbox and
its companion proxbox-api backend. The workflow deliberately separates package
index validation from final publication so failed published artifacts are never
reused.
For the broader CI job map and Docker 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 + netbox_proxbox/__init__.py + uv.lock]
TagTest[Create tag vX.Y.Z\nor vX.Y.Z.postN]
TestCI[CI builds dist\nvalidates tag/version/lockfile]
TestUpload[Upload to TestPyPI\nwithout --skip-existing]
TestValidate[Install netbox-proxbox from TestPyPI\nrun package checks]
TestE2E[E2E Docker\nnetbox-proxbox from TestPyPI\nproxbox-api from TestPyPI]
TestFailed{Any TestPyPI\nvalidation failed?}
RCBump[Bump to next vX.Y.Z.postN\nfor code or packaging fixes]
RCTag[Create PyPI candidate tag\nvX.Y.ZrcN]
RCValidate[Run PyPI candidate checks\nlocal package + E2E against PyPI proxbox-api]
RCUpload[Upload vX.Y.ZrcN to PyPI]
RCInstall[Install rcN from PyPI\nrun post-upload checks]
RCFailed{RC 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\nrun post-upload E2E]
FinalFailed{Post-release fix needed?}
Post[Bump to vX.Y.Z.postN\nrepeat TestPyPI then PyPI]
Done([Release is green])
Start --> Bump --> TagTest --> TestCI --> TestUpload --> TestValidate --> TestE2E --> TestFailed
TestFailed -- yes --> RCBump --> TagTest
TestFailed -- no --> RCTag --> RCValidate --> RCUpload --> RCInstall --> RCFailed
RCFailed -- yes --> NextRC --> RCTag
RCFailed -- no --> FinalTag --> FinalUpload --> FinalValidate --> FinalFailed
FinalFailed -- yes --> Post --> TagTest
FinalFailed -- no --> Done
Cross-Package E2E Contract¶
The plugin does not import proxbox-api as a Python dependency. It consumes the
backend as a runtime HTTP service, so release coupling is validated in Docker
E2E rather than package metadata.
sequenceDiagram
participant Tag as Release Tag
participant WF as netbox-proxbox publish workflow
participant TP as TestPyPI
participant PY as PyPI
participant E2E as e2e-docker.yml
participant NB as NetBox container
participant API as proxbox-api container
Tag->>WF: vX.Y.Z or vX.Y.Z.postN
WF->>TP: Upload netbox-proxbox package
WF->>E2E: install_source=testpypi, dependency_mode=testpypi-package
E2E->>NB: pip install netbox-proxbox==X.Y.Z from TestPyPI
E2E->>API: pip install proxbox-api==configured version from TestPyPI
E2E-->>WF: Full stack sync checks pass
Tag->>WF: vX.Y.ZrcN or publish_target=pypi
WF->>PY: Upload netbox-proxbox package
WF->>E2E: install_source=pypi, dependency_mode=pypi-package
E2E->>NB: pip install netbox-proxbox==X.Y.ZrcN or X.Y.Z from PyPI
E2E->>API: pip install proxbox-api==configured version from PyPI
E2E-->>WF: Post-publish checks pass
Workflow Rules¶
pyproject.toml,netbox_proxbox/__init__.py,uv.lock, and the Git tag must all describe the same version.- Normal and
.postNtag pushes publish to TestPyPI. rcNtag pushes, GitHub releases, or manual dispatch withpublish_target=pypipublish to PyPI.- Package uploads intentionally omit
twine --skip-existing; a consumed version must move forward to the next.postNorrcN. proxbox_api_versioncan be supplied manually. If omitted, the workflow reads repository variables in this order:PROXBOX_API_TESTPYPI_VERSION/PROXBOX_API_PYPI_VERSION,PROXBOX_API_RELEASE_VERSION, then the checked-in default.
Operator Checklist¶
- Publish and validate
proxbox-apion TestPyPI first. - Publish and validate
netbox-proxboxon TestPyPI using that TestPyPIproxbox-apiversion. - Promote
proxbox-apithrough PyPI release candidates and final PyPI release. - Promote
netbox-proxboxthrough PyPI release candidates and final PyPI release using the matching PyPIproxbox-apiversion. - If any published validation fails, bump to the next
.postNorrcN; never retry the same artifact version.