name: Deploy to Production on: push: tags: - 'v*' jobs: deploy: runs-on: splendid-bear steps: - name: Checkout tag env: GITEA_TOKEN: ${{ gitea.token }} run: | set -e export HOME=/tmp git config --global credential.helper '!f() { echo "username=oauth2"; echo "password=$GITEA_TOKEN"; }; f' git config --global --add safe.directory "${{ vars.PROD_APP_DIR }}" cd "${{ vars.PROD_APP_DIR }}" git remote set-url origin "${{ gitea.server_url }}/${{ gitea.repository }}.git" git fetch --tags --force git checkout "${{ gitea.ref_name }}" - name: Write .env env: PROD_ENV_FILE: ${{ secrets.PROD_ENV_FILE }} run: | printf '%s' "$PROD_ENV_FILE" > "${{ vars.PROD_APP_DIR }}/.env" - name: Build image run: | cd "${{ vars.PROD_APP_DIR }}" docker compose build - name: Migrate legacy MinIO and deploy env: APP_VERSION: ${{ vars.APP_VERSION }} run: | set -euo pipefail cd "${{ vars.PROD_APP_DIR }}" MIGRATION_COMPOSE="docker compose --profile storage-migration" LEGACY_MINIO_CONTAINER=$($MIGRATION_COMPOSE ps -a -q minio) if [ -n "$LEGACY_MINIO_CONTAINER" ]; then echo "Legacy MinIO found; pausing writers and migrating its buckets to RustFS." APP_WAS_RUNNING=$(docker compose ps --status running -q app) SCHEDULER_WAS_RUNNING=$(docker compose ps --status running -q scheduler) MIGRATION_SUCCEEDED=0 restart_old_workers_on_failure() { result=$? if [ "$result" -ne 0 ] && [ "$MIGRATION_SUCCEEDED" -eq 0 ]; then # Before a complete copy, restore the old public MinIO endpoint # before bringing back the old app. docker compose stop rustfs || true MINIO_PUBLISHED_API_PORT=9010 MINIO_PUBLISHED_CONSOLE_PORT=9011 $MIGRATION_COMPOSE up -d minio || true [ -z "$APP_WAS_RUNNING" ] || docker compose start app || true [ -z "$SCHEDULER_WAS_RUNNING" ] || docker compose start scheduler || true elif [ "$result" -ne 0 ]; then echo "Data migration succeeded; leaving RustFS in place for recovery from the app rollout failure." >&2 fi return "$result" } trap restart_old_workers_on_failure EXIT docker compose stop app scheduler || true docker compose up -d db mail # Move the legacy service off the RustFS public port before starting RustFS. $MIGRATION_COMPOSE up -d minio docker compose up -d rustfs $MIGRATION_COMPOSE up --build --abort-on-container-exit --exit-code-from storage_migrate storage_migrate MIGRATION_SUCCEEDED=1 echo "Migration succeeded; deploying the RustFS-only stack." docker compose up -d --wait --wait-timeout 180 app scheduler # Remove only the legacy service containers. Do not use -v: the old # MinIO volume is retained as a rollback/backup until manually retired. $MIGRATION_COMPOSE rm -sf minio storage_migrate trap - EXIT else echo "No legacy MinIO container found; deploying the RustFS-only stack." docker compose up -d fi