Motivation
Dart is very suitable for building quick-and-dirty CLI tools and share them among your collegue, since it produces a single binary with dart compile exe
.
It would be useful if organization-internal tools are published in GitHub Releases like this:
Unfortunately, Dart doesn't support cross-compile at this moment and we have to compile the source code on each platform (Windows, macOS, Linux) before publishing the binaries, while Golang supports cross-compile and GoReleaser already made it easy to publish the binaries for each platform.
GitHub Actions provides Windows/macOS/Linux build environments for free and it would be really useful for compiling and publishing the CLI tools composed with Dart.
This article shows how to configure the GitHub Actions.
GitHub Actions for build
As many articles already says, only 4 step are required for compiling the Dart code.
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1
- run: dart pub get
- run: dart compile exe bin/mycli.dart -o mycli
One point to consider is that the output binary should be named as mycli .exe on Windows and mycli (without extension) on macOS/Linux.
We can solve the naming by defining the matrix like below:
jobs:
compile:
name: dart compile exe
strategy:
matrix:
include:
- runs-on: ubuntu-latest
binary-name: mycli_linux_amd64
- runs-on: macos-latest
binary-name: mycli_macos_amd64
- runs-on: windows-latest
binary-name: mycli_windows.exe
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1
- run: dart pub get
- run: mkdir ${{ matrix.runs-on }}
- run: dart compile exe bin/mycli.dart -o ${{ matrix.runs-on }}/${{ matrix.binary-name }}
GitHub Actions for release
https://docs.github.com/en/rest/reference/releases
According to this reference, GitHub Release requires 2 steps for publishing some binaries:
- Create a release resource
POST https://api.github.com/repos/{owner}/{repo}/releases
- Upload the binaries into the release
POST https://uploads.github.com/repos/{owner}/{repo}/releases/{release_id}/assets
Use action-gh-release for simple uploading
action-gh-release really makes it easy to do these steps.
- uses: softprops/action-gh-release@v1
with:
draft: true
files: out/*
With this simple definition, GitHub Actions will upload all files in out/
into a new draft release.
files: |
out/mycli_linux
out/mycli_macos
out/mycli_windows
Also files
can be specified to individual file list instead of glob expression.
Combine the build process with the release process using artifact
Each of 3 build actions generate a binary and release process should upload them all at once. The flow can be implemented with GitHub artifact.
name: Publish
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
jobs:
compile:
name: dart compile exe
strategy:
matrix:
include:
- runs-on: ubuntu-latest
binary-name: mycli_linux_amd64
- runs-on: macos-latest
binary-name: mycli_macos_amd64
- runs-on: windows-latest
binary-name: mycli_windows.exe
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1
- run: dart pub get
- run: mkdir ${{ matrix.runs-on }}
- run: dart compile exe bin/mycli.dart -o ${{ matrix.runs-on }}/${{ matrix.binary-name }}
- uses: actions/upload-artifact@v2
with:
name: bin-${{ matrix.runs-on }}
path: ${{ matrix.runs-on }}
release:
needs: compile
name: github release
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v2
with:
name: bin-ubuntu-latest
path: bin-linux
- uses: actions/download-artifact@v2
with:
name: bin-macos-latest
path: bin-macos
- uses: actions/download-artifact@v2
with:
name: bin-windows-latest
path: bin-windows
- uses: softprops/action-gh-release@v1
with:
draft: true
files: bin-*/*
This works expectedly like below:
and the artifacts are successfully uploaded to GitHub Releases! :)
Top comments (1)
Sweet. A little bit outdated but in general it works like a charm. Thank you!