diff --git a/docs/appendices/0.6.0-migration-guide.md b/docs/appendices/0.6.0-migration-guide.md index ed587123826..d5d773577d7 100644 --- a/docs/appendices/0.6.0-migration-guide.md +++ b/docs/appendices/0.6.0-migration-guide.md @@ -1,6 +1,7 @@ # 0.6.0 Migration Guide ## zero-downtime deployment + - You can now **actually** disable zero-downtime deployments per-app and per-process-type - Some config variables have been moved around - `DOKKU_CHECKS_ENABLED` has been migrated to `DOKKU_CHECKS_SKIPPED` @@ -9,5 +10,17 @@ - See the [updated `checks`](/dokku/checks-examples/) docs for more info ## proxy port mapping + - You can now configure host -> container proxy port mappings - The UI is handled by the [proxy](/dokku/proxy/) interface plugin by setting the `DOKKU_PROXY_PORT_MAP` config variable in the format of `scheme:host-port:container-port`. The default `nginx-vhosts` proxy plugin supports both the `http` and `https` schemes. + +## calling the dokku binary + +- Plugins should *not* call the dokku binary directly. Clients using the `--app` argument are potentially broken, amongst others, when doing so. Instead, please source the `functions` file for a given plugin when attempting to call dokku internal functions. As a result, the following dokku commands are no longer publicly exposed: + - dokku build + - dokku receive + - dokku release + - dokku tar:build + - dokku tar:build-locked + - dokku git:build + - dokku git:build-locked diff --git a/docs/development/plugin-creation.md b/docs/development/plugin-creation.md index c08749d90b8..26c717f7074 100644 --- a/docs/development/plugin-creation.md +++ b/docs/development/plugin-creation.md @@ -155,3 +155,4 @@ A few notes: - From time to time you may want to allow other plugins access to (some of) your plugin's functionality. You can expose this by including a `functions` file in your plugin for others to source. Consider all functions in that file to be publicly accessible by other plugins. Any functions not wished to be made "public" should reside within your plugin trigger or commands files. - As of 0.4.0, we allow image tagging and deployment of said tagged images. Therefore, hard-coding of `$IMAGE` as `dokku/$APP` is no longer sufficient. Instead, for non `pre/post-build-*` plugins, use `get_running_image_tag()` & `get_app_image_name()` as sourced from common/functions. See the [plugin triggers](/dokku/development/plugin-triggers) doc for examples. - As of 0.5.0, we use container labels to help cleanup intermediate containers with `dokku cleanup`. If manually calling `docker run`, include `$DOKKU_GLOBAL_RUN_ARGS`. This will ensure you intermediate containers labeled correctly. +- As of 0.6.0, we advise you to *not* call the dokku binary directly from within plugins. Clients using the `--app` argument are potentially broken, amongst other issues, when doing so. Instead, please source the `functions` file for a given plugin when attempting to call dokku internal functions diff --git a/docs/development/plugin-triggers.md b/docs/development/plugin-triggers.md index 4b2933f441c..c39de89d18d 100644 --- a/docs/development/plugin-triggers.md +++ b/docs/development/plugin-triggers.md @@ -164,7 +164,7 @@ esac ### `docker-args-build` - Description: -- Invoked by: `dokku build` +- Invoked by: `internal function dokku_build() (build phase)` - Arguments: `$APP $IMAGE_SOURCE_TYPE` - Example: @@ -300,7 +300,7 @@ nginx -t ### `post-build-buildpack` - Description: Allows you to run commands after the build image is create for a given app. Only applies to applications using buildpacks. -- Invoked by: `dokku build` +- Invoked by: `internal function dokku_build() (build phase)` - Arguments: `$APP` - Example: @@ -315,7 +315,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x ### `post-build-dockerfile` - Description: Allows you to run commands after the build image is create for a given app. Only applies to applications using a dockerfile. -- Invoked by: `dokku build` +- Invoked by: `internal function dokku_build() (build phase)` - Arguments: `$APP` - Example: @@ -423,7 +423,7 @@ haproxy-build-config "$APP" ### `post-release-buildpack` - Description: Allows you to run commands after environment variables are set for the release step of the deploy. Only applies to applications using buildpacks. -- Invoked by: `dokku release` +- Invoked by: `internal function dokku_release() (release phase)` - Arguments: `$APP $IMAGE_TAG` - Example: @@ -450,7 +450,7 @@ docker commit $ID $IMAGE > /dev/null ### `post-release-dockerfile` - Description: Allows you to run commands after environment variables are set for the release step of the deploy. Only applies to applications using a dockerfile. -- Invoked by: `dokku release` +- Invoked by: `internal function dokku_release() (release phase)` - Arguments: `$APP $IMAGE_TAG` - Example: @@ -486,7 +486,7 @@ dokku config:set --no-restart $APP MANUALLY_STOPPED=1 ### `pre-build-buildpack` - Description: Allows you to run commands before the build image is created for a given app. For instance, this can be useful to add env vars to your container. Only applies to applications using buildpacks. -- Invoked by: `dokku build` +- Invoked by: `internal function dokku_build() (build phase)` - Arguments: `$APP` - Example: @@ -501,7 +501,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x ### `pre-build-dockerfile` - Description: Allows you to run commands before the build image is created for a given app. For instance, this can be useful to add env vars to your container. Only applies to applications using a dockerfile. -- Invoked by: `dokku build` +- Invoked by: `internal function dokku_build() (build phase)` - Arguments: `$APP` - Example: @@ -580,7 +580,7 @@ echo "$APP" > "$TMP_WORK_DIR/dokku-is-awesome" ### `pre-release-buildpack` - Description: Allows you to run commands before environment variables are set for the release step of the deploy. Only applies to applications using buildpacks. -- Invoked by: `dokku release` +- Invoked by: `internal function dokku_release() (release phase)` - Arguments: `$APP $IMAGE_TAG` - Example: @@ -607,7 +607,7 @@ docker commit $ID $IMAGE > /dev/null ### `pre-release-dockerfile` - Description: Allows you to run commands before environment variables are set for the release step of the deploy. Only applies to applications using a dockerfile. -- Invoked by: `dokku release` +- Invoked by: `internal function dokku_release() (release phase)` - Arguments: `$APP $IMAGE_TAG` - Example: diff --git a/dokku b/dokku index b80742acc3d..4238b4f1044 100755 --- a/dokku +++ b/dokku @@ -100,13 +100,10 @@ execute_dokku_cmd() { nginx|nginx:*) local PLUGIN_NAME=${PLUGIN_NAME/nginx/nginx-vhosts} ;; - receive|deploy|build|release) + deploy|delete|ls|run|cleanup) local PLUGIN_NAME="00_dokku-standard" ;; - trace|delete|ls|run|cleanup) - local PLUGIN_NAME="00_dokku-standard" - ;; - url|urls|report|version) + trace|url|urls|report|version) local PLUGIN_NAME="00_dokku-standard" ;; esac diff --git a/plugins/00_dokku-standard/subcommands/build b/plugins/00_dokku-standard/subcommands/build deleted file mode 100755 index 4df74e26b40..00000000000 --- a/plugins/00_dokku-standard/subcommands/build +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_AVAILABLE_PATH/config/functions" - -dokku_build_cmd() { - declare desc="build phase" - local cmd="build" - local APP="$2"; local IMAGE_SOURCE_TYPE="$3"; local TMP_WORK_DIR="$4"; local IMAGE=$(get_app_image_name "$APP") - verify_app_name "$APP" - - local CACHE_DIR="$DOKKU_ROOT/$APP/cache" - - eval "$(config_export app "$APP")" - pushd "$TMP_WORK_DIR" &> /dev/null - - case "$IMAGE_SOURCE_TYPE" in - herokuish) - local id=$(tar -c . | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$DOKKU_IMAGE" /bin/bash -c "mkdir -p /app && tar -xC /app") - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - [[ -d $CACHE_DIR ]] || mkdir -p "$CACHE_DIR" - plugn trigger pre-build-buildpack "$APP" - - local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") - [[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true " - # shellcheck disable=SC2086 - local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -v $CACHE_DIR:/cache -e CACHE_PATH=/cache $DOCKER_ARGS $IMAGE /build) - docker attach "$id" - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - - plugn trigger post-build-buildpack "$APP" - ;; - - dockerfile) - # extract first port from Dockerfile - local DOCKERFILE_PORTS=$(get_dockerfile_exposed_ports Dockerfile) - [[ -n "$DOCKERFILE_PORTS" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKERFILE_PORTS" - - # extract ENTRYPOINT/CMD from Dockerfile - local DOCKERFILE_ENTRYPOINT=$(extract_directive_from_dockerfile Dockerfile ENTRYPOINT) - [[ -n "$DOCKERFILE_ENTRYPOINT" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_ENTRYPOINT="$DOCKERFILE_ENTRYPOINT" - local DOCKERFILE_CMD=$(extract_directive_from_dockerfile Dockerfile CMD) - [[ -n "$DOCKERFILE_CMD" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_CMD="$DOCKERFILE_CMD" - plugn trigger pre-build-dockerfile "$APP" - - [[ "$DOKKU_DOCKERFILE_CACHE_BUILD" == "false" ]] && DOKKU_DOCKER_BUILD_OPTS="$DOKKU_DOCKER_BUILD_OPTS --no-cache" - local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") - # strip --volume and -v args from DOCKER_ARGS - local DOCKER_ARGS=$(sed -e "s/--volume=[[:graph:]]\+[[:blank:]]\?//g" -e "s/-v[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" <<< "$DOCKER_ARGS") - - # shellcheck disable=SC2086 - docker build $DOCKER_ARGS $DOKKU_DOCKER_BUILD_OPTS -t $IMAGE . - - plugn trigger post-build-dockerfile "$APP" - ;; - - *) - dokku_log_fail "Building image source type $IMAGE_SOURCE_TYPE not supported!" - ;; - esac -} - -dokku_build_cmd "$@" diff --git a/plugins/00_dokku-standard/subcommands/deploy b/plugins/00_dokku-standard/subcommands/deploy index 68f1a2252d8..888165a4cfb 100755 --- a/plugins/00_dokku-standard/subcommands/deploy +++ b/plugins/00_dokku-standard/subcommands/deploy @@ -1,175 +1,6 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_AVAILABLE_PATH/checks/functions" -source "$PLUGIN_AVAILABLE_PATH/config/functions" -source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" - -dokku_deploy_cmd() { - declare desc="deploy phase" - local cmd="deploy" - [[ -z $2 ]] && dokku_log_fail "Please specify an app to deploy" - local APP="$2"; local IMAGE_TAG="$3"; local IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG") - verify_app_name "$APP" - plugn trigger pre-deploy "$APP" "$IMAGE_TAG" - - is_image_herokuish_based "$IMAGE" && local DOKKU_HEROKUISH=true - local DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" - local oldids=$(get_app_container_ids "$APP") - - local DOKKU_DEFAULT_DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG") - local DOKKU_IS_APP_PROXY_ENABLED="$(is_app_proxy_enabled "$APP")" - local DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)" - [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}" - - local line; local PROC_TYPE; local PROC_COUNT; local CONTAINER_INDEX - while read -r line || [[ -n "$line" ]]; do - [[ "$line" =~ ^#.* ]] && continue - line="$(strip_inline_comments "$line")" - PROC_TYPE=${line%%=*} - PROC_COUNT=${line#*=} - CONTAINER_INDEX=1 - - if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "true" ]]; then - dokku_log_info1 "zero downtime is disabled for app ($APP.$PROC_TYPE). stopping currently running containers" - local cid proctype_oldids="$(get_app_container_ids "$APP" "$PROC_TYPE")" - for cid in $proctype_oldids; do - dokku_log_info2 "stopping $APP.$PROC_TYPE ($cid)" - # shellcheck disable=SC2086 - docker stop $DOCKER_STOP_TIME_ARG "$cid" &> /dev/null - done - fi - - while [[ $CONTAINER_INDEX -le $PROC_COUNT ]]; do - local id=""; local port=""; local ipaddr="" - local DOKKU_CONTAINER_ID_FILE="$DOKKU_ROOT/$APP/CONTAINER.$PROC_TYPE.$CONTAINER_INDEX" - local DOKKU_IP_FILE="$DOKKU_ROOT/$APP/IP.$PROC_TYPE.$CONTAINER_INDEX" - local DOKKU_PORT_FILE="$DOKKU_ROOT/$APP/PORT.$PROC_TYPE.$CONTAINER_INDEX" - - # start the app - local DOCKER_ARGS="$DOKKU_DEFAULT_DOCKER_ARGS" - local DOCKER_ARGS+=" -e DYNO='$PROC_TYPE.$CONTAINER_INDEX' " - [[ "$DOKKU_TRACE" ]] && local DOCKER_ARGS+=" -e TRACE=true " - - [[ -n "$DOKKU_HEROKUISH" ]] && local START_CMD="/start $PROC_TYPE" - - if [[ -z "$DOKKU_HEROKUISH" ]]; then - local DOKKU_DOCKERFILE_PORTS=($(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true)) - local DOKKU_DOCKERFILE_START_CMD=$(config_get "$APP" DOKKU_DOCKERFILE_START_CMD || true) - local DOKKU_PROCFILE_START_CMD=$(get_cmd_from_procfile "$APP" "$PROC_TYPE") - local START_CMD=${DOKKU_DOCKERFILE_START_CMD:-$DOKKU_PROCFILE_START_CMD} - fi - - if [[ "$PROC_TYPE" == "web" ]]; then - if [[ -z "${DOKKU_DOCKERFILE_PORTS[*]}" ]]; then - local port=5000 - local DOKKU_DOCKER_PORT_ARGS+="-p $port" - else - local p - for p in ${DOKKU_DOCKERFILE_PORTS[*]};do - if [[ ! "$p" =~ .*udp.* ]]; then - # set port to first non-udp port - local p=${p//\/tcp} - local port=${port:="$p"} - fi - local DOKKU_DOCKER_PORT_ARGS+=" -p $p " - done - fi - if [[ "$DOKKU_IS_APP_PROXY_ENABLED" == "true" ]]; then - # shellcheck disable=SC2086 - local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -e PORT=$port $DOCKER_ARGS $IMAGE $START_CMD) - local ipaddr=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$id") - # Docker < 1.9 compatibility - if [[ -z $ipaddr ]]; then - local ipaddr=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$id") - fi - else - # shellcheck disable=SC2086 - local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOKKU_DOCKER_PORT_ARGS -e PORT=$port $DOCKER_ARGS $IMAGE $START_CMD) - local port=$(docker port "$id" "$port" | sed 's/[0-9.]*://') - local ipaddr=127.0.0.1 - fi - else - # shellcheck disable=SC2086 - local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOCKER_ARGS $IMAGE $START_CMD) - fi - - kill_new() { - declare desc="wrapper function to kill newly started app container" - local id="$1" - docker inspect "$id" &> /dev/null && docker stop "$id" > /dev/null && docker kill "$id" &> /dev/null - trap - INT TERM EXIT - kill -9 $$ - } - - # run checks first, then post-deploy hooks, which switches proxy traffic - trap 'kill_new $id' INT TERM EXIT - if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "false" ]]; then - dokku_log_info1 "Attempting pre-flight checks" - plugn trigger check-deploy "$APP" "$id" "$PROC_TYPE" "$port" "$ipaddr" - fi - trap - INT TERM EXIT - - # now using the new container - [[ -n "$id" ]] && echo "$id" > "$DOKKU_CONTAINER_ID_FILE" - [[ -n "$ipaddr" ]] && echo "$ipaddr" > "$DOKKU_IP_FILE" - [[ -n "$port" ]] && echo "$port" > "$DOKKU_PORT_FILE" - - # cleanup pre-migration files - rm -f "$DOKKU_ROOT/$APP/CONTAINER" "$DOKKU_ROOT/$APP/IP" "$DOKKU_ROOT/$APP/PORT" - - local CONTAINER_INDEX=$(( CONTAINER_INDEX + 1 )) - done - # cleanup when we scale down - if [[ "$PROC_COUNT" == 0 ]]; then - local CONTAINER_IDX_OFFSET=0 - else - local CONTAINER_IDX_OFFSET=$((PROC_COUNT + 1)) - fi - local container_state_filetype - for container_state_filetype in CONTAINER IP PORT; do - cd "$DOKKU_ROOT/$APP" - find . -maxdepth 1 -name "$container_state_filetype.$PROC_TYPE.*" -printf "%f\n" | sort -t . -k 3 -n | tail -n +$CONTAINER_IDX_OFFSET | xargs rm -f - done - done < "$DOKKU_SCALE_FILE" - - dokku_log_info1 "Running post-deploy" - plugn trigger post-deploy "$APP" "$port" "$ipaddr" "$IMAGE_TAG" - - # kill the old container - if [[ -n "$oldids" ]]; then - - if [[ -z "$DOKKU_WAIT_TO_RETIRE" ]]; then - local DOKKU_APP_DOKKU_WAIT_TO_RETIRE=$(config_get "$APP" DOKKU_WAIT_TO_RETIRE || true) - local DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE=$(config_get --global DOKKU_WAIT_TO_RETIRE || true) - local DOKKU_WAIT_TO_RETIRE=${DOKKU_APP_DOKKU_WAIT_TO_RETIRE:="$DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE"} - fi - - # Let the old container finish processing requests, before terminating it - local WAIT="${DOKKU_WAIT_TO_RETIRE:-60}" - dokku_log_info1 "Shutting down old containers in $WAIT seconds" - local oldid - for oldid in $oldids; do - dokku_log_info2 "$oldid" - done - ( - exec >/dev/null 2>/dev/null /dev/null - dokku build "$APP" "$IMAGE_SOURCE_TYPE" "$TMP_WORK_DIR" - release_and_deploy "$APP" -} - -dokku_receive_cmd "$@" diff --git a/plugins/00_dokku-standard/subcommands/release b/plugins/00_dokku-standard/subcommands/release deleted file mode 100755 index 7dc14801474..00000000000 --- a/plugins/00_dokku-standard/subcommands/release +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_AVAILABLE_PATH/config/functions" - -dokku_release_cmd() { - declare desc="release phase" - local cmd="release" - local APP="$2"; local IMAGE_SOURCE_TYPE="$3"; local IMAGE_TAG="$4"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG") - verify_app_name "$APP" - - case "$IMAGE_SOURCE_TYPE" in - herokuish) - plugn trigger pre-release-buildpack "$APP" "$IMAGE_TAG" - if [[ -n $(config_export global) ]]; then - local id=$(config_export global | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/00-global-env.sh") - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - fi - if [[ -n $(config_export app "$APP") ]]; then - local id=$(config_export app "$APP" | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/01-app-env.sh") - test "$(docker wait "$id")" -eq 0 - docker commit "$id" "$IMAGE" > /dev/null - fi - plugn trigger post-release-buildpack "$APP" "$IMAGE_TAG" - ;; - - dockerfile) - # buildstep plugins don't necessarily make sense for dockerfiles. call the new breed!!! - plugn trigger pre-release-dockerfile "$APP" "$IMAGE_TAG" - plugn trigger post-release-dockerfile "$APP" "$IMAGE_TAG" - ;; - - *) - dokku_log_fail "Releasing image source type $IMAGE_SOURCE_TYPE not supported!" - ;; - esac -} - -dokku_release_cmd "$@" diff --git a/plugins/checks/install b/plugins/checks/install index be3feb8d372..28185822aba 100755 --- a/plugins/checks/install +++ b/plugins/checks/install @@ -6,8 +6,8 @@ source "$PLUGIN_AVAILABLE_PATH/config/functions" migrate_checks_vars_0_5_0() { declare desc="migrates deprecated CHECKS config variables to simplified counter part introduced in 0.5.x" local APPS="$(dokku_apps)" - local GLOBAL_SKIP_ALL_CHECKS=$(dokku config:get --global DOKKU_SKIP_ALL_CHECKS || true) - local GLOBAL_SKIP_DEFAULT_CHECKS=$(dokku config:get --global DOKKU_SKIP_DEFAULT_CHECKS || true) + local GLOBAL_SKIP_ALL_CHECKS=$(config_get --global DOKKU_SKIP_ALL_CHECKS || true) + local GLOBAL_SKIP_DEFAULT_CHECKS=$(config_get --global DOKKU_SKIP_DEFAULT_CHECKS || true) local app @@ -16,8 +16,8 @@ migrate_checks_vars_0_5_0() { dokku_log_info2 "Please use dokku checks:[disable|enable] to control zero downtime functionality" for app in $APPS; do - local APP_SKIP_ALL_CHECKS=$(dokku config:get "$app" DOKKU_SKIP_ALL_CHECKS || true) - local APP_SKIP_DEFAULT_CHECKS=$(dokku config:get "$app" DOKKU_SKIP_DEFAULT_CHECKS || true) + local APP_SKIP_ALL_CHECKS=$(config_get "$app" DOKKU_SKIP_ALL_CHECKS || true) + local APP_SKIP_DEFAULT_CHECKS=$(config_get "$app" DOKKU_SKIP_DEFAULT_CHECKS || true) if [[ "$APP_SKIP_ALL_CHECKS" == "true" ]] || [[ "$APP_SKIP_DEFAULT_CHECKS" == "true" ]] || [[ "$GLOBAL_SKIP_ALL_CHECKS" == "true" ]] || [[ "$GLOBAL_SKIP_DEFAULT_CHECKS" == "true" ]]; then dokku_log_info2 "" @@ -48,9 +48,9 @@ migrate_checks_vars_0_6_0() { dokku_log_info1 "Migrating zero downtime env variables to 0.6.x. The following variables will be migrated" dokku_log_info2 "DOKKU_CHECKS_ENABLED -> DOKKU_CHECKS_SKIPPED" for app in $APPS; do - local APP_DOKKU_CHECKS_ENABLED=$(dokku config:get "$app" DOKKU_CHECKS_ENABLED || true) + local APP_DOKKU_CHECKS_ENABLED=$(config_get "$app" DOKKU_CHECKS_ENABLED || true) if [[ $APP_DOKKU_CHECKS_ENABLED ]]; then - if [[ "$DOKKU_CHECKS_ENABLED" == "0" ]]; then + if [[ "$APP_DOKKU_CHECKS_ENABLED" == "0" ]]; then dokku_log_info2 "" dokku_log_info2 "zero downtime checks disabled for app ($app)" config_set --no-restart "$app" DOKKU_CHECKS_SKIPPED="_all_" diff --git a/plugins/common/functions b/plugins/common/functions index 9fb90c6d1e9..c495e8af1a6 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -414,6 +414,272 @@ is_app_running() { fi } +dokku_build() { + declare desc="build phase" + source "$PLUGIN_AVAILABLE_PATH/config/functions" + + local APP="$1"; local IMAGE_SOURCE_TYPE="$2"; local TMP_WORK_DIR="$3"; local IMAGE=$(get_app_image_name "$APP") + verify_app_name "$APP" + + local CACHE_DIR="$DOKKU_ROOT/$APP/cache" + + eval "$(config_export app "$APP")" + pushd "$TMP_WORK_DIR" &> /dev/null + + case "$IMAGE_SOURCE_TYPE" in + herokuish) + local id=$(tar -c . | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$DOKKU_IMAGE" /bin/bash -c "mkdir -p /app && tar -xC /app") + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + [[ -d $CACHE_DIR ]] || mkdir -p "$CACHE_DIR" + plugn trigger pre-build-buildpack "$APP" + + local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") + [[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true " + # shellcheck disable=SC2086 + local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -v $CACHE_DIR:/cache -e CACHE_PATH=/cache $DOCKER_ARGS $IMAGE /build) + docker attach "$id" + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + + plugn trigger post-build-buildpack "$APP" + ;; + + dockerfile) + # extract first port from Dockerfile + local DOCKERFILE_PORTS=$(get_dockerfile_exposed_ports Dockerfile) + [[ -n "$DOCKERFILE_PORTS" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKERFILE_PORTS" + + # extract ENTRYPOINT/CMD from Dockerfile + local DOCKERFILE_ENTRYPOINT=$(extract_directive_from_dockerfile Dockerfile ENTRYPOINT) + [[ -n "$DOCKERFILE_ENTRYPOINT" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_ENTRYPOINT="$DOCKERFILE_ENTRYPOINT" + local DOCKERFILE_CMD=$(extract_directive_from_dockerfile Dockerfile CMD) + [[ -n "$DOCKERFILE_CMD" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_CMD="$DOCKERFILE_CMD" + plugn trigger pre-build-dockerfile "$APP" + + [[ "$DOKKU_DOCKERFILE_CACHE_BUILD" == "false" ]] && DOKKU_DOCKER_BUILD_OPTS="$DOKKU_DOCKER_BUILD_OPTS --no-cache" + local DOCKER_ARGS=$(: | plugn trigger docker-args-build "$APP" "$IMAGE_SOURCE_TYPE") + # strip --volume and -v args from DOCKER_ARGS + local DOCKER_ARGS=$(sed -e "s/--volume=[[:graph:]]\+[[:blank:]]\?//g" -e "s/-v[[:blank:]]\?[[:graph:]]\+[[:blank:]]\?//g" <<< "$DOCKER_ARGS") + + # shellcheck disable=SC2086 + docker build $DOCKER_ARGS $DOKKU_DOCKER_BUILD_OPTS -t $IMAGE . + + plugn trigger post-build-dockerfile "$APP" + ;; + + *) + dokku_log_fail "Building image source type $IMAGE_SOURCE_TYPE not supported!" + ;; + esac +} + +dokku_release() { + declare desc="release phase" + source "$PLUGIN_AVAILABLE_PATH/config/functions" + + local APP="$1"; local IMAGE_SOURCE_TYPE="$2"; local IMAGE_TAG="$3"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG") + verify_app_name "$APP" + + case "$IMAGE_SOURCE_TYPE" in + herokuish) + plugn trigger pre-release-buildpack "$APP" "$IMAGE_TAG" + if [[ -n $(config_export global) ]]; then + local id=$(config_export global | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/00-global-env.sh") + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + fi + if [[ -n $(config_export app "$APP") ]]; then + local id=$(config_export app "$APP" | docker run "$DOKKU_GLOBAL_RUN_ARGS" -i -a stdin "$IMAGE" /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/01-app-env.sh") + test "$(docker wait "$id")" -eq 0 + docker commit "$id" "$IMAGE" > /dev/null + fi + plugn trigger post-release-buildpack "$APP" "$IMAGE_TAG" + ;; + + dockerfile) + # buildstep plugins don't necessarily make sense for dockerfiles. call the new breed!!! + plugn trigger pre-release-dockerfile "$APP" "$IMAGE_TAG" + plugn trigger post-release-dockerfile "$APP" "$IMAGE_TAG" + ;; + + *) + dokku_log_fail "Releasing image source type $IMAGE_SOURCE_TYPE not supported!" + ;; + esac +} + +dokku_deploy_cmd() { + declare desc="deploy phase" + local cmd="deploy" + source "$PLUGIN_AVAILABLE_PATH/checks/functions" + source "$PLUGIN_AVAILABLE_PATH/config/functions" + source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" + + [[ -z $1 ]] && dokku_log_fail "Please specify an app to deploy" + local APP="$1"; local IMAGE_TAG="$2"; local IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG") + verify_app_name "$APP" + plugn trigger pre-deploy "$APP" "$IMAGE_TAG" + + is_image_herokuish_based "$IMAGE" && local DOKKU_HEROKUISH=true + local DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" + local oldids=$(get_app_container_ids "$APP") + + local DOKKU_DEFAULT_DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG") + local DOKKU_IS_APP_PROXY_ENABLED="$(is_app_proxy_enabled "$APP")" + local DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)" + [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}" + + local line; local PROC_TYPE; local PROC_COUNT; local CONTAINER_INDEX + while read -r line || [[ -n "$line" ]]; do + [[ "$line" =~ ^#.* ]] && continue + line="$(strip_inline_comments "$line")" + PROC_TYPE=${line%%=*} + PROC_COUNT=${line#*=} + CONTAINER_INDEX=1 + + if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "true" ]]; then + dokku_log_info1 "zero downtime is disabled for app ($APP.$PROC_TYPE). stopping currently running containers" + local cid proctype_oldids="$(get_app_container_ids "$APP" "$PROC_TYPE")" + for cid in $proctype_oldids; do + dokku_log_info2 "stopping $APP.$PROC_TYPE ($cid)" + # shellcheck disable=SC2086 + docker stop $DOCKER_STOP_TIME_ARG "$cid" &> /dev/null + done + fi + + while [[ $CONTAINER_INDEX -le $PROC_COUNT ]]; do + local id=""; local port=""; local ipaddr="" + local DOKKU_CONTAINER_ID_FILE="$DOKKU_ROOT/$APP/CONTAINER.$PROC_TYPE.$CONTAINER_INDEX" + local DOKKU_IP_FILE="$DOKKU_ROOT/$APP/IP.$PROC_TYPE.$CONTAINER_INDEX" + local DOKKU_PORT_FILE="$DOKKU_ROOT/$APP/PORT.$PROC_TYPE.$CONTAINER_INDEX" + + # start the app + local DOCKER_ARGS="$DOKKU_DEFAULT_DOCKER_ARGS" + local DOCKER_ARGS+=" -e DYNO='$PROC_TYPE.$CONTAINER_INDEX' " + [[ "$DOKKU_TRACE" ]] && local DOCKER_ARGS+=" -e TRACE=true " + + [[ -n "$DOKKU_HEROKUISH" ]] && local START_CMD="/start $PROC_TYPE" + + if [[ -z "$DOKKU_HEROKUISH" ]]; then + local DOKKU_DOCKERFILE_PORTS=($(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true)) + local DOKKU_DOCKERFILE_START_CMD=$(config_get "$APP" DOKKU_DOCKERFILE_START_CMD || true) + local DOKKU_PROCFILE_START_CMD=$(get_cmd_from_procfile "$APP" "$PROC_TYPE") + local START_CMD=${DOKKU_DOCKERFILE_START_CMD:-$DOKKU_PROCFILE_START_CMD} + fi + + if [[ "$PROC_TYPE" == "web" ]]; then + if [[ -z "${DOKKU_DOCKERFILE_PORTS[*]}" ]]; then + local port=5000 + local DOKKU_DOCKER_PORT_ARGS+="-p $port" + else + local p + for p in ${DOKKU_DOCKERFILE_PORTS[*]};do + if [[ ! "$p" =~ .*udp.* ]]; then + # set port to first non-udp port + local p=${p//\/tcp} + local port=${port:="$p"} + fi + local DOKKU_DOCKER_PORT_ARGS+=" -p $p " + done + fi + if [[ "$DOKKU_IS_APP_PROXY_ENABLED" == "true" ]]; then + # shellcheck disable=SC2086 + local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d -e PORT=$port $DOCKER_ARGS $IMAGE $START_CMD) + local ipaddr=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$id") + # Docker < 1.9 compatibility + if [[ -z $ipaddr ]]; then + local ipaddr=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$id") + fi + else + # shellcheck disable=SC2086 + local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOKKU_DOCKER_PORT_ARGS -e PORT=$port $DOCKER_ARGS $IMAGE $START_CMD) + local port=$(docker port "$id" "$port" | sed 's/[0-9.]*://') + local ipaddr=127.0.0.1 + fi + else + # shellcheck disable=SC2086 + local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOCKER_ARGS $IMAGE $START_CMD) + fi + + kill_new() { + declare desc="wrapper function to kill newly started app container" + local id="$1" + docker inspect "$id" &> /dev/null && docker stop "$id" > /dev/null && docker kill "$id" &> /dev/null + trap - INT TERM EXIT + kill -9 $$ + } + + # run checks first, then post-deploy hooks, which switches proxy traffic + trap 'kill_new $id' INT TERM EXIT + if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "false" ]]; then + dokku_log_info1 "Attempting pre-flight checks" + plugn trigger check-deploy "$APP" "$id" "$PROC_TYPE" "$port" "$ipaddr" + fi + trap - INT TERM EXIT + + # now using the new container + [[ -n "$id" ]] && echo "$id" > "$DOKKU_CONTAINER_ID_FILE" + [[ -n "$ipaddr" ]] && echo "$ipaddr" > "$DOKKU_IP_FILE" + [[ -n "$port" ]] && echo "$port" > "$DOKKU_PORT_FILE" + + # cleanup pre-migration files + rm -f "$DOKKU_ROOT/$APP/CONTAINER" "$DOKKU_ROOT/$APP/IP" "$DOKKU_ROOT/$APP/PORT" + + local CONTAINER_INDEX=$(( CONTAINER_INDEX + 1 )) + done + # cleanup when we scale down + if [[ "$PROC_COUNT" == 0 ]]; then + local CONTAINER_IDX_OFFSET=0 + else + local CONTAINER_IDX_OFFSET=$((PROC_COUNT + 1)) + fi + local container_state_filetype + for container_state_filetype in CONTAINER IP PORT; do + cd "$DOKKU_ROOT/$APP" + find . -maxdepth 1 -name "$container_state_filetype.$PROC_TYPE.*" -printf "%f\n" | sort -t . -k 3 -n | tail -n +$CONTAINER_IDX_OFFSET | xargs rm -f + done + done < "$DOKKU_SCALE_FILE" + + dokku_log_info1 "Running post-deploy" + plugn trigger post-deploy "$APP" "$port" "$ipaddr" "$IMAGE_TAG" + + # kill the old container + if [[ -n "$oldids" ]]; then + + if [[ -z "$DOKKU_WAIT_TO_RETIRE" ]]; then + local DOKKU_APP_DOKKU_WAIT_TO_RETIRE=$(config_get "$APP" DOKKU_WAIT_TO_RETIRE || true) + local DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE=$(config_get --global DOKKU_WAIT_TO_RETIRE || true) + local DOKKU_WAIT_TO_RETIRE=${DOKKU_APP_DOKKU_WAIT_TO_RETIRE:="$DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE"} + fi + + # Let the old container finish processing requests, before terminating it + local WAIT="${DOKKU_WAIT_TO_RETIRE:-60}" + dokku_log_info1 "Shutting down old containers in $WAIT seconds" + local oldid + for oldid in $oldids; do + dokku_log_info2 "$oldid" + done + ( + exec >/dev/null 2>/dev/null /dev/null + dokku_build "$APP" "$IMAGE_SOURCE_TYPE" "$TMP_WORK_DIR" + release_and_deploy "$APP" +} + docker_cleanup() { declare desc="cleans up all exited/dead containers and removes all dangling images" # delete all non-running containers @@ -820,3 +1103,36 @@ merge_dedupe_list() { local merged_list="$(tr "$delimiter" $'\n' <<< "$input_lists" | sort | uniq | xargs)" echo "$merged_list" } + +acquire_app_deploy_lock() { + declare desc="acquire advisory lock for use in git/tar deploys" + local APP="$1"; verify_app_name "$APP" + local LOCK_TYPE="${2:-waiting}" + local APP_DEPLOY_LOCK_FD="200" + local APP_DEPLOY_LOCK_FILE="$DOKKU_ROOT/$APP/.deploy.lock" + local LOCK_WAITING_MSG="$APP is currently being deployed. Waiting..." + local LOCK_FAILED_MSG="$APP is currently being deployed. Exiting..." + local SHOW_MSG=true + + eval "exec $APP_DEPLOY_LOCK_FD>$APP_DEPLOY_LOCK_FILE" + if [[ "$LOCK_TYPE" == "waiting" ]]; then + while [[ $(flock -n "$APP_DEPLOY_LOCK_FD" &>/dev/null ; echo $?) -ne 0 ]]; do + if [[ "$SHOW_MSG" == "true" ]]; then + echo "$LOCK_WAITING_MSG" + SHOW_MSG=false + fi + sleep 1 + done + else + flock -n "$APP_DEPLOY_LOCK_FD" &>/dev/null || dokku_log_fail "$LOCK_FAILED_MSG" + fi +} + +release_app_deploy_lock() { + declare desc="release advisory lock used in git/tar deploys" + local APP="$1"; verify_app_name "$APP" + local APP_DEPLOY_LOCK_FD="200" + local APP_DEPLOY_LOCK_FILE="$DOKKU_ROOT/$APP/.deploy.lock" + + flock -u "$APP_DEPLOY_LOCK_FD" && rm -f "$APP_DEPLOY_LOCK_FILE" &> /dev/null +} diff --git a/plugins/config/functions b/plugins/config/functions index b2a1e83659a..c97ff7c5706 100755 --- a/plugins/config/functions +++ b/plugins/config/functions @@ -160,6 +160,8 @@ config_get() { config_set() { declare desc="set value of given config var" + source "$PLUGIN_AVAILABLE_PATH/ps/functions" + [[ "$1" == "config:set" ]] || set -- "config:set" "$@" config_parse_args "$@" @@ -214,12 +216,14 @@ ${var}" [[ $APP ]] && local DOKKU_APP_RESTORE=$(config_get "$APP" DOKKU_APP_RESTORE || true) if [[ "$DOKKU_CONFIG_RESTART" == "true" ]] && [[ "$DOKKU_APP_RESTORE" != 0 ]]; then dokku_log_info1 "Restarting app $APP" - dokku ps:restart "$APP" + ps_restart "$APP" fi } config_unset() { declare desc="unset given config var" + source "$PLUGIN_AVAILABLE_PATH/ps/functions" + [[ "$1" == "config:unset" ]] || set -- "config:unset" "$@" config_parse_args "$@" local SANITIZED_ARGS=($(get_sanitized_config_args "$@")) @@ -247,6 +251,6 @@ config_unset() { [[ $APP ]] && local DOKKU_APP_RESTORE=$(config_get "$APP" DOKKU_APP_RESTORE || true) if [[ "$DOKKU_CONFIG_RESTART" == "true" ]] && [[ "$DOKKU_APP_RESTORE" != 0 ]]; then dokku_log_info1 "Restarting app $APP" - dokku ps:restart "$APP" + ps_restart "$APP" fi } diff --git a/plugins/git/commands b/plugins/git/commands index f7f409b0233..7df19a867ad 100755 --- a/plugins/git/commands +++ b/plugins/git/commands @@ -1,130 +1,6 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_AVAILABLE_PATH/apps/functions" -source "$PLUGIN_AVAILABLE_PATH/config/functions" - -git_build_app_repo() { - declare desc="builds local git app repo for app" - verify_app_name "$1" - local APP="$1"; local REV="$2" - - # clean up after ourselves - local GIT_BUILD_APP_REPO_TMP_WORK_DIR=$(mktemp -d "/tmp/dokku_git.XXXX") - trap 'rm -rf "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null' RETURN INT TERM EXIT - - - # git clone - this method creates a new git repository and adds the primary - # repo as a remote, then does a fetch depth=1 to avoid cloning - # the entire repo - local TMP_TAG="dokku/$REV" - chmod 755 "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" - unset GIT_DIR GIT_WORK_TREE - pushd "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null - [[ ! -d "$DOKKU_ROOT/$APP" ]] && apps_create "$APP" - GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true - GIT_DIR="$DOKKU_ROOT/$APP" git tag "$TMP_TAG" "$REV" &> /dev/null - git init &> /dev/null - git config advice.detachedHead false - git remote add origin "$DOKKU_ROOT/$APP" &> /dev/null - git fetch --depth=1 origin "refs/tags/$TMP_TAG" &> /dev/null - git reset --hard FETCH_HEAD &> /dev/null - git submodule update --init --recursive &> /dev/null - GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true - find -name .git -prune -exec rm -rf {} \; > /dev/null - - if [[ -f Dockerfile ]] && [[ "$([[ -f .env ]] && grep -q BUILDPACK_URL .env; echo $?)" != "0" ]] && [[ ! -f ".buildpacks" ]] && [[ -z $(config_get "$APP" BUILDPACK_URL || true) ]]; then - plugn trigger pre-receive-app "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" - dokku receive "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" - else - plugn trigger pre-receive-app "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" - dokku receive "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" - fi -} - -git_hook_cmd() { - declare desc="kick off receive-app trigger from git prereceive hook" - local cmd="git-hook" - local APP="$2" - - local oldrev newrev refname - while read -r oldrev newrev refname; do - # Only run this script for the master branch. You can remove this - # if block if you wish to run it for others as well. - if [[ $refname = "refs/heads/master" ]]; then - # broken out into plugin so we might support other methods to receive an app - # shellcheck disable=SC2086 - plugn trigger receive-app $APP $newrev - else - if [[ $(find "$PLUGIN_PATH"/enabled/*/receive-branch 2>/dev/null | wc -l) != 0 ]]; then - # shellcheck disable=SC2086 - plugn trigger receive-branch $APP $newrev $refname - else - echo $'\e[1G\e[K'"-----> WARNING: deploy did not complete, you must push to master." - echo $'\e[1G\e[K'"-----> for example, try 'git push ${refname/refs\/heads\/}:master'" - fi - fi - done -} - -git_upload_pack_cmd() { - declare desc="executes git-upload-pack" - local cmd="git-upload-pack" - local APP="$(echo "$2" | perl -pe 's/(?/dev/null ; echo $?) -ne 0 ]] && echo "$APP_BUILD_LOCK_MSG" - - shift 1 - flock -o "$APP_BUILD_LOCK" dokku git-build-locked "$@" -} - -git_build_locked_cmd() { - declare desc="setup and call git_build_app_repo" - local cmd="git-build-locked" - local APP="$2" - if [[ $# -ge 3 ]]; then - local REF="$3" - else - local REF=$(< "$DOKKU_ROOT/$APP/refs/heads/master") - fi - # shellcheck disable=SC2086 - git_build_app_repo $APP $REF -} - -git_glob_cmd() { - declare desc="catch-all for any other git-* commands" - local cmd="git-*" - local APP="$(echo "$2" | perl -pe 's/(? /dev/null - local PRERECEIVE_HOOK="$APP_PATH/hooks/pre-receive" - cat > "$PRERECEIVE_HOOK" < /dev/null' RETURN INT TERM EXIT + + # git clone - this method creates a new git repository and adds the primary + # repo as a remote, then does a fetch depth=1 to avoid cloning + # the entire repo + local TMP_TAG="dokku/$REV" + chmod 755 "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" + unset GIT_DIR GIT_WORK_TREE + pushd "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null + [[ ! -d "$DOKKU_ROOT/$APP" ]] && apps_create "$APP" + GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true + GIT_DIR="$DOKKU_ROOT/$APP" git tag "$TMP_TAG" "$REV" &> /dev/null + git init &> /dev/null + git config advice.detachedHead false + git remote add origin "$DOKKU_ROOT/$APP" &> /dev/null + git fetch --depth=1 origin "refs/tags/$TMP_TAG" &> /dev/null + git reset --hard FETCH_HEAD &> /dev/null + git submodule update --init --recursive &> /dev/null + GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true + find -name .git -prune -exec rm -rf {} \; > /dev/null + + if [[ -f Dockerfile ]] && [[ "$([[ -f .env ]] && grep -q BUILDPACK_URL .env; echo $?)" != "0" ]] && [[ ! -f ".buildpacks" ]] && [[ -z $(config_get "$APP" BUILDPACK_URL || true) ]]; then + plugn trigger pre-receive-app "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" + dokku_receive "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" + else + plugn trigger pre-receive-app "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" + dokku_receive "$APP" "herokuish" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" | sed -u "s/^/"$'\e[1G'"/" + fi +} + +git_hook_cmd() { + declare desc="kick off receive-app trigger from git prereceive hook" + local cmd="git-hook" + local APP="$2" + + local oldrev newrev refname + while read -r oldrev newrev refname; do + # Only run this script for the master branch. You can remove this + # if block if you wish to run it for others as well. + if [[ $refname = "refs/heads/master" ]]; then + # broken out into plugin so we might support other methods to receive an app + # shellcheck disable=SC2086 + plugn trigger receive-app $APP $newrev + else + if [[ $(find "$PLUGIN_PATH"/enabled/*/receive-branch 2>/dev/null | wc -l) != 0 ]]; then + # shellcheck disable=SC2086 + plugn trigger receive-branch $APP $newrev $refname + else + echo $'\e[1G\e[K'"-----> WARNING: deploy did not complete, you must push to master." + echo $'\e[1G\e[K'"-----> for example, try 'git push ${refname/refs\/heads\/}:master'" + fi + fi + done +} + +git_build() { + declare desc="setup and call git_build_app_repo" + local APP="$1" + if [[ $# -ge 2 ]]; then + local REF="$2" + else + local REF=$(< "$DOKKU_ROOT/$APP/refs/heads/master") + fi + + # shellcheck disable=SC2086 + git_build_app_repo $APP $REF +} + +git_upload_pack_cmd() { + declare desc="executes git-upload-pack" + local cmd="git-upload-pack" + local APP="$(echo "$2" | perl -pe 's/(? /dev/null + local PRERECEIVE_HOOK="$APP_PATH/hooks/pre-receive" + cat > "$PRERECEIVE_HOOK" </dev/null ; echo $?) -ne 0 ]] && echo "$APP_BUILD_LOCK_MSG" - - shift 1 - flock -o "$APP_BUILD_LOCK" dokku tar:build-locked "$@" -} - -tar_build_cmd "$@" diff --git a/plugins/tar/subcommands/from b/plugins/tar/subcommands/from index c51b74fbf16..9e66df76a7a 100755 --- a/plugins/tar/subcommands/from +++ b/plugins/tar/subcommands/from @@ -1,15 +1,5 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -tar_from_cmd() { - declare desc="deploys app from tarball at URL via command line" - local cmd="tar:from" - verify_app_name "$2" - local APP=$2 - local URL=$3 - shift 3 - curl -# --insecure -L "$URL" | dokku tar:in "$APP" "$@" -} +source "$PLUGIN_AVAILABLE_PATH/tar/functions" tar_from_cmd "$@" diff --git a/plugins/tar/subcommands/in b/plugins/tar/subcommands/in index 7bbdb5f87c3..d39277d7540 100755 --- a/plugins/tar/subcommands/in +++ b/plugins/tar/subcommands/in @@ -1,15 +1,5 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -tar_in_cmd() { - declare desc="deploys app from tarball on STDIN via command line" - local cmd="tar:in" - local APP="$2" - - verify_app_name "$2" - tee "$DOKKU_ROOT/$APP/src.tar" | wc -c - plugn trigger receive-app "$APP" -} +source "$PLUGIN_AVAILABLE_PATH/tar/functions" tar_in_cmd "$@"