forked from hasura/graphql-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdev.sh
executable file
·863 lines (756 loc) · 31.6 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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
#!/usr/bin/env bash
# shellcheck disable=SC1091 # We do not want Shellcheck to validate that sourced scripts are present.
set -euo pipefail
shopt -s globstar
# for extended case patterns:
shopt -s extglob
# A development swiss army knife script. The goals are to:
#
# - encode some best practices and hard-won knowledge of quirks and corners of
# our tooling
# - simplify development; especially for new-comers; instead of writing a huge
# document describing how to do various dev tasks (or worse yet, not writing
# one), make it runnable
#
# This makes use of 'cabal/dev-sh*.project' files when building.
# See 'cabal/dev-sh.project.local' for details, and $CABAL_PROJECT_FILE below.
#
# The configuration for the containers of each backend is stored in
# separate files, see files in 'scripts/containers'
echo_pretty() {
echo ">>> $(tput setaf 2)$1$(tput sgr0)"
}
echo_error() {
echo ">>> $(tput setaf 1)$1$(tput sgr0)"
}
echo_warn() {
echo ">>> $(tput setaf 3)$1$(tput sgr0)"
}
die_usage() {
cat <<EOL
A swiss-army script for local graphql-engine development
Usage: $0 <COMMAND>
Available COMMANDs:
graphql-engine [--optimized | --prof-ticky | --prof-heap-infomap |--prof-ghc-debug] [-- <extra_args>]
Launch graphql-engine, connecting to a database launched with
'$0 postgres'. <extra_args> will be passed to graphql-engine directly.
--optimized : will launch a prod-like optimized build
--prof-ticky : "Ticky ticky" profiling for accounting of allocations (see: cabal/README.md)
--prof-heap-infomap : Heap profiling (see: cabal/README.md)
--prof-ghc-debug : Enable ghc-debug (see: cabal/README.md)
--prof-time : Time profiling (see: cabal/README.md)
postgres
Launch a postgres container suitable for use with graphql-engine, watch its
logs, clean up nicely after
mssql
Launch a MSSQL container suitable for use with graphql-engine, watch its
logs, clean up nicely after
citus
Launch a Citus single-node container suitable for use with graphql-engine,
watch its logs, clean up nicely after
mysql
Launch a MySQL container suitable for use with graphql-engine, watch its
logs, clean up nicely after
test [--integration [pytest_args...] | --unit | --hlint]
Run the unit and integration tests, handling spinning up all dependencies.
This will force a recompile. A combined code coverage report will be
generated for all test suites.
Either integration or unit tests can be run individually with their
respective flags. With '--integration' any arguments that follow will be
passed to the pytest invocation. Run the hlint code linter individually
using '--hlint'.
For unit tests, you can limit the number of tests by using
'test --unit --match "runTx" mssql'
EOL
exit 1
}
# See: TODO
cabal --version | grep -q -E ' 3\.10|3\.12' || {
echo_error "Please use cabal >=3.10, as cabal broke 'import' and we can't make it compatible"
exit 1
}
# The default configuration this script expects. May be overridden depending on
# flags passed to subcommands, or this can be edited for one-off tests:
CABAL_PROJECT_FILE=cabal/dev-sh.project
# Prettify JSON output, if possible
try_jq() {
if command -v jq >/dev/null; then
command jq --unbuffered -R -r '. as $line | try fromjson catch $line'
else
cat
fi
}
case "${1-}" in
graphql-engine?(-pro) )
## The differences between OSS and Enterprise/pro defined here:
EDITION_NAME="${1-}"
if [ "$EDITION_NAME" = "graphql-engine-pro" ];then
EDITION_ABBREV=ee
if [ -z "${HASURA_GRAPHQL_EE_LICENSE_KEY-}" ]; then
echo_warn "You don't have the HASURA_GRAPHQL_EE_LICENSE_KEY environment variable defined."
echo_warn "Ask a pro developer for the dev key."
echo_warn " Or: Press enter to continue with the pro binary in non-pro mode [will proceed in 15s]"
read -r -t15 || true
fi
# This is required for pro with EE license available:
if [ -z "${HASURA_GRAPHQL_ADMIN_SECRET-}" ]; then
# This should match benchmarks and other dev utilities:
export HASURA_GRAPHQL_ADMIN_SECRET=my-secret
fi
else
EDITION_ABBREV=ce
fi
# pass arguments after '--' directly to engine:
GRAPHQL_ENGINE_EXTRA_ARGS=()
case "${2-}" in
--no-rebuild)
echo_error 'The --no-rebuild option is no longer supported.'
die_usage
;;
--prof-ticky)
if [ -f "$EDITION_NAME.ticky" ]; then
echo_error "The file '$EDITION_NAME.ticky' exists and we would clobber it. Please delete or rename it and try again."
exit 1
fi
echo_warn "This will perform significant recompilation. Ok?"
echo_warn " Press enter to continue [will proceed in 10s]"
read -r -t10 || true
CABAL_PROJECT_FILE=cabal/dev-sh-prof-ticky.project
HASURA_PROF_MODE=ticky
GRAPHQL_ENGINE_EXTRA_ARGS+=( +RTS -r -RTS )
case "${3-}" in
--)
GRAPHQL_ENGINE_EXTRA_ARGS+=( "${@:4}" )
;;
esac
;;
--prof-heap-infomap)
echo_warn "This will delete any '$EDITION_NAME.eventlog' and '$EDITION_NAME.eventlog.html' and perform significant recompilation. Ok?"
echo_warn "Press enter to continue [will proceed in 10s]"
read -r -t10 || true
# Avoid confusion:
rm -f "$EDITION_NAME.eventlog"
rm -f "$EDITION_NAME.eventlog.html"
CABAL_PROJECT_FILE=cabal/dev-sh-prof-heap-infomap.project
HASURA_PROF_MODE=heap-infomap
GRAPHQL_ENGINE_EXTRA_ARGS+=( +RTS -hi -l-agu -RTS )
case "${3-}" in
--)
GRAPHQL_ENGINE_EXTRA_ARGS+=( "${@:4}" )
;;
esac
;;
--prof-ghc-debug)
# Used by ghc-debug-stub:
export GHC_DEBUG_SOCKET=/tmp/ghc-debug
echo_warn "This will require significant recompilation unless you just ran with --prof-heap-infomap "
echo_warn "A GHC debug socket will be opened at $GHC_DEBUG_SOCKET"
echo_warn "See examples of client code here: https://github.com/hasura/hasura-debug/"
echo_warn "Press enter to continue [will proceed in 10s]"
read -r -t10 || true
# NOTE: we just need IPE info so can re-use this:
CABAL_PROJECT_FILE=cabal/dev-sh-prof-heap-infomap.project
# This will open the debug socket:
export HASURA_GHC_DEBUG=true
HASURA_PROF_MODE=ghc-debug
case "${3-}" in
--)
GRAPHQL_ENGINE_EXTRA_ARGS+=( "${@:4}" )
;;
esac
;;
--prof-time)
echo_warn "This will delete any $EDITION_NAME.prof and perform significant recompilation."
echo_warn "Press enter to continue [will proceed in 10s]"
read -r -t10 || true
rm -f "$EDITION_NAME.prof"
rm -f "$EDITION_NAME.profiterole.html"
CABAL_PROJECT_FILE=cabal/dev-sh-prof-time.project
HASURA_PROF_MODE="time"
GRAPHQL_ENGINE_EXTRA_ARGS+=( +RTS -P -RTS )
# TODO alternatively we can do `-pj` and use speedscope (unfortunately we
# can't get both formats of output), but I think profiterole is more
# useful
# GRAPHQL_ENGINE_EXTRA_ARGS+=( +RTS -pj -RTS )
case "${3-}" in
--)
GRAPHQL_ENGINE_EXTRA_ARGS+=( "${@:4}" )
;;
esac
;;
--optimized)
CABAL_PROJECT_FILE=cabal/dev-sh-optimized.project
case "${3-}" in
--)
GRAPHQL_ENGINE_EXTRA_ARGS+=( "${@:4}" )
;;
esac
;;
--)
GRAPHQL_ENGINE_EXTRA_ARGS+=( "${@:3}" )
;;
"")
;;
*)
die_usage
;;
esac
;;
postgres)
;;
mssql)
;;
citus)
;;
mysql)
;;
test)
case "${2-}" in
--unit)
UNIT_TEST_ARGS=( "${@:3}" )
RUN_INTEGRATION_TESTS=false
RUN_UNIT_TESTS=true
RUN_HLINT=false
;;
--integration)
PYTEST_ARGS=( "${@:3}" )
RUN_INTEGRATION_TESTS=true
RUN_UNIT_TESTS=false
RUN_HLINT=false
source scripts/parse-pytest-backend
;;
--hlint)
RUN_INTEGRATION_TESTS=false
RUN_UNIT_TESTS=false
RUN_HLINT=true
;;
"")
RUN_INTEGRATION_TESTS=true
RUN_UNIT_TESTS=true
RUN_HLINT=true
BACKEND="postgres"
;;
*)
die_usage
;;
esac
;;
*)
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"
# In CI we use the get version script to actually populate the version number
# that will be compiled into the server. For local development we use this
# magic number, which means we won't recompile unnecessarily. This number also
# gets explicitly ignored in the version test in integration tests.
echo '12345' > "$PROJECT_ROOT/server/CURRENT_VERSION"
# Use pyenv if available to set an appropriate python version that will work with pytests etc.
# Note: this does not help at all on 'nix' environments since 'pyenv' is not
# something you normally use under nix.
if command -v pyenv >/dev/null; then
# Use the latest version of Python installed with `pyenv`.
# Ensure that it is at least v3.9, so that generic types are fully supported.
v="$(pyenv versions --bare | (grep '^ *3' || true) | awk '{ print $1 }' | tail -n1)"
# Awk fails when you compare e.g. 3.9 and 3.10, because 3.9 is a higher
# number than 3.1 (having coerced both to floats). So, we convert a version
# like 1.20.3 to a number like 001020003000 (every section becomes a
# three-digit number) and we compare them instead.
formatted="$(printf "%03d%03d%03d%03d" $(echo $v | tr '.' ' '))"
if [[ "$formatted" -lt "003009000000" ]]; then
# shellcheck disable=SC2016
echo_error 'Please `pyenv install` a version of python >= 3.9 (found '$v')'
exit 2
fi
echo_pretty "Pyenv found. Using Python version: $v"
export PYENV_VERSION=$v
python3 --version
else
echo_warn "Pyenv not installed. Proceeding with Python from the path, version: $(python3 --version)"
fi
####################################
### Containers setup ###
####################################
source scripts/containers/postgres
source scripts/containers/mssql.sh
source scripts/containers/citus
source scripts/containers/mysql.sh
source scripts/data-sources-util.sh
PG_RUNNING=0
MSSQL_RUNNING=0
CITUS_RUNNING=0
MYSQL_RUNNING=0
function cleanup {
echo
if [ -n "${GRAPHQL_ENGINE_PID-}" ]; then
# Kill the cabal new-run and its children. This may already have been killed:
pkill -P "$GRAPHQL_ENGINE_PID" &>/dev/null || true
fi
if [ $PG_RUNNING -eq 1 ]; then pg_cleanup; fi
if [ $MSSQL_RUNNING -eq 1 ]; then mssql_cleanup; fi
if [ $CITUS_RUNNING -eq 1 ]; then citus_cleanup; fi
if [ $MYSQL_RUNNING -eq 1 ]; then mysql_cleanup; fi
echo_pretty "Done"
}
trap cleanup EXIT
function pg_start() {
if [ $PG_RUNNING -eq 0 ]; then
pg_launch_container
PG_RUNNING=1
pg_wait
fi
}
function mssql_start() {
if [ $MSSQL_RUNNING -eq 0 ]; then
mssql_launch_container
MSSQL_RUNNING=1
mssql_wait
fi
}
function citus_start() {
if [ $CITUS_RUNNING -eq 0 ]; then
citus_launch_container
CITUS_RUNNING=1
citus_wait
fi
}
function mysql_start() {
if [ $MYSQL_RUNNING -eq 0 ]; then
mysql_launch_container
MYSQL_RUNNING=1
mysql_wait
fi
}
function start_dbs() {
# always launch the postgres container
pg_start
case "$BACKEND" in
citus)
citus_start
;;
mssql)
mssql_start
;;
mysql)
mysql_start
;;
# bigquery deliberately omitted as its test setup is atypical. See:
# https://github.com/hasura/graphql-engine/blob/master/server/py-tests/README.md#running-bigquery-tests
esac
}
#################################
### Graphql-engine ###
#################################
if [ "$MODE" = "graphql-engine" ] || [ "$MODE" = "graphql-engine-pro" ]; then
# Set the file descriptor limit up to the hard limit. The common default of
# 1024 is too low to really properly test subscriptions for instance.
# It might be best just to do this in the engines:
# https://hackage.haskell.org/package/unix-2.8.1.1/docs/System-Posix-Resource.html
ulimit -Sn unlimited
cd "$PROJECT_ROOT"
# Existing tix files for a different hge binary will cause issues:
rm -f "$EDITION_NAME.tix"
# Attempt to run this after a CTRL-C:
function cleanup {
echo
### Run analysis or visualization tools, if we ran in one of the profiling modes
case "${HASURA_PROF_MODE-}" in
ticky)
TICKY_FILENAME=$("$PROJECT_ROOT"/scripts/get-version.sh)-$(date +%s).ticky
if [ -f "$EDITION_NAME.ticky" ]; then
# Sort the main part of the profile by allocations and reassemble:
TICKY_TEMPD=$(mktemp -d)
awk -v TICKY_TEMPD="$TICKY_TEMPD" \
'/-------------[-]+$|\*\*\*\*\*[*]+$/{n++}{print >TICKY_TEMPD "/" "x" n }' \
"$EDITION_NAME.ticky"
ticky_tmp=$(mktemp hasura_devsh_ticky.tmp.XXXXXXX)
{
cat "$TICKY_TEMPD/x" "$TICKY_TEMPD/x1" ;
head -n1 "$TICKY_TEMPD/x2" ;
# This is the main section we care about, with allocation counts by name:
tail -n +2 "$TICKY_TEMPD/x2" | sort -k2 -r -n | tee "$ticky_tmp";
cat "$TICKY_TEMPD/x3"
} >> "$TICKY_FILENAME"
# Make sure we didn't screw anything up, e.g. if ticky format changes:
TICKY_FILENAME_sz=$(wc -c <"$TICKY_FILENAME")
wc_c=$(wc -c <"$EDITION_NAME.ticky")
if [ "$TICKY_FILENAME_sz" -ne "$wc_c" ]; then
echo_error "Erm... seems our processing of ticky file has a bug. Please fix me"
fi
rm -r "$TICKY_TEMPD"
echo_warn "Done. View the ticky report at: $TICKY_FILENAME"
echo_warn "See: https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#using-ticky-ticky-profiling-for-implementors"
echo_warn "Lookup referenced STG names dumped to their respective module files: dist-newstyle/**/*.dump-stg-final"
### Do some additional analysis:
# Extract module names, along with allocation counts
ticky_tmp2=$(mktemp hasura_devsh_ticky2.tmp.XXXXXXX)
if command -v rg >/dev/null ; then
rg -o ' +[0-9]+ +([0-9]+).*( | \()([A-Z][a-zA-Z]*(\.[A-Z][A-Za-z]*)*)' -r '$1 $3' \
"$ticky_tmp" > "$ticky_tmp2"
awk '{sum[$2]+=$1} END {for (val in sum) printf "%'"'"'20d\t%s\n", sum[val], val }' "$ticky_tmp2" \
| sort -nr -k1 \
> "$TICKY_FILENAME.modules"
echo
echo_warn "Here are the top modules by allocation (see $TICKY_FILENAME.modules for all):"
head -n5 "$TICKY_FILENAME.modules"
echo
else
echo_error "Please install ripgrep (rg) to get per-module allocation summary"
fi
# NOTE: this should equal the sum of allocations in all entries
# in the list and we find it does within ~1% for e.g. a benchmark
# workload, but it's not clear why it doesn't exactly match:
instrumented_bytes_allocated=$(grep ALLOC_HEAP_tot "$EDITION_NAME.ticky" | awk '{print $1}')
echo_warn "There were..."
printf "%'20d\n" "$instrumented_bytes_allocated"
echo_warn "...bytes allocated from instrumented code in the profile."
echo_warn "Compare this to the \"bytes allocated in the heap\" reported from the"
echo_warn "'+RTS -s' above to see how many allocations aren't visible due to dependencies"
echo_warn "not being instrumented (TODO --prof-ticky-all mode, maybe)"
rm "$ticky_tmp" "$ticky_tmp2" "$EDITION_NAME.ticky"
else
echo_error "Hmmm. $EDITION_NAME.ticky wasn't generated for some reason..."
fi
;;
heap-infomap)
if command -v eventlog2html >/dev/null ; then
echo_warn "Running eventlog2html against the event log we just generated: $EDITION_NAME.eventlog"
eventlog2html --bands 100 "$EDITION_NAME.eventlog"
echo_warn "Done. View the report at: $EDITION_NAME.eventlog.html"
echo_warn "Lookup referenced STG names dumped to their respective module files: dist-newstyle/**/*.dump-stg-final"
else
echo_warn "Please install eventlog2html"
fi
;;
ghc-debug)
# TODO maybe integrate snapshotting + common analysis here
;;
time)
if command -v profiterole >/dev/null ; then
if [ -f "$EDITION_NAME.prof" ]; then
echo_warn "Running profiterole..."
profiterole "$EDITION_NAME.prof"
echo_warn "Done. Check out..."
echo_warn " - $EDITION_NAME.prof ...for the top-down report"
echo_warn " - $EDITION_NAME.profiterole.html ...for the folded report"
echo_warn "Lookup referenced STG names dumped to their respective module files: dist-newstyle/**/*.dump-stg-final"
else
echo_error "No $EDITION_NAME.prof was created... :("
fi
else
echo_warn "You may wish to install profiterole"
fi
;;
"")
;;
*)
echo_error "Bug!: HASURA_PROF_MODE = $HASURA_PROF_MODE"
exit 1
;;
esac
### Generate coverage, which can be useful for debugging or understanding
if command -v hpc >/dev/null && command -v jq >/dev/null ; then
# FIXME: this was broken some time ago
# Get the appropriate mix dir (the newest one); this way this hopefully
# works when 'cabal/dev-sh.project.local' is edited to turn on
# optimizations.
#
# See also: https://hackage.haskell.org/package/cabal-plan
distdir=$(jq -r '."install-plan"[] | select(."id" == "graphql-engine-1.0.0-inplace")? | ."dist-dir"' dist-newstyle/cache/plan.json)
hpcdir="$distdir/hpc/dyn/mix/graphql-engine-1.0.0"
echo_pretty "Generating code coverage report..."
COVERAGE_DIR="dist-newstyle/dev.sh-coverage"
hpc_invocation=(hpc markup
--exclude=Main
--hpcdir "$hpcdir"
--reset-hpcdirs graphql-engine.tix
--fun-entry-count
--destdir="$COVERAGE_DIR")
"${hpc_invocation[@]}" >/dev/null
echo_pretty "To view full coverage report open:"
echo_pretty " file://$(pwd)/$COVERAGE_DIR/hpc_index.html"
tix_archive=dist-newstyle/graphql-engine.tix.$(date "+%Y.%m.%d-%H.%M.%S")
mv graphql-engine.tix "$tix_archive"
echo_pretty ""
echo_pretty "The tix file we used has been archived to: $tix_archive"
echo_pretty ""
echo_pretty "You might want to use 'hpc combine' to create a diff of two different tix"
echo_pretty "files, and then generate a new report with something like:"
echo_pretty " $ ${hpc_invocation[*]}"
else
echo_warn "Please install 'hpc' and 'jq' to get a code coverage report"
fi
}
trap cleanup EXIT
export HASURA_GRAPHQL_DATABASE_URL=${HASURA_GRAPHQL_DATABASE_URL-$PG_DB_URL}
export HASURA_GRAPHQL_SERVER_PORT=${HASURA_GRAPHQL_SERVER_PORT-8181}
# Add 'developer' to the default list, for more visiblility:
export HASURA_GRAPHQL_ENABLED_APIS=metadata,graphql,pgdump,config,developer,metrics
echo_pretty "We will connect to postgres at '$HASURA_GRAPHQL_DATABASE_URL'"
echo_pretty "If you haven't overridden HASURA_GRAPHQL_DATABASE_URL, you can"
echo_pretty "launch a fresh postgres container for us to connect to, in a"
echo_pretty "separate terminal with:"
echo_pretty " $ $0 postgres"
echo_pretty ""
RUN_INVOCATION=(cabal new-run --project-file="$CABAL_PROJECT_FILE" --RTS --
"exe:$EDITION_NAME" +RTS -N -T -s -RTS serve
--enable-console --console-assets-dir "$PROJECT_ROOT/frontend/dist/apps/server-assets-console-$EDITION_ABBREV"
"${GRAPHQL_ENGINE_EXTRA_ARGS[@]}"
)
echo_pretty 'About to do:'
echo_pretty " $ cabal new-build --project-file=$CABAL_PROJECT_FILE exe:$EDITION_NAME"
echo_pretty " $ ${RUN_INVOCATION[*]}"
echo_pretty ''
cabal new-build --project-file="$CABAL_PROJECT_FILE" "exe:$EDITION_NAME"
# We assume a PG is *already running*, and therefore bypass the
# cleanup mechanism previously set.
pg_wait
# 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 "▲▲▲ $EDITION_NAME startup logs above ▲▲▲"
echo_pretty ""
echo_pretty "You can set additional environment vars to tailor '$EDITION_NAME' 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/frontend\""
echo_pretty " $ yarn install && yarn server-build:$EDITION_ABBREV"
echo_pretty ""
echo_pretty "Useful endpoints when compiling with '$EDITION_NAME:developer' and running with '+RTS -T'"
echo_pretty " http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/dev/subscriptions/extended"
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 ""
if [ "$EDITION_NAME" = "graphql-engine-pro" ]; then
echo_pretty "If you want to observe traces, you can run jaeger all-in-oner:"
echo_pretty " $ docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 -e COLLECTOR_OTLP_ENABLED=true -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 4317:4317 -p 4318:4318 -p 14250:14250 -p 14268:14268 -p 14269:14269 -p 9411:9411 jaegertracing/all-in-one:1.44"
echo_pretty "...then configure http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT/console/settings/opentelemetry"
echo_pretty "...setting 'Endpoint' to: http://localhost:4318/v1/traces"
fi
echo_pretty "▼▼▼ additional $EDITION_NAME logs will appear below: ▼▼▼"
} &
# Logs printed until CTRL-C:
"${RUN_INVOCATION[@]}" | try_jq
exit 0
### END SCRIPT ###
#################################
### Postgres container ###
#################################
elif [ "$MODE" = "postgres" ]; then
pg_start
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 " $ $PG_DOCKER"
echo_pretty " or..."
echo_pretty " $ PGPASSWORD=$PG_PASSWORD psql -h 127.0.0.1 -p $PG_PORT postgres -U postgres"
echo_pretty ""
echo_pretty "Here is the database URL:"
echo_pretty " $PG_DB_URL"
echo_pretty ""
echo_pretty "If you want to launch a 'graphql-engine' that works with this database:"
echo_pretty " $ $0 graphql-engine # or graphql-engine-pro"
docker logs -f --tail=0 "$PG_CONTAINER_NAME"
#################################
### MSSQL Container ###
#################################
elif [ "$MODE" = "mssql" ]; then
mssql_start
echo_pretty "MSSQL logs will start to show up in realtime here. Press CTRL-C to exit and "
echo_pretty "shutdown this container."
echo_pretty ""
echo_pretty "Here is the database URL:"
echo_pretty " $MSSQL_CONN_STR"
echo_pretty ""
docker logs -f --tail=0 "$MSSQL_CONTAINER_NAME"
#################################
### Citus Container ###
#################################
elif [ "$MODE" = "citus" ]; then
citus_start
echo_pretty "CITUS 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 " $ $CITUS_DOCKER"
echo_pretty ""
echo_pretty "Here is the database URL:"
echo_pretty " $CITUS_DB_URL"
echo_pretty ""
docker logs -f --tail=0 "$CITUS_CONTAINER_NAME"
#################################
### MySQL Container ###
#################################
elif [ "$MODE" = "mysql" ]; then
mysql_start
echo_pretty "MYSQL 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 " $ $MYSQL_DOCKER"
echo_pretty ""
echo_pretty "If you want to import a SQL file into MYSQL:"
echo_pretty " $ $MYSQL_DOCKER -i <import_file>"
echo_pretty ""
docker logs -f --tail=0 "$MYSQL_CONTAINER_NAME"
elif [ "$MODE" = "test" ]; then
########################################
### Integration / unit tests ###
########################################
cd "$PROJECT_ROOT"
# Until we can use a real webserver for TestEventFlood, limit concurrency
export HASURA_GRAPHQL_EVENTS_HTTP_POOL_SIZE=8
# We'll get an hpc error if these exist; they will be deleted below too:
rm -f graphql-engine-tests.tix graphql-engine.tix graphql-engine-combined.tix
# Various tests take some configuration from the environment; set these up here:
export EVENT_WEBHOOK_HEADER="MyEnvValue"
export EVENT_WEBHOOK_HANDLER="http://localhost:5592"
export ACTION_WEBHOOK_HANDLER="http://localhost:5593"
export SCHEDULED_TRIGGERS_WEBHOOK_DOMAIN="http://localhost:5594"
export REMOTE_SCHEMAS_WEBHOOK_DOMAIN="http://localhost:5000"
export GRAPHQL_SERVICE_HANDLER="http://localhost:4001"
export GRAPHQL_SERVICE_1="http://localhost:4020"
export GRAPHQL_SERVICE_2="http://localhost:4021"
export GRAPHQL_SERVICE_3="http://localhost:4022"
if [ "$RUN_INTEGRATION_TESTS" = true ]; then
# It's better UX to build first (possibly failing) before trying to launch
# PG, but make sure that new-run uses the exact same build plan, else we risk
# rebuilding twice... ugh
# Formerly this was a `cabal build` but mixing cabal build and cabal run
# seems to conflict now, causing re-linking, haddock runs, etc. Instead do a
# `graphql-engine version` to trigger build
cabal run \
--project-file="$CABAL_PROJECT_FILE" \
-- exe:graphql-engine \
--metadata-database-url="$PG_DB_URL" \
version
start_dbs
fi
if [ "$RUN_UNIT_TESTS" = true ]; then
echo_pretty "Running Haskell test suite"
# unit tests need access to postgres and mssql instances:
mssql_start
pg_start
echo "${UNIT_TEST_ARGS[@]}"
HASURA_GRAPHQL_DATABASE_URL="$PG_DB_URL" \
HASURA_MSSQL_CONN_STR="$MSSQL_CONN_STR" \
cabal run \
--project-file="$CABAL_PROJECT_FILE" \
test:graphql-engine-tests \
-- "${UNIT_TEST_ARGS[@]}"
fi
if [ "$RUN_HLINT" = true ]; then
if command -v hlint >/dev/null; then
hlint "${PROJECT_ROOT}/server/src-"*
else
echo_warn "hlint is not installed: skipping"
fi
fi
if [ "$RUN_INTEGRATION_TESTS" = true ]; then
GRAPHQL_ENGINE_TEST_LOG=/tmp/hasura-dev-test-engine.log
echo_pretty "Starting graphql-engine, logging to $GRAPHQL_ENGINE_TEST_LOG"
export HASURA_GRAPHQL_SERVER_PORT=8088
# Extra sources for multi-source tests. Uses the default postgres DB if no extra sources
# are defined.
export HASURA_GRAPHQL_PG_SOURCE_URL_1=${HASURA_GRAPHQL_PG_SOURCE_URL_1-$PG_DB_URL}
export HASURA_GRAPHQL_PG_SOURCE_URL_2=${HASURA_GRAPHQL_PG_SOURCE_URL_2-$PG_DB_URL}
export HASURA_GRAPHQL_MSSQL_SOURCE_URL=$MSSQL_CONN_STR
export HGE_URL="http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT"
# Using --metadata-database-url flag to test multiple backends
# HASURA_GRAPHQL_PG_SOURCE_URL_* For a couple multi-source pytests:
cabal new-run \
--project-file="$CABAL_PROJECT_FILE" \
-- exe:graphql-engine \
--metadata-database-url="$PG_DB_URL" serve \
--stringify-numeric-types \
--enable-console \
--console-assets-dir ../frontend/dist/apps/server-assets-console-ce \
&> "$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
# If the server stopped abort immediately
if ! kill -0 $GRAPHQL_ENGINE_PID ; then
echo_error "The server crashed or failed to start!!"
exit 42
fi
done
echo " Ok"
add_sources $HASURA_GRAPHQL_SERVER_PORT
TEST_DIR="server/tests-py"
# Install and load Python test dependencies
PY_VENV="${TEST_DIR}/.hasura-dev-python-venv"
make "$PY_VENV"
source "${PY_VENV}/bin/activate"
# Install node.js test dependencies
make "${TEST_DIR}/node_modules"
cd "$TEST_DIR"
# TODO MAYBE: fix deprecation warnings, make them an error
if ! pytest \
--hge-urls http://127.0.0.1:$HASURA_GRAPHQL_SERVER_PORT \
--pg-urls "$PG_DB_URL" \
--assert=plain \
"${PYTEST_ARGS[@]}"
then
echo_error "^^^ graphql-engine logs from failed test run can be inspected at: $GRAPHQL_ENGINE_TEST_LOG"
fi
deactivate # python venv
cd "$PROJECT_ROOT/server"
# Kill the cabal new-run and its children. INT so we get hpc report:
pkill -INT -P "$GRAPHQL_ENGINE_PID"
wait "$GRAPHQL_ENGINE_PID" || true
echo
fi # RUN_INTEGRATION_TESTS
# If hpc available, combine any tix from haskell/unit tests:
if command -v hpc >/dev/null; then
if [ "$RUN_UNIT_TESTS" = true ] && [ "$RUN_INTEGRATION_TESTS" = true ]; then
# As below, it seems we variously get errors related to having two Main
# modules, so exclude:
hpc combine --exclude=Main graphql-engine-tests.tix graphql-engine.tix --union > graphql-engine-combined.tix
else
# One of these should exist
cp graphql-engine-tests.tix graphql-engine-combined.tix 2>/dev/null || true
cp graphql-engine.tix graphql-engine-combined.tix 2>/dev/null || true
fi
# Generate a report including the test code itself (see cabal.project.dev-sh.local):
# NOTE: we have to omit the .mix directory for the executable, since it
# seems hpc can't cope with two modules of the same name; '--exclude'
# didn't help.
echo_pretty "Generating code coverage report..."
COVERAGE_DIR="dist-newstyle/dev.sh-coverage"
hpc markup \
--exclude=Main \
--hpcdir dist-newstyle/build/*/ghc-*/graphql-engine-*/noopt/hpc/dyn/mix/graphql-engine-* \
--hpcdir dist-newstyle/build/*/ghc-*/graphql-engine-*/t/graphql-engine-tests/noopt/hpc/dyn/mix/graphql-engine-tests \
--reset-hpcdirs graphql-engine-combined.tix \
--fun-entry-count \
--destdir="$COVERAGE_DIR" >/dev/null
hpc report \
--exclude=Main \
--hpcdir dist-newstyle/build/*/ghc-*/graphql-engine-*/noopt/hpc/dyn/mix/graphql-engine-* \
--hpcdir dist-newstyle/build/*/ghc-*/graphql-engine-*/t/graphql-engine-tests/noopt/hpc/dyn/mix/graphql-engine-tests \
--reset-hpcdirs graphql-engine-combined.tix
echo_pretty "To view full coverage report open:"
echo_pretty " file://$(pwd)/$COVERAGE_DIR/hpc_index.html"
else
echo_warn "Please install hpc to get a combined code coverage report for tests"
fi
rm -f graphql-engine-tests.tix graphql-engine.tix graphql-engine-combined.tix
else
echo "impossible; fix script."
fi