DEV Community

Cover image for Dart + GitHub Actions: Publish your command-line tools for Windows/macOS/Linux into GitHub Releases
Yusuke Iwaki
Yusuke Iwaki

Posted on

Dart + GitHub Actions: Publish your command-line tools for Windows/macOS/Linux into GitHub Releases

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:
image

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
Enter fullscreen mode Exit fullscreen mode

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 }}
Enter fullscreen mode Exit fullscreen mode

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/*
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Also files can be specified to individual file list instead of glob expression.

Combine the build process with the release process using artifact

build and release

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-*/*
Enter fullscreen mode Exit fullscreen mode

This works expectedly like below:

flow

and the artifacts are successfully uploaded to GitHub Releases! :)

Released

Top comments (1)

Collapse
 
meamka profile image
Andrey M

Sweet. A little bit outdated but in general it works like a charm. Thank you!