Add prepare-compose.sh for composable docker-compose (#363)

* Add prepare-compose.sh for composible modules, options and overlays

* feat(prepare-compose): add --quiet and --skip-validation flags

Add loud() function for conditional output. Use --quiet to suppress
normal output, --skip-validation to bypass docker compose config check.

* chore: add mise config to gitignore

* chore: add GOCLAW_DIR env var and update context paths

- Add GOCLAW_DIR to prepare-compose.sh for .env generation
- Fix context paths in docker-compose files to use ${GOCLAW_DIR:-.}
- Restore symlinks in compose.d/ and compose.options/

* fix: broken symlink, safe .env update, export COMPOSE_FILE before validate

- Fix compose.d/00-goclaw.yml symlink: docker-compose.yml → ../docker-compose.yml
- Add compose.d/.gitkeep so directory is tracked
- Export COMPOSE_FILE before running docker compose config validation
- Replace rm+sed .env update pattern with safe temp file approach
- Quote GOCLAW_DIR value in .env to handle paths with spaces

---------

Co-authored-by: viettranx <viettranx@gmail.com>
This commit is contained in:
Keithandviettranx authored and GitHub committed 2026-03-30 08:02:57 +07:00
1 parent 23c227e18d
commit 172684a5a7
16 files changed
+111 -3

No files matched your search

+11
View File
@@ -77,3 +77,14 @@ goclaw.db-shm
# Auto-generated by Makefile (git describe)
VERSION
ui/desktop/frontend/dist/index.html
# Local compose modules
compose.d/*
!compose.d/.gitkeep
!compose.d/0*
# Mise-en-place
/.miserc.toml
/mise.*.toml
/mise
/.mise
View File
Whitespace-only changes.
+1
View File
@@ -0,0 +1 @@
../docker-compose.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.postgres.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.selfservice.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.upgrade.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.browser.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.otel.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.redis.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.sandbox.yml
+1
View File
@@ -0,0 +1 @@
../docker-compose.tailscale.yml
+1 -1
View File
@@ -9,7 +9,7 @@ services:
goclaw-ui:
image: ghcr.io/nextlevelbuilder/goclaw-web:latest
build:
context: ./ui/web
context: ${GOCLAW_DIR:-.}/ui/web
dockerfile: Dockerfile
ports:
- "${GOCLAW_UI_PORT:-3000}:80"
+1 -1
View File
@@ -16,7 +16,7 @@ services:
upgrade:
image: ghcr.io/nextlevelbuilder/goclaw:latest
build:
context: .
context: ${GOCLAW_DIR:-.}
dockerfile: Dockerfile
args:
ENABLE_OTEL: "false"
+1 -1
View File
@@ -17,7 +17,7 @@ services:
goclaw:
image: ghcr.io/nextlevelbuilder/goclaw:latest
build:
context: .
context: ${GOCLAW_DIR:-.}
dockerfile: Dockerfile
args:
ENABLE_OTEL: "${ENABLE_OTEL:-false}"
+12
View File
@@ -0,0 +1,12 @@
# Low CPU settings for postgres
services:
postgres:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
command:
- "postgres"
- "-c"
- "max_connections=10"
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Generates COMPOSE_FILE from compose.d/*.yml
set -euo pipefail
SCRIPT="${BASH_SOURCE[0]}"
SCRIPT_DIR="$(cd "$(dirname "${SCRIPT}")" && pwd)"
ENV_FILE="${GOCLAW_ENV_FILE:-$SCRIPT_DIR/.env}"
loud() {
[[ "${QUIET:-false}" != true ]] && echo "$@"
true
}
# Show help
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
echo "Usage: $SCRIPT [--quiet] [--skip-validation]"
echo ""
echo " --quiet Suppress normal output"
echo " --skip-validation Skip docker compose config validation"
echo ""
echo " Generates COMPOSE_FILE from compose.d/*.yml files (sorted)"
echo " Updates .env with the resulting COMPOSE_FILE value"
echo ""
echo "Note: docker-compose reads .env automatically"
echo " for podman-compose: source .env first"
exit 0
fi
# Parse flags
SKIP_VALIDATION=false
for arg in "$@"; do
case "$arg" in
--quiet) QUIET=true ;;
--skip-validation) SKIP_VALIDATION=true ;;
esac
done
cd "$SCRIPT_DIR" >/dev/null 2>&1
[[ ! -f "docker-compose.yml" ]] && echo "docker-compose.yml not found" && exit 1
# Build COMPOSE_FILE from compose.d files (sorted)
COMPOSE_FILE=""
for f in compose.d/*.yml; do
[[ -e "$f" ]] && COMPOSE_FILE="$COMPOSE_FILE${COMPOSE_FILE:+:}$f"
done
export COMPOSE_FILE
# Validate compose files
if [[ "$SKIP_VALIDATION" != true ]]; then
DOCKER_CMD="${DOCKER_CMD:-docker}"
$DOCKER_CMD compose config > /dev/null 2>&1 || { echo "Compose config validation failed"; exit 1; }
loud "Compose config valid"
fi
# Update a key=value line in .env safely (via temp file)
update_env() {
local key="$1" value="$2"
if grep -q "^${key}=" "$ENV_FILE" 2>/dev/null; then
sed "s|^${key}=.*|${key}='${value}'|" "$ENV_FILE" > "$ENV_FILE.tmp" && mv "$ENV_FILE.tmp" "$ENV_FILE"
else
echo "${key}='${value}'" >> "$ENV_FILE"
fi
}
# Update .env with COMPOSE_FILE and GOCLAW_DIR
if [[ -f "$ENV_FILE" ]]; then
update_env "COMPOSE_FILE" "$COMPOSE_FILE"
update_env "GOCLAW_DIR" "$SCRIPT_DIR"
loud "COMPOSE_FILE updated in $ENV_FILE"
loud " COMPOSE_FILE=$COMPOSE_FILE"
else
loud "File not found: $ENV_FILE"
fi
loud "(run '${SCRIPT} --help' for help)"