Releasing CodeNib¶
pyproject.toml is the only authored package-version source. Runtime
codenib.__version__, wheel metadata, and codenib --version read the
installed distribution metadata generated from it.
Automated Gates¶
The reusable Release verification workflow runs from both publishing
workflows. Pull requests build and inspect the complete distribution contract,
including the native ABI smoke. Pushes to main, version tags, and explicit
TestPyPI dispatches additionally run the heavier installed-service gates:
- Tests and production-builds the packaged Wiki frontend.
- Builds one source-only sdist and two
cp310-abi3-manylinux_2_28wheels, one each for x86-64 and AArch64. - Compiles the C extension against CPython 3.10's limited API with
-Wall -Wextra -Werror, then runstwine checkand validates artifact contents, metadata, and tags. - Installs the sdist with compilation deliberately disabled, proving that the core remains usable and local workspace support fails closed.
- Installs the native wheel on Python 3.10 through 3.14 and publishes, retains,
and closes one real
LocalWorkspaceProvidergeneration. - Builds a real BM25 index through the installed
codenibcommand. - Installs the public 0.2.2 package, materializes its catalog into a portable
context artifact, upgrades to the candidate wheel, verifies that the BM25
view and materialized artifact remain reusable, and proves that the
Wiki-only
codenib.storagefacade replaced the retired generic package and CLI commands. - Exercises the installed Wiki and MCP services end to end.
- Runs sparse Ask through a local OpenAI-compatible endpoint, including a real BM25 tool call, final answer, and source citation, without installing semantic or graph extras.
- Installs the graph extra and a pinned Python SCIP provider, then verifies repository-aware diagnostics, a real caller-to-callee graph edge, source anchors, and the installed Dependency Map API.
Manually dispatching the TestPyPI Release workflow from main runs these gates,
publishes to TestPyPI, then downloads that exact version from TestPyPI's public
simple index. The workflow selects the current host's compatible wheel and
byte-compares it with the corresponding verified build before installing it in
a fresh environment and exercising a real BM25 index build. Production
publishing remains in the separate Release workflow
and requires a v<version> tag that exactly matches project.version. Before
any upload, the production workflow proves MCP DNS ownership so a missing
record cannot leave a partial release. It then publishes to PyPI,
downloads and byte-compares the compatible public wheel, exercises its
installed Wiki and MCP services, publishes ai.codenib/codenib to the official
MCP Registry, and verifies Registry discovery. The final GitHub Release
contains both Linux wheels, the sdist, and SHA256SUMS; stable versions are
marked latest and PEP 440 prereleases remain prereleases. TestPyPI does not feed
the MCP Registry because the Registry accepts only official PyPI packages.
Native Artifact Contract¶
The production artifact set is exact:
codenib-<version>-cp310-abi3-manylinux_2_28_x86_64.whlcodenib-<version>-cp310-abi3-manylinux_2_28_aarch64.whlcodenib-<version>.tar.gz
Each wheel contains exactly one _workspace_owner_impl.abi3.so. The sdist
contains native/workspace_owner.c and no compiled extension. This lets
compiler-less, macOS, Windows, and other environments without a compatible
native extension install the Python core from source; the local workspace
provider then remains unavailable and fails before mutation. CodeNib does not
publish a prebuilt musllinux wheel, although a Linux source build can provide
the extension when a compatible C toolchain is available. Do not replace this
set with a universal wheel: its tag would falsely claim that the native
ownership boundary works on every platform.
Trusted Publisher Setup¶
For the first release, create a pending publisher on both the PyPI and TestPyPI account pages. Register these publisher identities:
| Registry | Project | Owner | Repository | Workflow | Environment |
|---|---|---|---|---|---|
| TestPyPI | codenib |
sysevol-ai |
CodeNib |
release-test.yml |
testpypi |
| PyPI | codenib |
sysevol-ai |
CodeNib |
release.yml |
pypi |
These values must match exactly; an unregistered or mismatched publisher fails
the OIDC exchange with invalid-publisher. Do not register the reusable
release-verify.yml workflow as a publisher: it never receives an OIDC token
or uploads a distribution.
PyPI and TestPyPI are separate registries: configuring one does not configure
the other. A GitHub pypi or testpypi deployment environment scopes the
workflow job but does not register a publisher with either registry. Confirm
that each pending publisher appears on the corresponding registry account page
before dispatching a publish workflow.
The corresponding GitHub environments should restrict deployments to trusted
maintainers. Both registries publish through OIDC; neither workflow accepts an
API-token password or reads a runner-local .pypirc. After the first successful
production OIDC publication, revoke any remaining bootstrap API token.
MCP Registry Namespace¶
The production tag publishes the branded ai.codenib/codenib namespace from
server.json. The package README carries the matching hidden mcp-name marker,
and release verification keeps both Registry versions plus the fixed uvx
extra synchronized with project.version.
DNS authentication requires one Ed25519 proof record at the codenib.ai apex.
Generate the key once on a trusted machine with OpenSSL 3, add the printed TXT
record through the DNS provider, and store only the extracted private scalar in
the protected GitHub environment:
openssl genpkey -algorithm Ed25519 -out key.pem
PUBLIC_KEY="$(openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64)"
echo "codenib.ai. IN TXT \"v=MCPv1; k=ed25519; p=${PUBLIC_KEY}\""
PRIVATE_KEY="$(openssl pkey -in key.pem -noout -text | grep -A3 'priv:' | tail -n +2 | tr -d ' :\n')"
printf '%s' "$PRIVATE_KEY" | gh secret set MCP_PRIVATE_KEY \
--repo sysevol-ai/CodeNib --env mcp-registry-publish
Do not commit key.pem. Configure mcp-registry-publish to allow only release
tags and require a maintainer approval. The publish job deliberately runs on
ubuntu-latest, not a self-hosted runner, and verifies the pinned publisher
archive before exposing the environment secret. A tag preflight performs this
authentication before PyPI upload; the Registry job repeats it immediately
before publication. The DNS record belongs at the domain apex, not
_mcp-auth.codenib.ai.
A manual Release workflow dispatch from a branch performs release-artifact and
Registry-metadata verification but deliberately skips protected DNS
authentication, because the mcp-registry-publish environment admits only
v* tags. To repeat only the authenticated ownership preflight, dispatch the
workflow against a v* tag whose checked-in release.yml contains the manual
dispatch guard:
Inspect older tags before dispatching them. Production PyPI, MCP Registry, and
GitHub Release jobs must require both a push event and a v* tag; a manual
tag dispatch must never replay publication.
Public Surface Gate¶
Before the production tag, make the repository public and manually dispatch
the Docs workflow from main. Confirm that the documentation site and the two
README assets are anonymously reachable:
https://docs.codenib.ai/
https://raw.githubusercontent.com/sysevol-ai/CodeNib/main/assets/codenib_logo.svg
https://raw.githubusercontent.com/sysevol-ai/CodeNib/main/assets/codenib_wiki.png
The README uses absolute asset URLs because it is also the PyPI project description; repository-relative images have no repository base when rendered on PyPI.
Release Checklist¶
- Move relevant entries from
Unreleasedinto a dated version section inCHANGELOG.md. - Confirm
pyproject.tomluses the release version,server.jsonmatches it,docs/releases/<version>.mdcontains the curated public release notes, and the README citation andmcp-namemarker remain present. - Run
pre-commit run --all-filesand the local package smoke. - Merge the release commit to
mainand confirm its package gates pass. - Confirm the TestPyPI trusted publisher is visible, then dispatch the
TestPyPI Release workflow from
main. - Confirm the TestPyPI registry-download and installed-CLI smoke job passes. Record its exact head SHA, freeze the release surface, and require the production tag to resolve to that same commit.
- Complete the public-surface gate above.
- Confirm the production PyPI publisher exactly names owner
sysevol-ai, repositoryCodeNib, workflowrelease.yml, and environmentpypi. - Confirm the
codenib.aiMCP proof TXT record and protectedmcp-registry-publishenvironment secret are active. - Create and push an annotated
v<version>tag at the accepted TestPyPI SHA. Do not include interveningmainchanges without repeating the candidate workflow. - Confirm PyPI, MCP Registry discovery, and the generated GitHub Release all identify the same version and that a stable release is marked latest.
- After the first successful production OIDC publication, revoke the bootstrap PyPI token from the GitHub environment and local configuration.
Do not reuse a published version. If publication partially succeeds, increment the version and produce new artifacts.