Releasing and safe updates¶
How to change Operator ETL without breaking trust signals (CI, tests, share PDFs) and without overwriting a published version.
Versions: VERSIONING.md — tags publish, master does not.
Agents: merge-feature-pr · cut-release · skill operator-release
Every change (any size)¶
make e2e
This runs OKF validate, pytest, and the FOIA demo on a fresh warehouse. Do not push if it fails. Current count is in the verify banner (today 95).
For OKF-only doc changes:
python3 scripts/okf_validate.py okf --strict
Pull request workflow¶
Follow okf/playbooks/merge-feature-pr.md. Summary:
- Branch from
master - Make changes
- Run
make e2elocally (./scripts/verify.shon a fresh clone) - If user-visible: add a bullet under
## [Unreleased]in CHANGELOG.md - Do not bump
pyproject.tomlversion unless this PR is the release (see below) - Open PR — template checklist must be complete
- Wait for all required checks green:
ci-gate, CodeQLAnalyze(see BUILD-HYGIENE.md) - Do not merge while any required check is red or pending
- Squash-merge (preferred) after checks pass
Repo admins: enforce this with a GitHub ruleset — Settings UI click-path + exact contexts in PUBLIC-READINESS.md. Legacy ruleset main is disabled until an admin activates it. Without Active enforcement, humans can still click merge on a red PR; treat that as a process failure.
Pushes to master update the wiki (Pages). They do not publish GitHub Packages or GHCR. Only a v* tag does.
Cut a release (freeze)¶
Do this when you intend to ship a beta or stable, not on every docs PR. Full agent playbook: okf/playbooks/cut-release.md.
- Release PR:
- Move
[Unreleased]to## [X.Y.Z]or## [X.Y.Z-beta.N](today’s date) - Set
versioninpyproject.toml(PEP 440:0.5.0b1for tagv0.5.0-beta.1) - Set
extra.operator_etl_versionin mkdocs.yml make e2e- Merge the PR
- Annotated tag on that merge commit, then push the tag only (not a force-push to
master):
git tag -a v0.5.0-beta.1 -m "Operator ETL 0.5.0-beta.1"
git push origin v0.5.0-beta.1
- Confirm Release is green: GitHub Release,
ghcr.io/khaosans/operator-etl:<version>, GitHub Packages wheel
If GHCR push fails with a permission error, add a PAT (write:packages) as repository secret GHCR_TOKEN. Details: VERSIONING.md.
Never move or retag v0.5.0-beta.1. Next drop is v0.5.0-beta.2 or v0.5.0. Full rules: VERSIONING.md. GitHub Release creation uses --prerelease for betas only — not a --latest flag (gh does not have one).
First tagged freeze after this process: v0.5.0-beta.1 (separate release PR; do not invent tags for 0.4.2–0.4.9).
Install a published version¶
See VERSIONING.md. Short form:
docker pull ghcr.io/khaosans/operator-etl:0.7.0
pip install operator-etl --index-url https://pypi.pkg.github.com/khaosans/simple/
Wheels are also attached to the GitHub Release (no Packages auth).
Dependency updates¶
Dependabot opens weekly PRs for pip and GitHub Actions.
Before merging a Dependabot PR:
- [ ] CI all green (including secret scan)
- [ ] Skim changelog for breaking changes
- [ ] If lockfile changes:
uv sync --frozen --extra dev && make e2elocally - [ ] Unreleased changelog bullet if the bump is user-visible; no package version bump
Manual bump:
uv lock --upgrade-package <name>
uv sync --frozen --extra dev
make e2e
Commit uv.lock with the dependency change.
External share (PDFs)¶
Before LinkedIn, interviews, or proposals:
make share # runs e2e first, then rebuilds PDFs
Checklist: FINAL-REVIEW.md pre-scale · okf/playbooks/qa-before-share.md
While preparing external posts: link repo + optional PDFs from share/README.md.
When repo is public: link https://github.com/khaosans/operator-etl and invite make e2e. Name a tag if you are pointing at a freeze, not floating master.
Infrastructure changes¶
Terraform:
cd infra/gcp
terraform init # commit .terraform.lock.hcl when providers change
terraform plan
Never commit terraform.tfvars — use terraform.tfvars.example.
GCP deploy: follow okf/playbooks/deploy-gcp-staging.md. Do not wire Cloud Build deploy to production without review.
What never ships in git¶
See CONTRIBUTING.md:
.env, vault keys, warehouse DBs- Real FOIA / production PII
.cursor/mcp.json(local paths)- Dated share archives (
docs/share/releases/)
GitHub Pages wiki¶
Docs in docs/ publish via MkDocs (.github/workflows/pages.yml) to https://khaosans.github.io/operator-etl/
The site always reflects master (living docs). Installable artifacts are tags. Footer version in mkdocs.yml is the last released package version; bump it only in a release PR.
Local check:
pip install mkdocs-material
mkdocs build --strict
GitHub Settings → Pages → source GitHub Actions (one-time).
GitHub Wiki tab¶
Do not copy every article into the GitHub Wiki (it drifts). Paste once from the repo:
- Wiki Home ← contents of docs/wiki/Home.md
- Wiki _Sidebar ← contents of docs/wiki/_Sidebar.md
Update those files in git when nav changes; re-paste if the Wiki tab is in use.
Going public¶
Complete every blocker in PUBLIC-READINESS.md before changing visibility.
After the first package publish: GitHub → Packages → GHCR package → enable tag immutability so :0.5.0-beta.1 cannot be overwritten in the registry either.
See also¶
- REPO-HYGIENE.md — branch policy and merge/commit hygiene
- VERSIONING.md
- CONTRIBUTING.md
- SECURITY.md
- PUBLIC-READINESS.md