-
-
Notifications
You must be signed in to change notification settings - Fork 185
Expand file tree
/
Copy pathsbpp.sh
More file actions
executable file
·276 lines (266 loc) · 12.3 KB
/
Copy pathsbpp.sh
File metadata and controls
executable file
·276 lines (266 loc) · 12.3 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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#!/usr/bin/env bash
# Convenience wrapper around docker compose for the SourceBans++ dev stack.
# Run from the repo root. Pass -h to see commands.
set -euo pipefail
cd "$(dirname "$0")"
usage() {
cat <<'EOF'
Usage: ./sbpp.sh <command> [args...]
Lifecycle:
up Build (if needed) and start the stack in the background.
down Stop and remove containers (volumes preserved).
reset Tear everything down AND drop all volumes (DB + vendor + cache).
rebuild Rebuild the web image from scratch and restart.
status Show service status.
logs [svc] Tail logs. Optional service name (web|db|adminer|mailpit).
Run things inside containers:
shell [svc] Open a shell. Default svc=web (root). svc=db opens mysql client.
composer ... Run composer inside the web container.
phpstan Run phpstan from web/phpstan.neon inside the web container.
test [args...] Run PHPUnit (web/phpunit.xml) inside the web container.
ts-check Run tsc --checkJs over web/scripts (npm-installs typescript on demand).
e2e [args...] Run the Playwright E2E suite inside the web container.
Lazily npm-installs @playwright/test + chromium on first run;
forwards args to `npx playwright test` (e.g. `--grep @screenshot`).
exec <cmd...> Run an arbitrary command in the web container.
mysql Open a mysql client connected to the dev DB.
Database:
db-dump [file] Dump the DB to file (default: dump-YYYYMMDD-HHMMSS.sql).
db-load <file> Load a SQL dump into the dev DB.
db-reset Drop the DB volume + wipe MD5-named files from web/demos/
(orphans after the DB drop). Faster than full reset.
db-seed [args] Populate the dev DB with realistic synthetic data.
Accepts --scale=small|medium|large (default medium) and
--seed=<int> (default pinned in code). Idempotent: every
run truncates synth-owned tables first. Refuses to touch
any DB other than `sourcebans`.
URLs once "up":
http://localhost:${SBPP_WEB_PORT:-8080} SourceBans++ panel (admin / admin)
http://localhost:${SBPP_ADMINER_PORT:-8081} Adminer
http://localhost:${SBPP_MAILPIT_UI_PORT:-8025} Mailpit (captured email)
EOF
}
dc() { docker compose "$@"; }
cmd="${1:-help}"
shift || true
case "$cmd" in
up)
dc up -d --build
echo
echo "panel: http://localhost:${SBPP_WEB_PORT:-8080} (admin / admin)"
echo "adminer: http://localhost:${SBPP_ADMINER_PORT:-8081}"
echo "mailpit: http://localhost:${SBPP_MAILPIT_UI_PORT:-8025}"
;;
down)
dc down
;;
reset)
dc down -v
;;
rebuild)
dc build --no-cache web
dc up -d
;;
status)
dc ps
;;
logs)
dc logs -f --tail=200 "$@"
;;
shell)
svc="${1:-web}"
case "$svc" in
db) dc exec db mariadb -usourcebans -psourcebans sourcebans ;;
*) dc exec "$svc" bash ;;
esac
;;
composer)
dc exec web composer "$@"
;;
phpstan)
# The project baseline assumes `web/config.php` is absent (CI's state).
# Our entrypoint generated one, which makes a couple of "file not
# found" warnings disappear and triggers PHPStan's
# `reportUnmatchedIgnoredErrors`. Stash config.php for the duration of
# the analysis so locally we get the same result CI does.
#
# phpstan-dba (#1100) needs a live MariaDB to introspect schema; the
# dev `db` service is reachable from inside the web container as
# `db:3306`. Set PHPSTAN_DBA_DISABLE=1 to bypass when working
# offline — the bootstrap also degrades gracefully if the connection
# fails for any other reason.
dc exec \
-e DBA_HOST=db -e DBA_PORT=3306 \
-e DBA_NAME=sourcebans \
-e DBA_USER=sourcebans -e DBA_PASS=sourcebans \
-e DBA_PREFIX=sb -e DBA_CHARSET=utf8mb4 \
-e PHPSTAN_DBA_DISABLE="${PHPSTAN_DBA_DISABLE:-}" \
web bash -lc '
cd /var/www/html/web
cleanup() { [ -f config.php.devstash ] && mv config.php.devstash config.php; }
trap cleanup EXIT
[ -f config.php ] && mv config.php config.php.devstash
includes/vendor/bin/phpstan analyse "$@"
' -- "$@"
;;
test)
# Behavioral gate added in #1081 alongside the xajax→JSON migration.
# Each test runs against a dedicated `sourcebans_test` database so it
# never stomps the dev data in `sourcebans`.
dc exec \
-e DB_HOST=db -e DB_PORT=3306 \
-e DB_NAME=sourcebans_test \
-e DB_USER=sourcebans -e DB_PASS=sourcebans \
-e DB_PREFIX=sb -e DB_CHARSET=utf8mb4 \
web includes/vendor/bin/phpunit -c /var/www/html/web/phpunit.xml --testdox "$@"
;;
ts-check)
# JS type-checking gate added in #1098. We `npm install` lazily on
# first run so a fresh dev container doesn't pay the cost up front;
# the install is a no-op once node_modules/ is populated thanks to
# `--prefer-offline`.
dc exec web bash -lc 'cd /var/www/html/web && npm install --silent --no-audit --no-fund --prefer-offline && npm run --silent ts-check'
;;
e2e)
# Playwright E2E gate added in #1124. Mirrors `ts-check`'s
# lazy-install pattern: first run apt-installs chromium's
# system deps via `playwright install --with-deps chromium`,
# subsequent runs are sub-second to start.
#
# We auto-bring-up the dev stack if it's not already running
# so `./sbpp.sh e2e` works from a fresh checkout. The suite
# then runs INSIDE the web container and hits Apache on the
# in-container port 80 (E2E_BASE_URL=http://localhost). The
# DB seeder (web/tests/e2e/fixtures/db.ts) flips
# E2E_IN_CONTAINER=1 so it calls `php` directly instead of
# `docker compose exec` (we're already inside the container,
# the Docker socket isn't reachable from here).
if [ -z "$(dc ps -q web 2>/dev/null)" ]; then dc up -d; fi
# Idempotent grant: ensures `sourcebans_e2e` is writable by
# the panel user even on dev stacks whose db-init/ ran before
# this script started provisioning the e2e DB. Fresh stacks
# already get the grant from docker/db-init/00-render-schema.sh.
dc exec -T db mariadb -uroot -proot -e "
GRANT ALL PRIVILEGES ON \`sourcebans_e2e\`.* TO 'sourcebans'@'%';
GRANT CREATE, DROP ON *.* TO 'sourcebans'@'%';
FLUSH PRIVILEGES;" >/dev/null
# Pin the panel at the e2e DB for the duration of the run, then
# restore on exit. docker/php/web-entrypoint.sh renders config.php
# once at container start with `define('DB_NAME', 'sourcebans')`
# — the dev DB. Apache+mod_php holds that constant for the life
# of the container, so the `-e DB_NAME=sourcebans_e2e` below only
# affects the bash shell that drives `npx playwright test` (and
# the truncate shim it shells into). Without this swap the panel
# the test browser hits writes to `sourcebans` while the fixture
# truncates `sourcebans_e2e`, and any spec that mutates DB state
# is non-hermetic across runs (#1124 Slice 3 was the first slice
# to exercise the write path; Slice 0's smoke specs only login,
# which masked the gap). Apache re-reads config.php on every
# request so an in-place sed takes effect immediately with no
# restart; the trap restores the dev-DB value so the developer's
# browser session is unaffected once the suite finishes.
e2e_db="${E2E_DB_NAME:-sourcebans_e2e}"
dc exec -T web bash -c "
set -e
cfg=/var/www/html/web/config.php
stash=/var/www/html/web/config.php.e2e-stash
[ ! -f \$stash ] && cp \$cfg \$stash
sed -i \"s/define('DB_NAME', '[^']*');/define('DB_NAME', '${e2e_db}');/\" \$cfg
"
restore_panel_db() {
dc exec -T web bash -c '
cfg=/var/www/html/web/config.php
stash=/var/www/html/web/config.php.e2e-stash
if [ -f $stash ]; then mv $stash $cfg; fi
' 2>/dev/null || true
}
trap restore_panel_db EXIT INT TERM
dc exec -T \
-e E2E_BASE_URL="${E2E_BASE_URL:-http://localhost}" \
-e E2E_IN_CONTAINER=1 \
-e SCREENSHOTS="${SCREENSHOTS:-}" \
-e CI="${CI:-}" \
-e DB_HOST=db -e DB_PORT=3306 \
-e DB_NAME="${e2e_db}" \
-e DB_USER=sourcebans -e DB_PASS=sourcebans \
-e DB_PREFIX=sb -e DB_CHARSET=utf8mb4 \
web bash -lc '
set -e
cd /var/www/html/web/tests/e2e
if [ ! -d node_modules/@playwright/test ]; then
npm install --silent --no-audit --no-fund --prefer-offline
fi
# Browser install is also lazy. The marker file is
# what `playwright install` drops once it has finished
# provisioning chromium + the Debian deps under
# ~/.cache/ms-playwright. If the user nukes the cache,
# the next run reinstalls.
if [ ! -d "$HOME/.cache/ms-playwright" ] || [ -z "$(ls "$HOME/.cache/ms-playwright" 2>/dev/null)" ]; then
npx playwright install --with-deps chromium
fi
exec npx playwright test "$@"
' -- "$@"
;;
exec)
dc exec web "$@"
;;
mysql)
dc exec db mariadb -usourcebans -psourcebans sourcebans
;;
db-dump)
out="${1:-dump-$(date +%Y%m%d-%H%M%S).sql}"
dc exec -T db mariadb-dump -uroot -proot sourcebans >"$out"
echo "wrote $out"
;;
db-load)
[[ $# -eq 1 ]] || { echo "usage: ./sbpp.sh db-load <file>"; exit 2; }
dc exec -T db mariadb -uroot -proot sourcebans <"$1"
;;
db-reset)
dc rm -fsv db
docker volume rm "$(basename "$PWD")_dbdata" 2>/dev/null || true
# `db-reset` wipes the DB but `web/demos/` is bind-mounted from
# the host worktree (not a named volume) so demo files written
# by a previous `db-seed` (or by any panel-side upload that
# happened against the dev stack) would otherwise survive as
# permanent orphans — the `_demos` rows that pointed at them
# vanish with the DB volume, and the next `db-seed`'s
# referenced-only wipe reads zero rows from the fresh DB and
# skips them. Strict MD5-name regex matches both shapes the
# demo write path produces (`Sbpp\Tests\Synthesizer::deterministicDemoFilename`
# for synth files, `Sbpp\Upload\UploadHandler::handle()` with
# `renameToHash: true` for panel uploads) while leaving the
# `.gitkeep` structural marker in place. Demos are dev-only
# ban evidence here; production installs never run `sbpp.sh`.
if [[ -d web/demos ]]; then
find web/demos -maxdepth 1 -type f -regextype posix-extended -regex '.*/[0-9a-f]{32}$' -delete 2>/dev/null || true
fi
dc up -d db
;;
db-seed)
# Dev-only synthetic data populator (#1238). Mirrors `e2e`'s
# auto-bring-up shim so `./sbpp.sh db-seed` works from a fresh
# checkout. The CLI driver lives at
# `web/tests/scripts/seed-dev-db.php`; the synthesizer is
# `Sbpp\Tests\Synthesizer`. Always truncate+reseed by design;
# `--scale=small|medium|large` and `--seed=<int>` are the only
# accepted flags. DB_NAME is pinned to `sourcebans` (the dev
# panel's DB) — the driver refuses any other value, including
# `sourcebans_test` / `sourcebans_e2e`.
if [ -z "$(dc ps -q web 2>/dev/null)" ]; then dc up -d; fi
dc exec \
-e DB_HOST=db -e DB_PORT=3306 \
-e DB_NAME=sourcebans \
-e DB_USER=sourcebans -e DB_PASS=sourcebans \
-e DB_PREFIX=sb -e DB_CHARSET=utf8mb4 \
web php /var/www/html/web/tests/scripts/seed-dev-db.php "$@"
;;
-h|--help|help|"")
usage
;;
*)
echo "unknown command: $cmd" >&2
usage
exit 2
;;
esac