Deploy to AWS (214/merge) #1008
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy to AWS | |
| run-name: ${{ (inputs.ref && format('[{0}] {1}', inputs.ref, inputs.commit_message)) || (github.event_name == 'repository_dispatch' && format('[{0}] {1}', github.event.client_payload.ref, github.event.client_payload.commit_message)) || format('Deploy to AWS ({0})', github.ref_name) }} | |
| on: | |
| push: | |
| branches: | |
| - otr-dev | |
| - otr-prod | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: "Environment to deploy to" | |
| required: true | |
| type: choice | |
| options: | |
| - otr-dev | |
| - otr-prod | |
| repository_dispatch: | |
| types: [deploy-otr-prod] | |
| workflow_call: | |
| inputs: | |
| ref: | |
| description: "Branch/ref to deploy" | |
| required: true | |
| type: string | |
| commit_hash: | |
| description: "Commit hash being deployed" | |
| required: true | |
| type: string | |
| commit_message: | |
| description: "Commit message" | |
| required: true | |
| type: string | |
| triggered_by: | |
| description: "What triggered this deployment" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| packages: write | |
| jobs: | |
| push_to_registry: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| digest: ${{ steps.digest.outputs.digest }} | |
| steps: | |
| - name: Display deployment info | |
| if: inputs.ref || github.event_name == 'repository_dispatch' | |
| run: | | |
| echo "🚀 **Deployment triggered by sync workflow**" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Details:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- Branch: \`${{ inputs.ref || github.event.client_payload.ref }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Commit: \`${{ inputs.commit_hash || github.event.client_payload.commit_hash }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Message: ${{ inputs.commit_message || github.event.client_payload.commit_message }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Triggered by: ${{ inputs.triggered_by || github.event.client_payload.triggered_by }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.ref || github.event_name == 'workflow_dispatch' && inputs.environment || github.event_name == 'workflow_call' && inputs.ref || github.ref }} | |
| - name: Log in to the container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata (tags, labels) for Docker | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/${{ github.repository_owner }}/convos-backend | |
| tags: | | |
| type=raw,value=${{ github.event_name == 'repository_dispatch' && github.event.client_payload.ref || github.event_name == 'workflow_dispatch' && inputs.environment || github.event_name == 'workflow_call' && inputs.ref || github.ref_name }} | |
| type=ref,event=pr | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v6 | |
| id: push | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| - name: Set digest output | |
| id: digest | |
| run: echo "digest=${{ steps.push.outputs.digest }}" >> $GITHUB_OUTPUT | |
| deploy_otr_dev: | |
| name: Deploy to OTR Development | |
| runs-on: ubuntu-latest | |
| needs: push_to_registry | |
| if: (inputs.ref == 'otr-dev') || (inputs.environment == 'otr-dev') || (github.ref == 'refs/heads/otr-dev' && !inputs.ref && !inputs.environment) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.ref || github.event_name == 'workflow_dispatch' && inputs.environment || github.event_name == 'workflow_call' && inputs.ref || github.ref }} | |
| - name: Deploy to OTR Dev Environment | |
| uses: xmtp-labs/terraform-deployer@v1 | |
| timeout-minutes: 20 | |
| with: | |
| timeout: 20m | |
| terraform-token: ${{ secrets.TERRAFORM_TOKEN }} | |
| terraform-org: xmtp | |
| terraform-workspace: convos-otr-dev | |
| variable-name: api_image | |
| variable-value: "ghcr.io/xmtplabs/convos-backend@${{ needs.push_to_registry.outputs.digest }}" | |
| variable-value-required-prefix: "ghcr.io/xmtplabs/convos-backend@sha256:" | |
| deploy_otr_prod: | |
| name: Deploy to OTR Production | |
| runs-on: ubuntu-latest | |
| needs: push_to_registry | |
| if: (inputs.ref == 'otr-prod') || (inputs.environment == 'otr-prod') || (github.ref == 'refs/heads/otr-prod' && !inputs.ref && !inputs.environment) || (github.event_name == 'repository_dispatch' && github.event.client_payload.ref == 'otr-prod') | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.ref || github.event_name == 'workflow_dispatch' && inputs.environment || github.event_name == 'workflow_call' && inputs.ref || github.ref }} | |
| - name: Deploy to OTR Production Environment | |
| uses: xmtp-labs/terraform-deployer@v1 | |
| timeout-minutes: 20 | |
| with: | |
| timeout: 20m | |
| terraform-token: ${{ secrets.TERRAFORM_TOKEN }} | |
| terraform-org: xmtp | |
| terraform-workspace: convos-otr-prod | |
| variable-name: api_image | |
| variable-value: "ghcr.io/xmtplabs/convos-backend@${{ needs.push_to_registry.outputs.digest }}" | |
| variable-value-required-prefix: "ghcr.io/xmtplabs/convos-backend@sha256:" | |
| test_lifecycle_dev: | |
| name: Test S3 Lifecycle Renewal (Dev) | |
| runs-on: ubuntu-latest | |
| needs: deploy_otr_dev | |
| steps: | |
| - name: Wait for deployment and verify health | |
| run: | | |
| echo "Waiting for deployment to stabilize..." | |
| for i in {1..10}; do | |
| sleep 10 | |
| if curl -sf "${{ vars.DEV_API_URL }}/healthcheck" > /dev/null 2>&1; then | |
| echo "Service is healthy after $((i * 10)) seconds" | |
| exit 0 | |
| fi | |
| echo "Waiting for service to be ready (attempt $i/10)..." | |
| done | |
| echo "::error::Service did not become healthy after 100s" | |
| exit 1 | |
| - name: Test lifecycle renewal endpoint | |
| run: | | |
| response=$(curl -s -w "\n%{http_code}" \ | |
| --max-time 60 \ | |
| --retry 3 \ | |
| --retry-connrefused \ | |
| -X POST "${{ vars.DEV_API_URL }}/api/v2/assets/test/lifecycle" \ | |
| -H "Authorization: Bearer ${{ secrets.LIFECYCLE_TEST_TOKEN }}") | |
| http_code=$(echo "$response" | tail -1) | |
| body=$(echo "$response" | head -n -1) | |
| echo "$body" | |
| if [ "$http_code" != "200" ] || ! echo "$body" | jq -e '.success == true' > /dev/null 2>&1; then | |
| echo "::error::Lifecycle test failed!" | |
| exit 1 | |
| fi | |
| echo "✅ Lifecycle renewal test passed (dev)" >> $GITHUB_STEP_SUMMARY | |
| test_lifecycle_prod: | |
| name: Test S3 Lifecycle Renewal (Prod) | |
| runs-on: ubuntu-latest | |
| needs: deploy_otr_prod | |
| steps: | |
| - name: Wait for deployment and verify health | |
| run: | | |
| echo "Waiting for deployment to stabilize..." | |
| for i in {1..10}; do | |
| sleep 10 | |
| if curl -sf "${{ vars.PROD_API_URL }}/healthcheck" > /dev/null 2>&1; then | |
| echo "Service is healthy after $((i * 10)) seconds" | |
| exit 0 | |
| fi | |
| echo "Waiting for service to be ready (attempt $i/10)..." | |
| done | |
| echo "::error::Service did not become healthy after 100s" | |
| exit 1 | |
| - name: Test lifecycle renewal endpoint | |
| run: | | |
| response=$(curl -s -w "\n%{http_code}" \ | |
| --max-time 60 \ | |
| --retry 3 \ | |
| --retry-connrefused \ | |
| -X POST "${{ vars.PROD_API_URL }}/api/v2/assets/test/lifecycle" \ | |
| -H "Authorization: Bearer ${{ secrets.LIFECYCLE_TEST_TOKEN }}") | |
| http_code=$(echo "$response" | tail -1) | |
| body=$(echo "$response" | head -n -1) | |
| echo "$body" | |
| if [ "$http_code" != "200" ] || ! echo "$body" | jq -e '.success == true' > /dev/null 2>&1; then | |
| echo "::error::Lifecycle test failed!" | |
| exit 1 | |
| fi | |
| echo "✅ Lifecycle renewal test passed (prod)" >> $GITHUB_STEP_SUMMARY |