-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeploy.sh
More file actions
executable file
·135 lines (122 loc) · 3.98 KB
/
deploy.sh
File metadata and controls
executable file
·135 lines (122 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env bash
# =============================================================================
# AI-Factory — compose deploy helper
# =============================================================================
# - Optionally fills missing .env keys (CORS / site URL from --public-url,
# Fernet key for firewall rules file, sandbox preview network isolation).
# - Builds and starts the stack (default: service ``app``).
#
# Usage:
# ./scripts/deploy.sh
# ./scripts/deploy.sh --public-url https://your-host.example.com
# ./scripts/deploy.sh --no-env-fill --no-build
# ./scripts/deploy.sh -- --profile dev # extra args after -- go to docker compose
#
# Env fill never overwrites existing keys; use your editor to change values.
# =============================================================================
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
ENV_FILE="${ENV_FILE:-$ROOT/.env}"
NO_ENV_FILL=0
NO_BUILD=0
PUBLIC_URL=""
COMPOSE_SERVICES=(app)
PASS_THROUGH=()
usage() {
sed -n '1,25p' "$0" | tail -n +2
}
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
--no-env-fill)
NO_ENV_FILL=1
shift
;;
--no-build)
NO_BUILD=1
shift
;;
--public-url)
PUBLIC_URL="${2:-}"
shift 2
;;
--)
shift
PASS_THROUGH=("$@")
break
;;
*)
echo "unknown option: $1" >&2
usage
exit 1
;;
esac
done
if [[ ! -f "$ENV_FILE" ]]; then
echo "error: $ENV_FILE not found. Create it first, e.g.:" >&2
echo " cp .env.example .env # then add API keys" >&2
exit 2
fi
# Refuse deploy from a truncated workspace (same guard as .gitea/workflows/deploy.yml).
require_intact_tree() {
local f
for f in \
README.md docker-compose.yml pipeline_worker.py entrypoint.sh Dockerfile \
llm/router.py orchestrator/sqlite_manager.py \
web/frontend/lib/api.ts web/backend/api/products.py \
; do
if [[ ! -f "$ROOT/$f" ]]; then
echo "FATAL: deploy aborted — missing $f (workspace looks truncated)" >&2
echo "Run: git restore . # from repo root, then retry deploy" >&2
exit 3
fi
done
}
require_intact_tree
if [[ "$NO_ENV_FILL" -eq 0 ]]; then
FILL_ARGS=(--env-file "$ENV_FILE")
if [[ -n "$PUBLIC_URL" ]]; then
FILL_ARGS+=(--public-url "$PUBLIC_URL")
fi
python3 "$ROOT/scripts/fill_production_env.py" "${FILL_ARGS[@]}"
fi
COMPOSE_FILES=(-f docker-compose.yml)
if [[ "${AIFACTORY_USE_HOST_DOCKER:-}" == "1" ]]; then
COMPOSE_FILES+=(-f docker-compose.host-docker.yml)
else
COMPOSE_FILES+=(-f docker-compose.dind.yml)
fi
# Only mount Docker secrets when every file referenced in docker-compose.secrets.yml exists.
_secrets_overlay_ready() {
local f
for f in deepseek_api_key anthropic_api_key groq_api_key together_api_key; do
[[ -f "$ROOT/data/secrets/llm/$f" ]] || return 1
done
}
if _secrets_overlay_ready; then
COMPOSE_FILES+=(-f docker-compose.secrets.yml)
fi
if [[ "$NO_BUILD" -eq 0 ]]; then
docker compose "${PASS_THROUGH[@]}" "${COMPOSE_FILES[@]}" build "${COMPOSE_SERVICES[@]}"
else
echo "deploy.sh: skipping docker compose build (--no-build)"
fi
docker compose "${PASS_THROUGH[@]}" "${COMPOSE_FILES[@]}" up -d "${COMPOSE_SERVICES[@]}"
# Post-up: LLM + sandbox previews on bind-mounted data (idempotent)
docker compose "${PASS_THROUGH[@]}" "${COMPOSE_FILES[@]}" exec -T app \
python3 -m llm.persist_deepseek 2>/dev/null || true
docker compose "${PASS_THROUGH[@]}" "${COMPOSE_FILES[@]}" exec -T app \
python3 /app/scripts/materialize_all_spec_landings.py 2>/dev/null \
|| python3 "$ROOT/scripts/materialize_all_spec_landings.py" 2>/dev/null \
|| true
if [[ -x "$ROOT/scripts/install-claude-code-deepseek.sh" ]]; then
"$ROOT/scripts/install-claude-code-deepseek.sh" -q || true
fi
echo ""
echo "deploy.sh: done. Default URLs (see AICOM_PORT_* in .env):"
echo " Frontend http://localhost:\${AICOM_PORT_FRONTEND:-9080}"
echo " API http://localhost:\${AICOM_PORT_API:-9081}/api/health"