Skip to main content

Working with Deployment Workflows

1. Defining Deployment Jobs

Property Description Values
jobs.<job_id>.name Human-readable name for the job string
jobs.<job_id>.runs-on Runner environment to execute the job on ubuntu-latest, macOS-latest, windows-latest, or custom runner labels
jobs.<job_id>.environment Environment to deploy to (optional) string or object
jobs.<job_id>.steps Sequence of actions to run in the job array of step objects
jobs.<job_id>.needs Job dependencies (optional) array of job IDs
jobs.<job_id>.if Conditional expression to run the job (optional) string

Example: Basic Deployment Job

jobs:
  deploy:
    name: Deploy to Production
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Deploy to Server
        run: |
          echo "Deploying application..."
Note: The environment property links to a defined environment in your repository settings, which can include protection rules and review approval requirements.

2. Using Deployment Environment

Property Description Values
environment.name Name of the deployment environment production, staging
environment.url URL where the deployment is accessible https://app.example.com
environment.protection_rules Protection rules to apply to the environment wait_timer, required_approvals

Example: Environment Configuration

name: Deploy to Production
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.example.com
Note: Environments can be configured with protection rules to require manual approval or a wait timer before deployment.

3. Requiring Manual Approval

Manual approval is a critical security and governance feature in GitHub Actions that allows workflows to pause and await human confirmation before proceeding to the next step. This is particularly useful for deployment workflows where you want to ensure that a human reviews and approves the deployment before it happens.

Setting Description Value
workflow_dispatch Triggers the workflow manually from the GitHub UI or API. true
on.workflow_dispatch Enables manual triggering of the workflow. {}
needs Specifies that a job depends on another job or jobs. approval

Example: Manual Approval Workflow

name: Manual Approval Workflow
on:
  workflow_dispatch: {}

jobs:
  approval:
    runs-on: ubuntu-latest
    steps:
      - name: Wait for manual approval
        run: echo "Waiting for manual approval..."

  deploy:
    needs: approval
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to production
        run: echo "Deploying to production..."
Note: The workflow_dispatch trigger allows the workflow to be manually triggered from the GitHub UI or API, which is useful for workflows that require human intervention.
Warning: Ensure that the approval job does not perform any actions that could be harmful if run without human oversight.

4. Setting Deployment URL

Property Description Example
github.event.deployment.url URL of the deployment, set by GitHub https://example.com/deployment/12345
env.DEPLOYMENT_URL Environment variable to store deployment URL https://myapp.vercel.app

Example: Set Deployment URL in Environment

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Vercel
        run: |
          DEPLOYMENT_URL=$(vercel --prod)
          echo "DEPLOYMENT_URL=$DEPLOYMENT_URL" >> $GITHUB_ENV
Note: The deployment URL is typically set by the deployment platform (e.g., Vercel, Netlify) and can be accessed via environment variables or API responses.

5. Tracking Deployment Status

Example: Using GitHub API to Check Deployment Status

const { Octokit } = require("@octokit/rest");

const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });

async function checkDeploymentStatus(owner, repo, deploymentId) {
  try {
    const response = await octokit.request("GET /repos/{owner}/{repo}/deployments/{deployment_id}", {
      owner,
      repo,
      deployment_id: deploymentId
    });

    console.log("Deployment Status:", response.data.status);
    return response.data;
  } catch (error) {
    console.error("Error fetching deployment status:", error);
  }
}

checkDeploymentStatus("octocat", "Hello-World", 123456);
Field Description Values
status Current status of the deployment success, failure, pending, error
environment Name of the environment the deployment targets production, staging, development
created_at Timestamp when the deployment was created 2023-04-15T10:00:00Z
updated_at Timestamp when the deployment was last updated 2023-04-15T11:00:00Z
Note: Deployment statuses can be updated via the GitHub API or through GitHub Actions workflows using the github.rest.repos.createDeploymentStatus endpoint.

Example: Updating Deployment Status in GitHub Actions

name: Update Deployment Status
on:
  workflow_run:
    workflows: ["Deploy"]
jobs:
  update-status:
    runs-on: ubuntu-latest
    steps:
      - name: Update deployment status to success
        uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const deploymentId = 123456;
            await github.rest.repos.createDeploymentStatus({
              owner: context.repo.owner,
              repo: context.repo.repo,
              deployment_id: deploymentId,
              state: "success",
              description: "Deployment completed successfully"
            });

6. Using Blue-Green Deployments

Blue-green deployment is a deployment strategy that reduces downtime and risk by running two identical production environments — one "blue" and one "green".

Environment Status Description
Blue ACTIVE Current production environment
Green INACTIVE Staging environment with new version

Example: GitHub Actions Workflow for Blue-Green Deployment

name: Blue-Green Deployment
on:
  push:
    branches: [ main ]

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

      - name: Deploy to Green
        run: |
          echo "Deploying new version to Green environment"
          # Deployment logic here

      - name: Validate Green
        run: |
          echo "Validating Green environment"
          # Validation logic here

      - name: Switch traffic to Green
        run: |
          echo "Switching traffic from Blue to Green"
          # Traffic switch logic here
Note: The switch between environments should be atomic to avoid downtime or partial updates.

Blue-Green Deployment Benefits

  • Zero Downtime: Traffic is switched atomically.
  • Rollback Capability: Easily switch back to the blue environment if issues arise.
  • Testing: New version can be tested in a production-like environment.

7. Implementing Canary Deployments

Canary deployments gradually roll out changes to a subset of users or servers before full deployment. This approach helps reduce risk and allows for quick rollback if issues arise.

Aspect Description Implementation
Deployment Strategy Gradually increase traffic to new version Use weighted routing or percentage-based distribution
Traffic Splitting Control how much traffic goes to new version Configure with service mesh or load balancer
Monitoring Track performance and errors during rollout Use metrics like latency, error rate, and user feedback

Example: Using GitHub Actions for Canary Deployment

name: Canary Deployment
on:
  push:
    branches:
      - main

jobs:
  deploy-canary:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Deploy to canary environment
        run: |
          echo "Deploying to canary..."
          # Deploy logic here

      - name: Validate deployment
        run: |
          echo "Validating canary deployment..."
          # Validation logic here

      - name: Gradually increase traffic
        run: |
          echo "Increasing traffic to canary..."
          # Traffic shifting logic here
Note: Canary deployments are particularly useful in microservices architectures where gradual rollout minimizes impact on users.

Key Benefits of Canary Deployments

  • Reduced risk of full system failure
  • Early detection of issues in production
  • Gradual user adoption of new features
  • Ability to quickly rollback if problems occur

8. Rolling Back Deployments

Option Values Notes
github.event.inputs.rollback_to sha or tag Commit SHA or tag to rollback to
github.event.inputs.environment production or staging Environment to rollback deployment in

Example: Rolling Back to Previous Commit

name: Rollback Deployment
on:
  workflow_dispatch:
    inputs:
      rollback_to:
        description: 'Commit SHA to rollback to'
        required: true
        type: string
      environment:
        description: 'Environment to rollback in'
        required: true
        type: choice
        options:
          - production
          - staging

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.rollback_to }}
      - name: Deploy rollback
        run: |
          echo "Deploying to ${{ github.event.inputs.environment }} from commit ${{ github.event.inputs.rollback_to }}"
Note: Ensure that the rollback target commit is available in the repository history and has been previously deployed successfully.
Warning: Rolling back deployments can cause data loss or inconsistencies if the rollback target is not compatible with current state.

9. Using Deployment Gates

Deployment gates are conditions that must be met before a workflow can proceed to deployment. They help ensure that deployments only happen when certain criteria are satisfied.

Gate Type Description Configuration Notes
Manual Approval Requires manual approval before deployment needs: [approval] Use github.event.inputs.approval to check approval status
Environment Protection Rules Enforce rules on environments (e.g., required reviewers, branches) Defined in environment settings Can include conditions like branch name, deployment status
Wait for Status Checks Waits for specific checks to pass before proceeding status-checks: [check-name] Can be used to wait for CI checks or external validation

Example: Manual Approval Gate

jobs:
  deploy:
    needs: [approval]
    steps:
      - name: Deploy to production
        run: echo "Deploying..."

Example: Environment Protection Rule

jobs:
  deploy:
    environment:
      name: production
      url: https://myapp.com
    steps:
      - name: Deploy to production
        run: echo "Deploying..."
Note: Deployment gates can be combined with other conditions to create complex deployment workflows.
Warning: Manual approval gates require user interaction, which can slow down automated deployments.

10. Configuring Auto-Deployments

Option Values Notes
on push Triggers workflow on push to branch
on pull_request Triggers workflow on pull request
on workflow_dispatch Allows manual triggering of workflow
env DEPLOY_ENV Environment variable for deployment target
env DEPLOY_TOKEN Token for deployment authentication

Example: Basic Auto-Deployment Workflow

name: Deploy to Production
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Server
        run: |
          echo "Deploying to production server..."

Example: Conditional Deployment Based on Branch

name: Conditional Deployment
on:
  push:
    branches:
      - main
      - staging
jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Production
        run: |
          echo "Deploying to production..."
Note: Ensure that deployment tokens and secrets are properly stored in GitHub Secrets to avoid exposing sensitive credentials.

11. Using Deployment Notifications

Notification Type Trigger Configuration Notes
GitHub Status Checks Workflow completion status: success|failure Shows up in PRs and commits
Slack Notifications Workflow completion slack webhook url Requires Slack app setup
Email Notifications Workflow completion email address Only for GitHub Enterprise
Webhook Notifications Workflow completion webhook url Custom payload support

Example: Slack Notification

name: Slack Notification
on:
  workflow_run:
    workflows: ["Deploy"]
    types: [completed]
jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Send to Slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#deployments'
Note: Slack notifications require a Slack app with appropriate permissions and a valid webhook URL.
Warning: Email notifications are only available in GitHub Enterprise and may have rate limits.

12. Monitoring Deployment History

Field Description Values
deployment.id Unique identifier for the deployment 12345
deployment.name Name of the deployment Production Deploy
deployment.status Current status of the deployment success, failure, pending
deployment.environment Environment where the deployment occurred production, staging
deployment.created_at Timestamp when the deployment was created 2025-04-01T12:00:00Z
deployment.updated_at Timestamp when the deployment was last updated 2025-04-01T12:05:00Z

Example: Retrieve Deployment History

const { GitHub } = require("@actions/github");

async function getDeploymentHistory() {
  const github = new GitHub(process.env.GITHUB_TOKEN);
  const { data: deployments } = await github.rest.repos.listDeployments({
    owner: "owner",
    repo: "repo-name",
    environment: "production"
  });

  console.log(deployments);
}

getDeploymentHistory();
Note: Deployment history can be retrieved using the GitHub REST API or via GitHub Actions workflows.
Warning: Ensure that the GITHUB_TOKEN has appropriate permissions to read deployment data.

Was this article helpful?