This repository provides a reusable GitHub Actions workflow that creates a temporary (ephemeral) GitHub Actions runner on DigitalOcean, runs a job on it, and automatically deletes the droplet after the job completes.
This approach is ideal for:
- Cost-efficient CI/CD
- Clean, isolated build environments
- Heavy or untrusted workloads
- Self-hosted runner scaling
- Creates a DigitalOcean droplet
- Registers it as a GitHub Actions runner
- Runs your job on that runner
- Deletes the droplet (
state: absent) - Leaves no running infrastructure behind
create-runner β run-job β destroy-runner
β β β
β β ββ Deletes droplet
β ββ Job runs on ephemeral VM
ββ Creates VM + GitHub runner
- β Ephemeral (one-time) runner per job
- β No idle VMs
- β Automatic cleanup using DigitalOcean API
- β Works with any shell command
- β Safe cleanup using
if: always()
The reusable workflow is defined at:
.github/workflows/ephemeral-do-runner.yml
| Input Name | Required | Default | Description |
|---|---|---|---|
do_size |
No | s-1vcpu-1gb |
DigitalOcean droplet size |
do_region |
No | nyc1 |
DigitalOcean region |
job_command |
Yes | β | Shell command(s) to run on the runner |
| Secret Name | Required | Description |
|---|---|---|
DIGITAL_OCEAN_ACCESS_TOKEN |
Yes | DigitalOcean API token with droplet permissions |
name: Build on Ephemeral Runner
on:
workflow_dispatch:
jobs:
build:
uses: ./.github/workflows/ephemeral-do-runner.yml
with:
job_command: |
echo "Running on ephemeral DO runner"
uname -a- The workflow uses
if: always()to ensure the destroy step runs even if the job fails - The droplet is deleted, not stopped
- No manual cleanup required
β οΈ In rare cases (GitHub outage, control runner failure), cleanup could be skipped.
For maximum safety, consider adding VM self-shutdown logic inside the runner.
- Use small droplet sizes for CI jobs
- Prefer short-lived workloads
- Avoid storing persistent data on the runner
- Treat the runner as disposable
- Requires a control runner (
self-hosted, control-runner) to create and delete droplets - The ephemeral runner exists only for the duration of the job
- Designed for reuse across multiple repositories
MIT License