In 2020, I published the Pub package github_actions_toolkit
to write GitHub Actions with Dart more easily. However, GitHub Actions runners don't support natively the Dart language, and some steps are necessary to execute a Dart program in a GitHub Actions workflow.
Below I compare three ways to create a GitHub Action with Dart, with their pros and cons.
. | Shared Dart container | Isolated Dart container | Natively compiled executable |
---|---|---|---|
✍️ Defines the environment | User | Developer | Developer |
♻️ Environment reusable by other actions | ✔ | ❌ | ❌ |
⏱️ Set-up speed | 🟠 Slow (but environment is reusable) | 🔴 Slow | 🟢 Fast |
🔐 Security hardening by SHA pinning | ✔ | ✔ | ❌ |
JavaScript is natively supported on all GitHub runners. In this solution, JavaScript is used to launch the Dart program using the dart
command. This only works if Dart has already been installed during the workflow, either by setting it up during a previous step, or by running the entire workflow in a Dart container.
Example workflow:
jobs:
example:
runs-on: ubuntu-latest
container: google/dart:2 # Required to run the action
steps:
- uses: axel-op/hello-world-dart-action@master
- ✍️ The user defines the Dart environment as they want.
- ♻️ The Dart environment is shared with the other steps of the workflow and can be reused.
- ⏱️ Requires the full Dart SDK to be installed: this is time consuming and cumbersome if it's only required for a single action.
- ✍️ The creator of the action cannot control the environment.
Besides JavaScript actions, Docker actions are the other type of GitHub Actions.
With this solution, the action sets up its own Dart container whose configuration is defined in a Dockerfile.
Example workflow:
jobs:
example:
runs-on: ubuntu-latest
steps:
- uses: axel-op/containerized-dart-action@master
- ✍️ The user doesn't need to set up the Dart SDK by themselves: no extra steps in the workflow.
- ✍️ The creator of the action defines the environment needed for the action to run.
- ♻️ The Dart environment cannot be reused by the other steps.
- ⏱️ A new Dart environment will be set up even if one has already been installed previously in the workflow.
- ⏱️ The container must be built before every execution of the workflows containing the action.
With this solution, the Dart action is pre-compiled (with dart compile
) to a native executable that is then wrapped in a tiny container. This is another way to build a Dart action with Docker, but here the container size is much smaller than in the previous solution.
The container wrapping the compiled executable is pushed to a Docker registry, and retrieved during a workflow execution.
Example workflow:
jobs:
example:
runs-on: ubuntu-latest
steps:
- uses: docker://ghcr.io/axel-op/self-contained-dart-action:main
- ⏱️ No Dart environment required in the workflow for the action to run.
- ⏱️ The action runs fast as the container is very lightweight.
- ✍️ The action is retrieved from a container registry and not from its GitHub repository directly: there can be discrepancies between the code in the repository and the code that is actually executed.
- 🔐 The user cannot pin the action to a specific commit, and this can be a security problem.