name: React - Deploy to Amplify
on: workflow_call: inputs: runner: description: 'Runner type' required: false type: string default: 'ubuntu-latest' environment: description: 'GitHub environment (develop, staging, production)' required: false type: string default: 'develop' build_output_dir: description: 'Build output directory name (must match build artifact)' required: false type: string default: 'build'
aws_role_to_assume: description: >- IAM role ARN to assume via GitHub OIDC. When set, no static access key is sent and AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY are not read. Empty keeps the static-key path, which is the default so that existing consumers keep working. required: false type: string default: ''
secrets: AWS_ACCESS_KEY_ID: required: true AWS_SECRET_ACCESS_KEY: required: true AWS_REGION: required: true AWS_AMPLIFY_APP_ID: required: true AWS_AMPLIFY_BRANCH: required: true
outputs: deploy_status: description: 'Deployment status' value: ${{ jobs.deploy.outputs.status }}
# Least privilege for what this workflow actually does. Without it the# job inherits whatever the calling repository's default happens to be,# which on older repositories is write-all.permissions: contents: read # Inert unless aws_role_to_assume is set. A reusable workflow cannot # exceed its own declaration, so the OIDC path needs it declared here. id-token: write
jobs: deploy: name: Deploy to Amplify runs-on: ${{ inputs.runner }} environment: ${{ inputs.environment }} timeout-minutes: 15
outputs: status: ${{ steps.deploy.outputs.status }}
steps: - name: Download build artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: build-output-${{ github.run_id }} path: ${{ inputs.build_output_dir }}
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0 with: # One step, two paths. A long-lived access key in a repository secret # is a credential nobody rotates and everybody with write access can # exfiltrate; OIDC mints a token scoped to this repository that # expires with the job. The keys are only sent when no role is given, # because passing both makes the action assume the role *with* the # static key and the key stays in play. role-to-assume: ${{ inputs.aws_role_to_assume }} aws-access-key-id: ${{ inputs.aws_role_to_assume == '' && secrets.AWS_ACCESS_KEY_ID || '' }} aws-secret-access-key: ${{ inputs.aws_role_to_assume == '' && secrets.AWS_SECRET_ACCESS_KEY || '' }} aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy to Amplify id: deploy env: AMPLIFY_APP_ID: ${{ secrets.AWS_AMPLIFY_APP_ID }} AMPLIFY_BRANCH: ${{ secrets.AWS_AMPLIFY_BRANCH }} run: | echo "Deploying to Amplify app: $AMPLIFY_APP_ID (branch: $AMPLIFY_BRANCH)"
# Create zip of build output cd ${{ inputs.build_output_dir }} zip -r ../build-output.zip . cd ..
# Create deployment DEPLOYMENT=$(aws amplify create-deployment \ --app-id "$AMPLIFY_APP_ID" \ --branch-name "$AMPLIFY_BRANCH" \ --output json)
JOB_ID=$(echo "$DEPLOYMENT" | jq -r '.jobId') UPLOAD_URL=$(echo "$DEPLOYMENT" | jq -r '.zipUploadUrl')
echo "Upload URL received, uploading build artifacts..."
# Upload build artifacts curl --request PUT \ --upload-file build-output.zip \ "$UPLOAD_URL"
# Start deployment aws amplify start-deployment \ --app-id "$AMPLIFY_APP_ID" \ --branch-name "$AMPLIFY_BRANCH" \ --job-id "$JOB_ID"
echo "Deployment started with job ID: $JOB_ID"
# Wait for deployment to complete echo "Waiting for deployment to complete..." aws amplify wait job-completed \ --app-id "$AMPLIFY_APP_ID" \ --branch-name "$AMPLIFY_BRANCH" \ --job-id "$JOB_ID" || true
# Check deployment status JOB_STATUS=$(aws amplify get-job \ --app-id "$AMPLIFY_APP_ID" \ --branch-name "$AMPLIFY_BRANCH" \ --job-id "$JOB_ID" \ --query 'job.summary.status' \ --output text)
if [ "$JOB_STATUS" = "SUCCEED" ]; then echo "status=success" >> $GITHUB_OUTPUT else echo "Deployment failed with status: $JOB_STATUS" echo "status=failed" >> $GITHUB_OUTPUT exit 1 fi
# Summary echo "### Amplify Deployment Completed" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY echo "| **App ID** | $AMPLIFY_APP_ID |" >> $GITHUB_STEP_SUMMARY echo "| **Branch** | $AMPLIFY_BRANCH |" >> $GITHUB_STEP_SUMMARY echo "| **Environment** | ${{ inputs.environment }} |" >> $GITHUB_STEP_SUMMARY echo "| **Job ID** | $JOB_ID |" >> $GITHUB_STEP_SUMMARY echo "| **Status** | $JOB_STATUS |" >> $GITHUB_STEP_SUMMARY echo "| **Source** | ${{ inputs.build_output_dir }} |" >> $GITHUB_STEP_SUMMARYReact·Reusable workflow·on: workflow_call
React Deploy Amplify
React - Deploy to Amplify
.github/workflows/react-deploy-amplify.yml