The branch was 12 commits behind dev and GitHub reported it CONFLICTING, which is
why the real CI workflow had not run since 2026-08-10 - a conflicting PR has no
mergeable ref, so pull_request-triggered workflows are skipped. Only the
lightweight checks (semantic title, CodeQL, CodeRabbit) were still reporting,
which made the PR look green while nothing was actually being tested.
Three conflicts, all of them this branch's barrel-diet work meeting dev's new
What's Up Docker integration. In every case the branch's structure is kept and
WUD is absorbed into it rather than the reverse:
integrations/base/creator.ts keep the lazy loader map; add wud as
() => import(...) rather than dev's static import,
which would have undone the lazy creator
integrations/src/index.ts keep the slim barrel; re-export WudStats and
WudContainerUpdate as `export type`, which is
erased at build and so adds no runtime module
widgets/src/index.tsx stays deleted - this was the barrel that put
every widget in the initial client graph
Registering WUD in the slimmed structures then needed three more entries that the
merge could not infer: base/kind-map.ts (type-only kind -> class map),
widgets/src/import.ts (type-only WidgetImports map, both the import and the
member). Each was found by typecheck rather than guessed at.
Verified: 37/37 packages typecheck, 1866/1881 unit tests pass. The 3 failures are
home-assistant and pi-hole, both testcontainers-based; both pass 11/11 in
isolation and fail only under 150-file parallel load with the container's payload
half-initialised.
93 lines
3.1 KiB
Bash
93 lines
3.1 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Create sub directories in volume
|
|
mkdir -p /appdata/db
|
|
mkdir -p /appdata/redis
|
|
mkdir -p /appdata/trusted-certificates
|
|
|
|
# Run migrations
|
|
# --max-old-space-size bounds the old generation; without it V8 sizes the heap from
|
|
# the *host's* RAM, so a big host lets RSS drift for a long time before collecting.
|
|
# --max-semi-space-size bounds the young generation, which V8 also sizes generously
|
|
# by default (16 MB per semi-space). Measured on a restored 28-widget board: 4 MB cut
|
|
# idle anonymous memory ~19% and peak ~21% for ~8% more CPU, with no board-load
|
|
# latency regression. Both are overridable for hosts that want to trade back.
|
|
export NODE_OPTIONS="--max-old-space-size=${HOMARR_MAX_OLD_SPACE_SIZE:-512} --max-semi-space-size=${HOMARR_MAX_SEMI_SPACE_SIZE:-4} ${NODE_OPTIONS}"
|
|
if [ "$DB_MIGRATIONS_DISABLED" = "true" ]; then
|
|
echo "DB migrations are disabled, skipping"
|
|
else
|
|
echo "Running DB migrations"
|
|
DISABLE_REDIS_LOGS=true node ./db/migrations/$DB_DIALECT/migrate.cjs ./db/migrations/$DB_DIALECT
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: DB migrations failed, aborting startup"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Auth secret is generated every time the container starts as it is required, but not used because we don't need JWTs or Mail hashing
|
|
export AUTH_SECRET=$(openssl rand -base64 32)
|
|
|
|
# Start nginx proxy
|
|
# 1. Replace the HOSTNAME in the nginx template file
|
|
# 2. Create the nginx configuration file from the template
|
|
# 3. Start the nginx server
|
|
# Only listen on IPv6 when the host actually has IPv6 configured (#4596).
|
|
# Otherwise nginx aborts with "socket() [::]:7575 failed (97: Address family
|
|
# not supported by protocol)". Check HOMARR_DISABLE_IPV6 first so users can
|
|
# force IPv4-only even when the host supports IPv6, then probe for IPv6
|
|
# addresses via grep (not -s: proc files always report size 0).
|
|
export HOSTNAME
|
|
export NGINX_LISTEN_IPV6=''
|
|
if [ "${HOMARR_DISABLE_IPV6:-false}" != "true" ] && grep -q . /proc/net/if_inet6 2>/dev/null; then
|
|
NGINX_LISTEN_IPV6='listen [::]:7575;'
|
|
fi
|
|
envsubst '${HOSTNAME} ${NGINX_LISTEN_IPV6}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf
|
|
# Start services in the background and store their PIDs
|
|
nginx -g 'daemon off;' &
|
|
NGINX_PID=$!
|
|
|
|
if [ "$REDIS_IS_EXTERNAL" = "true" ]; then
|
|
echo "Using external Redis server at redis://$REDIS_HOST:$REDIS_PORT"
|
|
REDIS_PID=""
|
|
else
|
|
echo "Starting internal Redis server"
|
|
redis-server /app/redis.conf &
|
|
REDIS_PID=$!
|
|
fi
|
|
|
|
SHUTTING_DOWN=false
|
|
|
|
terminate() {
|
|
SHUTTING_DOWN=true
|
|
echo "Shutting down..."
|
|
kill -TERM $NEXTJS_PID 2>/dev/null
|
|
wait $NEXTJS_PID 2>/dev/null
|
|
kill -TERM $NGINX_PID 2>/dev/null
|
|
wait $NGINX_PID 2>/dev/null
|
|
if [ -n "$REDIS_PID" ]; then
|
|
kill -TERM $REDIS_PID 2>/dev/null
|
|
wait $REDIS_PID 2>/dev/null
|
|
fi
|
|
echo "Shutdown complete."
|
|
exit 0
|
|
}
|
|
|
|
trap terminate TERM INT
|
|
|
|
node apps/nextjs/server.js &
|
|
NEXTJS_PID=$!
|
|
|
|
while true; do
|
|
wait $NEXTJS_PID
|
|
EXIT_CODE=$?
|
|
|
|
if [ "$SHUTTING_DOWN" = true ]; then
|
|
break
|
|
fi
|
|
|
|
echo "Next.js exited with code $EXIT_CODE, restarting in 1s..."
|
|
sleep 1
|
|
node apps/nextjs/server.js &
|
|
NEXTJS_PID=$!
|
|
done
|