Skip to content

How Queen ships

The registries a release touches, which two of them CI publishes and which four a human publishes, where the version number lives, and which parts of the older release note no longer hold.

Updated View as Markdown

A release touches the broker image, five client SDKs and the CLI, across five package registries plus GitHub Releases. Two of those channels are published by CI on a trigger; the rest are published by a person running a command. Knowing which is which is the point of this page.

Where the version lives

server/server.json is the single source. Three separate things read it:

  • server/build.rs extracts version and exports it as QUEEN_VERSION, which is what GET /health, the boot log and queenctl ping report. A version bump therefore forces a rebuild of the broker.
  • build.sh uses name and version to tag and push the image locally.
  • .github/workflows/docker-build.yml reads both with jq for the same purpose in CI.

Everything else carries its own version, or none at all.

Artifact Where its version lives
Broker image server/server.json
JavaScript client clients/client-js/package.json
Python client clients/client-py/pyproject.toml
PHP/Laravel client nowhere: composer.json has no version field; Packagist reads the git tag
Go client nowhere: the git tag is the version
queenctl nowhere: the tag is the version, injected at build time with -ldflags
C++ client nowhere: header-only, taken at whatever tag you check out
Dashboard (app/) app/package.json, private, never published separately

The versioning rule

The broker and the SDKs are version-aligned at 1.0.0. One MAJOR.MINOR.PATCH for the broker image, npm, PyPI, Packagist, the Go module tag and the CLI tag, so a client version tells you which broker it was released against without a compatibility matrix.

What CI publishes

The container images

.github/workflows/docker-build.yml publishes two images to GHCR, as a matrix over the two Dockerfiles:

Image Dockerfile Version from
ghcr.io/queen-mq/queen Dockerfile server/server.json
ghcr.io/queen-mq/queen-proxy proxy/Dockerfile proxy/Cargo.toml

Both build for linux/amd64 and linux/arm64 from the repository root: the proxy crate embeds ../server/webapp/dist, so its context cannot be proxy/. Each gets three tags: its own version, sha-<short>, and latest. The broker also receives QUEENCTL_VERSION and QUEENCTL_COMMIT as build arguments so that queenctl version inside the container matches what the broker reports.

Authentication is the workflow’s own GITHUB_TOKEN under permissions: packages: write, so there are no registry secrets to rotate. Layer caching is the GitHub Actions cache, scoped per image (scope=${{ matrix.image }}); a shared scope would make the two matrix legs evict each other’s layers and cold-build every run.

Triggers are a push to the release branch, a v* tag, or workflow_dispatch. A pull request against release builds both images without pushing.

The CLI

.github/workflows/release-cli.yml fires on a tag matching clients/client-cli/v* and runs GoReleaser v2, which cross-compiles queenctl for linux, darwin and windows on amd64 and arm64 (windows/arm64 excluded), produces tar.gz archives (zip on windows) with checksums and pre-built shell completions, and attaches them to a GitHub Release. Version, commit and build date go in through -ldflags, so queenctl version reports the tag.

The directory-prefixed tag shape is required by Go’s module proxy for a nested module, and GoReleaser wants bare semver, so the workflow strips the prefix into GORELEASER_CURRENT_TAG and runs with --skip=validate. The bare semver tag does not physically exist at the release commit, only the prefixed one does.

What a human publishes

Four channels have no workflow. Each needs a command run by a maintainer.

Channel Package How
npm queen-mq npm publish from clients/client-js
PyPI queen-mq clients/client-py/publish.sh, which builds the wheel and sdist and uploads with twine
Go modules github.com/smartpricing/queen/clients/client-go push a clients/client-go/vX.Y.Z tag; the module proxy picks it up
Packagist smartpricing/queen-mq push a vX.Y.Z tag; a webhook makes Packagist pull it

The C++ client needs nothing published: consumers take clients/client-cpp/queen_client.hpp at the tag.

Two tag shapes are load-bearing and easy to get wrong. Both nested Go modules need the directory-prefixed form (clients/client-go/v1.0.0 and clients/client-cli/v1.0.0) because that is how Go’s module proxy resolves a module that is not at the repository root. Without the prefix, go get reports no matching versions. The tags already in the repository follow both shapes, alongside the plain vX.Y.Z broker tags.

Order

The broker tag and image go first, because every SDK is released against a broker; then npm, because most downstream consumers wait on it; then PyPI; then the Go module tag; then the plain vX.Y.Z tag that Packagist and the C++ header hang off; then the CLI tag, which triggers its own workflow.

Rollback, and the one place additivity stops

Schema application is idempotent by construction. server/src/schema.rs applies schema.sql and all 34 stored-procedure files at every boot, in lexical order, under a session advisory lock, and every statement is CREATE OR REPLACE, IF NOT EXISTS or ADD COLUMN IF NOT EXISTS. So re-applying is always safe, and rolling the broker image back to a previous 1.x is safe at the database level.

There is one hard exception, and it is the boundary into 1.0. server/sql/procedures/040_log_drop_legacy.sql runs before the log-engine schema and drops the retired seg_* engine: every queen.seg_* function, discovered dynamically over pg_proc so no straggler survives, then the legacy tables, then the seg-era columns folded into queen.partition_consumers. It is written to be a no-op on a database that never had them and a full teardown on one that did.

What the older release note gets wrong

developer/14-release.md is the pre-1.0 checklist and is still in the tree. Read it for the publishing mechanics of npm, PyPI and Packagist, which are unchanged. Everything below it says no longer holds.

It says Actually
the version is 0.14.1.beta.1 in server/server.json it is 1.0.0-beta.1, shipping as 1.0.0
the release covers “the C++ broker binary, libqueen, and five client SDKs” there is no C++ broker and no lib/. The image carries the Rust broker, the dashboard and queenctl
the pre-release checklist runs cd lib && make test-contention that directory does not exist. The gate is test/run.sh. See Testing
user-facing docs live in docs/*.html, and a version bump has to edit docs/index.html and docs/quickstart.html that site is retired. Documentation is webdoc/, and it is built and gated by its own workflow
the version lives “in nine places” including those HTML files the live places are server/server.json, proxy/Cargo.toml, app/package.json, clients/client-js/package.json, clients/client-py/pyproject.toml, README.md, and the image tag shown in these docs
a rolled-back procedure can be re-applied from lib/schema/procedures/ procedures live in server/sql/procedures/ and are embedded in the binary, so the binary and the procedures roll together: you cannot roll one back independently
helm/, helm_queen/ and proxy/helm/ are release artifacts to update those directories are gitignored and untracked. Nothing in CI reads them and they are not shipped
the schema is “always additive between versions”, so a rollback is always safe true within 1.x, false across the 0.16-to-1.0 boundary. See the warning above

One workflow is dead in the same way. .github/workflows/cpp-server-build.yml triggers on the release branch and runs make deps and make build-only in server/, targets that were removed with the C++ broker; it cannot succeed. And .github/workflows/cli.yml pins its end-to-end broker to smartnessai/queen-mq:0.14.3, so the CLI’s end-to-end suite currently tests against a pre-log-engine broker.

Post-release

  • Smoke-test the published packages from a clean directory rather than a local link: install queen-mq from npm and from PyPI, and go get the client module at the new version.
  • Write release notes covering schema changes, new environment variables and anything removed. A removed route or environment variable is a major-version change.
  • Re-check that the published image tag in these docs matches what was pushed. It appears in Start here and Self-hosting.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close