-
-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathmise.toml
More file actions
197 lines (169 loc) · 7.82 KB
/
Copy pathmise.toml
File metadata and controls
197 lines (169 loc) · 7.82 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
monorepo_root = true
[monorepo]
lockfile = true
config_roots = [
"apps/*",
"packages/*",
]
# bun/uv workspace providers infer project roots. Keep codegen edges and
# non-JS/Python projects as overrides (i18n/tokens write files into apps).
[monorepo.projects."node:web"]
depends_add = ["node:@workspace/design-tokens", "node:@workspace/i18n"]
[monorepo.projects."custom:mobile"]
root = "apps/mobile"
depends_add = ["node:@workspace/design-tokens", "node:@workspace/i18n"]
[monorepo.projects."custom:infra"]
root = "apps/infra"
# Polyglot-safe default only: env/sources/cache are ecosystem-specific and
# would be wrong on Flutter/uv if shared. Collection fields do not merge, so
# a project that sets its own depends would drop ^build.
[monorepo.task_defaults.build]
depends = ["^build"]
[settings]
experimental = true
lockfile = true
[hooks]
postinstall = '''
mkdir -p .git/hooks
# commit-msg
cat > .git/hooks/commit-msg <<'EOF'
#!/bin/sh
exec mise run git:commit-msg -- "$1"
EOF
chmod +x .git/hooks/commit-msg
# pre-commit
cat > .git/hooks/pre-commit <<'EOF'
#!/bin/sh
exec mise run git:pre-commit
EOF
chmod +x .git/hooks/pre-commit
# pre-push
cat > .git/hooks/pre-push <<'EOF'
#!/bin/sh
exec mise run git:pre-push
EOF
chmod +x .git/hooks/pre-push
'''
[tools]
node = "24"
python = "3.12"
bun = "latest"
uv = "latest"
flutter = "3.44.8"
terraform = "1"
hadolint = "latest"
"github:Infisical/cli" = "latest"
[tasks]
"db:migrate" = { depends = ["//apps/api:migrate"], description = "Run database migrations" }
"dev:web" = { depends = ["//apps/api:dev", "//apps/web:dev"], description = "Start API and Web services" }
"dev:mobile" = { depends = ["//apps/api:dev", "//apps/mobile:dev"], description = "Start API and Mobile services" }
dev = { depends = ["//apps/api:dev", "//apps/web:dev", "//apps/worker:dev"], description = "Start all services" }
format = { depends = ["//apps/api:format", "//apps/web:format", "//apps/worker:format"], description = "Format all apps" }
"gen:api" = { depends = ["//apps/api:gen:openapi"], run = [{ tasks = ["//apps/web:gen:api", "//apps/mobile:gen:api"] }], description = "Generate OpenAPI schema and API clients" }
"i18n:build" = { depends = ["//packages/i18n:build"], run = [{ tasks = ["//apps/mobile:gen:l10n"] }], description = "Build i18n files (web JSON + mobile ARB + dart l10n)" }
"infra:down" = { depends = ["//apps/api:infra:down"], description = "Stop local infrastructure" }
"infra:up" = { depends = ["//apps/api:infra:up"], description = "Start local infrastructure" }
install = { run = ["bun install", "uv sync --all-packages", "mise //apps/mobile:install"], description = "Install workspace dependencies" }
lint = { depends = ["//apps/api:lint", "//apps/web:lint", "//apps/worker:lint"], description = "Lint all apps" }
test = { depends = ["//apps/api:test", "//apps/web:test", "//apps/worker:test"], description = "Test all apps" }
"tokens:build" = { depends = ["//packages/design-tokens:build"], description = "Build design tokens" }
typecheck = { depends = ["//apps/api:typecheck", "//apps/web:typecheck"], description = "Type check all apps" }
[tasks."git:commit-msg"]
description = "Validate commit message using commitlint"
# Pin bunx's extract cache to a persistent dir so macOS's periodic $TMPDIR
# (/var/folders) reaper can't partially prune it and corrupt commitlint.
# Cross-platform: the run line has no shell-specific syntax, so it works under
# both `sh -c` (unix) and `cmd /c` (windows); mise appends the commit-msg path.
# TMPDIR is inert on Windows (bun resolves temp via %TEMP%), and bunx auto-
# creates the dir, so no mkdir/export is needed.
env = { TMPDIR = "{{env.HOME}}/.bun/bunx-tmp" }
run = "bunx @commitlint/cli@20 --edit"
[tasks."git:pre-commit"]
description = "Run conditional checks for staging files"
run = '''
#!/usr/bin/env bash
changed=$(git diff --cached --name-only)
if echo "$changed" | grep -q "^apps/api/"; then
echo "[pre-commit] apps/api detected, running lint..."
mise //apps/api:lint || exit 1
fi
if echo "$changed" | grep -q "^apps/web/"; then
echo "[pre-commit] apps/web detected, running lint..."
mise //apps/web:lint || exit 1
fi
if echo "$changed" | grep -q "^apps/worker/"; then
echo "[pre-commit] apps/worker detected, running lint..."
mise //apps/worker:lint || exit 1
fi
if echo "$changed" | grep -q "^apps/mobile/"; then
echo "[pre-commit] apps/mobile detected, running lint..."
# Clear leaked git hook env so flutter's internal git targets its own SDK,
# not this worktree (GIT_DIR is absolute in linked worktrees and hijacks it).
env -u GIT_DIR -u GIT_WORK_TREE -u GIT_INDEX_FILE mise //apps/mobile:lint || exit 1
fi
if echo "$changed" | grep -qE "Dockerfile$"; then
echo "[pre-commit] Dockerfile detected, running hadolint..."
echo "$changed" | grep -E "Dockerfile$" | xargs hadolint || exit 1
fi
'''
[tasks."git:pre-push"]
description = "Validate branch name and run tests before push"
run = '''
#!/usr/bin/env bash
bunx @gracefullight/validate-branch || exit 1
# Gate verdicts are cached by content, because a suite's result is a pure
# function of the code it ran against. Pushing the same commits again — a
# rejected race, or a re-push after a rebase that moved nothing a gate reads —
# then costs nothing instead of replaying the full pytest/vitest/flutter runs.
#
# The key is the git tree hash of the paths a gate actually depends on plus
# mise.toml (the gate definition itself), so a web-only change does not
# invalidate the mobile cache. This replaces the old "diff against
# origin/main, grep for ^apps/<name>/" selector, which missed changes that
# reach an app from outside its own directory (packages/*) and silently fell
# back to HEAD~1 whenever origin/main was absent. Dependency lists are
# deliberately over-inclusive: an extra rerun is cheap, a false skip is not.
#
# Only clean-tree passes are cached. The suites run against the WORKING TREE
# while the key describes HEAD, so caching a dirty run would let uncommitted
# code vouch for the commits being pushed.
CACHE_DIR="$(cd "$(git rev-parse --git-common-dir)" && pwd)/pre-push-cache"
mkdir -p "$CACHE_DIR"
find "$CACHE_DIR" -type f -mtime +14 -delete 2>/dev/null || true
# cached_gate <name> <dep-paths> <command...>
cached_gate() {
name=$1; deps=$2; shift 2
# --verify -q keeps an absent path from echoing the rev back into the key.
key=$( { echo "$name"
for p in mise.toml $deps; do
git rev-parse --verify -q "HEAD:$p" || echo "absent $p"
done
} | git hash-object --stdin )
marker="$CACHE_DIR/$key"
if [ -f "$marker" ]; then
echo "[pre-push] $name: unchanged since it last passed, skipping."
return 0
fi
echo "[pre-push] $name: running..."
"$@" || return 1
# mise.toml joins the dirty check: the gate body that just ran came from the
# working tree, but the key describes the committed one.
if [ -n "$(git status --porcelain -- mise.toml $deps)" ]; then
echo "[pre-push] $name: passed but not cached (uncommitted changes present)."
else
: > "$marker"
fi
}
# packages/design-tokens and packages/i18n generate sources into apps/web and
# apps/mobile. A built output already lands in the app tree; listing the source
# too keeps an unbuilt token or message change from skipping the app's suite.
WEB_DEPS="apps/web packages/design-tokens packages/i18n"
MOBILE_DEPS="apps/mobile packages/design-tokens packages/i18n"
cached_gate api "apps/api" mise //apps/api:test || exit 1
cached_gate web "$WEB_DEPS" mise //apps/web:test || exit 1
cached_gate worker "apps/worker" mise //apps/worker:test || exit 1
# Clear leaked git hook env so flutter's internal git targets its own SDK,
# not this worktree (GIT_DIR is absolute in linked worktrees and hijacks it).
cached_gate mobile "$MOBILE_DEPS" \
env -u GIT_DIR -u GIT_WORK_TREE -u GIT_INDEX_FILE mise //apps/mobile:test || exit 1
'''