mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-08-27 23:33:31 +02:00
* refactor(webtop,webtop_kde,claude_desktop): share the Selkies startup scripts All three add-ons are built on the LinuxServer Selkies base image and had independently drifted copies of the same startup scripts. claude_desktop's copies carry a set of fixes the two webtops never received, so make claude_desktop the single source and symlink the shared scripts from webtop_kde/rootfs (which webtop/rootfs already symlinks in full). Shared by symlink: 20-folders.sh, 21-gpu_permissions.sh, 80-configuration.sh, 90-ingress.sh and the six etc/nginx/includes files. Kept add-on specific: everything Claude-only stays in claude_desktop (81/82/83/84 tool installs, 85-openbox_autostart.sh, defaults/, usr/local/bin, svc-headroom), and everything webtop-only stays in webtop_kde (90-ssl.sh, helpers/microsoft-edge-stable, and the new 81-microsoft_edge.sh). To make the shared scripts add-on agnostic: - 20-folders.sh derives its default data location from the home directory the Dockerfile baked into the abc user instead of hardcoding /data/data. That yields /data/data on claude_desktop and /config/data_kde on both webtops, matching each add-on's previous behaviour exactly. - The permission_mode: bypass root guard is skipped on add-ons that do not declare that option. - 80-configuration.sh falls back to pip when the image does not ship uv. - The Microsoft Edge install moves out of 80-configuration.sh into a webtop-only 81-microsoft_edge.sh, which also absorbs the ownership fixup that used to run in 20-folders.sh before Edge was installed and so never matched anything. CI: the builder's symlink-resolution step made a single pass over a pre-computed file list, so resolving webtop/rootfs (a directory symlink) could copy the symlinks inside it verbatim, leaving links that escape the webtop build context. Verified on this tree: the old loop leaves 10 dangling symlinks under webtop/. Extract it to .github/scripts/resolve_symlinks.sh, repeat until a pass finds nothing, and run it in the PR check too, which had no resolution step at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: guard two startup aborts found in review Both are crash paths in code added by this PR, not hardening: - 20-folders.sh: getent exits 2 when the user does not exist, and under bashio's `set -o pipefail` plus the script's `set -e` that aborts at the assignment, so the "could not read abc's home" fallback below it was unreachable. Same trap already documented in 21-gpu_permissions.sh. Verified: without the guard the shell exits 2; with it the fallback runs. - 81-microsoft_edge.sh: the ownership fixup lost the `-f` guard the original had in 20-folders.sh. Without nullglob an unmatched /usr/bin/microsoft-edge* reaches chown as a literal and `set -e` kills container startup. Now a nullglob array with a warning when empty. Also make resolve_symlinks.sh fail on a broken symlink instead of deleting it. Dropping it silently yields an image that builds clean and misbehaves at runtime; a red build is easier to diagnose. Verified both paths: the repo as-is resolves to 0 symlinks and exit 0, and an injected broken link exits 1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: address review comments on data-location default and Edge downloads Two findings from CodeRabbit, both correctness rather than hardening: - 20-folders.sh rewrites abc's home in /etc/passwd further down, so re-reading it on the next boot returned the *previously selected* location as the image default. On a restart that reuses the container's writable layer, clearing data_location would strand the user on their old custom path instead of restoring the built-in one. Cache the value in /etc/.addon_image_home, which shares the writable layer's lifetime with the edit it compensates for: a rebuilt or recreated container starts from a pristine /etc/passwd and regenerates it. Simulated all three cases (first boot, reused container with a rewritten passwd, recreated container) under `set -e` + `set -o pipefail`. - 81-microsoft_edge.sh: both curl calls were unbounded, so a stalled packages.microsoft.com would hang cont-init.d and with it the whole add-on. Add --fail/--connect-timeout/--max-time and skip the install with a logged error when version discovery or the download fails. The desktop is useful without Edge; an add-on wedged before Selkies starts is not. Not addressed, deliberately: escaping $LOCATION/$DEFAULT_LOCATION for sed, and validating symlink targets in resolve_symlinks.sh. Both are hardening against inputs that are not reachable in normal use, both predate this PR, and the maintainer has asked to prioritise usability over that class of change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
46 lines
1.7 KiB
Bash
Executable File
46 lines
1.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Replace every symlink in the checked-out repository with a real copy of its target.
|
|
#
|
|
# Add-ons share files by symlinking across add-on directories (e.g. webtop/rootfs ->
|
|
# ../webtop_kde/rootfs, and files inside it -> ../../../../claude_desktop/rootfs/...). A
|
|
# Docker build context is a single add-on directory, so any symlink that escapes it has to be
|
|
# materialised before the build.
|
|
#
|
|
# The loop repeats because resolving one symlink can create others: copying a directory
|
|
# symlink with `cp -a` preserves the symlinks *inside* it, and those copies are not part of
|
|
# the file list the current pass is iterating over. Repeating until a pass finds nothing makes
|
|
# the result independent of the order `find` happens to return.
|
|
set -euo pipefail
|
|
|
|
for _ in 1 2 3 4 5; do
|
|
mapfile -t links < <(find . -type l)
|
|
if [ "${#links[@]}" -eq 0 ]; then
|
|
exit 0
|
|
fi
|
|
|
|
for link in "${links[@]}"; do
|
|
target=$(readlink -f "$link" || true)
|
|
if [ -z "$target" ] || [ ! -e "$target" ]; then
|
|
# Fail rather than drop it. A broken link here means an add-on is missing a file
|
|
# it expects to ship; silently removing it produces an image that builds fine and
|
|
# misbehaves at runtime, which is far harder to diagnose than a red build.
|
|
echo "::error::Broken symlink: $link -> $(readlink "$link")"
|
|
exit 1
|
|
fi
|
|
|
|
rm "$link"
|
|
if [ -d "$target" ]; then
|
|
mkdir -p "$link"
|
|
cp -a "$target/." "$link/"
|
|
else
|
|
cp "$target" "$link"
|
|
fi
|
|
done
|
|
done
|
|
|
|
if [ -n "$(find . -type l)" ]; then
|
|
echo "::error::Symlinks still present after 5 resolution passes; possible symlink cycle"
|
|
find . -type l
|
|
exit 1
|
|
fi
|