Historical release documentation: These instructions describe the PyPI handoff before it occurred. Current PyPI releases install the Go CLI after the version break; older pinned releases are the Python implementation. See installation.
Release and deployment runbook #
A release is complete only when the tested tag, published artifacts, pinned workloads, completed content builds, and live sites agree. Creating a GitHub Release or updating a container tag is not enough.
1. Freeze a tested source revision #
- Choose the exact main-branch commit after CI passes; record the 40-character SHA and release version. Maintain Go on
0.x; the next intended version after v0.13.0 is v0.14.0, not 1.0. - Require green lint, Linux core/CLI/site integration shards, macOS and Windows tests, and the snapshot package check. No unresolved red CI jobs.
- In particular,
TestCacheDeterminism_ColdVsHot_WithFeedsAllFormatsmust not depend on whether a public CDN happened to answer. If the test fails due to an intermittent download, investigate and rerun; record the diagnosis and a durable fix rather than treating a red run as pass. - Check any open release-affecting PRs and verify the approved source contains the intended code and docs.
- Do not tag a moving
mainbranch by accident: record the exact commit and compare it to the final release ref.
Local maintainer commands (Go 1.27 required):
git fetch origin --tags
git checkout main
git pull --ff-only
go test -race ./...
go vet ./...
goreleaser check
go run ./scripts/rendering-contract --check
# See the dedicated snapshot workflow and check-rc-artifacts.sh.
git rev-parse HEAD
After all checks pass, an authorized maintainer creates and pushes an annotated version tag:
git tag -a v0.14.0 <verified-full-commit-sha> -m "Markata v0.14.0"
git push origin v0.14.0
Do not push that tag while the release CI is red. This repository’s tag-driven Release workflow tests the tagged Go source, uses GoReleaser, and publishes signed binaries/checksums and SBOMs. The Docker workflow publishes tagged GHCR images including compatibility aliases.
2. Verify artifacts and document the release #
- Check the canonical GitHub Release, specifically that it is not draft or failed and points to the expected commit.
- Confirm
markata_0.14.0_*andmarkata-go_0.14.0_*archives for Linux, macOS and Windows, checksums, Cosign signatures and SBOMs. Validate one installed binary of each name. - Confirm
ghcr.io/waylonwalker/markata-builder:0.14.0and itsmarkata-go-builder:0.14.0compatibility alias, as well as applicable search image sources. Do not infer publication solely from a workflow that was queued. - Include a curated summary, important compatibility notes, upgrade/rollback instructions and a link to v0.14.0 release notes in the published GitHub release body; the autogenerated commit changelog is supplemental.
- Never replace a published tag with a different commit. Issue a subsequent patch release for corrections.
3. Publish PyPI independently, if its handoff gate is ready #
The current PyPI project name markata historically belongs to Python Markata. Publishing Go wheels is an intentional breaking installation-path handoff with its own review gate. See PyPI binary wheels.
- Verify PyPI trusted publisher for owner
WaylonWalker, repomarkata, workflowpypi-go-wheels.ymland environmentpypi. - Verify protected GitHub
pypienvironment and freeze/disable the old Python repository’s publishing workflow. - Run Go Markata PyPI wheels on
mainwith version0.14.0,publish=trueand the workflow’s required confirmation only after the above prerequisites are satisfied. - Confirm all eight native wheel files on PyPI and test a new virtual environment with
python -m pip install --only-binary=:all: markata==0.14.0,markata versionandpython -m markata version. Unsupported platforms may otherwise fall back to an older Python package. - Keep GitHub Release and PyPI states separately labelled until both have succeeded.
4. Deploy one immutable release through Argo CD #
Never change production GitOps to reference an unbuilt tag or a mutable latest image. In each multi-source Helm Application pin the chart targetRevision: v0.14.0 and align every Markata fetch, builder and search image tag: "0.14.0" with that source. Preserve other application settings, storage modes, secrets and feature flags. If search is intentionally independently pinned, verify the compatible search version first; record the exception explicitly.
Use a separate GitOps PR that can be held until all artifacts are verified. Progressive rollout:
| Order | Surface | GitOps source | Expected action |
|---|---|---|---|
| 1 | go.waylonwalker.com |
argo-apps/apps/go-waylonwalker-com.yaml |
Canary chart/builder/search pins; rebuild and smoke |
| 2 | waylonwalker.com |
argo-apps/apps/waylonwalker-com-prod.yaml |
Full site build; smoke archive/images/sidebar/navigation |
| 3 | rhiannonwalker.com |
argo-apps/apps/rhiannonwalker-com-prod.yaml |
Build via Builder Admin and confirm site |
| 4 | wyattbubbylee.com |
argo-apps/apps/wyattbubbylee-com-prod.yaml |
Build via Builder Admin and confirm site |
| 5 | recipes.waylonwalker.com |
k8s/recipes-waylonwalker-com/deployment.yaml and site-config.yaml |
Replace both mutable latest references with 0.14.0; confirm recipe build |
The markata-docs Deployment uses a separate Python-based documentation generator and separately versioned docs images; it is not a Markata CLI runtime and should not be falsely counted as an old Markata deployment. platgo currently has an example/commented Markata builder setting, not an active runtime. A historical rhiannonwalker source-seed bootstrap Job has a pinned image; audit it only if bootstrap is still required.
For each Argo Application: compare desired manifests with running pod image digests and chart revision; confirm it synced successfully and is healthy. On Builder Admin, compare running binary revision with most recent successfully published build. If the feature’s automatic build-on-new-revision does not run, invoke a full build through the authenticated builder. Verify site content before counting it complete.
Example read-only checks (use your configured kubectl context; do not assume remote cluster access from CI):
kubectl -n argocd get applications
kubectl -n waylonwalker-com-prod-notes get deployments,pods
kubectl -n go-waylonwalker-com-notes get deployments,pods
kubectl -n rhiannonwalker-com-prod-notes get deployments,pods
kubectl -n wyattbubbylee-com-prod-notes get deployments,pods
kubectl -n recipes-waylonwalker-com get deployments,pods
curl -fIsS https://waylonwalker.com/
curl -fIsS https://waylonwalker.com/archive/
curl -fIsS https://waylonwalker.com/images/
5. Rollback and closeout #
Before each promotion, record old chart SHA, old image digests, the most recent good site release identifier and an application-specific rollback procedure. If the new build fails, pause further promotions, restore the old immutable chart/image pins in GitOps, reconcile, and activate the last known-good site release. A content rollback and a binary rollback are different operations; verify both.
Keep a deployment record with: release version, tag commit, binary artifacts, PyPI status, container digests, Argo commit, per-site desired/running image, build revision, site release ID, full-build result, public smoke results and timestamp. Mark each site verified, blocked, or not applicable; never call the release “deployed everywhere” with unknowns.