diff --git a/.circleci/deploy.sh b/.circleci/deploy.sh index d0bb6749..50842cb6 100755 --- a/.circleci/deploy.sh +++ b/.circleci/deploy.sh @@ -79,6 +79,15 @@ deploy_console() { unset DIST_PATH } +# build and push container for auto-migrations +build_and_push_cli_migrations_image() { + IMAGE_TAG="hasura/graphql-engine:${CIRCLE_TAG}.cli-migrations" + cd "$ROOT/scripts/cli-migrations" + cp /build/_cli_output/binaries/cli-hasura-linux-amd64 . + docker build -t "$IMAGE_TAG" . + docker push "$IMAGE_TAG" +} + # copy docker-compose-https manifests to gcr for digital ocean one-click app deploy_do_manifests() { gsutil cp "$ROOT/install-manifests/docker-compose-https/docker-compose.yaml" \ @@ -125,6 +134,7 @@ deploy_console deploy_server if [[ ! -z "$CIRCLE_TAG" ]]; then deploy_server_latest + build_and_push_cli_migrations_image CHANGELOG_TEXT=$(changelog server) CHANGELOG_TEXT+=$(changelog cli) CHANGELOG_TEXT+=$(changelog console) @@ -136,5 +146,4 @@ EOF configure_git send_pr_to_repo graphql-engine-heroku deploy_do_manifests - fi diff --git a/docs/graphql/manual/migrations/auto-apply-migrations.rst b/docs/graphql/manual/migrations/auto-apply-migrations.rst new file mode 100644 index 00000000..b4cd0ae2 --- /dev/null +++ b/docs/graphql/manual/migrations/auto-apply-migrations.rst @@ -0,0 +1,40 @@ +Auto-apply migrations when server starts +======================================== + +Hasura ships a special docker container which can be used to +automatically apply migrations when the server starts: + +.. code-block:: bash + + hasura/graphql-engine:.cli-migrations + +The ``migrations`` directory created by Hasura CLI (the one next to +``config.yaml``) can be mounted at ``/hasura-migrations`` path of this docker +container and the container's entrypoint script will apply the migrations before +starting the server. If no directory is mounted at the designated path, server +will start ignoring migrations. + +.. note:: + + This container image includes Hasura CLI at ``/bin/hasura-cli`` and can be + used for running any other CI/CD scripts in your workflow. + +If you want to mount the migrations directory at some location other than +``/hasura-migrations``, set the following environment variable: + +.. code-block:: bash + + HASURA_GRAPHQL_MIGRATIONS_DIR=/custom-path-for-migrations + +Once the migrations are applied, the container resumes operation as a normal +Hasura GraphQL Engine server. + +Example: + +.. code-block:: bash + + # Start Hasura after applying the migrations present in /home/me/my-project/migrations + docker run -p 8080:8080 \ + -v /home/me/my-project/migrations:/hasura-migrations \ + -e HASURA_GRAPHQL_DATABASE_URL=postgres://postgres:@postgres:5432/postgres \ + hasura/graphql-engine:v1.0.0-alpha27.cli-migrations diff --git a/docs/graphql/manual/migrations/index.rst b/docs/graphql/manual/migrations/index.rst index 196b2844..cc5455b2 100644 --- a/docs/graphql/manual/migrations/index.rst +++ b/docs/graphql/manual/migrations/index.rst @@ -19,9 +19,14 @@ Follow the guide that best fits your scenario: - :doc:`Migrations with a database with an existing migration system `: Use Hasura only for GraphQL schema changes and not database migrations. +Advanced: + +- :doc:`Auto-apply migrations when server starts ` + .. toctree:: :hidden: For new project For existing project With a database with an existing migration system + Auto-apply migrations when server starts diff --git a/scripts/cli-migrations/.gitignore b/scripts/cli-migrations/.gitignore new file mode 100644 index 00000000..42f0444c --- /dev/null +++ b/scripts/cli-migrations/.gitignore @@ -0,0 +1 @@ +cli-hasura-linux-amd64 \ No newline at end of file diff --git a/scripts/cli-migrations/Dockerfile b/scripts/cli-migrations/Dockerfile new file mode 100644 index 00000000..4bdc4f19 --- /dev/null +++ b/scripts/cli-migrations/Dockerfile @@ -0,0 +1,11 @@ +FROM hasura/graphql-engine:v1.0.0-alpha27 + +ENV HASURA_GRAPHQL_ENABLE_CONSOLE=true + +COPY docker-entrypoint.sh /bin/ +COPY cli-hasura-linux-amd64 /bin/hasura-cli +RUN chmod +x /bin/hasura-cli + +ENTRYPOINT ["docker-entrypoint.sh"] + +CMD ["graphql-engine", "serve"] diff --git a/scripts/cli-migrations/docker-entrypoint.sh b/scripts/cli-migrations/docker-entrypoint.sh new file mode 100755 index 00000000..c93b9662 --- /dev/null +++ b/scripts/cli-migrations/docker-entrypoint.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +set -e + +DEFAULT_MIGRATIONS_DIR="/hasura-migrations" +TEMP_MIGRATIONS_DIR="/tmp/hasura-migrations" + +# wait for a port to be ready +wait_for_port() { + local PORT=$1 + echo "waiting for $PORT" + for i in `seq 1 30`; + do + nc localhost $PORT > /dev/null 2>&1 && echo "port $PORT is ready" && return + echo -n . + sleep 1 + done + echo "failed waiting for $PORT" && exit 1 +} + +echo "starting graphql engine on port 8080..." + +# start graphql engine +graphql-engine serve & +# store the pid to kill it later +PID=$! + +# wait for port 8080 to be ready +wait_for_port 8080 + +# check if migration directory is set, default otherwise +if [ -z ${HASURA_GRAPHQL_MIGRATIONS_DIR+x} ]; then + echo "env var HASURA_GRAPHQL_MIGRATIONS_DIR is not set" + echo "defaulting to $DEFAULT_MIGRATIONS_DIR" + HASURA_GRAPHQL_MIGRATIONS_DIR="$DEFAULT_MIGRATIONS_DIR" +fi + +# apply migrations if the directory exist +if [ -d "$HASURA_GRAPHQL_MIGRATIONS_DIR" ]; then + echo "applying migrations in $HASURA_GRAPHQL_MIGRATIONS_DIR..." + mkdir -p "$TEMP_MIGRATIONS_DIR" + cp -a "$HASURA_GRAPHQL_MIGRATIONS_DIR/." "$TEMP_MIGRATIONS_DIR/migrations/" + cd "$TEMP_MIGRATIONS_DIR" + echo "endpoint: http://localhost:8080" > config.yaml + hasura-cli migrate apply +else + echo "directory $HASURA_GRAPHQL_MIGRATIONS_DIR does not exist" + echo "skipping migration apply" +fi + +# kill graphql engine that we started earlier +kill $PID + +# pass control to CMD +exec "$@" diff --git a/scripts/tag-release.sh b/scripts/tag-release.sh index ebee0215..82036e98 100755 --- a/scripts/tag-release.sh +++ b/scripts/tag-release.sh @@ -16,6 +16,9 @@ set -e # get the repo root ROOT="$(readlink -f ${BASH_SOURCE[0]%/*}/../)" +# paths to replace versions +VERSION_PATHS="$ROOT/install-manifests $ROOT/scripts/cli-migrations" + # check if required argument is set if [ -z "$1" ]; then echo "Usage: ./tag-release.sh []" @@ -32,10 +35,10 @@ if [ -z "$MESSAGE" ]; then fi # replace the image version with latest tag for all references in install-manifests -find "$ROOT/install-manifests" -type f -exec sed -i -E 's#(hasura/graphql-engine:)v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?( \\)*$#\1'"${TAG}"'\9#' {} \; +find "$VERSION_PATHS" -type f -exec sed -i -E 's#(hasura/graphql-engine:)v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?( \\)*$#\1'"${TAG}"'\9#' {} \; -git add "$ROOT/install-manifests" -git commit -m "update installation manifests to $TAG" +git add "$VERSION_PATHS" +git commit -m "update manifests to $TAG" git tag -a "$TAG" -m "$MESSAGE"