mirror of
https://github.com/different-ai/openwork
synced 2026-04-26 01:25:10 +02:00
198 lines
6.1 KiB
Bash
Executable File
198 lines
6.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Bring up a dev stack with random host ports.
|
|
#
|
|
# Usage (from _repos/openwork repo root):
|
|
# packaging/docker/dev-up.sh
|
|
#
|
|
# Defaults to isolated OpenCode dev state inside the container.
|
|
# Escape hatch: set OPENWORK_DOCKER_DEV_MOUNT_HOST_OPENCODE=1 to import host
|
|
# OpenCode config/auth into the isolated dev state for this stack.
|
|
#
|
|
# Outputs:
|
|
# - Web UI URL
|
|
# - OpenWork server URL
|
|
# - Share service URL
|
|
# - Token file path
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
COMPOSE_FILE="$ROOT_DIR/packaging/docker/docker-compose.dev.yml"
|
|
WORKSPACE_DIR="$ROOT_DIR/packaging/docker/workspace"
|
|
DEV_RUNTIME_DIR="$ROOT_DIR/tmp/docker-dev"
|
|
MOUNT_HOST_OPENCODE="${OPENWORK_DOCKER_DEV_MOUNT_HOST_OPENCODE:-0}"
|
|
|
|
resolve_opencode_config_dir() {
|
|
local override="${OPENWORK_OPENCODE_CONFIG_DIR:-}"
|
|
if [ -n "$override" ]; then
|
|
if [ -d "$override" ]; then
|
|
printf '%s\n' "$override"
|
|
return 0
|
|
fi
|
|
echo "warning: OPENWORK_OPENCODE_CONFIG_DIR is not a directory: $override" >&2
|
|
fi
|
|
|
|
local candidates=()
|
|
if [ -n "${XDG_CONFIG_HOME:-}" ]; then
|
|
candidates+=("${XDG_CONFIG_HOME}/opencode")
|
|
fi
|
|
candidates+=("${HOME}/.config/opencode")
|
|
if [ "$(uname -s)" = "Darwin" ]; then
|
|
candidates+=("${HOME}/Library/Application Support/opencode")
|
|
fi
|
|
|
|
local files=("opencode.jsonc" "opencode.json" "config.json" "AGENTS.md")
|
|
local candidate file
|
|
for candidate in "${candidates[@]}"; do
|
|
[ -d "$candidate" ] || continue
|
|
for file in "${files[@]}"; do
|
|
if [ -f "$candidate/$file" ]; then
|
|
printf '%s\n' "$candidate"
|
|
return 0
|
|
fi
|
|
done
|
|
if [ -n "$(ls -A "$candidate" 2>/dev/null)" ]; then
|
|
printf '%s\n' "$candidate"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
resolve_opencode_data_dir() {
|
|
local override="${OPENWORK_OPENCODE_DATA_DIR:-}"
|
|
if [ -n "$override" ]; then
|
|
if [ -d "$override" ]; then
|
|
printf '%s\n' "$override"
|
|
return 0
|
|
fi
|
|
echo "warning: OPENWORK_OPENCODE_DATA_DIR is not a directory: $override" >&2
|
|
fi
|
|
|
|
local candidates=()
|
|
if [ -n "${XDG_DATA_HOME:-}" ]; then
|
|
candidates+=("${XDG_DATA_HOME}/opencode")
|
|
fi
|
|
candidates+=("${HOME}/.local/share/opencode")
|
|
if [ "$(uname -s)" = "Darwin" ]; then
|
|
candidates+=("${HOME}/Library/Application Support/opencode")
|
|
fi
|
|
|
|
local files=("auth.json" "mcp-auth.json")
|
|
local candidate file
|
|
for candidate in "${candidates[@]}"; do
|
|
[ -d "$candidate" ] || continue
|
|
for file in "${files[@]}"; do
|
|
if [ -f "$candidate/$file" ]; then
|
|
printf '%s\n' "$candidate"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
echo "docker is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
pick_port() {
|
|
node -e "
|
|
const net = require('net');
|
|
const s = net.createServer();
|
|
s.listen(0, '127.0.0.1', () => {
|
|
const { port } = s.address();
|
|
console.log(port);
|
|
s.close();
|
|
});
|
|
"
|
|
}
|
|
|
|
DEV_ID="$(node -e "console.log(require('crypto').randomUUID().slice(0, 8))")"
|
|
PROJECT="openwork-dev-$DEV_ID"
|
|
|
|
mkdir -p "$WORKSPACE_DIR"
|
|
mkdir -p "$DEV_RUNTIME_DIR"
|
|
|
|
OPENCODE_CONFIG_FALLBACK_DIR="$DEV_RUNTIME_DIR/host-opencode-config"
|
|
OPENCODE_DATA_FALLBACK_DIR="$DEV_RUNTIME_DIR/host-opencode-data"
|
|
mkdir -p "$OPENCODE_CONFIG_FALLBACK_DIR" "$OPENCODE_DATA_FALLBACK_DIR"
|
|
|
|
HOST_OPENCODE_CONFIG_DIR="$OPENCODE_CONFIG_FALLBACK_DIR"
|
|
HOST_OPENCODE_DATA_DIR="$OPENCODE_DATA_FALLBACK_DIR"
|
|
|
|
if [ "$MOUNT_HOST_OPENCODE" = "1" ]; then
|
|
HOST_OPENCODE_CONFIG_DIR="$(resolve_opencode_config_dir || true)"
|
|
HOST_OPENCODE_DATA_DIR="$(resolve_opencode_data_dir || true)"
|
|
|
|
if [ -z "$HOST_OPENCODE_CONFIG_DIR" ]; then
|
|
HOST_OPENCODE_CONFIG_DIR="$OPENCODE_CONFIG_FALLBACK_DIR"
|
|
fi
|
|
if [ -z "$HOST_OPENCODE_DATA_DIR" ]; then
|
|
HOST_OPENCODE_DATA_DIR="$OPENCODE_DATA_FALLBACK_DIR"
|
|
fi
|
|
fi
|
|
|
|
OPENWORK_PORT="$(pick_port)"
|
|
WEB_PORT="$(pick_port)"
|
|
if [ "$WEB_PORT" = "$OPENWORK_PORT" ]; then
|
|
WEB_PORT="$(pick_port)"
|
|
fi
|
|
SHARE_PORT="${SHARE_PORT:-$(pick_port)}"
|
|
if [ "$SHARE_PORT" = "$OPENWORK_PORT" ] || [ "$SHARE_PORT" = "$WEB_PORT" ]; then
|
|
SHARE_PORT="$(pick_port)"
|
|
fi
|
|
|
|
echo "Starting Docker Compose project: $PROJECT" >&2
|
|
echo "- OPENWORK_PORT=$OPENWORK_PORT" >&2
|
|
echo "- WEB_PORT=$WEB_PORT" >&2
|
|
echo "- SHARE_PORT=$SHARE_PORT" >&2
|
|
echo "- OPENWORK_DEV_MODE=1" >&2
|
|
if [ "$MOUNT_HOST_OPENCODE" = "1" ]; then
|
|
echo "- Host OpenCode import: enabled" >&2
|
|
else
|
|
echo "- Host OpenCode import: disabled (isolated dev state)" >&2
|
|
fi
|
|
|
|
start_stack() {
|
|
local config_dir="$1"
|
|
local data_dir="$2"
|
|
OPENWORK_DEV_ID="$DEV_ID" OPENWORK_PORT="$OPENWORK_PORT" WEB_PORT="$WEB_PORT" SHARE_PORT="$SHARE_PORT" \
|
|
OPENWORK_DEV_MODE="1" \
|
|
OPENWORK_HOST_OPENCODE_CONFIG_DIR="$config_dir" \
|
|
OPENWORK_HOST_OPENCODE_DATA_DIR="$data_dir" \
|
|
docker compose -p "$PROJECT" -f "$COMPOSE_FILE" up -d
|
|
}
|
|
|
|
ACTIVE_OPENCODE_CONFIG_DIR="$HOST_OPENCODE_CONFIG_DIR"
|
|
ACTIVE_OPENCODE_DATA_DIR="$HOST_OPENCODE_DATA_DIR"
|
|
|
|
echo "- OPENWORK_HOST_OPENCODE_CONFIG_DIR=$ACTIVE_OPENCODE_CONFIG_DIR" >&2
|
|
echo "- OPENWORK_HOST_OPENCODE_DATA_DIR=$ACTIVE_OPENCODE_DATA_DIR" >&2
|
|
|
|
if ! start_stack "$ACTIVE_OPENCODE_CONFIG_DIR" "$ACTIVE_OPENCODE_DATA_DIR"; then
|
|
if [ "$ACTIVE_OPENCODE_CONFIG_DIR" != "$OPENCODE_CONFIG_FALLBACK_DIR" ] || [ "$ACTIVE_OPENCODE_DATA_DIR" != "$OPENCODE_DATA_FALLBACK_DIR" ]; then
|
|
echo "Detected host OpenCode config mount failed; retrying with empty fallback dirs." >&2
|
|
docker compose -p "$PROJECT" -f "$COMPOSE_FILE" down >/dev/null 2>&1 || true
|
|
ACTIVE_OPENCODE_CONFIG_DIR="$OPENCODE_CONFIG_FALLBACK_DIR"
|
|
ACTIVE_OPENCODE_DATA_DIR="$OPENCODE_DATA_FALLBACK_DIR"
|
|
echo "- OPENWORK_HOST_OPENCODE_CONFIG_DIR=$ACTIVE_OPENCODE_CONFIG_DIR" >&2
|
|
echo "- OPENWORK_HOST_OPENCODE_DATA_DIR=$ACTIVE_OPENCODE_DATA_DIR" >&2
|
|
start_stack "$ACTIVE_OPENCODE_CONFIG_DIR" "$ACTIVE_OPENCODE_DATA_DIR"
|
|
else
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "" >&2
|
|
echo "OpenWork web UI: http://localhost:$WEB_PORT" >&2
|
|
echo "OpenWork server: http://localhost:$OPENWORK_PORT" >&2
|
|
echo "Share service: http://localhost:$SHARE_PORT" >&2
|
|
echo "Token file: $ROOT_DIR/tmp/.dev-env-$DEV_ID" >&2
|
|
echo "" >&2
|
|
echo "To stop this stack:" >&2
|
|
echo " docker compose -p $PROJECT -f $COMPOSE_FILE down" >&2
|