docs(readme): the release write-back and the command scripts (t44 3, R2)
Releases: the section described the manifest/date fallback only, and pointed at `.github/workflows/release.yml`, which does not exist. It now covers the same-day `vYYYY.MM.DD.N` suffix (lowest free N, gaps reused), the manifest write-back commit and WHY it exists (HACS compares against the default-branch manifest, so a tag-only release is offered to nobody — v2026.10.09 shipped that way), what `[skip ci]` means and what it does not (release commits only; Gitea's own handling can still skip an ordinary commit whose body mentions the marker), the refusal to publish when the default branch disagrees, and the branch-protection failure path. t44 R2, both halves of the tag's identity: with a write-back the tag names the bot commit, so `git describe --tags` on a developer commit reports the previous release (expected, not a missing tag); hand-bumping the manifest keeps the tag on the developer's own commit, because the workflow then has nothing to write back. Command scripts: a new section under Options, with the command/variable table (`level` for volume_set, `is_volume_muted` for volume_mute, `app_name` for select_source), the "instead of, never both" rule, the fact that an unset selector means the native path, and a copy-pasteable script block covering the three cases the user asked for — a speaker switch owning the volume, an AVR owning the input, a mute that hits the switch too. It says plainly that scripts are set on the Configure page and not in the YAML seed, which stays address + transport only (the seed example is unchanged and still the only `nvidia_shield:` block). Verified: 414 passed / 2 skipped, 415 / 1 with androidtvremote2, test_config_flow_ux 61, test_standalone_setup + test_config_flow_protocol 58, ruff clean, drift engine exit 0 under real HA, and every fenced YAML block in the README parses with pyyaml.
This commit is contained in:
1 parent
b03cfbae13
commit
0cfa045190
1 file changed
+94
-5
@@ -188,12 +188,34 @@ full retirement mapping this section summarises.
|
||||
|
||||
## Releases
|
||||
|
||||
- **Date-based versioning**: `vYYYY.MM.DD` (e.g. `v2026.10.08`).
|
||||
- **Date-based versioning**: `vYYYY.MM.DD`, and `vYYYY.MM.DD.N` (N from 2) for a
|
||||
second release in the same UTC day.
|
||||
- Pushes to `master` on [Gitea](https://git.notexpectedyet.com/notexpectedyet/ha-nvidia-shield)
|
||||
run the release workflow (`.github/workflows/release.yml`):
|
||||
- A plain push publishes the current day's release (same-day pushes are deduped).
|
||||
- Bumping `version` in `custom_components/nvidia_shield/manifest.json` forces that
|
||||
specific version's release before the date fallback kicks in.
|
||||
run the release workflow (`.gitea/workflows/release.yml`):
|
||||
- A plain push publishes today's release. If that date is already tagged it takes
|
||||
the lowest free `.N`, so a gap left by an earlier failure is reused rather than
|
||||
skipped.
|
||||
- Setting `version` in `custom_components/nvidia_shield/manifest.json` to an
|
||||
untagged value releases exactly that version instead.
|
||||
- **The release commit.** When the resolved version differs from the manifest, the
|
||||
workflow writes it back, commits `chore(release): v<VERSION> [skip ci]`, pushes it
|
||||
to `master`, and tags *that* commit. It has to do this: HACS compares the installed
|
||||
version against the manifest on the default branch, so a release that only ever
|
||||
existed as a tag is offered to nobody (v2026.10.09 shipped that way).
|
||||
- Because the tag names the bot commit, `git describe --tags` on a *developer*
|
||||
commit reports the **previous** release. That is expected, not a missing tag.
|
||||
- Bump it by hand instead and the tag lands on your own commit: set `version` in
|
||||
the manifest, commit, push. The workflow then has nothing to write back (it sees
|
||||
an untagged manifest version and tags your commit).
|
||||
- **`[skip ci]`**: the bot commit carries it, and the workflow's job additionally
|
||||
checks the commit *subject* (`chore(release): …`), so a write-back cannot start a
|
||||
second release. Both only recognise release commits — a normal commit whose message
|
||||
body merely mentions `[skip ci]` can still be skipped by Gitea's own handling, so
|
||||
keep the marker out of ordinary commit messages.
|
||||
- The workflow refuses to publish unless the default branch's manifest already carries
|
||||
the version it is about to tag, and fails loudly (with a "bump the manifest by hand"
|
||||
instruction and nothing tagged) if the write-back push is rejected, for example by
|
||||
branch protection.
|
||||
- Releases land on Gitea with the tag and a `nvidia_shield.zip` asset for manual
|
||||
installs. (No automatic mirroring — see the HACS note below.)
|
||||
|
||||
@@ -264,6 +286,73 @@ helper the flow calls is a coroutine and its dedup only runs when awaited.
|
||||
transport on or off
|
||||
- **Shield address / ADB port** — the Shield's IP, and the ADB port if you
|
||||
changed it from 5555
|
||||
- **Command scripts** — one optional script per command; see below
|
||||
|
||||
### Command scripts (per-command overrides)
|
||||
|
||||
Some commands need hardware this integration deliberately does not drive: a speaker
|
||||
switch that owns the volume, an AVR input that has to move with the Shield, a mute
|
||||
that has to hit two devices. For those, the Configure page takes a **script per
|
||||
command**:
|
||||
|
||||
| Command | Runs when | Variables passed |
|
||||
| --- | --- | --- |
|
||||
| `turn_on`, `turn_off` | turn on/off, from the media player *or* the remote | — |
|
||||
| `volume_up`, `volume_down` | volume step | — |
|
||||
| `volume_set` | absolute volume (there is no native path — the protocol has VOLUME_UP/DOWN/MUTE only) | `level` |
|
||||
| `volume_mute` | mute/unmute | `is_volume_muted` |
|
||||
| `select_source` | source selection (no native path) | `app_name` |
|
||||
|
||||
A command with a script calls the script **instead of** the protocol/ADB path, never
|
||||
both. Left unset — the default — every command behaves exactly as it did before, and
|
||||
clearing a selector on the Configure page restores that. `volume_set` and
|
||||
`select_source` only appear as services while their script is configured, because
|
||||
there is nothing native to fall back on.
|
||||
|
||||
The scripts are ordinary Home Assistant scripts. This block covers all three awkward
|
||||
cases: a speaker switch owning the volume, an AVR owning the input, and a mute that
|
||||
has to hit the switch as well.
|
||||
|
||||
```yaml
|
||||
script:
|
||||
shield_volume: # select as "Volume set script"
|
||||
alias: Shield volume (speaker switch)
|
||||
sequence:
|
||||
- action: media_player.volume_set
|
||||
target:
|
||||
entity_id: media_player.living_room_speaker
|
||||
data:
|
||||
volume_level: "{{ level }}"
|
||||
shield_source: # select as "Select source script"
|
||||
alias: Shield source (AVR)
|
||||
sequence:
|
||||
- action: media_player.select_source
|
||||
target:
|
||||
entity_id: media_player.avr
|
||||
data:
|
||||
source: "{{ app_name }}"
|
||||
shield_mute: # select as "Mute script"
|
||||
alias: Shield mute (speaker switch)
|
||||
sequence:
|
||||
- choose:
|
||||
- conditions: "{{ is_volume_muted }}"
|
||||
sequence:
|
||||
- action: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.living_room_speaker
|
||||
default:
|
||||
- action: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.living_room_speaker
|
||||
```
|
||||
|
||||
Then set `script.shield_volume` as **Volume set script**, `script.shield_source` as
|
||||
**Select source script** and so on on the Configure page. Scripts are set there, not
|
||||
in the YAML seed above — the seed only carries the address and the transport choice.
|
||||
|
||||
A script that fails surfaces as an error on the service call that triggered it (the
|
||||
command is not retried over protocol/ADB), because a silent no-op is the one outcome
|
||||
that leaves you guessing.
|
||||
|
||||
## Entities
|
||||
|
||||
|
||||
Reference in new issue
Block a user