name: Deploy Frontend on: push: branches: [ main ] paths: - 'frontend/**' - '.github/workflows/cd-frontend.yml' workflow_dispatch: env: GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }} GCP_REGION: us-central1 BUCKET_NAME: ${{ secrets.FRONTEND_BUCKET_NAME }} CDN_URL_MAP: accessible-video-frontend NODE_VERSION: "20" jobs: build-and-deploy: name: Build and Deploy Frontend runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' permissions: contents: read id-token: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install dependencies working-directory: ./frontend run: npm ci - name: Build for production working-directory: ./frontend env: VITE_API_BASE_URL: ${{ secrets.PRODUCTION_API_URL }} VITE_APP_ENV: production VITE_SENTRY_DSN: ${{ secrets.FRONTEND_SENTRY_DSN }} run: npm run build - name: Authenticate to Google Cloud uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.WIF_PROVIDER }} service_account: ${{ secrets.WIF_SERVICE_ACCOUNT }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v2 - name: Deploy to Cloud Storage working-directory: ./frontend run: | # Sync build files to Cloud Storage bucket gsutil -m rsync -r -d dist/ gs://${{ env.BUCKET_NAME }}/ # Set public read permissions for web assets gsutil -m acl ch -r -u AllUsers:R gs://${{ env.BUCKET_NAME }} # Set cache headers for different file types gsutil -m setmeta -h "Cache-Control:public, max-age=31536000, immutable" "gs://${{ env.BUCKET_NAME }}/**/*.js" gsutil -m setmeta -h "Cache-Control:public, max-age=31536000, immutable" "gs://${{ env.BUCKET_NAME }}/**/*.css" gsutil -m setmeta -h "Cache-Control:public, max-age=86400" "gs://${{ env.BUCKET_NAME }}/**/*.html" gsutil -m setmeta -h "Cache-Control:public, max-age=86400" "gs://${{ env.BUCKET_NAME }}/index.html" - name: Configure Load Balancer and CDN run: | # Create backend bucket if it doesn't exist gcloud compute backend-buckets describe ${{ env.BUCKET_NAME }}-backend || \ gcloud compute backend-buckets create ${{ env.BUCKET_NAME }}-backend \ --gcs-bucket-name=${{ env.BUCKET_NAME }} # Update the URL map to route to the bucket gcloud compute url-maps describe ${{ env.CDN_URL_MAP }} || \ gcloud compute url-maps create ${{ env.CDN_URL_MAP }} \ --default-backend-bucket=${{ env.BUCKET_NAME }}-backend # Create or update HTTPS proxy gcloud compute target-https-proxies describe ${{ env.CDN_URL_MAP }}-https-proxy || \ gcloud compute target-https-proxies create ${{ env.CDN_URL_MAP }}-https-proxy \ --url-map=${{ env.CDN_URL_MAP }} \ --ssl-certificates=${{ secrets.SSL_CERT_NAME }} # Create or update global forwarding rule gcloud compute forwarding-rules describe ${{ env.CDN_URL_MAP }}-https-rule --global || \ gcloud compute forwarding-rules create ${{ env.CDN_URL_MAP }}-https-rule \ --global \ --target-https-proxy=${{ env.CDN_URL_MAP }}-https-proxy \ --ports=443 - name: Invalidate CDN cache run: | # Invalidate CDN cache for immediate deployment gcloud compute url-maps invalidate-cdn-cache ${{ env.CDN_URL_MAP }} \ --path="/*" \ --async - name: Run smoke tests working-directory: ./frontend env: FRONTEND_URL: https://${{ secrets.FRONTEND_DOMAIN }} run: | # Wait a bit for CDN propagation sleep 30 # Basic smoke test - check if main page loads curl -f -s -o /dev/null -w "%{http_code}" "$FRONTEND_URL" | grep -q "200" || { echo "Frontend smoke test failed - main page not accessible" exit 1 } # Check if assets are loading curl -f -s -o /dev/null -w "%{http_code}" "$FRONTEND_URL/assets/" | grep -qE "(200|404)" || { echo "Frontend smoke test failed - assets not accessible" exit 1 } echo "✅ Frontend smoke tests passed" notify-deployment: name: Notify Deployment Status runs-on: ubuntu-latest needs: [build-and-deploy] if: always() steps: - name: Notify success if: needs.build-and-deploy.result == 'success' run: | echo "✅ Frontend deployment completed successfully" echo "Frontend is now live at: https://${{ secrets.FRONTEND_DOMAIN }}" # Add Slack/email notification here if needed - name: Notify failure if: needs.build-and-deploy.result == 'failure' run: | echo "❌ Frontend deployment failed" # Add Slack/email notification here if needed