Skip to main content

Checks

Checks are automated validations that run on every commit to ensure code quality, security, and standards compliance. They're the primary way Dagger helps you maintain quality in your codebase.

A check is a function that validates your code without requiring any arguments. This means checks can run anywhere—locally before you commit, in CI on every push, by your coding agent, or before deploying to production—with a simple dagger check command.

Running Checks​

Use the dagger check command to run all available checks:

# Run all checks concurrently
dagger check

# List available checks
dagger check -l

# Run specific checks using patterns
dagger check lint-*
dagger check security-scan

Checks are automatically executed in parallel for maximum performance. The command exits with a non-zero status if any check fails, making it easy to integrate into CI/CD pipelines:

# Example GitHub Actions
- name: Run checks
run: dagger check

Since checks are just Dagger Functions, they run consistently across all environments with full access to Dagger's caching and parallelization capabilities.

Checks from Toolchains​

The easiest way to add checks to your project is by installing toolchains that provide them. Toolchain checks are automatically available when you run dagger check:

# Install toolchains that provide checks
dagger toolchain install github.com/example/black
dagger toolchain install github.com/example/pytest
dagger toolchain install github.com/example/security-scanner

# List all checks (including toolchain checks)
dagger check -l

# Example output:
# black:format
# pytest:test
# security-scanner:scan
# security-scanner:dependency-check

Toolchain checks are namespaced with the toolchain name, making it easy to identify their source:

# Run all checks from the pytest toolchain
dagger check pytest:*

# Run a specific toolchain check
dagger check security-scanner:scan

This makes it easy to compose validation workflows by installing multiple tool-specific toolchains that each provide their own checks.

Filtering and Ignoring Checks​

Filtering Checks​

You can use glob patterns to selectively run checks:

# Run all lint checks
dagger check lint-*

# Run security-related checks
dagger check security-*

# Run a specific check
dagger check code-style

When multiple patterns are provided, checks matching any pattern will run.

Ignoring Checks from Toolchains​

When you install a module as a toolchain, you can ignore specific checks from that toolchain in your dagger.json:

{
"name": "my-app",
"toolchains": [
{
"name": "scanner",
"source": "github.com/example/security-scanner",
"ignoreChecks": [
"dependency-scan",
"container-*"
]
}
]
}

Check patterns in toolchain ignoreChecks are scoped to that toolchain, so you don't need to include the toolchain name prefix.

Creating Checks​

To create a check, mark a Dagger Function with the check annotation. Checks must not require any arguments—they should validate the current state of the repository when run with no input. However, checks can accept optional arguments to customize behavior, such as filtering which tests to run or adjusting validation strictness. This design ensures checks can run automatically in any environment while still being flexible for advanced use cases.

Checks can return an error (for pass/fail validation) or a container (for tools that produce exit codes).

Use the +check comment annotation:

// Runs linting checks on the code
// +check
func (m *MyModule) LintCode(ctx context.Context) error {
_, err := dag.Container().
From("golangci/golangci-lint:latest").
WithExec([]string{"golangci-lint", "run"}).
Sync(ctx)
return err
}

// Runs security scan with optional severity filter
// +check
func (m *MyModule) SecurityScan(
ctx context.Context,
// +optional
// +default="HIGH,CRITICAL"
severity string,
) error {
_, err := dag.Container().
From("aquasec/trivy:latest").
WithExec([]string{"trivy", "fs", "--severity", severity, "."}).
Sync(ctx)
return err
}