name: Deploy Vault to Production Environment on: push: branches: - prod-env concurrency: group: prod-deploy cancel-in-progress: false jobs: deploy: runs-on: prod-runner steps: - name: Checkout Branch uses: actions/checkout@v4 - name: Connect Runner to Overlay Network run: | docker network connect iklimco-net $(hostname) || true - name: Set up SSH Key and Add to known_hosts run: | mkdir -p ~/.ssh echo "${{ secrets.STORAGEBOX_SSH_PRIV }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -p 23 ${{ vars.STORAGEBOX_USER }}.your-storagebox.de >> ~/.ssh/known_hosts - name: Download Deploy Inputs run: | mkdir -p deploy # Fetch environment files from Storagebox scp -P 23 ${{ vars.STORAGEBOX_USER }}@${{ vars.STORAGEBOX_USER }}.your-storagebox.de:prod/secrets/iklim.co/.env ./.env scp -P 23 ${{ vars.STORAGEBOX_USER }}@${{ vars.STORAGEBOX_USER }}.your-storagebox.de:prod/secrets/iklim.co/.env.secrets.forecast ./.env.secrets.forecast # Fetch base scripts and service manifests curl -sL -H "Authorization: token ${{ secrets.REPO_ACCESS_TOKEN }}" \ "https://git.tarla.io/iklim.co/BE_TopParent/raw/branch/prod-env/common-functions-base.sh" \ -o /workspace/iklim.co/common-functions-base.sh curl -sL -H "Authorization: token ${{ secrets.REPO_ACCESS_TOKEN }}" \ "https://git.tarla.io/iklim.co/BE_TopParent/raw/branch/prod-env/common-functions-prod.sh" \ -o common-functions-prod.sh curl -sL -H "Authorization: token ${{ secrets.REPO_ACCESS_TOKEN }}" \ "https://git.tarla.io/iklim.co/BE-Forecast/raw/branch/prod-env/deploy/prod.env" \ -o deploy/prod.env curl -sL -H "Authorization: token ${{ secrets.REPO_ACCESS_TOKEN }}" \ "https://git.tarla.io/iklim.co/BE-Forecast/raw/branch/prod-env/docker-stack-service.yml" \ -o deploy/docker-stack-service.yml curl -sL -H "Authorization: token ${{ secrets.REPO_ACCESS_TOKEN }}" \ "https://git.tarla.io/iklim.co/BE-Forecast/raw/branch/prod-env/docker-stack-service.prod.yml" \ -o deploy/docker-stack-service.prod.yml test -s common-functions-prod.sh test -s deploy/prod.env test -s deploy/docker-stack-service.yml test -s deploy/docker-stack-service.prod.yml - name: Validate Deployment Manifest id: manifest run: | set -a; . ./deploy/prod.env; set +a if [ -z "${SOURCE_IMAGE_DIGEST:-}" ] || [ -z "${PROD_IMAGE_TAG:-}" ]; then echo "❌ SOURCE_IMAGE_DIGEST and PROD_IMAGE_TAG are required in deploy/prod.env" exit 1 fi case "$SOURCE_IMAGE_DIGEST" in registry.tarla.io/iklimco/forecast-service@sha256:*) ;; *) echo "❌ SOURCE_IMAGE_DIGEST must be registry.tarla.io/iklimco/forecast-service@sha256:"; exit 1 ;; esac case "$PROD_IMAGE_TAG" in *-rc*) echo "❌ PROD_IMAGE_TAG must not be an rc tag"; exit 1 ;; esac echo "source_image_digest=$SOURCE_IMAGE_DIGEST" >> $GITHUB_OUTPUT echo "prod_image=registry.tarla.io/iklimco/forecast-service:$PROD_IMAGE_TAG" >> $GITHUB_OUTPUT echo "🏷️ Promote: $SOURCE_IMAGE_DIGEST -> registry.tarla.io/iklimco/forecast-service:$PROD_IMAGE_TAG" - name: Promote Harbor Image run: | echo "${{ secrets.HARBOR_CI_TOKEN }}" | \ docker login registry.tarla.io -u robot-ci-push-iklimco --password-stdin docker pull "${{ steps.manifest.outputs.source_image_digest }}" docker tag "${{ steps.manifest.outputs.source_image_digest }}" "${{ steps.manifest.outputs.prod_image }}" docker push "${{ steps.manifest.outputs.prod_image }}" echo "✅ Promoted: ${{ steps.manifest.outputs.prod_image }}" - name: Docker Login for Swarm Pull run: | echo "${{ secrets.HARBOR_PULL_TOKEN }}" | \ docker login registry.tarla.io -u robot-swarm-pull-iklimco --password-stdin - name: Update Swarm Service run: | set -a; . ./.env; . ./.env.secrets.forecast; set +a SERVICE_IMAGE="${{ steps.manifest.outputs.prod_image }}" \ docker stack deploy \ --with-registry-auth \ -c deploy/docker-stack-service.yml \ -c deploy/docker-stack-service.prod.yml \ iklimco - name: Verify Deployment run: | sleep 15 docker service ps iklimco_forecast-service \ --filter "desired-state=running" \ --format "table {{.Name}}\t{{.CurrentState}}\t{{.Image}}" | head -5