这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.hasura-dev-python-venv
server/tests-py/.devsh_version
npm-debug.log
*.temp
*.DS_Store
Expand All @@ -8,5 +9,8 @@ test-server-flags-output
.vscode
.idea

# Standardize on 'venv' as the name for python venv directories
venv

# Test artifacts
*.tix
263 changes: 171 additions & 92 deletions scripts/dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ set -euo pipefail
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
Expand All @@ -28,15 +34,22 @@ Available COMMANDs:
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.
test [--integration [pytest_args...] | --unit]
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

EOL
exit 1
}

# Bump this to:
# - force a reinstall of dependencies
DEVSH_VERSION=1.2

case "${1-}" in
graphql-engine)
case "${2-}" in
Expand All @@ -54,7 +67,24 @@ case "${1-}" in
postgres)
;;
test)
PYTEST_ARGS="${@:2}"
case "${2-}" in
--unit)
RUN_INTEGRATION_TESTS=false
RUN_UNIT_TESTS=true
;;
--integration)
PYTEST_ARGS="${@:3}"
RUN_INTEGRATION_TESTS=true
RUN_UNIT_TESTS=false
;;
"")
RUN_INTEGRATION_TESTS=true
RUN_UNIT_TESTS=true
;;
*)
die_usage
;;
esac
;;
*)
die_usage
Expand All @@ -68,6 +98,20 @@ MODE="$1"
PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" # ... https://stackoverflow.com/a/246128/176841
cd "$PROJECT_ROOT"

# Use pyenv if available to set an appropriate python version that will work with pytests etc.
if command -v pyenv >/dev/null; then
# For now I guess use the greatest python3 >= 3.5
v=$(pyenv versions --bare | (grep '^ *3' || true) | awk '{if($1>=3.5)print$1}' | tail -n1)
if [ -z "$v" ]; then
echo_error 'Please `pyenv install` a version of python >= 3.5 so we can use it'
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 system python version: $(python3 --version)"
fi

####################################
### Shared environment stuff ###
Expand Down Expand Up @@ -112,15 +156,14 @@ if [ "$MODE" = "graphql-engine" ]; then
export HASURA_GRAPHQL_SERVER_PORT=${HASURA_GRAPHQL_SERVER_PORT-8181}

# Prettify JSON output if possible:
if command -v jq ; then
if command -v jq >/dev/null; 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

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-}"

Expand All @@ -140,6 +183,7 @@ if [ "$MODE" = "graphql-engine" ]; then
else
$BUILD_INVOCATION
fi
wait_docker_postgres

# Print helpful info after startup logs so it's visible:
{
Expand Down Expand Up @@ -181,7 +225,6 @@ 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)
Expand All @@ -200,19 +243,18 @@ 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
function launch_postgres_container(){
echo_pretty "Launching postgres container: $PG_CONTAINER_NAME"
docker run --name "$PG_CONTAINER_NAME" -p 127.0.0.1:"$PG_PORT":$PG_PORT --expose="$PG_PORT" \
-e POSTGRES_PASSWORD="$PGPASSWORD" -d circleci/postgres:11.5-alpine-postgis \
$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
Expand All @@ -221,41 +263,43 @@ if [[ \$@ == *" -f"* ]]; then
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
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
# 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
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
case "$MODE" in
test|postgres)
# Since scripts here are tailored to the env we've just launched:
rm -r "$DEV_SHIM_PATH"

wait_docker_postgres
echo_pretty "Removing $PG_CONTAINER_NAME and its volumes in 5 seconds!"
echo_pretty " PRESS CTRL-C TO ABORT removal, or ENTER to clean up right away"
read -t5 || true
docker stop "$PG_CONTAINER_NAME"
docker rm -v "$PG_CONTAINER_NAME"
;;
graphql-engine)
;;
esac

echo_pretty "Done"
}
trap cleanup EXIT
}


if [ "$MODE" = "postgres" ]; then
launch_postgres_container
wait_docker_postgres
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 ""
Expand Down Expand Up @@ -284,54 +328,89 @@ elif [ "$MODE" = "test" ]; then
echo_pretty "Rebuilding for code coverage"
$BUILD_INVOCATION --coverage

echo_pretty "Running Haskell test suite"
HASURA_GRAPHQL_DATABASE_URL="$DB_URL" $TEST_INVOCATION --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 wheel
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\""
# It's better UX to build first (possibly failing) before trying to launch PG:
launch_postgres_container
wait_docker_postgres

source "$PY_VENV/bin/activate"
# These also depend on a running DB:
if [ "$RUN_UNIT_TESTS" = true ]; then
echo_pretty "Running Haskell test suite"
HASURA_GRAPHQL_DATABASE_URL="$DB_URL" $TEST_INVOCATION --coverage
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
if [ "$RUN_INTEGRATION_TESTS" = true ]; then
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"

### Check for and install dependencies in venv
cd "$PROJECT_ROOT/server/tests-py"
PY_VENV=.hasura-dev-python-venv
DEVSH_VERSION_FILE=.devsh_version
# Do we need to force reinstall?
if [ "$DEVSH_VERSION" = "$(cat $DEVSH_VERSION_FILE 2>/dev/null || true)" ]; then
true # ok
else
echo_warn 'dev.sh version was bumped. Forcing reinstallation of dependencies.'
rm -r "$PY_VENV"
echo "$DEVSH_VERSION" > "$DEVSH_VERSION_FILE"
fi
set +u # for venv activate
if [ ! -d "$PY_VENV" ]; then
python3 -m venv "$PY_VENV"
source "$PY_VENV/bin/activate"
pip3 install wheel
# If the maintainer of this script or pytests needs to change dependencies:
# - alter requirements-top-level.txt as needed
# - delete requirements.txt
# - run this script, then check in the new frozen requirements.txt
if [ -f requirements.txt ]; then
pip3 install -r requirements.txt
else
pip3 install -r requirements-top-level.txt
pip3 freeze > requirements.txt
fi
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

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

# 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
# Combine any tix from haskell/unit tests:
if [ "$RUN_UNIT_TESTS" = true ]; then
stack exec hpc -- combine "$(stack path --local-hpc-root)/graphql-engine/graphql-engine-tests/graphql-engine-tests.tix" graphql-engine.tix --union > graphql-engine-combined.tix
stack hpc report graphql-engine-combined.tix
else
stack hpc report graphql-engine.tix
fi
fi
rm -f graphql-engine.tix graphql-engine-combined.tix

else
echo "impossible; fix script."
Expand Down
1 change: 1 addition & 0 deletions server/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ own machine and how to contribute.
- brotli
- libpq-dev
- python >= 3.5 with pip3
- [pyenv](https://github.com/pyenv/pyenv) (Recommended, not required)

The Brotli can be installed from source using `git`, `cmake` and `pkgconf` on Debian with:

Expand Down
5 changes: 3 additions & 2 deletions server/tests-py/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,9 @@ def v1q(self, q, headers = {}):

def v1q_f(self, fn):
with open(fn) as f:
# NOTE: preserve ordering with RoundTripLoader:
return self.v1q(yaml.load(f, yaml.RoundTripLoader))
# NOTE: preserve ordering with ruamel
yml = yaml.YAML()
return self.v1q(yml.load(f))

def teardown(self):
self.http.close()
Expand Down
Loading