Releasing
How Conduit is versioned, how to verify what you download, how to upgrade, and how a maintainer cuts a release.
Versioning policy
Conduit uses Semantic Versioning. It is pre-1.0: a
minor version (0.x.0) may contain breaking changes, and a patch version
(0.x.y) will not. Breaking changes are called out in the
changelog.
The policy covers this public API:
- The gRPC ingestion API in
proto/(reference) - The exported APIs of the Go and Python SDKs
- Environment variables and subcommands (configuration reference)
It does not cover packages under internal/, the root Go module’s other packages
(that module runs the services and provides generated types to the SDK), the UI’s
HTML, or the exact ClickHouse schema. Schema changes reach existing data through
migrations, which the collector applies at startup.
All artifacts of a release share one version number.
| Artifact | Where | Version form |
|---|---|---|
| Images | ghcr.io/tjscanlan/conduit-{gateway,collector,ui,init,demo-agent} |
v0.2.0 |
| Go SDK | github.com/tjscanlan/conduit/sdk/go |
tag sdk/go/v0.2.0, used as @v0.2.0 |
| Python SDK | conduit-observability |
0.1.0 |
Verifying images
Images are built by the release workflow and signed with keyless
cosign, so a valid signature shows the image came
from this repository’s workflow at a version tag:
cosign verify ghcr.io/tjscanlan/conduit-gateway:v0.2.0 \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github\.com/tjscanlan/conduit/\.github/workflows/release\.yml@refs/tags/v'
Each image also carries an SBOM and build provenance as attestations in its manifest list. To see them:
docker buildx imagetools inspect ghcr.io/tjscanlan/conduit-gateway:v0.2.0 --raw
In production, deploy by digest rather than by tag.
Upgrading
- Read the changelog entries between your version and the new one.
- Follow Upgrading an existing deployment.
Cutting a release
Only a maintainer pushes tags.
One-time setup
On PyPI, add a trusted publisher for the project conduit-observability: owner
tjscanlan, repository conduit, workflow release.yml, environment pypi. If
the project doesn’t exist yet, add it as a pending publisher in your account
settings. If it does, add it in the project’s settings. Consider also requiring a
reviewer on the pypi environment in the repository settings.
Each release
- On a branch, set the new version in all of these, then merge:
sdk/python/pyproject.toml- the
require github.com/tjscanlan/conduitline insdk/go/go.mod - the image tags in
deployments/k8s/deployment.yaml - the
${CONDUIT_VERSION:-vX.Y.Z}image defaults indeployments/quickstart/compose.yml(embedded inconduitctl) CHANGELOG.md: move[Unreleased]into an[X.Y.Z]section and update the links at the bottom
scripts/release-check.sh vX.Y.Zchecks that these agree, and CI runs it. -
Tag the merge commit and push both tags at once. The SDK requires the root module at the same version, and the workflow refuses a mismatch:
git switch main && git pull git tag v0.2.0 && git tag sdk/go/v0.2.0 git push --atomic origin v0.2.0 sdk/go/v0.2.0 - Watch the
releaseworkflow. It tests the commit, builds, pushes and signs the images (gateway, collector, ui, and the quickstart’s init and demo-agent), builds theconduitctlbinaries with a cosign-signedSHA256SUMS, publishes to PyPI, checks that the Go SDK resolves the way a consumer would fetch it, and creates the GitHub Release from the changelog section.
A failed run can be re-run: images are rebuilt and re-signed, and PyPI files that already exist are skipped. PyPI versions and Go module tags are permanent, so fix a bad release with a new patch version rather than by moving a tag.