diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 61c2ebd..c2e1838 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -1,181 +1,181 @@ name: Build, Tag & Deploy to Dev on: - push: - branches: - - dev + push: + branches: + - dev jobs: - build-and-deploy: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Get latest tag from Docker Hub - id: get_tag - run: | - # Fetch tags from Docker Hub - REPO="${{ secrets.DOCKER_USERNAME }}/api-yapper-backend" - - echo "🔍 Fetching tags from Docker Hub for $REPO..." - - # Get Docker Hub token for authenticated API access - TOKEN=$(curl -s -H "Content-Type: application/json" -X POST \ - -d '{"username": "${{ secrets.DOCKER_USERNAME }}", "password": "${{ secrets.DOCKER_PASSWORD }}"}' \ - https://hub.docker.com/v2/users/login/ | jq -r .token) - - if [ "$TOKEN" = "null" ] || [ -z "$TOKEN" ]; then - echo "❌ Failed to authenticate with Docker Hub" - exit 1 - fi - - # Get all tags from Docker Hub API - TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" \ - "https://hub.docker.com/v2/repositories/$REPO/tags/?page_size=100" | \ - jq -r '.results[].name' | \ - grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | \ - sort -V | \ - tail -1) - - # If no tags found, start with v0.0.0 - if [ -z "$TAGS" ]; then - LATEST_TAG="v0.0.0" - echo "âš ī¸ No version tags found on Docker Hub, starting from v0.0.0" - else - LATEST_TAG="$TAGS" - echo "đŸ“Ļ Latest tag found on Docker Hub: $LATEST_TAG" - fi - - echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT - - # Parse version components - VERSION=${LATEST_TAG#v} - IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION" - - # Increment patch version - PATCH=$((PATCH + 1)) - NEW_TAG="v${MAJOR}.${MINOR}.${PATCH}" - - echo "new_tag=$NEW_TAG" >> $GITHUB_OUTPUT - echo "🚀 New version: $NEW_TAG" - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build and push Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./docker/Dockerfile - - push: true - tags: | - ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:${{ steps.get_tag.outputs.new_tag }} - ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:dev - - - name: Confirm image push - run: | - echo "✅ Image pushed: ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:${{ steps.get_tag.outputs.new_tag }}" - echo "✅ Image tagged: ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:dev" - - - name: SSH into Dev VM and deploy - uses: appleboy/ssh-action@v1.0.0 - env: - IMG_TAG: ${{ steps.get_tag.outputs.new_tag }} - with: - host: ${{ secrets.DEV_SERVER_HOST }} - username: ${{ secrets.DEV_SERVER_USER }} - key: ${{ secrets.DEV_SERVER_SSH_KEY }} - envs: IMG_TAG - script: | - set -e - cd ~/yapper # path to your app on VM - - echo "🧭 Getting current running image tag..." - CURRENT_TAG=$(IMG_TAG="" docker compose ps -q api | xargs docker inspect -f '{{ .Config.Image }}' | cut -d':' -f2 || echo "unknown") - echo "CURRENT_TAG: $CURRENT_TAG" - echo "đŸŗ Setting new image tag for deployment..." - echo "Deploying version: $IMG_TAG" - - echo "🔄 Pulling new image and restarting app container..." - IMG_TAG=$IMG_TAG docker compose pull api api-local api-test - IMG_TAG=$IMG_TAG docker compose up -d api api-local api-test - - echo "âŗ Waiting for health check..." - sleep 10 - - HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${{ secrets.DEV_HEALTHCHECK_URL }}) - - if [ "$HTTP_CODE" = "200" ]; then - echo "✅ Dev deployment successful for version $IMG_TAG" - - echo "🔄 Running migrations for all services..." - MIGRATION_FAILED=0 - - echo "đŸ“Ļ Running migration for api..." - docker compose exec -T api npm run migration:run:prod 2>&1 | tee /tmp/api-migration.log - if grep -q "Error during migration" /tmp/api-migration.log || grep -q "Cannot find module" /tmp/api-migration.log; then - echo "❌ Migration for api failed!" - cat /tmp/api-migration.log - MIGRATION_FAILED=1 - elif grep -q "No migrations are pending" /tmp/api-migration.log || grep -q "No pending migrations" /tmp/api-migration.log; then - echo "â„šī¸ No pending migrations for api" - else - echo "✅ Migration for api completed successfully" - fi - - echo "đŸ“Ļ Running migration for api-local..." - docker compose exec -T api-local npm run migration:run:prod 2>&1 | tee /tmp/api-local-migration.log - if grep -q "Error during migration" /tmp/api-local-migration.log || grep -q "Cannot find module" /tmp/api-local-migration.log; then - echo "❌ Migration for api-local failed!" - cat /tmp/api-local-migration.log - MIGRATION_FAILED=1 - elif grep -q "No migrations are pending" /tmp/api-local-migration.log || grep -q "No pending migrations" /tmp/api-local-migration.log; then - echo "â„šī¸ No pending migrations for api-local" - else - echo "✅ Migration for api-local completed successfully" - fi - - echo "đŸ“Ļ Running migration for api-test..." - docker compose exec -T api-test npm run migration:run:prod 2>&1 | tee /tmp/api-test-migration.log - if grep -q "Error during migration" /tmp/api-test-migration.log || grep -q "Cannot find module" /tmp/api-test-migration.log; then - echo "❌ Migration for api-test failed!" - cat /tmp/api-test-migration.log - MIGRATION_FAILED=1 - elif grep -q "No migrations are pending" /tmp/api-test-migration.log || grep -q "No pending migrations" /tmp/api-test-migration.log; then - echo "â„šī¸ No pending migrations for api-test" - else - echo "✅ Migration for api-test completed successfully" - fi - - if [ "$MIGRATION_FAILED" = "1" ]; then - echo "❌ One or more migrations failed! Rolling back..." - if [ "$CURRENT_TAG" != "unknown" ]; then - IMG_TAG=$CURRENT_TAG docker compose up -d api api-local api-test - echo "🔙 Rolled back to $CURRENT_TAG" - fi - exit 1 - fi - - echo "✅ All migrations completed successfully" - else - echo "❌ Health check failed (HTTP $HTTP_CODE)! Rolling back app container..." - if [ "$CURRENT_TAG" != "unknown" ]; then - IMG_TAG=$CURRENT_TAG docker compose up -d api api-local api-test - echo "🔙 Rolled back to $CURRENT_TAG" - fi - exit 1 - fi - - - name: Deployment summary - if: success() - run: | - echo "🎉 Deployment Complete!" - echo "Version: ${{ steps.get_tag.outputs.new_tag }}" - echo "Branch: dev" - echo "Commit: ${{ github.sha }}" + build-and-deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Get latest tag from Docker Hub + id: get_tag + run: | + # Fetch tags from Docker Hub + REPO="${{ secrets.DOCKER_USERNAME }}/api-yapper-backend" + + echo "🔍 Fetching tags from Docker Hub for $REPO..." + + # Get Docker Hub token for authenticated API access + TOKEN=$(curl -s -H "Content-Type: application/json" -X POST \ + -d '{"username": "${{ secrets.DOCKER_USERNAME }}", "password": "${{ secrets.DOCKER_PASSWORD }}"}' \ + https://hub.docker.com/v2/users/login/ | jq -r .token) + + if [ "$TOKEN" = "null" ] || [ -z "$TOKEN" ]; then + echo "❌ Failed to authenticate with Docker Hub" + exit 1 + fi + + # Get all tags from Docker Hub API + TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" \ + "https://hub.docker.com/v2/repositories/$REPO/tags/?page_size=100" | \ + jq -r '.results[].name' | \ + grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | \ + sort -V | \ + tail -1) + + # If no tags found, start with v0.0.0 + if [ -z "$TAGS" ]; then + LATEST_TAG="v0.0.0" + echo "âš ī¸ No version tags found on Docker Hub, starting from v0.0.0" + else + LATEST_TAG="$TAGS" + echo "đŸ“Ļ Latest tag found on Docker Hub: $LATEST_TAG" + fi + + echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT + + # Parse version components + VERSION=${LATEST_TAG#v} + IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION" + + # Increment patch version + PATCH=$((PATCH + 1)) + NEW_TAG="v${MAJOR}.${MINOR}.${PATCH}" + + echo "new_tag=$NEW_TAG" >> $GITHUB_OUTPUT + echo "🚀 New version: $NEW_TAG" + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:${{ steps.get_tag.outputs.new_tag }} + ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:dev + + - name: Confirm image push + run: | + echo "✅ Image pushed: ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:${{ steps.get_tag.outputs.new_tag }}" + echo "✅ Image tagged: ${{ secrets.DOCKER_USERNAME }}/api-yapper-backend:dev" + + - name: SSH into Dev VM and deploy + uses: appleboy/ssh-action@v1.0.0 + env: + IMG_TAG: ${{ steps.get_tag.outputs.new_tag }} + with: + host: ${{ secrets.DEV_SERVER_HOST }} + username: ${{ secrets.DEV_SERVER_USER }} + key: ${{ secrets.DEV_SERVER_SSH_KEY }} + envs: IMG_TAG + script: | + set -e + cd ~/yapper # path to your app on VM + + echo "🧭 Getting current running image tag..." + CURRENT_TAG=$(IMG_TAG="" docker compose ps -q api | xargs docker inspect -f '{{ .Config.Image }}' | cut -d':' -f2 || echo "unknown") + echo "CURRENT_TAG: $CURRENT_TAG" + echo "đŸŗ Setting new image tag for deployment..." + echo "Deploying version: $IMG_TAG" + + echo "🔄 Pulling new image and restarting app container..." + IMG_TAG=$IMG_TAG docker compose pull api api-local api-test + IMG_TAG=$IMG_TAG docker compose up -d api api-local api-test + + echo "âŗ Waiting for health check..." + sleep 10 + + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${{ secrets.DEV_HEALTHCHECK_URL }}) + + # if [ "$HTTP_CODE" = "200" ]; then + # echo "✅ Dev deployment successful for version $IMG_TAG" + + # echo "🔄 Running migrations for all services..." + # MIGRATION_FAILED=0 + + # echo "đŸ“Ļ Running migration for api..." + # docker compose exec -T api npm run migration:run:prod 2>&1 | tee /tmp/api-migration.log + # if grep -q "Error during migration" /tmp/api-migration.log || grep -q "Cannot find module" /tmp/api-migration.log; then + # echo "❌ Migration for api failed!" + # cat /tmp/api-migration.log + # MIGRATION_FAILED=1 + # elif grep -q "No migrations are pending" /tmp/api-migration.log || grep -q "No pending migrations" /tmp/api-migration.log; then + # echo "â„šī¸ No pending migrations for api" + # else + # echo "✅ Migration for api completed successfully" + # fi + + # echo "đŸ“Ļ Running migration for api-local..." + # docker compose exec -T api-local npm run migration:run:prod 2>&1 | tee /tmp/api-local-migration.log + # if grep -q "Error during migration" /tmp/api-local-migration.log || grep -q "Cannot find module" /tmp/api-local-migration.log; then + # echo "❌ Migration for api-local failed!" + # cat /tmp/api-local-migration.log + # MIGRATION_FAILED=1 + # elif grep -q "No migrations are pending" /tmp/api-local-migration.log || grep -q "No pending migrations" /tmp/api-local-migration.log; then + # echo "â„šī¸ No pending migrations for api-local" + # else + # echo "✅ Migration for api-local completed successfully" + # fi + + # echo "đŸ“Ļ Running migration for api-test..." + # docker compose exec -T api-test npm run migration:run:prod 2>&1 | tee /tmp/api-test-migration.log + # if grep -q "Error during migration" /tmp/api-test-migration.log || grep -q "Cannot find module" /tmp/api-test-migration.log; then + # echo "❌ Migration for api-test failed!" + # cat /tmp/api-test-migration.log + # MIGRATION_FAILED=1 + # elif grep -q "No migrations are pending" /tmp/api-test-migration.log || grep -q "No pending migrations" /tmp/api-test-migration.log; then + # echo "â„šī¸ No pending migrations for api-test" + # else + # echo "✅ Migration for api-test completed successfully" + # fi + + # if [ "$MIGRATION_FAILED" = "1" ]; then + # echo "❌ One or more migrations failed! Rolling back..." + # if [ "$CURRENT_TAG" != "unknown" ]; then + # IMG_TAG=$CURRENT_TAG docker compose up -d api api-local api-test + # echo "🔙 Rolled back to $CURRENT_TAG" + # fi + # exit 1 + # fi + + # echo "✅ All migrations completed successfully" + # else + # echo "❌ Health check failed (HTTP $HTTP_CODE)! Rolling back app container..." + # if [ "$CURRENT_TAG" != "unknown" ]; then + # IMG_TAG=$CURRENT_TAG docker compose up -d api api-local api-test + # echo "🔙 Rolled back to $CURRENT_TAG" + # fi + # exit 1 + # fi + + - name: Deployment summary + if: success() + run: | + echo "🎉 Deployment Complete!" + echo "Version: ${{ steps.get_tag.outputs.new_tag }}" + echo "Branch: dev" + echo "Commit: ${{ github.sha }}"