diff --git a/.gitea/workflows/harmony-fleet-operator.yaml b/.gitea/workflows/harmony-fleet-operator.yaml index 140d8c83..674b2542 100644 --- a/.gitea/workflows/harmony-fleet-operator.yaml +++ b/.gitea/workflows/harmony-fleet-operator.yaml @@ -1,12 +1,23 @@ -name: Build and push harmony-fleet-operator image +name: harmony-fleet-operator — release +# A `harmony-fleet-operator-v*` tag builds + publishes the operator image +# and helm chart (one tag → both at the same version). Deploying the +# published chart is `harmony apply` +# (harmony-fleet-deploy --operator-chart-version), run manually today; a +# CD job lands once the cluster KUBECONFIG + NATS secrets are provisioned. +# Tag parsing lives in Rust (harmony-fleet-release), not in YAML. on: push: - branches: - - master + tags: + - 'harmony-fleet-operator-v*' workflow_dispatch: + inputs: + tag: + description: 'Release tag, e.g. harmony-fleet-operator-v0.1.0' + required: true + type: string jobs: - build_and_push: + release: container: image: hub.nationtech.io/harmony/harmony_composer:latest runs-on: dind @@ -14,7 +25,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Log in to hub.nationtech.io + - name: Log in to hub.nationtech.io (docker) uses: docker/login-action@v3 with: registry: hub.nationtech.io @@ -24,21 +35,17 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # Build context is the workspace root because the operator's - # Cargo.toml has `path = "../../harmony"` deps. The multi-stage - # Dockerfile runs `cargo build` itself inside a pinned rust - # image, so no host-side cargo step is needed. - # - # TODO: add buildx layer caching. Each run currently recompiles - # the whole `harmony` workspace from scratch in the builder - # stage. Add `cache-from: type=gha` + `cache-to: type=gha,mode=max` - # below once build time becomes the bottleneck. If layer cache - # alone isn't enough, consider splitting the Dockerfile with - # cargo-chef (no other crate in this repo does that yet). - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - file: fleet/harmony-fleet-operator/Dockerfile - push: true - tags: hub.nationtech.io/harmony/harmony-fleet-operator:latest + # TODO: bake helm into harmony_composer so this step disappears. + - name: Install helm + run: curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + + - name: Log in to hub.nationtech.io (helm OCI) + run: | + echo "${{ secrets.HUB_BOT_PASSWORD }}" \ + | helm registry login hub.nationtech.io \ + --username "${{ secrets.HUB_BOT_USER }}" --password-stdin + + - name: Build + push image and chart + env: + TAG: ${{ inputs.tag || github.ref_name }} + run: cargo run --release -p harmony-fleet-deploy --bin harmony-fleet-release -- --from-tag "$TAG" diff --git a/fleet/deployment-process.md b/fleet/deployment-process.md new file mode 100644 index 00000000..8b649972 --- /dev/null +++ b/fleet/deployment-process.md @@ -0,0 +1,70 @@ +# 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-release -- \ + --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-release -- \ + --from-tag harmony-fleet-operator-v0.0.2 --no-push +``` + +## 2. Deploy a published version (`harmony apply`) + +`--operator-chart-version` switches the operator to install the +published `oci://hub.nationtech.io/harmony/harmony-fleet-operator:0.0.2` +chart instead of rendering one from local source. Same command +bootstraps and upgrades; re-running with the same version is a no-op. + +```sh +export HARMONY_FLEET_NATS_ADMIN_USER=… HARMONY_FLEET_NATS_ADMIN_PASS=… +export HARMONY_FLEET_NATS_DEVICE_USER=… HARMONY_FLEET_NATS_DEVICE_PASS=… + +harmony-fleet-deploy \ + --filter FleetOperatorScore \ + --operator-chart-version 0.0.2 \ + --namespace fleet-system \ + --yes +``` + +## 3. Roll forward + +Same command, a newer (or previous-good) version: + +```sh +harmony-fleet-deploy --filter FleetOperatorScore --operator-chart-version 0.0.3 --namespace fleet-system --yes +``` + +`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) | +| Deploy a published version + roll forward | Manual `harmony apply` (above) | + +A staging-auto / production-gated CD job is a follow-up — it needs the +cluster `KUBECONFIG` + NATS secrets provisioned, which is out of scope +for the initial CD branch (ADR-012-2). The release job is fully +functional today.