All checks were successful
Run Check Script / check (pull_request) Successful in 2m16s
74 lines
2.9 KiB
Markdown
74 lines
2.9 KiB
Markdown
# Fleet operator — release & deploy
|
|
|
|
How the operator ships: build + publish a versioned image and helm
|
|
chart, then `harmony apply` (a plain `helm upgrade --install` of that
|
|
published chart). No Argo, no GitOps controller — Harmony owns the loop
|
|
(ADR-012-2). CD is **roll-forward only**: to back out a bad release,
|
|
deploy a previous good version.
|
|
|
|
## 1. Cut a release (automated on tag)
|
|
|
|
```sh
|
|
git tag harmony-fleet-operator-v0.0.2 && git push --tags
|
|
```
|
|
|
|
The `harmony-fleet-operator` workflow builds the image and the hydrated
|
|
helm chart and pushes both to `hub.nationtech.io` at `0.0.2`. No human
|
|
touches a Dockerfile, chart, or registry.
|
|
|
|
Laptop fallback (does exactly what the workflow's job does):
|
|
|
|
```sh
|
|
# docker + helm must be logged in to hub.nationtech.io first.
|
|
cargo run --release -p harmony-fleet-deploy --bin harmony-fleet-publish -- \
|
|
--from-tag harmony-fleet-operator-v0.0.2
|
|
|
|
# build + package only, no push (local k3d smoke-test):
|
|
cargo run -p harmony-fleet-deploy --bin harmony-fleet-publish -- \
|
|
--from-tag harmony-fleet-operator-v0.0.2 --no-push
|
|
```
|
|
|
|
## 2. Deploy a published version to staging (manual, for now)
|
|
|
|
Push to staging is manual until headless OpenBao auth (Zitadel machine
|
|
identity) lands; secrets still come from shared OpenBao config. Point at
|
|
your staging kube context and OpenBao, then run the operator deploy:
|
|
|
|
```sh
|
|
export OPENBAO_URL=<your OpenBao URL>
|
|
export OPENBAO_TOKEN=<scoped read token for secret/<ns>/*>
|
|
harmony-fleet-deploy --filter FleetOperatorScore \
|
|
--from-tag <release-tag> --namespace fleet-staging --yes
|
|
```
|
|
|
|
It installs the published
|
|
`oci://hub.nationtech.io/harmony/harmony-fleet-operator-chart:<version>` chart;
|
|
the version is parsed from the tag in Rust (the tag is the only source
|
|
of truth). Same command bootstraps and upgrades; re-running the same tag
|
|
is a no-op. Auth is Zitadel-SSO-only: the operator gets its zitadel-jwt
|
|
`operator_credentials_toml` from `FleetDeploySecrets` in OpenBao (no
|
|
user/pass on the published-chart path). For manual deploy, store that
|
|
config **without** a `kubeconfig` field so your own kube context is used.
|
|
|
|
## 3. Roll forward
|
|
|
|
Re-run with a newer (or previous-good) tag. `helm upgrade --install`
|
|
applies it and fails loudly if convergence fails — no automatic
|
|
rollback. Fix the spec, bump, re-run.
|
|
|
|
## Automated vs. manual
|
|
|
|
| Step | Where |
|
|
|---|---|
|
|
| Build + push image + chart on tag | CI (`release` job, on tag) |
|
|
| Push to staging + roll forward | Manual (operator runs the deploy) |
|
|
|
|
## Future: in-cluster CD (blocked on headless OpenBao auth)
|
|
|
|
Once `harmony_config` can authenticate to OpenBao headlessly (Zitadel
|
|
machine identity), these exports become a `deploy-staging` workflow on an
|
|
in-cluster, permissionless Gitea runner that pulls a `fleet-deployer`
|
|
`kubeconfig` + operator credentials from OpenBao at job time (provisioned
|
|
via a `TenantScore` with one extra egress CIDR to the OpenBao/Zitadel
|
|
ingress). Production-gated promotion is a later step (ADR-012-2).
|