Running Dagger Pipelines on GitHub Actions
You've successfully "daggerized" your project, and it runs perfectly on your machine. The next step is to get your pipeline running on GitHub Actions.
While the initial steps are straightforward, there are a few considerations that can affect the structure and performance of your pipeline.
In this tutorial, we'll dive into these in detail.
💡 You can follow this tutorial on your own machine or use the provided online playground.
Preparations
If you’re running the tutorial locally, we recommend installing the GitHub CLI first.
Copy the template repository
This tutorial comes with a demo repository that includes a basic Dagger pipeline.
Throughout this tutorial you will migrate the existing GitHub Actions workflow to run Dagger pipelines.
To get started, create a new repository named tutorial-dagger-gha
from this template.
Using GitHub CLI (on your machine)
gh repo create --private \
--template sagikazarmark/template-tutorial-dagger-gha \
tutorial-dagger-gha
Authenticate with GitHub
This is only required when using the online playground.
Create a new Fine-grained access token with the following parameters:
- Repository access: Only select repositories
- Select your
tutorial-dagger-gha
repository - Repository permissions
- Contents: Read and write
- Workflows: Read and write
Hint
Check out this tutorial for a more detailed guide.
Finally, clone the repository:
gh repo clone tutorial-dagger-gha ~/tutorial
Examine the tutorial repository
Enter the tutorial
directory and list the available Dagger functions:
cd ~/tutorial
dagger functions
Feel free to explore or run the functions.
Next, go to the IDE tab and open the tutorial/.github/workflows/ci.yaml
file.
Examine the jobs in the GitHub Actions workflow.
💡 You can always compare your changes with the tutorial/.github/workflows/ci-dagger.yaml
file that serves as a reference.
Running Dagger on GitHub Actions
As a first step, update the tutorial/.github/workflows/ci.yaml
file and replace the Go test steps in the test
job with a Dagger pipeline call:
- name: Run pipeline
uses: dagger/dagger-for-github@main
with:
version: latest
verb: call
args: test
⚠️ In production, avoid floating tags—pin both the GitHub Action and Dagger to explicit version tags instead of using main
or latest
.
Hint 1 💡
- - name: Set up Go
- uses: actions/setup-go@v5
-
- - name: Test
- run: go test -race -v -shuffle=on ./...
+ - name: Run pipeline
+ uses: dagger/dagger-for-github@main
+ with:
+ version: latest
+ verb: call
+ args: test
Do the same with the lint
job.
Hint 2 💡
- - name: Set up Go
- uses: actions/setup-go@v5
-
- - name: Lint
- uses: golangci/golangci-lint-action@v7
+ - name: Run pipeline
+ uses: dagger/dagger-for-github@main
+ with:
+ version: latest
+ verb: call
+ args: lint
Commit and push the changes, then check out the Actions tab of your repository:
git commit -am "Add Dagger pipeline"
git push
Pipeline or Pipelines?
In the previous section, you replaced existing workflow steps with calls to Dagger functions while preserving the overall workflow structure (i.e., jobs).
Although this is a solid first step toward adopting Dagger, you can often simplify your workflows further by consolidating multiple functions into a single pipeline.
A key advantage of Dagger is that it organizes steps into a directed acyclic graph (DAG), allowing most independent steps to run in parallel. GitHub Actions can run jobs in parallel but not individual steps, which often leads us to split workflows into multiple jobs to optimize performance.
In many cases, however, you can achieve similar performance by merging several functions into one pipeline. This also makes local execution easier, since you no longer need to invoke each function separately.
The demo repository includes a check
function that orchestrates all of the other functions.
In your ci.yaml
, add a new check
job that invokes this check
function.
Hint 3 💡
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run pipeline
uses: dagger/dagger-for-github@main
with:
version: latest
verb: call
args: check
Commit and push the changes, then check out the Actions tab of your repository:
git commit -am "Add a new job running the check function"
git push
The caveat of this approach is that you lose the ability to view individual steps in pull requests. If something fails, you'll have to dig into the logs to find out what went wrong. A potential solution is to use Dagger Cloud traces to drill down into the failed step in the pipeline.
tl;dr Experiment with consolidating separate functions into a single pipeline. If the performance is comparable, consider replacing the separate function calls.
To checkout or not to checkout?
A common question is whether to rely on actions/checkout
to clone your repository or let Dagger do it via its built-in mechanism.
The answer depends on several factors.
As a general rule, keeping your pipelines self‑contained is a good practice. When Dagger pulls the source, the workflow is no longer coupled to GitHub Actions, so it’s easier to port to other CI systems—and your Actions YAML stays leaner.
Practically, you can have Dagger clone the repository by applying the defaultPath
pragma
to a constructor function parameter that loads your source directory:
- When the module runs locally, the source directory is loaded from the filesystem.
- When the module runs remotely, the source directory is loaded from the repository root.
Below is the module constructor from the demo repository:
func New(
// Project source directory.
//
// +defaultPath="/"
source *dagger.Directory,
) *Tutorial {
return &Tutorial{
Source: source,
}
}
Alternatively, you can use Dagger's Git feature to clone a repository,
but using the defaultPath
pragma is recommended for most cases.
Add a new without_checkout
job to your workflow file, pass the module and ref to Dagger (you can use the check
job as example, but remove any actions/checkout
steps):
steps:
- name: Run pipeline
uses: dagger/dagger-for-github@main
with:
module: github.com/${{ github.repository }}@${{ github.ref }}
verb: call
args: ...
Hint 4 💡
without_checkout:
name: Without Checkout
runs-on: ubuntu-latest
steps:
- name: Run pipeline
uses: dagger/dagger-for-github@main
with:
version: latest
module: github.com/${{ github.repository }}@${{ github.ref }}
verb: call
args: check
Commit and push the changes, then check out the Actions tab of your repository:
git commit -am "Checkout repository using Dagger"
git push
Sometimes, however, the platform’s native checkout is more convenient.
For example, cloning private repositories is often easier with GitHub’s built‑in authentication.
Likewise, if you plan to use Dagger Cloud, the CLI reads source information from the local repository
(that actions/checkout
populates), helping it map traces to the correct commit or pull request.
tl;dr If you use Dagger in private repositories, or plan to use Dagger Cloud, stick with actions/checkout
.
Using secrets
Dagger provides first‑class support for secrets, so you can use sensitive data (API keys, passwords, etc.) securely in your pipelines.
You can source secrets from different providers:
You can then inject them into your pipeline as secret arguments.
GitHub Actions also offers a way to manage secrets: store your secrets securely in the repository settings, expose them to your workflow via environment variables, and then pass them into Dagger as arguments.
Here is an example:
check:
name: Check
runs-on: ubuntu-latest
steps:
# checkout
- name: Run pipeline
uses: dagger/dagger-for-github@main
with:
version: latest
verb: call
args: check --github-token GITHUB_TOKEN
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Feel free to experiment with injecting a secret into the pipeline!
Hint 5 💡
You can quickly create a secret in GitHub with the following CLI command:
gh secret set MYSECRET --body "VALUE" [--repo <owner/repo>]
Integrate with Dagger Cloud
Dagger Cloud gives you rich, interactive pipeline visualizations—complete with detailed traces—so you can pinpoint failures and troubleshoot performance bottlenecks in seconds. Its clean, graphical interface is far easier to navigate (and prettier to look at) than going through raw GitHub Actions logs.
Dagger Cloud is free for individuals (at the moment), you can sign up for a free account here.
After completing the setup, you can get an API token and add it to your repository as a secret.
💡 Be sure to check out the documentation on configuring Dagger Cloud.
From there, it's only a matter of passing the token into the Dagger action:
check:
name: Check
runs-on: ubuntu-latest
steps:
# checkout
- name: Run pipeline
uses: dagger/dagger-for-github@main
with:
version: latest
verb: call
args: check
cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
Improve build times by better caching
One hurdle with Dagger on GitHub Actions is caching: GitHub’s hosted runners are ephemeral, so anything you cache won’t survive between workflow runs unless you’re on self‑hosted runners. While the Dagger team is actively enhancing built‑in caching, you’ll need a stopgap to speed up your builds today.
Enter Depot. Depot’s first‑class Dagger integration persists caches across runs, often yielding dramatic reductions in build times.
💡 Check out this case study from OpenMeter, where they sped up their CI pipeline by 5× and cut costs in half.
Depot offers a 7-day free trial to get started which is ample time to try their features.
First, sign up for Dagger Cloud (required to use the special Dagger runners in Depot).
Then sign up for Depot and follow the instructions here to connect Depot with your GitHub account and Dagger Cloud.
⚠️ Depot does NOT work with personal GitHub accounts. You must use a GitHub organization account.
Finally, update your workflow to use the Dagger runner:
check:
name: Check
runs-on: depot-ubuntu-latest,dagger=0.18.3
steps:
# checkout
- name: Run pipeline
run: dagger call check
Notice that you need pin the Dagger version via the runs-on
field and since the runner comes with the Dagger binary preinstalled, you can drop the Dagger Action and invoke the CLI directly.
For I/O‑intensive pipelines with cacheable steps, you should see a significant reduction in average build times.
💡 Read more about Depot and Dagger here.
Summary
In this tutorial, you learned how to use Dagger in GitHub Actions, including how to use secrets and how to integrate with Dagger Cloud.
You also learned how running Dagger pipelines on GitHub Actions can affect the structure of your pipelines.
Level up your Server Side game — Join 10,000 engineers who receive insightful learning materials straight to their inbox