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
|
## 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)
|
- Pushes to `master` on [Gitea](https://git.notexpectedyet.com/notexpectedyet/ha-nvidia-shield)
|
||||||
run the release workflow (`.github/workflows/release.yml`):
|
run the release workflow (`.gitea/workflows/release.yml`):
|
||||||
- A plain push publishes the current day's release (same-day pushes are deduped).
|
- A plain push publishes today's release. If that date is already tagged it takes
|
||||||
- Bumping `version` in `custom_components/nvidia_shield/manifest.json` forces that
|
the lowest free `.N`, so a gap left by an earlier failure is reused rather than
|
||||||
specific version's release before the date fallback kicks in.
|
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
|
- Releases land on Gitea with the tag and a `nvidia_shield.zip` asset for manual
|
||||||
installs. (No automatic mirroring — see the HACS note below.)
|
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
|
transport on or off
|
||||||
- **Shield address / ADB port** — the Shield's IP, and the ADB port if you
|
- **Shield address / ADB port** — the Shield's IP, and the ADB port if you
|
||||||
changed it from 5555
|
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
|
## Entities
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user