Skip to main contentSkip to navigationSkip to products sectionSkip to venture studio sectionSkip to contact section
Skip to main content
Back to Blog

Seamless CI/CD with AWS Amplify & GitHub Actions

Discover how to automate AWS Amplify web app deployments using GitHub Actions.

Nidhin B

Nidhin B

5 min read
Seamless CI/CD with AWS Amplify & GitHub Actions

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 and main
  • 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.

Nidhin B

Written by

Nidhin B

Cloud Solutions Architect @Psypher.ai

Share this article

Help spread the knowledge!

Related Articles