Release Rust embedded firmware using Github Actions

Github Actions #

Github Actions is a nice way to setup CI/CD pipelines for your Github projects. Let’s setup it for an embedded firmware project written in Rust.

Continuous integration script would run every time when new code is pushed to master branch and release script would run only if a new tag is pushed.

Release in Github looks like this:
release.jpg

Let’s get started. We need following files in project root:

.github/workflows/ci.yaml
.github/workflows/release.yaml

File names actually do not matter.

ci.yaml #

It is assumed that your Cargo project is setup in such a way that you could just run cargo build --release in root directory and everything builds. This script is doing just that:

name: Continuous Integration

on:
  push:
    branches:
      - master

env:
  CARGO_TERM_COLOR: always

jobs:
  compile:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain:
          - stable
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust ${{ matrix.toolchain }}
        uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ matrix.toolchain }}
          target: thumbv6m-none-eabi
          override: true

      - name: cargo build release
        uses: actions-rs/cargo@v1
        with:
          command: build
          args: --release

release.yaml #

It is assumed that all tags are like 0.9.1, 1.0.0 etc. So when such a tag is pushed following action will run:

name: Release

on:
  push:
    tags:
      - '*.*.*'

env:
  CARGO_TERM_COLOR: always

jobs:
  compile:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain:
          - stable
    steps:
      - uses: actions/checkout@v2
      - name: Install Rust ${{ matrix.toolchain }}
        uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ matrix.toolchain }}
          target: thumbv6m-none-eabi
          override: true
          components: llvm-tools-preview

      - name: Install cargo-binutils
        uses: actions-rs/install@v0.1
        with:
          crate: cargo-binutils
          version: latest
          use-tool-cache: true

      - name: Run cargo build --release
        uses: actions-rs/cargo@v1
        with:
          command: build
          args: --release

      - name: Run cargo objcopy
        uses: actions-rs/cargo@v1
        with:
          command: objcopy
          args: --release --bin firmware -- -O binary firmware.bin

      - name: Extract version from tag
        id: version_tag
        run: echo ::set-output name=TAG_VERSION::${GITHUB_REF#refs/tags/}

      - name: Rename .elf and .bin files
        env:
          TAG_VERSION: ${{ steps.version_tag.outputs.TAG_VERSION }}
        run: |
          mv target/thumbv6m-none-eabi/release/firmware firmware-$TAG_VERSION.elf
          mv firmware.bin firmware-$TAG_VERSION.bin

      - name: Create release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: firmware*
          tag: ${{ github.ref }}
          overwrite: true
          file_glob: true

This is a little bit more involved. Basically we would like to release following files if tag 1.0.1 is pushed:

firmware-1.0.1.elf
firmware-1.0.1.bin

Those files can be downloaded from Github release page.

Notes #

It was kind of pain to strip 1.0.1 part out of tag which is like refs/tags/1.0.1. That is why there is separate step for that:

- name: Extract version from tag
  id: version_tag
  run: echo ::set-output name=TAG_VERSION::${GITHUB_REF#refs/tags/}

Later it can be used as an expression (do not confuse it with bash environment variable) :

${{ steps.version_tag.outputs.TAG_VERSION }}

Notice that this script also installs llvm-tools-preview and basically does cargo install cargo-binutils which is needed to convert from .elf to .bin.

There you have it!

 
8
Kudos
 
8
Kudos

Now read this

Last touches to the ESTCube-1 communication module

Last months have been very busy time to all ESTCube-1 core developers, because deadline to really, really handover the satellite was closing quickly. It is over now. History # So it is time to do a little overview about what was... Continue →