agentleFS
NodeJSmithNodeJSmith/hassette/.claude/skills/ha-version-bump/SKILL.md

ha-version-bump

Skill81 starsChanged 7 months agoMITView on GitHub

Use when the user says "new HA version", "bump HA version", "update the HA pin", "pull the new Home Assistant release", "monthly HA bump", or when the ha-version-drift workflow has filed a drift issue. Pulls the latest Home Assistant core release, updates every pinned reference, regenerates typed models, checks the developer blog for anything that needs a manual follow-up, and prepares (but does not push) the commit.

  • Reads credentials

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 2 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If $PINNED already equals $LATEST, tell the user there's nothing to bump and stop.

    line 25
  2. Very specific:

    If $LATEST's year component is ahead of $PINNED's (a year rollover, e.g.

    line 30
  3. Very specific:

    Update that one line to the new minor version (HA image tags are minor-version only — 2026.7, not 2026.7.1).

    line 54
  4. Distinctive:

    If that shows uncommitted changes, stop and ask the user how to proceed (stash, discard, or investigate) rather than switching tags out …

    line 77
  5. Very specific:

    Read the full diff of every changed generated file (git diff, not --stat).

    line 96
  6. Distinctive:

    Stop here if any command fails: Do not proceed to Phase 5 or 6 on a red suite — fix the failure or report it to the user and end the run.

    line 128
  7. Very specific:

    Check whether codegen already picked up the new shape (Phase 3's diff) or whether the old name is hardcoded somewhere in src/hassette/ …

    line 148
  8. Very specific:

    Run the mine-review skill on the working-tree diff before committing.

    line 158
  9. Very specific:

    Commit type is chore (codegen output isn't user-facing until it ships in a release) unless a breaking change was found, in which case use …

    line 198

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

HA Version Bump

Monthly maintenance. Hassette's typed entity/state models are generated from a local checkout of home-assistant/core, pinned to an exact release. This skill re-runs that pipeline against the latest release and surfaces anything a human needs to judge. It does not silently rubber-stamp the diff.

.github/workflows/ha-version-drift.yml already detects pin drift daily and files a tracking issue covering the pin, the local checkout, codegen, and tests. It doesn't cover the compose-file image tags or the blog-reading step — this skill is the fuller recipe, and the sole place those two are bumped.

Phase 1: Check for drift

PINNED=$(cat codegen/ha-version.txt)
LATEST=$(gh api repos/home-assistant/core/releases/latest --jq .tag_name)

If $PINNED already equals $LATEST, tell the user there's nothing to bump and stop. Otherwise, note the two values — each Bash tool call is a fresh shell, so $LATEST doesn't survive into later phases; treat the version string as a fact you carry forward, not a shell variable, and write it out literally in every command below.

If $LATEST's year component is ahead of $PINNED's (a year rollover, e.g. 2026.x to 2027.0), flag this to the user before proceeding: major HA releases are far more likely to carry breaking entity/API changes than a routine minor bump, and this skill is now the only gate on that risk (Renovate's old dependencyDashboardApproval rule for major jumps was removed along with the rest of its homeassistant/home-assistant handling — see Phase 2). Ask whether to continue or wait for a closer look. In an unattended run there's no one to ask (see Phase 6's "Unattended invocation" note for how to tell you're in one) — stop and report this instead of guessing.

Phase 2: Update every pinned reference

echo "<LATEST from Phase 1, substituted literally>" > codegen/ha-version.txt

scripts/docker/ha-demo.yml and tests/system/docker-compose.yml both derive their HA image tag from ${HA_VERSION}, interpolated by docker-compose from scripts/docker/.env (tests/system/.env is a symlink to the same file) — so there is exactly one place left to bump, not a fixed or grep-discovered list of compose files:

grep -n "^HA_VERSION=" scripts/docker/.env

Update that one line to the new minor version (HA image tags are minor-version only — 2026.7, not 2026.7.1). If a future grep -rn "homeassistant/home-assistant:" . finds a literal (non-${HA_VERSION}) tag anywhere outside design/ (a new compose file added without wiring it to scripts/docker/.env), treat that as its own bug to fix, not just a value to bump. This skill is the sole owner of the HA_VERSION value — renovate.json explicitly disables Renovate for homeassistant/home-assistant (packageRules — "enabled": false) precisely so there's no second, weekly bump racing this monthly one. If renovate.json no longer has that rule, or the rule is present but its enabled value is no longer exactly false, something reverted it; flag that to the user rather than proceeding as if Renovate will catch the drift.

scripts/docker/.env also holds HASS_HASSETTE_VERSION, the hass-hassette integration release both stacks install. Renovate owns that pin (customManagers in renovate.json), so leave it alone here. scripts/docker/hass-hassette.yml uses homeassistant/home-assistant:${HA_VERSION} too; that interpolated tag is expected.

Then update the local core checkout (path from reference_ha-core-local-checkout memory, default ~/source/core):

cd ~/source/core && git status --short

If that shows uncommitted changes, stop and ask the user how to proceed (stash, discard, or investigate) rather than switching tags out from under in-progress work. In an unattended run there's no one to ask (see Phase 6's "Unattended invocation" note for how to tell you're in one) — stop and report this instead of guessing which option is safe. If clean, run the checkout as its own self-contained command — re-cd explicitly and substitute the literal version from Phase 1 rather than a shell variable, since neither the working directory nor $LATEST can be assumed to have survived from the previous command:

cd ~/source/core && git fetch --tags && git checkout "<LATEST from Phase 1, substituted literally>"

Phase 3: Regenerate and review

uv run hassette-codegen generate --ha-core-path ~/source/core

Read the full diff of every changed generated file (git diff, not --stat). Classify each change against these three buckets.

  • Additive. New device class, new unit, new enum member, new optional field. Safe.
  • Removed or renamed field, changed field type, removed enum member. A breaking change for anyone using the generated models. Flag it explicitly to the user before proceeding. Do not silently absorb it into the commit.
  • Enum members that collapse to aliases of a same-valued member (Python StrEnum behavior when two members share a value). Before flagging this as a bug, check whether HA core's own source does the same thing: grep the corresponding ~/source/core file for EnumWithDeprecatedMembers or a comment marking the older member deprecated. If HA's own enum already collapses the same way, hassette's codegen is faithfully reproducing upstream, not introducing a defect.

Example from the 2026.7.1 to 2026.8.0 bump: a new radon device class, new Bq/m³/pCi/L units, and a new ButtonEventType enum were all additive. A climate.py change that looked like a broken enum (TARGET_TEMPERATURE/TEMPERATURE sharing a value) turned out to mirror HA's own deprecation pattern once checked against ~/source/core. Also safe to commit as-is.

Phase 4: Test and lint

HA_CORE_PATH=~/source/core uv run pytest codegen/tests -q --rootdir=codegen \
  && ptest uv run nox -s dev \
  && prek -a \
  && prek pyright -a --stage pre-push

(ptest per feedback_use-ptest-for-local-tests memory: bare pytest/nox invocations over roughly 10 CPU-minutes get killed by the orphan-test reaper on this machine.)

Stop here if any command fails. Do not proceed to Phase 5 or 6 on a red suite — fix the failure or report it to the user and end the run. A generated-model change that breaks tests is exactly the case this skill exists to catch before it ships.

This gate skips the system tests; CI runs them on push. tests/system/test_hass_hassette.py loads the pinned hass-hassette release into the new HA image there. If only that test fails, the integration needs a release that supports the new HA version. Report that rather than holding the bump.

Phase 5: Read the developer blog

Find the date of the last version bump commit (git log --follow -1 --format=%aI -- codegen/ha-version.txt on the previous commit, or ask the user if unclear). Fetch https://developers.home-assistant.io/blog and read every post published since that date, not just titles. For each post, judge relevance against what hassette actually touches: entity/state models, the WebSocket/REST API, the codegen extraction logic. Most HA blog posts are integration-specific or frontend-specific and don't apply. Two patterns are worth checking directly against src/hassette/ before dismissing a post:

  • A property/attribute rename or deprecation on a domain hassette generates models for. Check whether codegen already picked up the new shape (Phase 3's diff) or whether the old name is hardcoded somewhere in src/hassette/ outside codegen output.
  • A deprecated API hassette's hand-written code calls directly (grep -rn <name> src/hassette/). Codegen regenerating models doesn't fix a hand-written call site.

Report what you read and why each post does or doesn't need action. "Read N posts, none applicable" is a valid, expected outcome most months.

Phase 6: Review gate and commit

Run the mine-review skill on the working-tree diff before committing. This is a real commit to a shared branch, not a throwaway change, so it gets the same code-reviewer, integration-reviewer, and wtf-reviewer pass as any other commit (git-workflow.md — Mandatory Code Review Before Commit). Verify any flagged enum/alias finding against the upstream HA source per Phase 3 before accepting it.

Present a summary: version old to new, which files changed, test/lint results, blog findings, review findings.

Unattended invocation. This skill is also invoked from an external automated pipeline (hassette-autofix) whose fix session picks up the size:small tracking issues that ha-version-drift.yml files. That pipeline runs with no human present to answer a question, and its invoking prompt explicitly disallows AskUserQuestion. Either of these is sufficient on its own to put you in this mode, not a primary check with a fallback: the invoking prompt telling you this is a one-shot, non-interactive invocation, or AskUserQuestion simply not being in your available tools.

In that mode: if Phase 3 or Phase 5 flagged something needing a human call (a breaking change, or any other judgment item), there is no one to consult — stop and report it now instead of committing, the same way Phase 1's year-rollover check and Phase 2's dirty-checkout check already do for their own gates. Otherwise, treat a clean review as an implicit "yes, commit": skip straight to committing, using the summary presented above.

Otherwise (a human is running this interactively), gate on confirmation — this applies even when Phase 3 or Phase 5 flagged something, since the summary above already surfaces it and the human can decide in the moment:

AskUserQuestion:
  question: "Bump reviewed and clean — commit it?"
  header: "Commit"
  multiSelect: false
  options:
    - label: "Commit"
      description: "Stage the pin + regenerated files and commit with the summary above"
    - label: "Hold off"
      description: "Leave the changes uncommitted for further review"

Commit type is chore (codegen output isn't user-facing until it ships in a release) unless a breaking change was found, in which case use fix!/feat! per changelog-quality.md and get explicit user sign-off on the BREAKING CHANGE: footer wording.

Design decisions

Why check the blog manually instead of trusting codegen's diff to catch everything? Codegen only sees what's in ~/source/core's Python source. Deprecations, migration timelines, and "this will break in HA 2027.X" warnings live in prose, not in a diff a generator can produce.

Why does this skill own the compose-file image tags instead of Renovate? The first run (2026-08-06) hand-edited both compose files in the same commit as the codegen pin. A review pass flagged that as duplicating a Renovate rule that already bumped the same tags weekly — so the skill was changed to defer to Renovate instead. In practice, Renovate's weekly PR for this one package went unreviewed; entity-model changes almost never land in HA patch releases, so there was no forcing function to look at it between monthly bumps. Renovate is now explicitly disabled for homeassistant/home-assistant (renovate.json) and this skill is the sole place the tags move, in lockstep with the codegen pin they're meant to track.

Why verify enum-alias findings against upstream before accepting them? This is a recurring false-positive pattern for this specific codegen pipeline: a code reviewer sees two StrEnum members with the same value and calls it a bug, when it's actually hassette faithfully mirroring a deprecation pattern HA core already uses. Confirmed 2026-08-06 against homeassistant/helpers/deprecation.py's EnumWithDeprecatedMembers metaclass and climate/const.py's TARGET_TEMPERATURE/TEMPERATURE pair. Worth checking every time this shape recurs instead of re-deriving it from scratch.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.