Seamless CI/CD with AWS Amplify & GitHub Actions
Discover how to automate AWS Amplify web app deployments using GitHub Actions.

Nidhin B

Continuous Deployment with GitHub Actions and AWS Amplify
Continuous Deployment is a key part of modern app development.
If you’re deploying a web app and want a smooth, automated pipeline using GitHub Actions and AWS Amplify, this guide is for you.
In this post, I’ll walk you through setting up an Amplify deployment workflow that’s:
- Simple
- Production-ready
- With Slack notifications
- Handles running jobs gracefully
Why AWS Amplify?
AWS Amplify offers a fully managed hosting service that supports frontend frameworks like React, Vue, Next.js, and more.
What makes it great?
- Git-based deployments
- Preview branches
- Built-in SSL & global CDN
- Easy rollback
But sometimes you want a bit more control — and that’s where GitHub Actions comes in.
CI/CD Workflow with GitHub Actions
Here’s the full YAML setup we use to:
- Trigger on
develop
andmain
- Deploy to Beta (
develop
) or Production (main
) - Avoid triggering new jobs if a job is already running
- Send Slack notifications on trigger or skip
.github/workflows/deploy-web.yml
name: Deploy Web App to Amplify
on:
push:
branches:
- main
- develop
paths:
- 'apps/web/**'
- '.github/workflows/deploy-web.yml'
jobs:
deploy:
name: Build and Deploy Web App
runs-on: ubuntu-latest
outputs:
deployment_status: ${{ steps.set_status.outputs.deployment_status }}
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install Dependencies
run: npm ci
- name: Build Web App
run: npx turbo run build --filter=web...
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy to Amplify (Beta)
id: deploy_beta
if: github.ref == 'refs/heads/develop'
run: |
echo "Deploying to Amplify Beta..."
JOBS=$(aws amplify list-jobs \
--app-id ${{ secrets.AMPLIFY_APP_ID_BETA }} \
--branch-name develop \
--query "jobSummaries[?jobStatus=='PENDING' || jobStatus=='RUNNING']" \
--output json)
if [[ $JOBS == "[]" ]]; then
aws amplify start-job \
--app-id ${{ secrets.AMPLIFY_APP_ID_BETA }} \
--branch-name develop \
--job-type RELEASE
echo "status=triggered" >> $GITHUB_OUTPUT
else
echo "Amplify job already running. Skipping."
echo "status=skipped" >> $GITHUB_OUTPUT
exit 0
fi
- name: Deploy to Amplify (Production)
id: deploy_prod
if: github.ref == 'refs/heads/main'
run: |
echo "Deploying to Amplify Production..."
JOBS=$(aws amplify list-jobs \
--app-id ${{ secrets.AMPLIFY_APP_ID_PROD }} \
--branch-name main \
--query "jobSummaries[?jobStatus=='PENDING' || jobStatus=='RUNNING']" \
--output json)
if [[ $JOBS == "[]" ]]; then
aws amplify start-job \
--app-id ${{ secrets.AMPLIFY_APP_ID_PROD }} \
--branch-name main \
--job-type RELEASE
echo "status=triggered" >> $GITHUB_OUTPUT
else
echo "Amplify job already running. Skipping."
echo "status=skipped" >> $GITHUB_OUTPUT
exit 0
fi
- name: Set Deployment Status Output
id: set_status
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "deployment_status=${{ steps.deploy_prod.outputs.status }}" >> $GITHUB_OUTPUT
else
echo "deployment_status=${{ steps.deploy_beta.outputs.status }}" >> $GITHUB_OUTPUT
fi
notify:
name: Send Slack Notification
needs: deploy
runs-on: ubuntu-latest
if: always()
steps:
- name: Send Slack Notification
uses: slackapi/slack-github-action@v1.24.0
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
payload: |
{
"text": "*Web App Deploy Status:*",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "${{ needs.deploy.outputs.deployment_status == 'triggered' && ':white_check_mark: Deployment triggered' || ':information_source: Deployment skipped (already in progress)' }} for `Web App` on `${{ github.ref_name }}`"
}
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Environment:*\n${{ github.ref == 'refs/heads/main' && 'Production' || 'Beta' }}" },
{ "type": "mrkdwn", "text": "*Commit:*\n<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}" }
]
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Workflow Run", "emoji": true },
"url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
]
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
Tips
- Avoid race conditions: The job checks for pending or running Amplify jobs before starting a new one.
- Don’t forget secrets: Add all AWS + Slack credentials in your GitHub repository settings.
- Add branch protection: Only allow merges via reviewed PRs before deploying.
Conclusion
With this GitHub Actions + AWS Amplify setup, you can confidently deploy your web apps automatically, keep your team informed via Slack, and eliminate manual deployment steps.
Automation done right — simple, fast, and reliable.

Written by
Nidhin B
Cloud Solutions Architect @Psypher.ai
Share this article
Help spread the knowledge!