Skip to content

feat(chairlift): add wallpaper slideshow and video wallpaper brew bundles - #1185

Merged
hanthor merged 4 commits into
projectbluefin:mainfrom
sramkrishna:feat/chairlift-wallpaper-bundles
Sep 26, 2026
Merged

hanthor merged 4 commits into
projectbluefin:mainfrom
sramkrishna:feat/chairlift-wallpaper-bundles

Conversation

@sramkrishna

Copy link
Copy Markdown
Contributor

Closes #1159.

ChairLift's applications_page.brew_bundles_group in
/usr/share/chairlift/config.yml already points bundles_paths at
/usr/share/ublue-os/homebrew and renders one installable bundle per
immediate *.Brewfile child, naming the bundle after the filename stem.
So exposing the two wallpaper apps is a matter of placing files in that
directory — no config.yml change, which is deliberate: ChairLift fails
closed on an unknown page, group, or field key and disables the whole
application, so no new group was invented.

Changes

Path Change
system_files/shared/usr/share/ublue-os/homebrew/wallpaper-slideshow.Brewfile new — flatpak "app.drey.Damask"
system_files/shared/usr/share/ublue-os/homebrew/video-wallpaper.Brewfile new — flatpak "io.github.jeffshee.Hidamari"
tests/test_chairlift_config.py 3 regression tests
docs/skills/brew-lifecycle/references/package-set.md documents the second consumer of the directory
docs/skills/brew-lifecycle/SKILL.md red flag + references row; last_updated bumped
docs/skills/index.json, docs/skills/index.md regenerated by scripts/generate_skill_index.py --write

Both files live in system_files/shared/ (all variants — bluefin,
bluefin-lts, dakota) and are mode 0644, matching every sibling Brewfile.
Both are direct children of the scan root with the exact .Brewfile suffix:
ChairLift does not recurse, so a file in a subdirectory would be silently
absent from the Applications page rather than an error.

Two deliberate constraints, both now documented in the skill:

  • Install only. Uninstall is ChairLift's flatpak_user_group /
    flatpak_system_group. A bundle has no uninstall action, and expressing
    one by inventing a group would trip the strict schema.
  • flatpak "..." is an opt-in Bluefin convention, not stock Homebrew
    Bundle. validate-brewfiles.sh and brew bundle both ignore it, so a
    flatpak-only Brewfile passes the Brewfile gate with zero package checks.
    Unit tests — not the validator — are what pin the app ids here.

Verification

Run locally in the worktree, all green:

  • python3 -m pytest tests/test_chairlift_config.py tests/test_skill_docs.py -q → 42 passed
  • npx --yes bats tests/test_native_recipes.bats → all ok (through ok 22)
  • npx --yes bats tests/test_validate_brewfiles.bats tests/test_suite_registration.bats → all ok
  • PATH="$HOME/.local/bin:$PATH" pre-commit run --all-files → all hooks passed, including "Validate docs/skills/index.json is up to date"
  • python3 scripts/generate_skill_index.py --check → up to date
  • just check → exit 0

Not run locally: bash scripts/validate-brewfiles.sh. The script requires
a brew binary on PATH and exits 2 with "Homebrew is required to validate
Brewfiles."
in this environment. Its CI counterpart
(.github/workflows/validate-brewfiles.yaml) triggers on
system_files/shared/usr/share/ublue-os/homebrew/** and will run on this PR;
given the files contain only comment lines and flatpak declarations, it
should report zero package checks for both. Flagging this rather than
claiming it was run.

The three new tests in tests/test_chairlift_config.py assert that
bundles_paths still resolves to the directory the files live in, that each
expected bundle is a 0644 regular file directly in that directory, that each
contains exactly its intended flatpak declaration, and that the bundle
names are unique. No new test file was added — tests/test_suite_registration.bats
enforces that every suite in tests/ is registered in the Justfile, so new
assertions belong in the existing file.

— hive: backend=litellm model=deepseek/deepseek-v4.1-flash

🐝 Hive Agent: contributor | SHA: c47b3c2

@castrojo
castrojo force-pushed the feat/chairlift-wallpaper-bundles branch from c47b3c2 to dc19001 Compare September 24, 2026 17:57
@castrojo

Copy link
Copy Markdown
Contributor

Rebased cleanly onto latest main.

  • Conflicts resolved: docs/skills/index.json and docs/skills/index.md regenerated via scripts/generate_skill_index.py. Clean automerge of tests/test_chairlift_config.py and docs/skills/brew-lifecycle/SKILL.md.
  • Tests run: pytest tests/test_chairlift_config.py (31 passed), just check.

sramkrishna and others added 2 commits September 25, 2026 01:14
…dles

ChairLift's `applications_page.brew_bundles_group` scans immediate
`*.Brewfile` children of `/usr/share/ublue-os/homebrew` and renders each as
an installable bundle, so a file dropped in that directory reaches the
Applications page with no further wiring.

Add two opt-in bundles:

- `wallpaper-slideshow.Brewfile` — `flatpak "app.drey.Damask"`
- `video-wallpaper.Brewfile` — `flatpak "io.github.jeffshee.Hidamari"`

Both are direct children of the scan root with the exact `.Brewfile`
suffix, since ChairLift does not recurse and a misplaced file is silently
absent from the UI. The bundle covers install only; uninstall stays with
ChairLift's `flatpak_user_group` / `flatpak_system_group`, and no new group
key was added because an unknown key fails ChairLift's strict schema
validation and disables the whole application.

`flatpak "..."` is a Bluefin convention that `validate-brewfiles.sh` and
`brew bundle` both ignore, so `tests/test_chairlift_config.py` gains three
tests pinning the app ids, the 0644 mode, and bundle-name uniqueness — the
Brewfile validator alone would pass with zero package checks.

The brew-lifecycle skill documents the second consumer of that directory
and the non-recursive requirement; `docs/skills/index.*` is regenerated.

Assisted-by: Claude via Claude Code
Co-authored-by: Claude <noreply@anthropic.com>
Hive-Run: projectbluefin#1159
Hive-Plan: projectbluefin#1159 implementation steps 1-3
Hive-Spec: projectbluefin#1159#testing-and-verification
Signed-off-by: sramkrishna <sramkrishna@users.noreply.github.com>
@castrojo
castrojo force-pushed the feat/chairlift-wallpaper-bundles branch from dc19001 to de7c2af Compare September 25, 2026 05:15
@castrojo

Copy link
Copy Markdown
Contributor

Rebased onto latest main (clearing upstream Homebrew tremor-runtime check failure from #1206) and added missing trailing newlines to video-wallpaper.Brewfile and wallpaper-slideshow.Brewfile to pass pre-commit end-of-file-fixer. Ran pytest tests/test_chairlift_config.py (31 passed).

@Danathar

Copy link
Copy Markdown
Contributor

The two Brewfiles look right. brew bundle check reads both and asks for the Damask and Hidamari flatpaks, and CI is green on de7c2af. I found two problems, one in the tests and one in the docs, that I'd like fixed before I approve.

1. An existing test got deleted by accident. On main, tests/test_chairlift_config.py has def test_help_links_point_at_bluefin():. This PR replaces that line with the new tests. The old test's body is now stuck on the end of test_bundle_names_do_not_collide_with_other_discovered_brewfiles(). The help-link checks still run, but if one fails, the report will say bundle names collide. You can see it in the counts: main has 29 tests in that file and this branch has 31 (3 added, 1 gone). Putting the def test_help_links_point_at_bluefin(): line back above resources = _load_config()["help_page"]... fixes it.

2. The docs say brew bundle ignores flatpak lines, and it doesn't. Homebrew Bundle installs flatpak "..." entries, and ChairLift installs a bundle by running brew bundle install --file=.... That is the only reason these two bundles install anything. With the Brewfile from this branch (Homebrew 7.0.6):

$ brew bundle check --file=.../wallpaper-slideshow.Brewfile --verbose
→ Flatpak app.drey.Damask needs to be installed.

What is true is that our scripts/validate-brewfiles.sh skips them, because it only checks brew and cask lines. Could the paragraph in package-set.md (and the PR description) say just that? Something like: "CI's Brewfile validator skips flatpak lines, so the unit tests are what pin these app ids."

Two smaller things, not blockers:

  • ChairLift won't show either file's comment. Current ChairLift joins all the leading # lines into one description, and drops it when it contains words like ujust or flatpak (the jargonMarkers list in chairlift's internal/views/bundleview/bundleview.go). Both files mention ujust bbrew, so both rows get the generic "A set of apps and tools put together for this system." A single plain sentence as the only leading comment, like "Damask cycles your desktop background through a folder or a featured set.", would show up as written.
  • The 0o644 check reads the mode of the checked-out file. That depends on the umask of whoever cloned the repo, because git only records 644 vs 755. I made a worktree with umask 002: the file came out 664 and test_bundle_brewfiles_are_discoverable_by_chairlift failed, even though nothing is wrong.

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bundles look reasonable, but there's a test regression to fix first:

  • tests/test_chairlift_config.py: the hunk replaces the def test_help_links_point_at_bluefin(): header with the new tests, so the old body (resources = _load_config()["help_page"]...) now runs as the tail of test_bundle_names_do_not_collide_with_other_discovered_brewfiles. Please restore the original function header so that test runs on its own again.
  • test_bundle_names_do_not_collide_with_other_discovered_brewfiles can't fail as written, because stems from a single glob over one directory are always unique. I'd drop it, or make it compare against the other bundle directories.
  • Placement: the Brewfiles live in shared/, so LTS and Dakota get them, while #1186 and #1187 configure Damask only under bluefin/. Please confirm that split is intended.

…docs

- restore separate def test_help_links_point_at_bluefin() function header
- clarify that CI's Brewfile validator skips flatpak lines (rather than brew bundle)
- relax file mode check to assert world-readability without brittle umask dependence
@castrojo

Copy link
Copy Markdown
Contributor

@Danathar @hanthor Addressed both review comments in commit 4e616cc:

  1. Restored def test_help_links_point_at_bluefin(): as an independent test function so its assertions are isolated from bundle-stem collision checks (32 passed in tests/test_chairlift_config.py).
  2. Corrected docs in package-set.md to clarify that it is CI's validate-brewfiles.sh validator that skips flatpak declarations, not brew bundle.
  3. Relaxed the permissions assertion to verify world-readability without brittleness to umask.

Awaiting re-review and secondary approval per the 2-reviewer requirement.

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. test_help_links_point_at_bluefin is its own test again (tests/test_chairlift_config.py:595), and the permission and docs tweaks are fine. Two small items left:

  • tests/test_chairlift_config.py:589-592: test_bundle_names_do_not_collide_with_other_discovered_brewfiles still can't fail, because stems from one glob in one directory are always unique. Please drop it or compare against the other bundle directories.
  • Placement: the Brewfiles are in system_files/shared/, so LTS and Dakota get them, while #1186 and #1187 wire up Damask only under bluefin/. Please confirm that's intended, or move them to bluefin/.

…ctories

Compare bundle stems across both system_files/shared and system_files/bluefin
homebrew directories to ensure no duplicate stems exist.
@castrojo

Copy link
Copy Markdown
Contributor

@hanthor Addressed feedback in commit 1f0e229:

  1. Updated test_bundle_names_do_not_collide_with_other_discovered_brewfiles to scan and compare bundle stems across all discoverable homebrew directories (system_files/**/usr/share/ublue-os/homebrew/*.Brewfile).
  2. Placement: Keeping the wallpaper bundles in shared/ is intended so that downstream LTS and Dakota images have access to the opt-in ChairLift bundles even if GNOME-specific setup hooks (feat(wallpaper): add Damask first-run setup hook and non-destructive defaults #1186, feat(damask): ship flatpak overrides and background systemd service #1187) remain scoped to Bluefin.

All 32 tests in test_chairlift_config.py pass. Ready for re-review.

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. test_bundle_names_do_not_collide_with_other_discovered_brewfiles now globs system_files/**/usr/share/ublue-os/homebrew/*.Brewfile, so it compares stems across shared/ and bluefin/ and can actually fail. Keeping the bundles in shared/ so LTS and Dakota get the opt-in bundles is fine with me. CI is green.

@hanthor
hanthor added this pull request to the merge queue Sep 26, 2026
Merged via the queue into projectbluefin:main with commit 64ae39c Sep 26, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ChairLift: Add Brewfile bundles for Wallpaper Slideshow and Video Wallpaper

4 participants