diff --git a/production/README.md b/production/README.md index a1f1b13..5889037 100644 --- a/production/README.md +++ b/production/README.md @@ -114,7 +114,7 @@ cd /opt/rentaldrivego docker load -i /opt/docker-image-transfer/carmanagement-latest.tar APP_ENV_FILE=.env.docker.production docker compose --env-file .env.docker.production -f docker-compose.production.yml up -d postgres redis APP_ENV_FILE=.env.docker.production docker compose --env-file .env.docker.production -f docker-compose.production.yml run --rm migrate -APP_ENV_FILE=.env.docker.production docker compose --env-file .env.docker.production -f docker-compose.production.yml up -d api storefront dashboard admin +APP_ENV_FILE=.env.docker.production docker compose --env-file .env.docker.production -f docker-compose.production.yml up -d api homepage storefront dashboard admin ``` ## Source Builds diff --git a/production/deploy-production.sh b/production/deploy-production.sh index 13b7495..e6fbc01 100755 --- a/production/deploy-production.sh +++ b/production/deploy-production.sh @@ -302,7 +302,7 @@ echo "Running database migrations" run_prod_migrations echo "Starting application services" -app_services=(api storefront dashboard admin) +app_services=(api homepage storefront dashboard admin) if [[ "${include_pgmanage}" -eq 1 ]]; then prod_compose --profile private-tools up -d "${app_services[@]}" pgmanage @@ -311,6 +311,7 @@ else fi wait_for_healthy api 180 +wait_for_healthy homepage 180 wait_for_healthy storefront 180 wait_for_healthy dashboard 180 wait_for_healthy admin 180 diff --git a/production/fetch-image-through-vpn.sh b/production/fetch-image-through-vpn.sh index 6c1c0c2..98d8d77 100755 --- a/production/fetch-image-through-vpn.sh +++ b/production/fetch-image-through-vpn.sh @@ -2,7 +2,38 @@ set -euo pipefail -IMAGE_TAG="${IMAGE_TAG:-${1:-13d0512048d86e9fe93e9395459d04663c2b7eb0}}" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="${ENV_FILE:-${SCRIPT_DIR}/.env.docker.production}" + +read_env_value() { + local key="$1" + local value + + if [[ ! -f "${ENV_FILE}" ]]; then + return 0 + fi + + value="$( + awk -F= -v key="$key" ' + $1 == key { + value = substr($0, index($0, "=") + 1) + } + END { + if (value != "") { + print value + } + } + ' "${ENV_FILE}" + )" + + value="${value%$'\r'}" + value="${value#\"}" + value="${value%\"}" + printf '%s' "${value}" +} + +IMAGE_TAG="${IMAGE_TAG:-${1:-$(read_env_value IMAGE_TAG)}}" +IMAGE_TAG="${IMAGE_TAG:-latest}" APP_IMAGE="${APP_IMAGE:-10.0.0.4/melabidi/carmanagement}" REGISTRY_USER="${REGISTRY_USER:-melabidi}" REGISTRY_TOKEN="${REGISTRY_TOKEN:-}" @@ -16,7 +47,7 @@ Usage: Optional env vars: APP_IMAGE Default: 10.0.0.4/melabidi/carmanagement - IMAGE_TAG Default: 13d0512048d86e9fe93e9395459d04663c2b7eb0 + IMAGE_TAG Default: IMAGE_TAG from .env.docker.production, otherwise latest REGISTRY_USER Default: melabidi REGISTRY_TOKEN Prompted when unset TRANSFER_DIR Default: /opt/docker-image-transfer @@ -26,6 +57,13 @@ The script uses skopeo inside the VPN container network and writes: EOF } +case "${1:-}" in + -h|--help) + usage + exit 0 + ;; +esac + if [[ -z "${IMAGE_TAG}" ]]; then usage >&2 exit 1 diff --git a/production/scripts/docker-prod-common.sh b/production/scripts/docker-prod-common.sh index 8474c95..3858ed9 100755 --- a/production/scripts/docker-prod-common.sh +++ b/production/scripts/docker-prod-common.sh @@ -209,6 +209,7 @@ pull_prod_release_images() { require_release_image if load_release_image_archives; then + verify_prod_release_image return 0 fi @@ -219,7 +220,27 @@ pull_prod_release_images() { exit 1 fi - prod_compose pull migrate api storefront dashboard admin + prod_compose pull migrate api homepage storefront dashboard admin + verify_prod_release_image +} + +verify_prod_release_image() { + require_release_image + + local image="${APP_IMAGE:-rentaldrivego/carmanagement}:${IMAGE_TAG}" + + echo "Verifying production image contents: ${image}" + if ! docker image inspect "${image}" >/dev/null 2>&1; then + echo "Production image is not available locally after load/pull: ${image}" >&2 + exit 1 + fi + + if ! docker run --rm --entrypoint sh "${image}" -c 'test -f /app/config/nextSecurityHeaders.js' >/dev/null 2>&1; then + echo "Production image is missing /app/config/nextSecurityHeaders.js: ${image}" >&2 + echo "This image cannot start the Next.js apps because their next.config.js files require ../../config/nextSecurityHeaders." >&2 + echo "Build and transfer a fresh image from the full repository, then rerun deployment." >&2 + exit 1 + fi } load_release_image_archives() { diff --git a/production/scripts/docker-prod-deploy.sh b/production/scripts/docker-prod-deploy.sh index 4e946b0..a96ad18 100755 --- a/production/scripts/docker-prod-deploy.sh +++ b/production/scripts/docker-prod-deploy.sh @@ -26,8 +26,9 @@ echo "Running database migrations" run_prod_migrations echo "Starting application services" -prod_compose up -d api storefront dashboard admin +prod_compose up -d api homepage storefront dashboard admin wait_for_healthy api 180 +wait_for_healthy homepage 180 wait_for_healthy storefront 180 wait_for_healthy dashboard 180 wait_for_healthy admin 180 diff --git a/production/scripts/docker-prod-restore.sh b/production/scripts/docker-prod-restore.sh index f5b16f1..41c8170 100755 --- a/production/scripts/docker-prod-restore.sh +++ b/production/scripts/docker-prod-restore.sh @@ -44,7 +44,7 @@ SKIP_RAW_RESTORE_VOLUMES=( ) echo "Stopping application services before restore..." -prod_compose stop api storefront dashboard admin pgmanage >/dev/null || true +prod_compose stop api homepage storefront dashboard admin pgmanage >/dev/null || true prod_compose stop redis >/dev/null || true stop_traefik diff --git a/production/scripts/docker-prod-run-pulled-image.sh b/production/scripts/docker-prod-run-pulled-image.sh index 6a539dc..2ea4430 100755 --- a/production/scripts/docker-prod-run-pulled-image.sh +++ b/production/scripts/docker-prod-run-pulled-image.sh @@ -90,7 +90,7 @@ echo "Applying migrations" prod_compose run --rm migrate echo "Starting application services" -app_services=(api storefront dashboard admin) +app_services=(api homepage storefront dashboard admin) if [[ "${INCLUDE_PGMANAGE}" == "1" ]]; then prod_compose --profile private-tools up -d "${app_services[@]}" pgmanage @@ -98,6 +98,7 @@ else prod_compose up -d "${app_services[@]}" fi wait_for_healthy api 180 +wait_for_healthy homepage 180 wait_for_healthy storefront 180 wait_for_healthy dashboard 180 wait_for_healthy admin 180 diff --git a/production/scripts/docker-prod-up-all.sh b/production/scripts/docker-prod-up-all.sh index 8f875ae..6a5c858 100755 --- a/production/scripts/docker-prod-up-all.sh +++ b/production/scripts/docker-prod-up-all.sh @@ -6,10 +6,11 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" source "${ROOT_DIR}/scripts/docker-prod-common.sh" start_traefik -start_prod_services postgres redis api storefront dashboard admin +start_prod_services postgres redis api homepage storefront dashboard admin wait_for_healthy api +wait_for_healthy homepage wait_for_healthy storefront wait_for_healthy dashboard wait_for_healthy admin -echo "Production stack is up and healthy: traefik, postgres, redis, api, storefront, dashboard, admin" +echo "Production stack is up and healthy: traefik, postgres, redis, api, homepage, storefront, dashboard, admin"