ci: deploy main to the box from woodpecker #1

Merged
varl merged 1 commit from runa/hass:ci/deploy-from-main into main 2026-10-19 13:58:56 +02:00
Member

Deploys main to the box from Woodpecker, so the config that runs is the config on main.

What's in it

  • .woodpecker/check.yml: HA's own check_config --fail-on-warnings on every push and PR, in home-assistant:2026.10.0 (what the box runs). No secrets needed, so it works for fork PRs. just check-local runs the same check.
  • .woodpecker/deploy.yml: on push to main, after the check passes, runs scripts/sync-box. just deploy runs the same script.
  • scripts/sync-box:
    • refuses on an HA version mismatch, drift from .deployed-rev, or a commit that doesn't descend from the deployed one;
    • holds a lock on the box, so two deploys can't run at once;
    • runs ha core check with the real secrets, and restores the last good tree if the box rejects the change;
    • restarts for sensors/, helpers/utility_meter.yaml and configuration.yaml, and reloads for everything else.
  • Deploys no longer push secrets. secrets.yaml stays on the box; just push-secrets from nikki is still the manual way to change it.

Tested

  • check-config against current main: passes. Invalid platform entries and bad YAML both fail it. Without --fail-on-warnings, the invalid platform entry passed with exit 0.
  • sync-box against a local fake box (fake ssh, ha and curl): first deploy, forced baseline, reload vs restart, drift, rejection by the box with restore, version mismatch, re-run of an old build, dirty tree, lock held.
  • Not tested against the real box: I have no SSH access to it.
  • Both pipelines pass woodpecker-cli lint for v3.16.0.

Before merging (yours)

  1. Generate a deploy key. Authorise its public half in the SSH add-on, and add the private half to this repo in Woodpecker as hass_ssh_key, limited to the push event.
  2. Activate meatbag/hass in Woodpecker.
  3. Check the host key pinned in .woodpecker/known_hosts against the box: ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub should print SHA256:yHrav+Yyo7D2P2Vwo3jkjV11+JTWtDhud6Qzk/fMqC4.
  4. Baseline the box once from nikki: just diff-box, then FORCE=1 just deploy. The box has no .deployed-rev yet, so the first CI deploy would refuse.

Things to know

  • Woodpecker can't limit a secret to a branch. Anyone who can push a branch to this repo can read hass_ssh_key, so keep direct pushes to yourself.
  • When the box updates HA, deploys stop until the image tag in check.yml is bumped. This is deliberate.
  • I couldn't test two assumptions about the SSH add-on: that a reload can use SUPERVISOR_TOKEN in the session, and that curl is installed there. If the first reload fails, that's where to look.
  • themes/ exists only on the box (configuration.yaml includes it) and isn't versioned.
Deploys main to the box from Woodpecker, so the config that runs is the config on main. **What's in it** - `.woodpecker/check.yml`: HA's own `check_config --fail-on-warnings` on every push and PR, in `home-assistant:2026.10.0` (what the box runs). No secrets needed, so it works for fork PRs. `just check-local` runs the same check. - `.woodpecker/deploy.yml`: on push to main, after the check passes, runs `scripts/sync-box`. `just deploy` runs the same script. - `scripts/sync-box`: - refuses on an HA version mismatch, drift from `.deployed-rev`, or a commit that doesn't descend from the deployed one; - holds a lock on the box, so two deploys can't run at once; - runs `ha core check` with the real secrets, and restores the last good tree if the box rejects the change; - restarts for `sensors/`, `helpers/utility_meter.yaml` and `configuration.yaml`, and reloads for everything else. - Deploys no longer push secrets. `secrets.yaml` stays on the box; `just push-secrets` from nikki is still the manual way to change it. **Tested** - `check-config` against current main: passes. Invalid platform entries and bad YAML both fail it. Without `--fail-on-warnings`, the invalid platform entry passed with exit 0. - `sync-box` against a local fake box (fake ssh, `ha` and `curl`): first deploy, forced baseline, reload vs restart, drift, rejection by the box with restore, version mismatch, re-run of an old build, dirty tree, lock held. - Not tested against the real box: I have no SSH access to it. - Both pipelines pass `woodpecker-cli lint` for v3.16.0. **Before merging (yours)** 1. Generate a deploy key. Authorise its public half in the SSH add-on, and add the private half to this repo in Woodpecker as `hass_ssh_key`, limited to the **push** event. 2. Activate `meatbag/hass` in Woodpecker. 3. Check the host key pinned in `.woodpecker/known_hosts` against the box: `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub` should print `SHA256:yHrav+Yyo7D2P2Vwo3jkjV11+JTWtDhud6Qzk/fMqC4`. 4. Baseline the box once from nikki: `just diff-box`, then `FORCE=1 just deploy`. The box has no `.deployed-rev` yet, so the first CI deploy would refuse. **Things to know** - Woodpecker can't limit a secret to a branch. Anyone who can push a branch to this repo can read `hass_ssh_key`, so keep direct pushes to yourself. - When the box updates HA, deploys stop until the image tag in `check.yml` is bumped. This is deliberate. - I couldn't test two assumptions about the SSH add-on: that a reload can use `SUPERVISOR_TOKEN` in the session, and that `curl` is installed there. If the first reload fails, that's where to look. - `themes/` exists only on the box (configuration.yaml includes it) and isn't versioned.
ci: deploy main to the box from woodpecker
Some checks failed
ci/woodpecker/push/check Pipeline was successful
ci/woodpecker/push/deploy Pipeline failed
fa73e54727
check.yml runs HA's own check_config --fail-on-warnings on every push and
PR, in a pinned HA image, against a stand-in secrets.yaml built from the
cleartext key names in secrets.sops.yaml -- so it needs no key and runs
for forks. Without --fail-on-warnings an invalid platform entry exits 0
and the sensor silently never loads on the box.

deploy.yml runs scripts/sync-box on push to main once the check passes;
`just deploy` runs the same script. It refuses when the box runs another
HA version than the pin, when the box has drifted from .deployed-rev,
or when the commit does not descend from the deployed one; holds a lock
on the box; syncs; runs `ha core check` with the real secrets and puts
the last good tree back if that fails; then restarts for sensors/,
utility meters and configuration.yaml, and reloads otherwise.

Deploys no longer push secrets: secrets.yaml stays on the box, and
`just push-secrets` remains the manual path from nikki.
varl merged commit fa73e54727 into main 2026-10-19 13:58:56 +02:00
varl deleted branch ci/deploy-from-main 2026-10-19 13:58:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
meatbag/hass!1
No description provided.