Skip to content

Merge pull request #845 from jpds/fix/morse-flowtap-jam #260

Merge pull request #845 from jpds/fix/morse-flowtap-jam

Merge pull request #845 from jpds/fix/morse-flowtap-jam #260

Workflow file for this run

name: CI
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
env:
CARGO_TERM_COLOR: always
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- run: .github/ci/format.sh
# Verify every Cargo.lock is in sync with its Cargo.toml. Catches the
# case where a deps bump in rmk/rmk-types is merged without refreshing
# example lockfiles (see scripts/fetch_all.sh).
fetch-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- run: bash scripts/fetch_all.sh --check
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt, llvm-tools
targets: thumbv6m-none-eabi,thumbv7m-none-eabi,thumbv7em-none-eabi,thumbv7em-none-eabihf,thumbv8m.main-none-eabihf,riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-check
# check.sh redirects cargo artifacts to target/ci/ via --target-dir
# (so cargo-batch can share compilation across manifests). Tell
# rust-cache about it, otherwise it only caches the per-crate
# target/ dirs which stay empty.
cache-directories: |
target/ci
- name: Install cargo-batch
run: cargo install --locked --git https://github.com/embassy-rs/cargo-batch cargo --bin cargo-batch
- run: .github/ci/check.sh
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt, llvm-tools
targets: thumbv6m-none-eabi,thumbv7m-none-eabi,thumbv7em-none-eabi,thumbv7em-none-eabihf,thumbv8m.main-none-eabihf,riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-test
# test.sh writes to target/ci/test via CARGO_TARGET_DIR; cache it
# explicitly so rust-cache doesn't miss it.
cache-directories: |
target/ci
- uses: taiki-e/install-action@v2
with:
tool: nextest@0.9
- name: Install cargo-expand
run: cargo install --locked cargo-expand
- run: .github/ci/test.sh
# Discover buildable examples for the matrix
discover:
runs-on: ubuntu-latest
outputs:
stable: ${{ steps.discover.outputs.stable }}
esp: ${{ steps.discover.outputs.esp }}
steps:
- uses: actions/checkout@v6
- id: discover
run: .github/ci/discover.sh
# Build each stable-toolchain example in parallel.
# Entries with bloat==true also compare binary sizes against the base branch.
build:
needs: discover
runs-on: ubuntu-latest
strategy:
fail-fast: false
# Leave runner slots for format/check/test/build-esp.
max-parallel: 15
matrix:
include: ${{ fromJson(needs.discover.outputs.stable) }}
steps:
- uses: actions/checkout@v6
with:
# Bloat entries need full history for git worktree to base revision.
# Shallow clone is fast for this repo, so always fetch full history.
fetch-depth: 0
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-build-${{ matrix.target }}
- name: Install target and tools
run: |
rustup target add ${{ matrix.target }}
cargo install flip-link 2>/dev/null || true
- name: Build
working-directory: ${{ matrix.dir }}
run: |
# Deny warnings so a stray lint (e.g. an unused import) fails CI here
# instead of slipping through. For bloat examples an undenied warning
# gets replayed onto stdout by `cargo size` and corrupts the size parser.
export RUSTFLAGS="-D warnings"
# For bloat examples, remap source paths so the absolute workspace
# prefix doesn't affect binary size (panic messages embed file!() paths).
if [[ "${{ matrix.bloat }}" == "true" ]]; then
export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix=$GITHUB_WORKSPACE=/rmk-build"
fi
cargo build --release
# ── Bloat: size + bloaty diff HEAD vs BASE, upload data ──
- name: Install bloat tools
if: github.event_name == 'pull_request' && matrix.bloat
run: |
rustup component add llvm-tools
cargo install cargo-binutils 2>/dev/null || true
# bloaty isn't in apt; extract the pre-built binary from the Docker image
# used by carlosperate/bloaty-action.
id=$(docker create ghcr.io/carlosperate/bloaty-action:latest)
sudo docker cp "$id:/usr/local/bin/bloaty" /usr/local/bin/bloaty
docker rm "$id" >/dev/null
- name: Measure sizes and compare with base
if: github.event_name == 'pull_request' && matrix.bloat
working-directory: ${{ matrix.dir }}
env:
BLOAT_BINS: ${{ matrix.bloat_bins }}
run: |
set -euo pipefail
# Determine which binaries to size.
if [[ -n "$BLOAT_BINS" ]]; then
IFS=',' read -ra bins <<< "$BLOAT_BINS"
else
bins=(default)
fi
# ── Build BASE ──
base_sha=$(git -C "$GITHUB_WORKSPACE" merge-base HEAD origin/main)
worktree=$(mktemp -d)
git -C "$GITHUB_WORKSPACE" worktree add --detach "$worktree" "$base_sha"
trap 'git -C "$GITHUB_WORKSPACE" worktree remove --force "$worktree" 2>/dev/null; rm -rf "$worktree"' EXIT
# Remap source paths so that HEAD and BASE binaries use the same
# virtual prefix. Without this, absolute paths embedded by panic
# messages (file!() macro) differ in length between $GITHUB_WORKSPACE
# and the temp worktree, producing false size diffs in .rodata/.text.
# HEAD also keeps `-D warnings` so RUSTFLAGS matches the Build step
# above and cargo reuses the binary; BASE uses the default lint level
# so a pre-existing warning on main doesn't fail this PR.
head_remap="-D warnings --remap-path-prefix=$GITHUB_WORKSPACE=/rmk-build"
base_remap="--remap-path-prefix=$worktree=/rmk-build"
base_dir="$worktree/${{ matrix.dir }}"
if [[ -d "$base_dir" ]]; then
(cd "$base_dir" && RUSTFLAGS="$base_remap" cargo build --release)
fi
# ── Output directory ──
safe_name=$(echo "${{ matrix.dir }}" | tr '/' '_')
outdir="$GITHUB_WORKSPACE/bloat-data/$safe_name"
mkdir -p "$outdir"
for bin in "${bins[@]}"; do
bin_flag=""
bin_label=""
bin_suffix=""
if [[ "$bin" != "default" ]]; then
bin_flag="--bin $bin"
bin_label="$bin"
bin_suffix="-$bin"
fi
# cargo size for HEAD — extract text/data/bss/total
# RUSTFLAGS must match the Build step so cargo reuses the existing binary.
RUSTFLAGS="$head_remap" cargo size --release $bin_flag 2>/dev/null > "$outdir/size-head${bin_suffix}.txt"
read -r h_text h_data h_bss head_size < <(awk 'NR==2 {print $1, $2, $3, $4}' "$outdir/size-head${bin_suffix}.txt")
# cargo size + bloaty for BASE
if [[ -d "$base_dir" ]]; then
(cd "$base_dir" && RUSTFLAGS="$base_remap" cargo size --release $bin_flag 2>/dev/null) > "$outdir/size-base${bin_suffix}.txt"
read -r b_text b_data b_bss base_size < <(awk 'NR==2 {print $1, $2, $3, $4}' "$outdir/size-base${bin_suffix}.txt")
# Section diffs
d_text=$((h_text - b_text))
d_data=$((h_data - b_data))
d_bss=$((h_bss - b_bss))
# Find ELF paths for bloaty
head_target_dir="target/${{ matrix.target }}/release"
base_target_dir="$base_dir/target/${{ matrix.target }}/release"
if [[ -n "$bin_label" ]]; then
head_elf="$head_target_dir/$bin_label"
base_elf="$base_target_dir/$bin_label"
else
head_elf=$(find "$head_target_dir" -maxdepth 1 -type f -executable ! -name "*.d" ! -name "*.rlib" ! -name "build-script-*" | head -1)
base_elf=$(find "$base_target_dir" -maxdepth 1 -type f -executable ! -name "*.d" ! -name "*.rlib" ! -name "build-script-*" | head -1)
fi
if [[ -f "$head_elf" && -f "$base_elf" ]]; then
bloaty "$head_elf" -- "$base_elf" > "$outdir/bloaty${bin_suffix}.txt" 2>&1 || true
fi
else
base_size=0; d_text=0; d_data=0; d_bss=0
echo "(base not available)" > "$outdir/size-base${bin_suffix}.txt"
fi
# Format: dir|bin_label|base_total|head_total|text_diff|data_diff|bss_diff
echo "${{ matrix.dir }}|${bin_label}|${base_size}|${head_size}|${d_text}|${d_data}|${d_bss}" >> "$outdir/size-data.txt"
done
echo "Size data:"
cat "$outdir/size-data.txt"
- name: Upload bloat data
if: github.event_name == 'pull_request' && matrix.bloat
uses: actions/upload-artifact@v7
with:
name: bloat-${{ hashFiles('bloat-data/*/size-data.txt') }}
path: bloat-data/
retention-days: 1
# Assemble bloat report from matrix artifacts and save for the comment workflow
bloat-report:
if: github.event_name == 'pull_request'
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v7
with:
path: bloat-artifacts
pattern: bloat-*
merge-multiple: true
- name: Generate report
run: |
report=$(.github/ci/bloat-report.sh bloat-artifacts)
mkdir -p bloat-comment
echo "${{ github.event.pull_request.number }}" > bloat-comment/pr-number.txt
echo "$report" > bloat-comment/report.md
- name: Upload comment data
uses: actions/upload-artifact@v7
with:
name: bloat-comment
path: bloat-comment/
retention-days: 1
# Build ESP/xtensa examples (separate toolchain)
build-esp:
needs: discover
if: fromJson(needs.discover.outputs.esp)[0] != null
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: cargo-bins/cargo-binstall@main
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-build-esp
# Both esp examples share one target dir (target-esp/, set in the
# build step); point rust-cache at it so per-dep artifacts survive.
workspaces: |
examples/use_config/esp32s3_ble -> ../../../target-esp
examples/use_rust/esp32s3_ble -> ../../../target-esp
- name: Install espup and esp toolchain
run: |
cargo binstall espup -y
espup install
- name: Build ESP examples
run: |
source "$HOME/export-esp.sh"
export CARGO_TARGET_DIR="$PWD/target-esp"
for dir in examples/use_rust/esp32s3_ble examples/use_config/esp32s3_ble; do
(cd "$dir" && CARGO_UNSTABLE_BUILD_STD=alloc,core cargo +esp build --release)
done