forked from Nixius/authelia
1
0
Fork 0
ATLAS/ship.sh

151 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build the production images on the target Docker context and deploy app.a250.ca.
set -Eeuo pipefail
DOMAIN="${DOMAIN:-app.a250.ca}"
STACK_NAME="${STACK_NAME:-atlas}"
DEPLOY_CONTEXT="${DOCKER_DEPLOY_CONTEXT:-${DEPLOY_CONTEXT:-}}"
DEPLOY_HOST="${DEPLOY_HOST:-app.a250.ca}"
STACK_FILE="${STACK_FILE:-stack.production.yml}"
SKIP_TESTS="${SKIP_TESTS:-1}"
SKIP_HEALTHCHECK="${SKIP_HEALTHCHECK:-1}"
PUSH_IMAGES="${PUSH_IMAGES:-1}"
REGISTRY_IMAGE="${REGISTRY_IMAGE:-git.nixc.us/a250/ss-atlas}"
SS_ATLAS_LOCAL_IMAGE="${SS_ATLAS_LOCAL_IMAGE:-atlas-ss-atlas:production}"
SS_ATLAS_PUSH_IMAGE="${SS_ATLAS_PUSH_IMAGE:-$REGISTRY_IMAGE:production}"
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
log() {
printf '[ship] %s\n' "$*"
}
fail() {
printf '[ship] ERROR: %s\n' "$*" >&2
exit 1
}
run() {
log "+ $*"
"$@"
}
run_docker() {
log "+ docker ${DOCKER_LABEL} $*"
docker "${DOCKER_ARGS[@]}" "$@"
}
require_command() {
command -v "$1" >/dev/null 2>&1 || fail "Missing required command: $1"
}
docker_target() {
docker "${DOCKER_ARGS[@]}" "$@"
}
service_exists() {
docker_target service inspect "$1" >/dev/null 2>&1
}
force_service_image() {
local service="$1"
local image="$2"
if service_exists "$service"; then
run_docker service update --force --image "$image" "$service"
else
log "Service $service is not present yet; stack deploy will create it."
fi
}
cd "$ROOT_DIR"
require_command git
require_command docker
if [ -z "$DEPLOY_CONTEXT" ]; then
if docker context inspect macmini7 >/dev/null 2>&1; then
DEPLOY_CONTEXT="macmini7"
else
DEPLOY_CONTEXT=""
fi
fi
if [ -n "$DEPLOY_CONTEXT" ]; then
DOCKER_ARGS=(--context "$DEPLOY_CONTEXT")
DOCKER_LABEL="--context $DEPLOY_CONTEXT"
else
DOCKER_ARGS=(-H "ssh://$DEPLOY_HOST")
DOCKER_LABEL="-H ssh://$DEPLOY_HOST"
fi
[ -f "$STACK_FILE" ] || fail "Missing $STACK_FILE"
grep -q "$DOMAIN" "$STACK_FILE" || fail "$STACK_FILE does not reference $DOMAIN"
if ! docker_target info >/dev/null 2>&1; then
fail "Docker target '${DOCKER_LABEL}' is not reachable"
fi
if [ "$(docker_target info --format '{{.Swarm.LocalNodeState}}')" != "active" ]; then
fail "Docker target '${DOCKER_LABEL}' is not an active swarm manager"
fi
BUILD_COMMIT="$(git rev-parse --short HEAD)"
if [ -n "$(git status --porcelain)" ]; then
BUILD_COMMIT="${BUILD_COMMIT}-dirty"
log "Working tree has uncommitted changes; shipping current checkout as $BUILD_COMMIT."
fi
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
log "Shipping $BUILD_COMMIT to https://$DOMAIN via docker ${DOCKER_LABEL}."
if [ "$SKIP_TESTS" != "1" ]; then
require_command go
log "+ (cd docker/ss-atlas && go test ./...)"
(cd docker/ss-atlas && go test ./...)
else
log "Skipping tests because SKIP_TESTS=1."
fi
run_docker build \
--pull \
--no-cache \
--build-arg "BUILD_COMMIT=$BUILD_COMMIT" \
--build-arg "BUILD_TIME=$BUILD_TIME" \
--label "org.opencontainers.image.revision=$BUILD_COMMIT" \
--label "org.opencontainers.image.created=$BUILD_TIME" \
-t "$SS_ATLAS_LOCAL_IMAGE" \
-t "$SS_ATLAS_PUSH_IMAGE" \
-f docker/ss-atlas/Dockerfile \
docker/ss-atlas
if [ "$PUSH_IMAGES" = "1" ]; then
run_docker push "$SS_ATLAS_PUSH_IMAGE"
else
log "Skipping image pushes because PUSH_IMAGES=0."
fi
run_docker stack deploy \
--with-registry-auth \
--resolve-image never \
-c "$STACK_FILE" \
"$STACK_NAME"
force_service_image "${STACK_NAME}_ss-atlas" "$SS_ATLAS_PUSH_IMAGE"
log "Current stack tasks:"
run_docker stack ps "$STACK_NAME" --no-trunc
if [ "$SKIP_HEALTHCHECK" != "1" ]; then
require_command curl
run curl -fsS "https://$DOMAIN/health"
printf '\n'
run curl -fsS "https://$DOMAIN/version"
printf '\n'
else
log "Skipping health checks because SKIP_HEALTHCHECK=1."
fi
log "Done. Requested $BUILD_COMMIT on https://$DOMAIN."