• Blog
  • Docs
  • Careers
  • Get Support
  • Contact Sales
DigitalOcean
  • Featured AI Products

    Compute

    Build, deploy, and scale cloud compute resources

    Containers and Images

    Safely store and manage containers and backups

    Managed Databases

    Fully managed resources running popular database engines

    Management and Dev Tools

    Control infrastructure and gather insights

    Networking

    Secure and control traffic to apps

    Security

    Help protect your account and resources with these security features

    Storage

    Store and access any amount of data reliably in the cloud

    Browse all products

  • AI/ML

    CMS

    Data and IoT

    Developer Tools

    Gaming and Media

    Hosting

    Security and Networking

    Startups and SMBs

    Web and App Platforms

    See all solutions

  • Community

    Documentation

    Developer Tools

    Get Involved

    Utilities and Help

  • Become a Partner

    Marketplace

  • Pricing
  • Log in
  • Sign up
  • Log in
  • Sign up

Company

  • About
  • Leadership
  • Blog
  • Careers
  • Customers
  • Partners
  • Referral Program
  • Affiliate Program
  • Press
  • Legal
  • Privacy Policy
  • Security
  • Investor Relations

Products

  • GPU Droplets
  • Bare Metal GPUs
  • Inference Engine
  • Data & Learning
  • Evaluations
  • Model Library
  • Droplets
  • Kubernetes
  • Functions
  • App Platform
  • Load Balancers
  • Managed Databases
  • Spaces
  • Block Storage
  • Network File Storage
  • API
  • Uptime
  • Cloud Security Posture Management (CSPM)
  • Identity and Access Management (IAM)
  • Cloudways
  • View all Products

Resources

  • Community Tutorials
  • Community Q&A
  • CSS-Tricks
  • Write for DOnations
  • Currents Research
  • DigitalOcean Startups
  • Wavemakers Program
  • Compass Council
  • Open Source
  • Newsletter Signup
  • Marketplace
  • Pricing
  • Pricing Calculator
  • Documentation
  • Release Notes
  • Code of Conduct
  • Shop Swag

Solutions

  • AI Training GPU
  • GPU Inference
  • VPS Hosting
  • Website Hosting
  • VPN
  • Docker Hosting
  • Node.js Hosting
  • Web Mobile Apps
  • WordPress Hosting
  • Virtual Machines
  • View all Solutions

Contact

  • Support
  • Sales
  • Report Abuse
  • System Status
  • Share your ideas

Company

  • About
  • Leadership
  • Blog
  • Careers
  • Customers
  • Partners
  • Referral Program
  • Affiliate Program
  • Press
  • Legal
  • Privacy Policy
  • Security
  • Investor Relations

Products

  • GPU Droplets
  • Bare Metal GPUs
  • Inference Engine
  • Data & Learning
  • Evaluations
  • Model Library
  • Droplets
  • Kubernetes
  • Functions
  • App Platform
  • Load Balancers
  • Managed Databases
  • Spaces
  • Block Storage
  • Network File Storage
  • API
  • Uptime
  • Cloud Security Posture Management (CSPM)
  • Identity and Access Management (IAM)
  • Cloudways
  • View all Products

Resources

  • Community Tutorials
  • Community Q&A
  • CSS-Tricks
  • Write for DOnations
  • Currents Research
  • DigitalOcean Startups
  • Wavemakers Program
  • Compass Council
  • Open Source
  • Newsletter Signup
  • Marketplace
  • Pricing
  • Pricing Calculator
  • Documentation
  • Release Notes
  • Code of Conduct
  • Shop Swag

Solutions

  • AI Training GPU
  • GPU Inference
  • VPS Hosting
  • Website Hosting
  • VPN
  • Docker Hosting
  • Node.js Hosting
  • Web Mobile Apps
  • WordPress Hosting
  • Virtual Machines
  • View all Solutions

Contact

  • Support
  • Sales
  • Report Abuse
  • System Status
  • Share your ideas
© 2026 DigitalOcean, LLC.Sitemap.
Engineering

Introducing new GitHub Actions for App Platform

author

By Markus Thömmes

  • Published: September 26, 2024
  • 8 min read
<- Back to blog home

GitHub Actions is the CI/CD platform our customers use the most for building and deploying their code. In the past, we’ve provided a supported action, called app_action, that could be used to update an App that already exists via a GitHub Action.

Today, we’re excited to introduce completely overhauled GitHub Actions for App Platform with improved pluggability to cater to all of the deployment needs you might think of.

GitHub for all the things

The new deploy action is the heart of our GitHub Actions ecosystem. Like the old one, it allows you to update an app that already exists. However, it also does much more than that: It also allows you to completely make the respective GitHub repository the source of truth in a GitOps-style fashion. Now, you can commit an AppSpec to your GitHub repository and handle the entire deployment process via GitHub Actions. It is no longer necessary to interact with DigitalOcean directly at all (apart from generating the token for the action to use).

The in-repository AppSpec can also contain environment variable placeholders that will be replaced before deploying the new spec. This can be used to update image references on the fly or to manage your secrets via Github’s secret mechanism.

We’ve also used the opportunity to provide more integration into the GitHub Actions ecosystem. The deploy action outputs the resulting app metadata and the build and deployment logs from the deployment that took place. Optionally, those logs are also logged in the action’s output itself. That metadata can be used to create rich integrations with App Platform, tailored to your specific needs.

Deploy an app from GitHub

To deploy an app purely from GitHub without needing to create it out of band first is as simple as committing the respective App Spec to the repository (the action defaults to .do/app.yaml) and setup an action like below. This will cause the app to redeploy whenever a new commit is pushed to main (note that deploy_on_push should be turned off in the App Spec for that matter). Any changes to the App Spec itself would also be applied.

name: Update App

on:
  push:
    branches: [main]
    
permissions:
  contents: read

jobs:
  deploy-app:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Deploy the app
        uses: digitalocean/app_action/deploy@v2
        with:
          token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}

Deploy an app from an image built in the GitHub Action

As a slightly more involved use-case, the below action builds an app from a Dockerfile in the repository inside the GitHub Action, not as part of the App Platform build. That image is then deployed by digest to ensure that this exact image is what’s being deployed as part of the app.

Note that the image digest is provided as the SAMPLE_DIGEST environment variable here. That’ll have to be referenced in the App Spec with the ${SAMPLE_DIGEST} notation.

name: Build, Push and Deploy a Docker Image

on:
  push:
    branches: [main]

permissions:
  contents: read
  packages: write

jobs:
  build-push-deploy-image:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Log in to the Container registry
        uses: docker/login-action@v3.3.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push Docker image
        id: push
        uses: docker/build-push-action@v6.5.0
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:latest
      - name: Deploy the app
        uses: digitalocean/app_action/deploy@v2
        env:
          SAMPLE_DIGEST: ${{ steps.push.outputs.digest }}
        with:
          token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}

Note that the image digest is provided as the SAMPLE_DIGEST environment variable here. That’ll have to be referenced in the App Spec with the ${SAMPLE_DIGEST} notation like so.

name: sample

services:
- name: sample
 image:
   registry_type: GHCR
   registry: YOUR_ORG
   repository: YOUR_REPO
   digest: ${SAMPLE_DIGEST}

Pull request previews

And lastly, pull request previews is a great example of the power of orchestratability. This feature allows you to deploy a new app for every pull request and surface the respective live URL [1] and the respective build [2] and deployment [3] logs to the pull request author, avoiding merging code that breaks the app in production.

With the new deploy action, creating such an integration in your repository becomes trivial. It comes with a specialized “PR-preview-mode”, which generates a unique app name for each pull request, sanitizes the app spec of potentially conflicting resources (for example, it drops domains and alerts), and updates all potential GitHub references to point to the respective PR’s branch.

Conversely, there’s also a new delete action, that allows you to delete apps again. Usually, this is done when a pull request is closed or merged to clean up resources.

Equipped with that, you can imagine an action like the below, which will deploy an app per pull request and upon successful deployment, will post a comment to the pull request with a link to the app. On failure, it will post a link to the action’s logs and collapsible sections for build and deploy logs respectively for quick debugging. The second action will make sure that the respective app is deleted when the pull request closes or is merged.

name: App Platform Preview

on:
  pull_request:
    branches: [main]

permissions:
  contents: read
  pull-requests: write

jobs:
  test:
    name: preview
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Deploy the app
        id: deploy
        uses: digitalocean/app_action/deploy@v2
        with:
          deploy_pr_preview: "true"
          token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
      - uses: actions/github-script@v7
        env:
          BUILD_LOGS: ${{ steps.deploy.outputs.build_logs }}
          DEPLOY_LOGS: ${{ steps.deploy.outputs.deploy_logs }}
        with:
          script: |
            const { BUILD_LOGS, DEPLOY_LOGS } = process.env
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `:rocket: :rocket: :rocket: The app was successfully deployed at ${{ fromJson(steps.deploy.outputs.app).live_url }}.`
            })
      - uses: actions/github-script@v7
        if: failure()
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `The app failed to be deployed. Logs can be found [here](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).

              ## Logs
              <details>
              <summary>Build logs</summary>
              
              \`\`\`
              ${BUILD_LOGS}
              \`\`\`
              </details>
              
              <details>
              <summary>Deploy logs</summary>

              \`\`\`
              ${DEPLOY_LOGS}
              \`\`\`
              </details>`
            })
name: Delete Preview

on:
  pull_request:
    types: [ closed ]

jobs:
  closed:
    runs-on: ubuntu-latest
    steps:
      - name: delete preview app
        uses: digitalocean/app_action/delete@v2
        with:
          from_pr_preview: "true"
          ignore_not_found: "true"
          token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}

The sky’s the limit!

You can find the code and documentation at the app_action GitHub repository. We’re excited to see what kind of an integration you can come up with! Give the new actions a try and bring your app platform deployments to the next level.

About the author

Markus Thömmes
Markus Thömmes
Author
See author profile
See author profile

Share

  • Engineering

Start building today

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.
Sign up

Related Articles

The Inference Alpha: Maximizing Frontier Models on AMD
Engineering

The Inference Alpha: Maximizing Frontier Models on AMD

Balaji Varadarajan

  • June 10, 2026
  • 12 min read

Read more

The Inference Tax: How Prefix-Aware Routing Eliminates the Hidden Cost of LLMs at Scale
Engineering

The Inference Tax: How Prefix-Aware Routing Eliminates the Hidden Cost of LLMs at Scale

Piyush Srivastava
  • June 1, 2026
  • 13 min read

Read more

DigitalOcean Serverless Inference: A Deep Dive
Engineering

DigitalOcean Serverless Inference: A Deep Dive

smehta
  • June 1, 2026
  • 17 min read

Read more