-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
Copy pathdev.sh
executable file
·332 lines (275 loc) · 10.4 KB
/
dev.sh
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#!/bin/bash
set -euo pipefail
# A convenience script that launches a fresh postgres container instance that
# can be used by the graphql-engine server. After launch the verbose postgres
# logs will be printed. On shutdown we'll try to clean up the container
# completely.
echo_pretty() {
echo ">>> $(tput setaf 2)$1$(tput sgr0)"
}
die_usage() {
cat <<EOL
A swiss-army script for local graphql-engine development
Usage: $0 <COMMAND>
Available COMMANDs:
graphql-engine [--no-rebuild]
Launch graphql-engine, connecting to a database launched with '$0 postgres'
You can pass --no-rebuild if you want to launch an instance from source you
previously built if you have a dirty tree.
postgres
Launch a postgres container suitable for use with graphql-engine, watch its logs,
clean up nicely after
test [pytest_args...]
Run the integration tests, handling spinning up all dependencies. This will force
a recompile. A code coverage report will be generated. All arguments after 'test'
will be passed to the 'pytest' invocation.
EOL
exit 1
}
case "${1-}" in
graphql-engine)
case "${2-}" in
--no-rebuild)
REBUILD=false
;;
"")
REBUILD=true
;;
*)
die_usage
;;
esac
;;
postgres)
;;
test)
PYTEST_ARGS="${@:2}"
;;
*)
die_usage
;;
esac
# For now:
MODE="$1"
PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" # ... https://stackoverflow.com/a/246128/176841
cd "$PROJECT_ROOT"
####################################
### Shared environment stuff ###
####################################
# Hopefully these don't clash with anything. We could try to be smarter:
if [ "$MODE" = "test" ]; then
# Choose a different port so PG is totally disposable:
PG_PORT=35432
else
PG_PORT=25432
fi
# export for psql, etc.
export PGPASSWORD=postgres
DB_URL="postgres://postgres:$PGPASSWORD@127.0.0.1:$PG_PORT/postgres"
PG_CONTAINER_NAME="hasura-dev-postgres-$PG_PORT"
# We can remove psql as a dependency:
DOCKER_PSQL="docker exec -u postgres -it $PG_CONTAINER_NAME psql -p $PG_PORT"
function wait_docker_postgres {
echo -n "Waiting for postgres to come up"
until $DOCKER_PSQL postgres -c '\l' &>/dev/null; do
echo -n '.' && sleep 0.2
done
echo " Ok"
}
#################################
### Graphql-engine ###
#################################
if [ "$MODE" = "graphql-engine" ]; then
cd "$PROJECT_ROOT/server"
export HASURA_GRAPHQL_SERVER_PORT=${HASURA_GRAPHQL_SERVER_PORT-8181}
# Prettify JSON output if possible:
if command -v jq ; then
PIPE_JQ="| jq --unbuffered -R -r '. as \$line | try fromjson catch \$line'"
fi
echo_pretty "We will connect to postgres container '$PG_CONTAINER_NAME'"
echo_pretty "If you haven't yet, please launch a postgres container in a separate terminal with:"
echo_pretty " $ $0 postgres"
echo_pretty "or press CTRL-C and invoke graphql-engine manually"
wait_docker_postgres
# Starts EKG, fast build without optimizations
BUILD_INVOCATION="stack build --fast --flag graphql-engine:developer --ghc-options=-j"
RUN_INVOCATION="stack exec graphql-engine -- --database-url='$DB_URL' serve --enable-console --console-assets-dir \'$PROJECT_ROOT/console/static/dist\' +RTS -N -T -RTS ${PIPE_JQ-}"
echo_pretty "About to do:"
echo_pretty " $ $BUILD_INVOCATION"
echo_pretty " $ $RUN_INVOCATION"
echo_pretty ""
# `stack exec` is a footgun, as it will happily execute a graphql-engine elsewhere in user's path:
if [ "$REBUILD" = false ]; then
if [[ ! -x "$(stack path --local-install-root)/bin/graphql-engine" ]]; then
echo "You requested --no-rebuild but graphql-engine hasn't been built."
echo "Please do e.g."
echo " $ $BUILD_INVOCATION" # Naughty and dangerous!
exit 3
fi
else
$BUILD_INVOCATION
fi
# Print helpful info after startup logs so it's visible:
{
until curl -s "http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/v1/query" &>/dev/null; do
sleep 0.2
done
sleep 1
echo_pretty "▲▲▲ graphql-engine startup logs above ▲▲▲"
echo_pretty ""
echo_pretty "You can set additional environment vars to tailor 'graphql-engine' next time you"
echo_pretty "invoke this script, e.g.:"
echo_pretty " # Keep polling statements out of logs"
echo_pretty " HASURA_GRAPHQL_EVENTS_FETCH_INTERVAL=3000000"
echo_pretty ""
echo_pretty "The hasura console is available at:"
echo_pretty " http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/console"
echo_pretty ""
echo_pretty " If the console was modified since your last build (re)build assets with:"
echo_pretty " $ cd \"$PROJECT_ROOT/console\""
echo_pretty " $ npm ci && npm run server-build "
echo_pretty ""
echo_pretty "Useful endpoints when compiling with 'graphql-engine:developer' and running with '+RTS -T'"
echo_pretty " http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/dev/subscriptions"
echo_pretty " http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/dev/plan_cache"
echo_pretty ""
echo_pretty "To view realtime GC stats and other info open in your browser:"
echo_pretty " file://$PROJECT_ROOT/scripts/ekg/ekg.html#$HASURA_GRAPHQL_SERVER_PORT"
echo_pretty ""
echo_pretty "▼▼▼ additional graphql-engine logs will appear below: ▼▼▼"
} &
# Logs printed until CTRL-C:
eval "$RUN_INVOCATION" # Naughty and dangerous!
exit 0
### END SCRIPT ###
fi
#################################
### Postgres Container ###
#################################
# Useful development defaults for postgres (no spaces here, please):
#
# setting 'port' in container is a workaround for the pg_dump endpoint (see tests)
# log_hostname=off to avoid timeout failures when running offline due to:
# https://forums.aws.amazon.com/thread.jspa?threadID=291285
CONF=$(cat <<-EOF
log_statement=all
log_connections=on
log_disconnections=on
log_hostname=off
log_duration=on
port=$PG_PORT
EOF
)
# log lines above as -c flag arguments we pass to postgres
CONF_FLAGS=$(echo "$CONF" | sed -e 's/^/-c /' | tr '\n' ' ')
# The unofficial 'mdillon/postgis' comes with postgis installed, needed for tests:
docker run --name "$PG_CONTAINER_NAME" -p 127.0.0.1:"$PG_PORT":$PG_PORT --expose="$PG_PORT" \
-e POSTGRES_PASSWORD="$PGPASSWORD" -d mdillon/postgis:11 \
$CONF_FLAGS
# graphql-engine calls the pg_dump executable. To avoid a version mismatch (and
# the dependency entirely) we create a shim that executes the pg_dump in the
# postgres container. Note output to file won't work.
DEV_SHIM_PATH="/tmp/hasura-dev-shims-$PG_PORT"
mkdir -p "$DEV_SHIM_PATH"
cat >"$DEV_SHIM_PATH/pg_dump" <<EOL
#!/bin/bash
# Generated from: $0
if [[ \$@ == *" -f"* ]]; then
echo "It looks like we're trying to pg_dump to a file, but that won't work with this shim. See $0" >&2
exit 1
fi
docker exec -u postgres $PG_CONTAINER_NAME pg_dump "\$@"
EOL
chmod a+x "$DEV_SHIM_PATH/pg_dump"
export PATH="$DEV_SHIM_PATH":$PATH
# Since launching the postgres container worked we can set up cleanup routines. This will catch CTRL-C
function cleanup {
echo
if [ ! -z "${GRAPHQL_ENGINE_PID-}" ]; then
# This may already have been killed:
kill "$GRAPHQL_ENGINE_PID" &>/dev/null || true
fi
case "$MODE" in
test|postgres)
# Since scripts here are tailored to the env we've just launched:
rm -r "$DEV_SHIM_PATH"
echo_pretty "Removing $PG_CONTAINER_NAME and its volumes in 5 seconds! PRESS CTRL-C TO ABORT."
sleep 5
docker stop "$PG_CONTAINER_NAME"
docker rm -v "$PG_CONTAINER_NAME"
;;
graphql-engine)
;;
esac
echo_pretty "Done"
}
trap cleanup EXIT
wait_docker_postgres
if [ "$MODE" = "postgres" ]; then
echo_pretty "Postgres logs will start to show up in realtime here. Press CTRL-C to exit and "
echo_pretty "shutdown this container."
echo_pretty ""
echo_pretty "You can use the following to connect to the running instance:"
echo_pretty " $ $DOCKER_PSQL"
echo_pretty " or..."
echo_pretty " $ PGPASSWORD="$PGPASSWORD" psql -h 127.0.0.1 -p "$PG_PORT" postgres -U postgres"
echo_pretty ""
echo_pretty "Here is the database URL:"
echo_pretty " $DB_URL"
echo_pretty ""
echo_pretty "If you want to launch a 'graphql-engine' that works with this database:"
echo_pretty " $ $0 graphql-engine"
# Runs continuously until CTRL-C, jumping to cleanup() above:
docker logs -f --tail=0 "$PG_CONTAINER_NAME"
elif [ "$MODE" = "test" ]; then
#################################
### Integration tests ###
#################################
cd "$PROJECT_ROOT/server"
export EVENT_WEBHOOK_HEADER="MyEnvValue"
export WEBHOOK_FROM_ENV="http://127.0.0.1:5592"
echo_pretty "Rebuilding for code coverage"
stack build --fast --flag graphql-engine:developer --ghc-options=-j --coverage
echo_pretty "Starting graphql-engine"
GRAPHQL_ENGINE_TEST_LOG=/tmp/hasura-dev-test-engine.log
export HASURA_GRAPHQL_SERVER_PORT=8088
# stopped in cleanup()
stack exec graphql-engine -- --database-url="$DB_URL" serve --enable-console --stringify-numeric-types \
--console-assets-dir ../console/static/dist &> $GRAPHQL_ENGINE_TEST_LOG & GRAPHQL_ENGINE_PID=$!
echo -n "Waiting for graphql-engine"
until curl -s "http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/v1/query" &>/dev/null; do
echo -n '.' && sleep 0.2
done
echo " Ok"
cd "$PROJECT_ROOT/server/tests-py"
PY_VENV=.hasura-dev-python-venv
set +u # for venv activate
if [ ! -d "$PY_VENV" ]; then
python3 -m venv "$PY_VENV"
source "$PY_VENV/bin/activate"
pip3 install -r requirements.txt
else
echo_pretty "It looks like python dependencies have been installed already. Skipping."
echo_pretty "If things fail please run this and try again"
echo_pretty " $ rm -r \"$PROJECT_ROOT/server/tests-py/$PY_VENV\""
source "$PY_VENV/bin/activate"
fi
# TODO MAYBE: fix deprecation warnings, make them an error
if pytest -W ignore::DeprecationWarning --hge-urls http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT --pg-urls "$DB_URL" $PYTEST_ARGS; then
PASSED=true
else
PASSED=false
echo_pretty "^^^ graphql-engine logs from failed test run can be inspected at: $GRAPHQL_ENGINE_TEST_LOG"
fi
deactivate # python venv
set -u
cd "$PROJECT_ROOT/server"
# INT so we get hpc report
kill -INT "$GRAPHQL_ENGINE_PID"
wait "$GRAPHQL_ENGINE_PID" || true
echo
stack hpc report graphql-engine.tix
rm graphql-engine.tix
else
echo "impossible; fix script."
fi