GitHub Actions Cloud Deployments

GitHub Actions connects directly to all major cloud platforms — AWS, Azure, and Google Cloud — to automate deployments. This topic shows how to authenticate securely with each cloud provider and deploy applications using GitHub Actions workflows.

Authentication: The Foundation of Cloud Deployments

Before deploying to any cloud platform, your workflow must prove its identity to that platform. Two authentication approaches exist:

Approach 1: Long-lived credentials (access keys)
  Store API keys as GitHub Secrets
  ✓ Simple to set up
  ✗ Keys can expire, leak, or be misused

Approach 2: OpenID Connect (OIDC) — recommended
  Cloud platform trusts GitHub directly
  ✓ No long-lived keys to manage
  ✓ Credentials expire automatically after the job
  ✓ More secure, industry standard

Understanding OIDC Authentication

OIDC works like a hotel keycard system. The hotel (cloud platform) trusts the keycard reader (GitHub's identity system). When you arrive (workflow runs), the reader issues a temporary keycard (short-lived token). The keycard opens doors (cloud resources) and expires when you check out (job ends).

Workflow starts
      ↓
GitHub issues a short-lived token (OIDC token)
      ↓
Cloud platform verifies token with GitHub
      ↓
Cloud platform grants temporary credentials
      ↓
Workflow deploys using those credentials
      ↓
Job ends → credentials expire automatically

Deploying to AWS with OIDC

First, configure an IAM identity provider and role in your AWS account that trusts GitHub. Then use the official AWS credential action:

name: Deploy to AWS

on:
  push:
    branches: [main]

permissions:
  id-token: write      ← Required for OIDC
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
          aws-region: us-east-1

      - name: Deploy to S3
        run: aws s3 sync ./dist s3://my-app-bucket --delete

      - name: Invalidate CloudFront cache
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ vars.CF_DISTRIBUTION_ID }} \
            --paths "/*"

Deploying to ECS (Elastic Container Service)

steps:
  - name: Login to ECR
    uses: aws-actions/amazon-ecr-login@v2

  - name: Build and push Docker image to ECR
    uses: docker/build-push-action@v6
    with:
      push: true
      tags: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:${{ github.sha }}

  - name: Deploy to ECS
    uses: aws-actions/amazon-ecs-deploy-task-definition@v2
    with:
      task-definition: task-definition.json
      service: my-app-service
      cluster: production-cluster
      wait-for-service-stability: true

Deploying to Azure with OIDC

Configure a federated identity credential in Azure AD, then use the official Azure login action:

name: Deploy to Azure

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Log in to Azure via OIDC
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Deploy to Azure App Service
        uses: azure/webapps-deploy@v3
        with:
          app-name: my-web-app
          slot-name: production
          package: ./dist

      - name: Deploy to Azure Container Apps
        uses: azure/container-apps-deploy-action@v1
        with:
          containerAppName: my-container-app
          resourceGroup: my-resource-group
          imageToDeploy: myregistry.azurecr.io/my-app:${{ github.sha }}

Deploying to Google Cloud with OIDC

Configure Workload Identity Federation in GCP, then use the official Google Cloud auth action:

name: Deploy to Google Cloud

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: projects/123/locations/global/workloadIdentityPools/my-pool/providers/my-provider
          service_account: deploy-sa@my-project.iam.gserviceaccount.com

      - name: Set up Google Cloud SDK
        uses: google-github-actions/setup-gcloud@v2

      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy my-app \
            --image gcr.io/my-project/my-app:${{ github.sha }} \
            --region us-central1 \
            --platform managed

Deploying to Other Platforms

Heroku

- uses: akhileshns/heroku-deploy@v3.13.15
  with:
    heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
    heroku_app_name: my-heroku-app
    heroku_email: team@example.com

Vercel

- name: Deploy to Vercel
  run: npx vercel --token ${{ secrets.VERCEL_TOKEN }} --prod

Netlify

- name: Deploy to Netlify
  uses: netlify/actions/cli@master
  with:
    args: deploy --dir=dist --prod
  env:
    NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
    NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

Cloud Deployment Checklist

Before deploying to any cloud:
  □ Set up OIDC or create minimal-permission service account
  □ Store credentials as GitHub Secrets or use OIDC
  □ Target the deployment job at a specific environment
  □ Add required reviewers for production environments
  □ Test the deployment workflow in staging first
  □ Add rollback instructions to your runbook
  □ Add Slack or email notifications for deployment events

Leave a Comment