Project › Releasing
Releasing
The checklist for cutting a release, kept in sync with .github/workflows/publish.yml, .github/workflows/ci.yml, and pyproject.toml. The goal: every published claim resolves to something in the repo, a test, a parity cell, or a reproducible number, at the moment of release.
On this page
Before tagging#
- Green
main. CI passes onmain:ruff check .,ruff format --check ., the offline Markdown link check,lint-imports,pytest -n auto --cov=doberman --cov-report=term-missing --cov-fail-under=80, the parity--checkstep, and the secret scan. - Parity matrix current.
python -m tools.parity.generate_parity --checkpasses (CI enforces it). Every checkmark inPARITY.mdstill resolves to a collected test. - Refresh the benchmark numbers. Re-run the suites per
BENCHMARKS.mdand update its Results tables in the release PR: - Synthetic (deterministic, from a cold clone):python -m tests.benchmarks.run --suite synthetic --profile before_after. - AgentDojo (operator-supplied):pip install agentdojoat a pinned commit, thenpython -m tests.benchmarks.run --suite agentdojo --profile before_after. Record the pinned commit and the run date. Keep the raw run out of git (test-logs/); transcribe only the aggregate numbers. - Update the "Fixed bypasses" wall with anything disclosed and fixed since the last release. - Version and changelog. Bump
versioninpyproject.toml(follow semver). Move shipped items intoCHANGELOG.md. Confirm the README roadmap and versioning reflect reality. - Docs sweep. Every protection claim in the README resolves to a parity cell or a benchmark number. No orphan adjectives.
Cut a release#
Publishing uses PyPI Trusted Publishing (OIDC) via .github/workflows/publish.yml. No API tokens are stored in this repo.
- Commit the version bump from step 4 above and merge to
main. - Optional dry run: GitHub -> Actions -> Publish -> Run workflow, on
main. This builds and uploads to TestPyPI. Verify:bash pip install -i https://test.pypi.org/simple/ \ --extra-index-url https://pypi.org/simple/ doberman-core - Create a GitHub Release with tag
vX.Y.Z(matching the version). Publishing the release triggers thepypi-publishjob, which uploads to PyPI and attaches a CycloneDX SBOM (sbom.json) to the release as a downloadable asset. The public core must build, test, and run with zero enterprise code installed (the standalone guarantee); CI's standalone step enforces this. - Verify from a clean environment:
bash python -m venv /tmp/dob && /tmp/dob/bin/pip install doberman-core /tmp/dob/bin/doberman --help
One-time PyPI setup (already done; reference only)#
Configuring PyPI/TestPyPI to trust this repo, in case it ever needs redoing:
- PyPI (production). Log in at https://pypi.org ↗, go to Account settings -> Publishing -> Add a pending publisher, and fill in PyPI project name
doberman-core, ownerfu351, repositoryDoberman-Core, workflowpublish.yml, environmentpypi. - TestPyPI (optional). Repeat at https://test.pypi.org ↗ with environment
testpypi. - GitHub Environments. In the repo: Settings -> Environments -> create
pypiandtestpypi(names must match the workflow). Add protection rules or required reviewers topypiso a human approves every production publish.
Software Bill of Materials (SBOM)#
Every published release ships a CycloneDX JSON SBOM as a GitHub Release asset (sbom.json), generated by pip-audit from the resolved dependency set in pyproject.toml. .github/workflows/publish.yml builds and attaches it automatically; there's nothing to do by hand for a normal release.
Generate one locally at any time:
pip install -e ".[sbom]"
pip-audit -f cyclonedx-json -o sbom.json .
pip-audit also reports known vulnerabilities in the resolved dependencies while it runs. The release workflow doesn't fail the build on a finding, since a newly disclosed CVE in a transitive dependency shouldn't silently block a release, but it does surface as a warning in the Actions run. Check there before shipping if one shows up.
Local build and inspect (sanity check before tagging)#
python -m pip install --upgrade build twine
python -m build # -> dist/doberman_core-X.Y.Z-py3-none-any.whl + .tar.gz
twine check dist/*
# Public-release safety: confirm nothing local leaks into the artifacts.
unzip -l dist/*.whl
tar tzf dist/*.tar.gz
The sdist file list is pinned in pyproject.toml ([tool.hatch.build.targets.sdist]) to src/doberman, tests, tools, README.md, LICENSE, and pyproject.toml, so graphify-out/, .doberman/, DBs, keys, and dev plan files can never ship.
Claiming the doberman name (PEP 541)#
doberman is already taken on PyPI by an unrelated, abandoned 2020 project, so releases publish as doberman-core until the name is reclaimed. Transferring it is a manual, human-reviewed process and not guaranteed.
- Contact the current owner first. Email the maintainer listed on https://pypi.org/project/doberman/ ↗ and ask if they'll transfer the name. Keep the message for your records.
- If there's no response, or they agree, file a name request under PEP 541 at https://github.com/pypi/support/issues ↗ (the project-name-related template). Note that the project is abandoned (last release 0.0.4, September 2020), link this repo as evidence of active intended use, and reference any prior contact attempt.
- If granted, add
dobermanas the distribution name (or publish a thindobermanpackage that depends ondoberman-core) and update the install docs.
Until then, doberman-core is the canonical install name.