Skip to main content

Dart Package

This workflow runs helpful checks on a Dart package according to the steps below. As with any workflow, it can be customized.

Steps​

The Dart package workflow consists of the following steps:

  1. Setup Dart
  2. Set SSH Key (if provided)
  3. Set Pub Tokens (if provided)
  4. Install dependencies
  5. Run Setup (if provided)
  6. Format
  7. Analyze
  8. Bloc Lint (if enabled)
  9. Cognitive Complexity (if enabled)
  10. Run tests (includes coverage collection and enforcement)
  11. Upload artifacts (if configured)

Inputs​

concurrency​

Optional The number of concurrent test suites run.

Default 4

coverage_excludes​

Optional Space-separated list of globs to exclude files from the coverage report (e.g. '**/*.g.dart **/gen/*.dart').

Default ""

dart_sdk​

Optional Which Dart SDK version to use. It can be a version (e.g. 3.5.0) or a channel (e.g. stable):

Default "stable"

format_line_length​

Optional The preferred line length preferred for running the dart format command. Be aware that this does not change the behavior of the analysis step and longer lines could still make the workflow fail if the rule lines_longer_than_80_chars is used.

min_coverage​

Optional The minimum coverage percentage allowed.

Default 100

working_directory​

Optional The path to the root of the Dart package.

Default "."

analyze_directories​

Optional A space-separated list of folders that should be analyzed.

Default "lib test"

format_directories​

Optional A space-separated list of folders that should be formatted.

Default "."

check_ignore​

Optional Whether to check for and respect coverage ignore comments (e.g. // coverage:ignore-line).

Default false

report_on​

Optional A comma-separated list of folders that should be checked in code coverage.

Default "lib"

runs_on​

Optional The operating system on which to run the workflow.

Default "ubuntu-latest"

timeout_minutes​

Optional The maximum number of minutes to let the job run before GitHub automatically cancels it.

Default 360

setup​

Optional A command that should be executed immediately after dependencies are installed. It can also be used to export environment variables for later steps (see Providing environment variables).

Default ""

platform​

Optional A comma-separated list of platforms on which to run the tests. [vm (default), chrome, firefox, safari, node]

Default "vm"

run_skipped​

Optional Run skipped tests instead of skipping them.

Default false

no_example​

Optional To avoid getting packages in example/ when running dart pub get (if it exists).

Default false

show_uncovered​

Optional Whether to show uncovered lines when coverage is below 100%. Implicitly enables coverage collection when used alone.

Default true

collect_coverage_from​

Optional Whether to collect coverage from imported files only or all files. Counting untested files against coverage (all) results in stricter enforcement.

Allowed values imports, all

Default "imports"

test_optimization​

Optional Whether to apply optimizations for test performance.

Default true

run_bloc_lint​

Optional Whether to run bloc lint on the package.

Default false

run_cognitive_complexity​

Optional Whether to run the cognitive_complexity audit on the package. See Cognitive complexity.

Default false

cognitive_complexity_targets​

Optional Space-separated list of directories or files to scan for cognitive complexity.

note

Like artifact_paths, these paths are resolved from the repository root, not from working_directory. For a package nested in a monorepo, write the prefix out in full (e.g. packages/my_package/lib).

Default "lib"

cognitive_complexity_fail_threshold​

Optional The maximum cognitive complexity score a function may reach before the job fails.

Default 15

cognitive_complexity_fail_on_increase​

Optional Whether to fail the job when cognitive complexity increases relative to cognitive_complexity_diff_base. The action resolves the diff base on its own.

Default false

cognitive_complexity_diff_base​

Optional Git reference to compare against when computing complexity changes (e.g. origin/main). An empty value lets the action auto-detect the base.

Default ""

artifact_paths​

Optional A newline-separated list of globs to upload as a workflow artifact once the tests finish. Runs on both passing and failing test runs, so it captures output from a failed run as well as reports produced by a green one. An empty value disables the upload entirely.

Default ""

Note: Unlike the other path inputs, these globs are resolved from the repository root, not from working_directory. This is a constraint of actions/upload-artifact, which has no working directory setting. See Uploading artifacts.

artifact_name​

Optional The name given to the uploaded artifact. Must be unique across every job in the same workflow run, otherwise the upload fails with a conflict. Only relevant when artifact_paths is set.

Default "artifacts"

Secrets​

ssh_key​

Optional An SSH key used to access private repositories when installing dependencies.

pub_tokens​

Optional Authentication tokens for custom package repositories, used to resolve dependencies hosted somewhere other than pub.dev. Provide one entry per line in the form <hosted-url> <token>. Each entry is registered with dart pub token add before dependencies are installed, so several repositories can be authenticated at once. The token is read through the recommended --env-var flag rather than being written to a configuration file. Lines that do not contain a space fail the workflow. See Custom package repositories.

Custom package repositories​

When a package depends on a custom (private) package repository, pass the credentials through the pub_tokens secret. Store the tokens in a repository or organization secret with one <hosted-url> <token> pair per line:

https://dart-packages.example.com TOKEN_VALUE
https://another-repo.example.com ANOTHER_TOKEN_VALUE

Then forward that secret to the workflow:

jobs:
build:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v2
secrets:
pub_tokens: ${{secrets.PUB_TOKENS}}

The step only runs when the secret is provided, so packages that depend solely on pub.dev need no extra configuration.

Uploading artifacts​

Set artifact_paths to keep files produced by the run, such as the coverage report. The step executes whether the tests pass or fail, and quietly does nothing when no file matches.

with:
artifact_paths: 'coverage/lcov.info'

Globs are resolved from the repository root rather than from working_directory, so a package nested in a monorepo needs the prefix written out in full:

with:
working_directory: packages/my_package
artifact_paths: 'packages/my_package/coverage/lcov.info'

Pass several globs on separate lines, and use artifact_name to keep names unique when more than one job uploads in the same run:

with:
artifact_paths: |
coverage/lcov.info
build/reports/**
artifact_name: 'artifacts-${{matrix.package}}'

Exclusions and the rest of the pattern syntax work as described in the actions/upload-artifact documentation.

Cognitive complexity​

Enable run_cognitive_complexity to audit the package with package:cognitive_complexity. The step fails when any function's score exceeds cognitive_complexity_fail_threshold, and can additionally block increases relative to a base ref via cognitive_complexity_fail_on_increase and cognitive_complexity_diff_base.

with:
run_cognitive_complexity: true
cognitive_complexity_targets: 'lib'
cognitive_complexity_fail_threshold: 15

When enabled, the workflow checks out the full git history so the action can resolve a merge base against the diff base. No extra configuration is required.

To post the complexity report as a pull request comment, grant the caller workflow pull-requests: write permission:

jobs:
build:
permissions:
contents: read
pull-requests: write
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v2
with:
run_cognitive_complexity: true

Providing environment variables​

Tests sometimes read values from the environment via Platform.environment, for example:

import 'dart:io';

final myVar = Platform.environment['MY_VAR'];

Because this is a reusable workflow, an env block defined in your caller workflow is not inherited by the steps that run inside dart_package.yml. To make a variable available to the test step, use the setup input to append it to $GITHUB_ENV. Variables written to $GITHUB_ENV are exported to every subsequent step in the job, including the one that runs your tests.

name: My Dart Workflow

on: pull_request

jobs:
build:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v2
with:
setup: echo "MY_VAR=true" >> $GITHUB_ENV

To provide multiple variables, chain the commands:

with:
setup: |
echo "MY_VAR=true" >> $GITHUB_ENV
echo "ANOTHER_VAR=some-value" >> $GITHUB_ENV

If a value is sensitive, pass it through a secret instead of hardcoding it:

with:
setup: echo "API_TOKEN=${{secrets.API_TOKEN}}" >> $GITHUB_ENV
note

Setting the variable inline before the test command (e.g. MY_VAR="true" dart test) is not possible through the setup input, because setup and the test step run in separate shells. Writing to $GITHUB_ENV is the supported way to share values across steps.

Example Usage​

name: My Dart Workflow

on: pull_request

jobs:
build:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v2
with:
coverage_excludes: '*.g.dart'
dart_sdk: 'stable'
platform: 'chrome,vm'
timeout_minutes: 10
working_directory: 'examples/my_dart_package'
secrets:
ssh_key: ${{secrets.EXAMPLE_KEY}}