Repository navigation
Ops Release
A release publishes the container images, the Helm chart and a GitHub release from one tag. The workflow is .github/workflows/release.yml; the decisions are in ADR 0029.
-
mainis green (CI includinge2e,e2e-weband thehelmchart checks). Optionally run the kind install test first:gh workflow run helm-kind.yml --ref main. -
Update
docs/phases.mdif the release closes a task or gate. -
Tag and push (semantic version,
vprefix):git tag -a v0.1.0 -m "MowDeck 0.1.0" git push origin v0.1.0
The tag starts release.yml and helm-kind.yml. A tag with a pre-release suffix (v0.2.0-rc.1) is published as a pre-release and does not move :latest.
Before the first release: if packages with these names (mowdeck/<image>, charts/mowdeck) already exist under the owner on GHCR, grant this repository write access to them or remove them before the first release; otherwise the push is refused.
Test builds without a tag: gh workflow run release.yml -f version=0.1.0-rc.1 builds and pushes the images and the chart with that version but creates no GitHub release (-f publish-release=true creates one; :latest moves only for a final version).
| Job | Output |
|---|---|
version |
the version from the tag (v0.1.0 gives 0.1.0) or the input, checked against semantic versioning |
images (one job per image, in parallel) |
identity, fleet, device-gateway, telemetry, realtime, notifications, scheduler, entitlements, planner, web and authz-bootstrap for linux/amd64 and linux/arm64 as one multi-platform image each: ghcr.io/<owner>/mowdeck/<image>:<version>, :v<version> and, for a final release, :latest. Built with Buildx, QEMU for arm64 (docker/setup-qemu-action, multi-platform builds) and the GitHub Actions cache (gha cache backend); base images as pinned in infra/compose/.env.example. Each image carries an SBOM and a provenance attestation (build attestations) and gets an SPDX SBOM file from anchore/sbom-action. |
chart |
helm package with version and appVersion set to the release version (so image.tag defaults to the released images), pushed as an OCI artifact to oci://ghcr.io/<owner>/charts/mowdeck:<version> (Helm registries) |
release |
a GitHub release v<version> with notes generated from the merged pull requests and commits since the previous tag (generated release notes, softprops/action-gh-release), an install snippet, the chart archive and the SBOM files |
The web app's build stage runs on the runner's platform (FROM --platform=$BUILDPLATFORM), because its output is static files; only the nginx stage is per platform. The Python images build their virtual environment per platform under QEMU (wheels are architecture specific), which makes the arm64 half the slow part of the job. Native arm64 runners (ubuntu-24.04-arm) would remove the emulation if they become available for the repository; the images have no architecture specific steps either way.
Install a release:
helm install mowdeck oci://ghcr.io/lukislp/charts/mowdeck --version 0.1.0 -n mowdeck --create-namespace -f my-values.yaml
helm show values oci://ghcr.io/lukislp/charts/mowdeck --version 0.1.0 # the commented valuesGHCR packages of a private repository are private. Pulling them needs docker login ghcr.io (or an imagePullSecrets entry, see Helm operations) with a token that has read:packages. To publish MowDeck without logins, change the visibility of each package once (GitHub: profile or organisation, Packages, mowdeck/<image> and charts/mowdeck, Package settings, Change visibility to public; GHCR documentation). New tags of a public package stay public.
Images are immutable per version, so a rollback is choosing an older version:
helm history mowdeck -n mowdeck
helm rollback mowdeck <revision> -n mowdeck --wait # previous chart, values and images
# or pin the image tag of a known good release with the current chart:
helm upgrade mowdeck oci://ghcr.io/lukislp/charts/mowdeck --version <current> -n mowdeck \
--reuse-values --set image.tag=0.1.0 --waitDatabase migrations are not rolled back: they are backward compatible, and the older images start against the newer schema (their wait-for-schema init container accepts a revision it does not know). A rollback across a release whose migrations were not backward compatible needs a database restore (Backups). The authorization model follows the release: rolling back runs the older bootstrap Job, which writes the older model as the latest one.
With Compose, the stack runs mowdeck/<service>:${MOWDECK_VERSION}; to run a published version instead of a local build, pull and retag it (docker pull ghcr.io/lukislp/mowdeck/<service>:0.1.0 && docker tag ghcr.io/lukislp/mowdeck/<service>:0.1.0 mowdeck/<service>:0.1.0 for every image), set MOWDECK_VERSION=0.1.0 and start with docker compose up -d --no-build --wait.
Images and the chart are not signed yet. Keyless signing with Cosign fits the workflow: add id-token: write to the images and chart jobs, install sigstore/cosign-installer, and run cosign sign --yes ghcr.io/<owner>/mowdeck/<image>@<digest> (digest from the build step's output) and cosign sign --yes ghcr.io/<owner>/charts/mowdeck@<digest> after helm push. Verification then pins the workflow identity: cosign verify --certificate-identity-regexp 'https://github.com/lukislp/mowdeck/.github/workflows/release.yml@refs/tags/v.*' --certificate-oidc-issuer https://token.actions.githubusercontent.com <image>.
Mirrored from docs/ops/release.md at commit 74ca60a96a5e0903c2f4f7277366ef3fc5ad6dce. Edit the file in the repository, not this wiki page.
Mirrored from the docs/ directory at commit 74ca60a96a5e0903c2f4f7277366ef3fc5ad6dce. Edit the files in the repository, not this wiki.
MowDeck documentation
- Home
- Phases
- Architecture
-
Decisions (ADR)
- Architecture decisions
- ADR 0001: OpenFGA instead of self-built authorization
- ADR 0002: Self-built Identity service in FastAPI instead of Keycloak or Zitadel
- ADR 0003: SvelteKit for the web app
- ADR 0004: Monorepo with a uv workspace
- ADR 0005: AGPL-3.0 for services and apps, Apache-2.0 for libraries
- ADR 0006: PostgreSQL for all persistence, no SQLite
- ADR 0007: NATS JetStream as event bus
- ADR 0008: Traefik as gateway
- ADR 0009: Command and event envelopes, subject naming and de-duplication
- ADR 0010: Python 3.13 for all services and libraries
- ADR 0011: Separate GPL-3.0 package for the PyMammotion adapter
- ADR 0012: Mower control interface and safety rules
- ADR 0013: Device-Gateway registry, sharding and per-mower concurrency
- ADR 0014: Authorization model, tuple ownership and the mowdeck-authz client
- ADR 0015: Tokens, sessions and key rotation
- ADR 0016: Fleet commands and authorization per command kind
- ADR 0017: Telemetry storage and retention
- ADR 0018: Realtime WebSocket protocol
- ADR 0019: Mammotion adapter transports, manual drive and secrets
- ADR 0020: Web app architecture
- ADR 0021: Browser authentication flow
- ADR 0022: Notifications: rules, recipients and delivery
- ADR 0023: Map rendering and projection
- ADR 0024: Scheduler: recurrence, rain pause and command issuing
- ADR 0025: Home Assistant integration as a pure API client
- ADR 0026: Manual drive channel over the Realtime WebSocket
- ADR 0027: Health history and theft alarm
- ADR 0028: Entitlements: plans as data and enforcement
- ADR 0029: Helm chart and release pipeline
- ADR 0030: Mowing patterns as plug-ins and the Planner
- ADR 0031: Billing with a Stripe adapter
- ADR 0032: Live camera over Agora, joined directly by the browser
- ADR 0033: Vision-assisted recovery with human approval
- ADR 0034: Linked cloud accounts and device discovery
- ADR 0035: Server-side camera frames and automatic AI analysis on errors
- ADR 0036: Native app shells with Capacitor, loading the web app from the server
- ADR 0037: Camera panorama calibration in the browser, with the AI supplying points only
- ADR 0038: Dual link per mower and firmware updates
- ADR 0039: Spot mowing by MowDeck-driven paths
- ADR 0040: Link heartbeat for online status
- ADR 0041: Spot runs from the dock: undock, transit and return
- ADR 0042: Drive calibration
- ADR 0043: Turn styles
- ADR 0044: Drive view with camera
- ADR 0045: Camera relay
- Development
- Operations
- Spikes
- Guides
- Original plan (German)