-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathzero
More file actions
executable file
·247 lines (206 loc) · 7.48 KB
/
Copy pathzero
File metadata and controls
executable file
·247 lines (206 loc) · 7.48 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#!/usr/bin/env bash
set -e
# Parse command line arguments
agent_mode=false
auto_yes=false
for arg in "$@"; do
case $arg in
--agent)
agent_mode=true
shift
;;
-y|--yes)
auto_yes=true
shift
;;
esac
done
interactive_only() {
if ! $agent_mode; then
"$@"
fi
}
onboarding_pass=true
# region: Onboarding checks
if [ ! -f "mise.local.toml" ]; then
cat > mise.local.toml << EOF
# Local mise configuration
# This file is gitignored and can contain tools and environment variables
# that you personally need for local development.
[tools]
# Add your local tools here. Example:
# dive = "latest"
[env]
# Add your local environment variables here. Example:
# EXAMPLE_VAR = "value"
EOF
echo "✅ Created mise.local.toml file"
fi
if [ -f "mise.worktree.local.toml" ]; then
echo "ℹ️ Found mise.worktree.local.toml. Running zero with MISE_ENV=worktree."
export MISE_ENV=worktree
fi
# Detect git worktree (a working tree distinct from the main one). When in a
# worktree, sync port mappings against mise.toml so newly-added _PORT vars
# and dependents land in mise.local.toml. Migrations are skipped here because
# ./zero applies them later.
if command -v git &> /dev/null && git rev-parse --is-inside-work-tree &> /dev/null; then
git_main_worktree=$(cd "$(git rev-parse --git-common-dir)/.." && pwd 2>/dev/null || true)
git_current_worktree=$(git rev-parse --show-toplevel 2>/dev/null || true)
if [ -n "$git_main_worktree" ] && [ -n "$git_current_worktree" ] && [ "$git_main_worktree" != "$git_current_worktree" ]; then
echo -e "\n⏳ Syncing worktree port mappings"
mise run git:worksync --no-migrate
fi
fi
check_command() {
local cmd=$1
local instructions=$2
if ! command -v "$cmd" &> /dev/null; then
onboarding_pass=false
echo "## \`$cmd\` not found:"
echo "$instructions" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
echo
fi
}
# Install mise automatically in agent mode
if $agent_mode && ! command -v mise &> /dev/null; then
echo "⏳ Installing mise..."
curl -fsSL https://mise.run | sh
export PATH="$HOME/.local/bin:$PATH"
mise trust
# printf %q shell-quotes the path (valid in bash and zsh) so the rc
# entry survives a $HOME containing spaces.
mise_bin=$(printf '%q' "$HOME/.local/bin/mise")
# The grep only matches uncommented activation lines, so a
# commented-out one doesn't suppress installing a working one.
bashrc="$HOME/.bashrc"
if [ ! -f "$bashrc" ] || ! grep -Eq '^[^#]*mise activate bash' "$bashrc"; then
echo "eval \"\$($mise_bin activate bash)\"" >> "$bashrc"
echo "✅ Added mise activation in $bashrc"
fi
# :- so a set-but-empty ZDOTDIR falls back to HOME too
zshrc="${ZDOTDIR:-$HOME}/.zshrc"
if [ ! -f "$zshrc" ] || ! grep -Eq '^[^#]*mise activate zsh' "$zshrc"; then
mkdir -p "${ZDOTDIR:-$HOME}"
echo "eval \"\$($mise_bin activate zsh)\"" >> "$zshrc"
echo "✅ Added mise activation in $zshrc"
fi
# mise activate exports MISE_SHELL; if it's unset, the current shell
# hasn't been activated yet.
if [ -z "${MISE_SHELL:-}" ]; then
echo "ℹ️ To take effect in your current shell, run:"
echo " eval \"\$($mise_bin activate bash)\" # bash"
echo " eval \"\$($mise_bin activate zsh)\" # zsh"
fi
else
check_command "mise" "
Install it from here: https://mise.jdx.dev/
- Make sure to update your .zshrc (zsh), .bashrc (bash), ...
- Additionaly enable completions for better DX: https://mise.jdx.dev/installing-mise.html#autocompletion
"
fi
if ! $agent_mode; then
check_command "docker" "
Install it from here: https://www.docker.com/
"
fi
if [ $onboarding_pass = "false" ]; then
echo "❌ Onboarding checks failed. Please fix the issues above and rerun this script."
exit 1
fi
# endregion: Onboarding checks
echo -e "\n⏳ Installing tools"
mise install
echo -e "\n⏳ Installing dependencies"
mise run install
echo -e "\n⏳ Setting up API keys and secrets"
interactive_only mise run zero:github
interactive_only mise run zero:openrouter
interactive_only mise run zero:idp
interactive_only mise run zero:melange
interactive_only mise run zero:fly
mise run zero:encryption
mise run zero:tls
# Env only here: the image build needs Docker, which infra:start confirms.
mise run zero:assistants --skip-image
echo -e "\n⏳ Updating VS Code and Cursor editor settings"
mise run install:vscode
echo -e "\n⏳ Syncing agent skills"
# One-time choice, persisted to mise.local.toml; skills:sync installs and
# keeps the SHA-pinned external set current whenever it is true.
if ! grep -q 'USE_RECOMMENDED_SKILLS' mise.local.toml 2>/dev/null; then
if $agent_mode || $auto_yes; then
mise set --file mise.local.toml USE_RECOMMENDED_SKILLS=true
else
echo "Install recommended agent skills? Third-party, pinned to commit SHAs,"
echo "kept out of git (see .agents/recommended-skills.json)."
echo -n "[y/N] "
read -r answer
if [ "$(echo "$answer" | tr '[:upper:]' '[:lower:]')" = "y" ]; then
mise set --file mise.local.toml USE_RECOMMENDED_SKILLS=true
else
mise set --file mise.local.toml USE_RECOMMENDED_SKILLS=false
fi
fi
fi
mise run skills:sync
echo -e "\n⏳ Setting up hooks"
if $agent_mode; then
mise run zero:hk --yes
else
mise run zero:hk
fi
interactive_only mise run zero:claude
echo -e "\n⏳ Cleaning up stale processes and Temporal state"
interactive_only mise run zero:cleanup
echo "✅ Cleaned up stale state"
# Compile the server/worker/streams binary while the steps below wait on
# Docker and the database. Those steps are IO-bound, so the build is nearly
# free in wall-clock terms, and it saves `mise run start` from doing three
# concurrent copies of the same cold compile. Backgrounded rather than
# depended on: a build failure must surface from the daemon that needs it, not
# abort the stack before infra is even up.
mise run build:server-cache &
server_cache_pid=$!
echo -e "\n⏳ Starting infra"
mise infra:start
echo -e "\n⏳ Configuring local assistant runtime"
mise run zero:assistants
echo -e "\n⏳ Running migrations"
mise run zero:migrations
mise db:migrate
mise clickhouse:migrate
mise run zero:devidp
echo -e "\n✅ All set up!"
# Use local:start if it's defined, otherwise fall back to the default start task.
start_task="start"
if mise tasks info local:start &>/dev/null; then
start_task="local:start"
fi
started=false
if $auto_yes || $agent_mode; then
started=true
else
echo "Want me to start the server and dashboard (\`mise run $start_task\`)?"
echo -n "[y/N] "
read -r answer
answer=$(echo "$answer" | tr '[:upper:]' '[:lower:]')
if [ "$answer" = "y" ]; then
started=true
fi
fi
if $started; then
# Let the build cache finish before the daemons race for it. `|| true`
# because a failed build must not abort the boot here -- the daemon that
# needs it rebuilds and reports the error where it is actionable.
wait "$server_cache_pid" || true
mise run "$start_task"
mise run seed
else
# Nothing will consume the cache, so stop paying for it: without this the
# build runs to completion in the background of a `./zero` the user
# declined to start, and is never reaped.
kill "$server_cache_pid" 2>/dev/null || true
wait "$server_cache_pid" 2>/dev/null || true
fi
mise run zero:summary