From f4ea01e9de18b7219b1d79c22b6dff7a04d0fad6 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 4 Jul 2026 17:08:47 -0400 Subject: [PATCH] Fix production deployment for public site routing - pass `NEXT_PUBLIC_CARPLACE_URL` into the production Docker build - keep `NEXT_PUBLIC_STOREFRONT_URL` as a backward-compatible fallback - run the production deploy script from the Gitea workflow after building - include `homepage` in production deploy, pull, and health-check service lists - allow deploy to use a release image already built locally on the VPS --- .gitea/workflows/build-and-deploy.yml | 49 ++++++++++++++++++++++++- scripts/docker-prod-common.sh | 8 +++- scripts/docker-prod-deploy.sh | 3 +- scripts/docker-prod-run-pulled-image.sh | 3 +- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/build-and-deploy.yml b/.gitea/workflows/build-and-deploy.yml index 75f54a8..3cff92e 100644 --- a/.gitea/workflows/build-and-deploy.yml +++ b/.gitea/workflows/build-and-deploy.yml @@ -92,6 +92,7 @@ jobs: env: NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} NEXT_PUBLIC_HOMEPAGE_URL: ${{ secrets.NEXT_PUBLIC_HOMEPAGE_URL }} + NEXT_PUBLIC_CARPLACE_URL: ${{ secrets.NEXT_PUBLIC_CARPLACE_URL }} NEXT_PUBLIC_STOREFRONT_URL: ${{ secrets.NEXT_PUBLIC_STOREFRONT_URL }} NEXT_PUBLIC_DASHBOARD_URL: ${{ secrets.NEXT_PUBLIC_DASHBOARD_URL }} NEXT_PUBLIC_ADMIN_URL: ${{ secrets.NEXT_PUBLIC_ADMIN_URL }} @@ -113,9 +114,13 @@ jobs: esac } + if [ -z "$NEXT_PUBLIC_CARPLACE_URL" ] && [ -n "$NEXT_PUBLIC_STOREFRONT_URL" ]; then + NEXT_PUBLIC_CARPLACE_URL="${NEXT_PUBLIC_STOREFRONT_URL%/}/carplace" + fi + validate_url NEXT_PUBLIC_API_URL "$NEXT_PUBLIC_API_URL" validate_url NEXT_PUBLIC_HOMEPAGE_URL "$NEXT_PUBLIC_HOMEPAGE_URL" - validate_url NEXT_PUBLIC_STOREFRONT_URL "$NEXT_PUBLIC_STOREFRONT_URL" + validate_url NEXT_PUBLIC_CARPLACE_URL "$NEXT_PUBLIC_CARPLACE_URL" validate_url NEXT_PUBLIC_DASHBOARD_URL "$NEXT_PUBLIC_DASHBOARD_URL" validate_url NEXT_PUBLIC_ADMIN_URL "$NEXT_PUBLIC_ADMIN_URL" validate_url SITE_ORIGIN "$SITE_ORIGIN" @@ -245,6 +250,7 @@ jobs: REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} NEXT_PUBLIC_HOMEPAGE_URL: ${{ secrets.NEXT_PUBLIC_HOMEPAGE_URL }} + NEXT_PUBLIC_CARPLACE_URL: ${{ secrets.NEXT_PUBLIC_CARPLACE_URL }} NEXT_PUBLIC_STOREFRONT_URL: ${{ secrets.NEXT_PUBLIC_STOREFRONT_URL }} NEXT_PUBLIC_DASHBOARD_URL: ${{ secrets.NEXT_PUBLIC_DASHBOARD_URL }} NEXT_PUBLIC_ADMIN_URL: ${{ secrets.NEXT_PUBLIC_ADMIN_URL }} @@ -259,6 +265,9 @@ jobs: fi SSH_OPTIONS="-i $HOME/.ssh/id_rsa -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=$HOME/.ssh/known_hosts" REGISTRY_PASSWORD_B64="$(printf '%s' "$REGISTRY_PASSWORD" | base64 | tr -d '\n')" + if [ -z "$NEXT_PUBLIC_CARPLACE_URL" ] && [ -n "$NEXT_PUBLIC_STOREFRONT_URL" ]; then + NEXT_PUBLIC_CARPLACE_URL="${NEXT_PUBLIC_STOREFRONT_URL%/}/carplace" + fi ssh $SSH_OPTIONS "${{ secrets.VPS_USER }}@$VPS_HOST" " set -e cd '$REMOTE_BUILD_DIR' @@ -281,7 +290,7 @@ jobs: --build-arg ADMIN_INTERNAL_URL=http://admin:3002 \ --build-arg NEXT_PUBLIC_API_URL='$NEXT_PUBLIC_API_URL' \ --build-arg NEXT_PUBLIC_HOMEPAGE_URL='$NEXT_PUBLIC_HOMEPAGE_URL' \ - --build-arg NEXT_PUBLIC_STOREFRONT_URL='$NEXT_PUBLIC_STOREFRONT_URL' \ + --build-arg NEXT_PUBLIC_CARPLACE_URL='$NEXT_PUBLIC_CARPLACE_URL' \ --build-arg NEXT_PUBLIC_DASHBOARD_URL='$NEXT_PUBLIC_DASHBOARD_URL' \ --build-arg NEXT_PUBLIC_ADMIN_URL='$NEXT_PUBLIC_ADMIN_URL' \ --build-arg SITE_ORIGIN='$SITE_ORIGIN' \ @@ -291,3 +300,39 @@ jobs: docker push '$IMAGE_LATEST' fi " + + - name: Deploy production stack on VPS + env: + IMAGE_REPOSITORY: ${{ steps.image-meta.outputs.repository }} + IMAGE_TAG: ${{ gitea.sha }} + ENV_DOCKER_PRODUCTION_B64: ${{ secrets.ENV_DOCKER_PRODUCTION_B64 }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + REMOTE_BUILD_DIR: ${{ env.DEPLOY_ROOT }}/build-context + VPS_HOST: ${{ secrets.VPS_IP }} + run: | + VPS_HOST="${VPS_HOST:-$DEPLOY_SSH_HOST}" + if [ -z "$VPS_HOST" ]; then + echo "::error::VPS_IP secret or DEPLOY_SSH_HOST is required" + exit 1 + fi + if [ -z "$ENV_DOCKER_PRODUCTION_B64" ]; then + echo "::error::ENV_DOCKER_PRODUCTION_B64 is required to deploy the production stack" + exit 1 + fi + SSH_OPTIONS="-i $HOME/.ssh/id_rsa -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=$HOME/.ssh/known_hosts" + ENV_DOCKER_PRODUCTION_B64_CLEAN="$(printf '%s' "$ENV_DOCKER_PRODUCTION_B64" | tr -d '[:space:]')" + REGISTRY_PASSWORD_B64="$(printf '%s' "$REGISTRY_PASSWORD" | base64 | tr -d '\n')" + ssh $SSH_OPTIONS "${{ secrets.VPS_USER }}@$VPS_HOST" " + set -e + mkdir -p '$DEPLOY_ROOT' + printf '%s' '$ENV_DOCKER_PRODUCTION_B64_CLEAN' | base64 -d > '$DEPLOY_ROOT/.env.docker.production' + chmod 600 '$DEPLOY_ROOT/.env.docker.production' + cd '$REMOTE_BUILD_DIR' + export APP_IMAGE='$DEPLOY_REGISTRY_HOST/$IMAGE_REPOSITORY' + export IMAGE_TAG='$IMAGE_TAG' + export REGISTRY_HOST='$DEPLOY_REGISTRY_HOST' + export REGISTRY_USER='$REGISTRY_USERNAME' + export REGISTRY_PASSWORD=\"\$(printf '%s' '$REGISTRY_PASSWORD_B64' | base64 -d)\" + bash scripts/docker-prod-deploy.sh + " diff --git a/scripts/docker-prod-common.sh b/scripts/docker-prod-common.sh index 19e46bc..02c7079 100644 --- a/scripts/docker-prod-common.sh +++ b/scripts/docker-prod-common.sh @@ -349,6 +349,12 @@ pull_prod_release_images() { require_release_image ensure_registry_transport_configured + local release_image="${APP_IMAGE:-rentaldrivego/carmanagement}:${IMAGE_TAG}" + if [[ "${IMAGE_TAG}" != "latest" ]] && docker image inspect "${release_image}" >/dev/null 2>&1; then + echo "Release image ${release_image} is already present locally; skipping docker pull." + return 0 + fi + if load_release_image_archives; then return 0 fi @@ -360,7 +366,7 @@ pull_prod_release_images() { exit 1 fi - prod_compose pull migrate api carplace dashboard admin + prod_compose pull migrate api homepage carplace dashboard admin } load_release_image_archives() { diff --git a/scripts/docker-prod-deploy.sh b/scripts/docker-prod-deploy.sh index c159f79..d4bf67e 100644 --- a/scripts/docker-prod-deploy.sh +++ b/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 carplace dashboard admin +prod_compose up -d api homepage carplace dashboard admin wait_for_healthy api 180 +wait_for_healthy homepage 180 wait_for_healthy carplace 180 wait_for_healthy dashboard 180 wait_for_healthy admin 180 diff --git a/scripts/docker-prod-run-pulled-image.sh b/scripts/docker-prod-run-pulled-image.sh index f96c071..c1d1656 100644 --- a/scripts/docker-prod-run-pulled-image.sh +++ b/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 carplace dashboard admin) +app_services=(api homepage carplace 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 carplace 180 wait_for_healthy dashboard 180 wait_for_healthy admin 180