Test what cont-init turns options.json into - #583
Open
MaxWinterstein wants to merge 2 commits into
Open
Conversation
Home Assistant only allows two levels of nesting in add-on options, so config.yaml flattens intense_fetch into two sibling keys and cont-init uses jq to fold them back into the nested shape the bridge reads. Nothing checked that, and it is the kind of transform that breaks quietly: jq's += writes null for a key that is not there rather than failing, so the bridge starts with a broken intense_fetch. The test runs the real cont-init inside the built image against a synthetic /data/options.json and asserts the result, including that a config missing those keys yields nulls. That second case is why DOCS.md has to keep listing them. Invoking bashio as the interpreter rather than running the script directly skips the with-contenv dependency on s6's container_environment, which does not exist outside a real Supervisor. Nothing here needs the Supervisor API: this add-on's cont-init only uses bashio::log.* and bashio::fs.file_exists. The job discovers add-ons by looking for test/*.test.sh, so adding a test elsewhere needs no workflow change. It is a separate job rather than a step in check-build because that job only runs for add-ons whose config.* changed, so a test-only or rootfs-only change would never run its own test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
|
Warning Review limit reachedNext included review available in 21 minutes. View limit detailsLimit details: You’ve used all 2 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The typos hook rewrote all 13 to io.hash while this branch was being prepared. Those are the labels Supervisor reads. #585 pins the word so it cannot happen again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first test in this repo that actually runs an add-on. Everything until now built images and never started one.
What it covers
Home Assistant only allows two levels of nesting in add-on options, so
config.yamlflattensintense_fetchinto two sibling keys andcont-initusesjqto fold them back into the nested shape the bridge reads:jq ".tgtg += { intense_fetch: { interval: .tgtg.intense_fetch_interval, period_of_time: .tgtg.intense_fetch_period_of_time}}"Nothing checked that, and it is exactly the kind of transform that breaks quietly.
jq's+=writesnullfor a key that isn't there rather than failing, so the bridge starts with a brokenintense_fetchand you find out from an issue report.The test runs the real
cont-initinside the freshly built image against a synthetic/data/options.jsonand asserts the output — including the negative case, that a config missing those keys yields nulls. That second assertion is the machine-readable reasonDOCS.mdhas to keep listing them (which is what #576 fixed).Two implementation notes worth reviewing
No mock Supervisor is needed here, and I checked rather than assumed.
bashio::configreads options from the Supervisor REST API, not from/data/options.json, so a naivedocker run -v options.json:/data/options.jsonproves nothing for most add-ons. This one is the exception: its cont-init only callsbashio::log.*andbashio::fs.file_exists, neither of which touches the API. Add-ons that do callbashio::configwill need a small mock sidecar.bashio is invoked as the interpreter rather than running the script directly:
The script's shebang is
#!/usr/bin/with-contenv bashio, andwith-contenvneeds s6's/run/s6/container_environment, which doesn't exist outside a real Supervisor. Going throughbashiodirectly works because its runner isBASH_ARGV0=${1:?}; shift; source "$0" "$@".Wiring
addon-testsdiscovers participants by globbing*/test/*.test.sh, so adding a test to another add-on needs no workflow edit. planefence already has atest/options.jsonand is correctly not picked up.It is a separate job, not a step inside
check-build, becausecheck-buildonly runs for add-ons whoseconfig.*changed — so a test-only orrootfs/-only change would never run its own test. That is the same class of bug as #579.Honest caveat
I can't run Docker in my environment, so this PR's CI run is the first real execution of this test. If it's red, that's me iterating, not the add-on being broken — I'll fix it from the logs. The shell itself is shellcheck-clean and the discovery logic I did verify locally.
🤖 Generated with Claude Code