From e8566b144778589ac7294737e0f1b078f5bfa068 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Mon, 14 Jul 2025 17:10:04 +0100 Subject: [PATCH] Adds a Justfile and a composite action. Now we are testing rust-latin, comment out the bad tests so it passes. --- .github/actions/setup/action.yml | 56 ++++ .github/workflows/parallel-build.yml | 304 +++++++----------- .github/workflows/weekly-canary-build.yml | 52 +-- build.sh | 83 ----- build_fns.sh | 144 --------- exercise-templates/rustlatin/step1/src/lib.rs | 15 +- exercise-templates/rustlatin/step2/src/lib.rs | 14 +- exercise-templates/rustlatin/step3/src/lib.rs | 15 +- exercise-templates/rustlatin/step4/src/lib.rs | 10 +- justfile | 130 ++++++++ 10 files changed, 359 insertions(+), 464 deletions(-) create mode 100644 .github/actions/setup/action.yml delete mode 100755 build.sh delete mode 100755 build_fns.sh create mode 100644 justfile diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 00000000..eaac2f23 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,56 @@ +# Common steps we do in most of our jobs + +name: Setup a Job + +inputs: + criticalup: + description: 'Install Criticalup' + required: false + default: "" + channel: + description: 'Rust channel' + required: false + default: "stable" + cache: + description: "Workspace to cache with Swatinem/rust-cache@v2" + required: false + default: "" + target: + description: "Extra target for rustup to install" + required: false + default: "" + +runs: + using: "composite" + steps: + - name: Install CriticalUp (optional) + if: ${{ inputs.criticalup != '' }} + shell: bash + env: + CRITICALUP_VERSION: ${{ inputs.criticalup }} + run: | + curl --proto '=https' --tlsv1.2 -LsSf https://github.com/ferrocene/criticalup/releases/download/${CRITICALUP_VERSION}/criticalup-installer.sh | sh + - name: Install Just 1.42 + uses: extractions/setup-just@v3 + with: + just-version: 1.42 + - name: Update Rust + shell: bash + run: | + rustup set profile minimal + rustup update ${RUSTUP_CHANNEL} --no-self-update + rustup default ${RUSTUP_CHANNEL} + env: + RUSTUP_CHANNEL: ${{ inputs.channel }} + - name: Install Target + if: ${{ inputs.target != '' }} + shell: bash + env: + RUSTUP_TARGET: ${{ inputs.target }} + run: | + rustup target add ${RUSTUP_TARGET} + - name: Setup Rust Cache + if: ${{ inputs.cache != '' }} + uses: Swatinem/rust-cache@v2 + with: + workspaces: ${{ inputs.cache }} diff --git a/.github/workflows/parallel-build.yml b/.github/workflows/parallel-build.yml index 958431ad..d6b86333 100644 --- a/.github/workflows/parallel-build.yml +++ b/.github/workflows/parallel-build.yml @@ -1,5 +1,5 @@ # This is a workflow file to run, build, and test all crates used as part of `rust-exercises`. -# It is cached with Swatinem/rust-cache@v2 and setup so that no jobs depend on any other jobs, +# It is cached with Swatinem/rust-cache@v2 and setup so that no jobs depend on any other jobs, # EXCEPT for the last `deploy` job, which pulls in artifacts-producing jobs in the `needs:` field. # The brunt of the work is defined in `build_fns.sh` where the actual build/testing logic is defined. @@ -21,224 +21,170 @@ on: - main # * All jobs defined here run independently of each other EXCEPT for `deploy`. -# * Jobs that have a `matrix` field will setup up a job per entry in said `matrix`. -# If you add any jobs that produce artifacts, make sure to add them to the `needs:` field of the `deploy` job, since that -# ensures `deploy` will run last and can pull said artifacts -# +# * Jobs that have a `matrix` field will setup up a job per entry in said +# `matrix`. +# +# If you add any jobs that produce artifacts, make sure to add them to the +# `needs:` field of the `deploy` job, since that ensures `deploy` will run +# last and can pull said artifacts +# # ========== TEMPLATE =========== # my_cool_new_job: -# runs-on: ubuntu-24.04 -# steps: -# - uses: actions/checkout@v4 # This is what downloads a fresh clone of the repo and cd's into it -# - name: Install tools -# uses: taiki-e/install-action@v2 # For adding arbitrary binaries as tools -# with: -# tool: name_of_binary_tool@v1.0 -# - uses: Swatinem/rust-cache@v2 -# with: -# workspaces: dir_where_I_want_results_cached # This job will look up this specific cached dir -# - name: Build foo -# run: | -# . ${{github.workspace}}/build_fns.sh -# cd interesting_directory -# command_defined_in_build_fns.sh +# runs-on: ubuntu-24.04 +# steps: +# - uses: actions/checkout@v4 # This is what downloads a fresh clone of the repo and cd's into it +# - uses: ./.github/actions/setup +# with: +# cache: dir_where_I_want_results_cached +# - uses: taiki-e/install-action@v2 # For adding arbitrary binaries as tools +# with: +# tool: name_of_binary_tool@v1.0 +# - run: just do-thing # =========== END TEMPLATE ======== # # And then you'd add `my_cool_new_job` to the `needs` field of `deploy`. jobs: - test_and_build_mdbook: + test-build-mdbook: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - name: Install mdbook, mdbook-mermaid - uses: taiki-e/install-action@v2 + - uses: ./.github/actions/setup with: - tool: mdbook@0.4,mdbook-mermaid@0.12 - # From Rust Cache Action: - # selecting a toolchain either by action or manual `rustup` calls should happen - # before the plugin, as the cache uses the current rustc version as its cache key - - run: rustup toolchain install stable --profile minimal - - # For the cache to be keyed properly, we need to declare the workspace and then `cd` into it. - - uses: Swatinem/rust-cache@v2 + cache: exercise-book + - uses: taiki-e/install-action@v2 with: - workspaces: exercise-book - - name: Build mdbook, Test mdbook, Load cache - run: | - . ${{github.workspace}}/build_fns.sh - cd exercise-book - mdbook_test_build - - # Uploading an artifact is how we can share data between different jobs - - name: Upload mdbook artifacts - uses: actions/upload-artifact@v4 + tool: mdbook@0.4,mdbook-mermaid@0.12 + - run: just test-mdbook + - run: just build-mdbook + - uses: actions/upload-artifact@v4 with: name: mdbook-dir path: exercise-book/book/ if-no-files-found: error - - test_exercise_solutions_and_examples: + + test-exercise-templates: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - run: | - rustup toolchain install stable --profile minimal - - - uses: Swatinem/rust-cache@v2 + - uses: ./.github/actions/setup with: - workspaces: exercise-solutions - - name: Test exercise-solutions and examples, with cache - run: | - . ${{github.workspace}}/build_fns.sh - cd exercise-solutions - test_examples - - test_exercise_solutions_standalone_crates: + cache: exercise-templates + - run: just test-exercise-templates + + test-exercise-solutions: runs-on: ubuntu-24.04 - strategy: - matrix: - crates: [exercise-solutions/connected-mailbox, - exercise-solutions/multi-threaded-mailbox] steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal - - - uses: Swatinem/rust-cache@v2 + - uses: ./.github/actions/setup with: - workspaces: ${{matrix.crates}} - - name: Test exercise-solutions standalone crates, Load cache - run: | - . ${{github.workspace}}/build_fns.sh - cd ${{matrix.crates}} - test_standalone + cache: exercise-solutions + - run: just test-exercise-solutions - build_qemu_core: + test-connected-mailbox: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --component rust-src + - uses: ./.github/actions/setup + - run: just test-connected-mailbox - - uses: Swatinem/rust-cache@v2 - with: - workspaces: qemu-code/uart-driver - - name: Build-qemu-code/uart-driver, load cache - run: | - cd qemu-code/uart-driver - . ../../build_fns.sh - build_qemu_core + test-multi-threaded-mailbox: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup + - run: just test-multi-threaded-mailbox - build_nrf52_usb_crates: + build-qemu-uart-driver: runs-on: ubuntu-24.04 - strategy: - matrix: - crates: [nrf52-code/boards/dk, - nrf52-code/boards/dk-solution, - nrf52-code/boards/dongle, - nrf52-code/radio-app, - nrf52-code/usb-app, - nrf52-code/usb-app-solutions, - nrf52-code/consts] steps: - - name: Install flip-link - uses: taiki-e/install-action@v2 + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup with: - tool: flip-link@0.1.10 + cache: qemu-code/uart-driver + target: thumbv7em-none-eabihf + - run: rustup component add rust-src + - run: just build-qemu-uart-driver + build-radio-app: + runs-on: ubuntu-24.04 + steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --target thumbv7em-none-eabihf - - uses: Swatinem/rust-cache@v2 + - uses: ./.github/actions/setup with: - workspaces: ${{matrix.crates}} - - - name: build-nrf52 usb crates, Load cache - run: | - . ${{github.workspace}}/build_fns.sh - cd ${{matrix.crates}} - build_thumbv7em + cache: nrf52-code/radio-app + target: thumbv7em-none-eabihf + - uses: taiki-e/install-action@v2 + with: + tool: flip-link@0.1.10 + - run: just build-radio-app - # This job is different from the one above because we cannot make individual steps conditional, - # but we can define a different `matrix` of files that we have to upload - build_nrf52_usb_crates_and_upload_fw: + build-usb-app: runs-on: ubuntu-24.04 - strategy: - matrix: - crates: [puzzle-fw, loopback-fw] steps: - - name: Install flip-link - uses: taiki-e/install-action@v2 + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup + with: + cache: nrf52-code/usb-app + target: thumbv7em-none-eabihf + - uses: taiki-e/install-action@v2 with: tool: flip-link@0.1.10 + - run: just build-usb-app + test-usb-lib: + runs-on: ubuntu-24.04 + steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --target thumbv7em-none-eabihf - - - uses: Swatinem/rust-cache@v2 + - uses: ./.github/actions/setup with: - workspaces: nrf52-code/${{matrix.crates}} - - name: build-only-nrf52 crates, load cache - run: | - . ${{github.workspace}}/build_fns.sh - cd nrf52-code/${{matrix.crates}} - build_thumbv7em + cache: nrf52-code/usb-lib + target: thumbv7em-none-eabihf + - run: just test-usb-lib - # We also upload the built binaries in the puzzle-fw and loopback-fw cases - - name: Upload ${{matrix.crates}} artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{matrix.crates}} - path: nrf52-code/${{matrix.crates}}/target/thumbv7em-none-eabihf/release/${{matrix.crates}} - if-no-files-found: error - - build_and_test_nrf52_crates: + build-puzzle-fw: runs-on: ubuntu-24.04 - strategy: - matrix: - crates: [nrf52-code/usb-lib-solutions/complete, - nrf52-code/usb-lib-solutions/get-descriptor-config, - nrf52-code/usb-lib-solutions/get-device, - nrf52-code/usb-lib-solutions/set-config] steps: - - name: Install flip-link - uses: taiki-e/install-action@v2 + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup + with: + cache: nrf52-code/puzzle-fw + target: thumbv7em-none-eabihf + - uses: taiki-e/install-action@v2 with: tool: flip-link@0.1.10 - - - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --target thumbv7em-none-eabihf - - - uses: Swatinem/rust-cache@v2 + - run: just build-puzzle-fw + env: + HIDDEN_MESSAGE: ${{ secrets.HIDDEN_MESSAGE }} + - uses: actions/upload-artifact@v4 with: - workspaces: ${{matrix.crates}} - - name: build-and-test nrf52 crates, load cache - run: | - . ${{github.workspace}}/build_fns.sh - cd ${{matrix.crates}} - build_test_thumbv7em + name: puzzle-fw + path: nrf52-code/puzzle-fw/target/thumbv7em-none-eabihf/release/puzzle-fw + if-no-files-found: error - check_templates: + build-loopback-fw: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal - - - uses: Swatinem/rust-cache@v2 + - uses: ./.github/actions/setup + with: + cache: nrf52-code/loopback-fw + target: thumbv7em-none-eabihf + - uses: taiki-e/install-action@v2 with: - workspaces: exercise-templates - - name: Check exercise-templates, Load cache - run: | - . ${{github.workspace}}/build_fns.sh - cd exercise-templates - check_templates + tool: flip-link@0.1.10 + - run: just build-loopback-fw + - uses: actions/upload-artifact@v4 + with: + name: loopback-fw + path: nrf52-code/loopback-fw/target/thumbv7em-none-eabihf/release/loopback-fw + if-no-files-found: error - check_fmt: + format-check: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --component rustfmt - - name: Check fmt - run: | - . ${{github.workspace}}/build_fns.sh - check_fmt + - uses: ./.github/actions/setup + - run: just format-check # This is the last job, and waits (`needs:`) only on those that pass artifacts to it. # It the necessary resulting builds as artifacts, zips them, and uploads with a tag if necessary. @@ -246,55 +192,37 @@ jobs: runs-on: ubuntu-24.04 # Notice that because our repo expects all checks to pass, we don't need to include every other job # as a dependency of the `deploy` job. - needs: [test_and_build_mdbook, build_nrf52_usb_crates_and_upload_fw] - + needs: [test-build-mdbook, build-puzzle-fw, build-loopback-fw] steps: - uses: actions/checkout@v4 - + - uses: ./.github/actions/setup # Download the produced artifacts - - name: Download mdbook-dir artifact - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v4 with: # Move the mdbook `book` dir to where we expect it to be name: mdbook-dir path: ./exercise-book/book - - - name: Download puzzle-fw artifact - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v4 with: name: puzzle-fw path: ./nrf52-code/puzzle-fw/target/thumbv7em-none-eabihf/release/ - - - name: Download loopback-fw artifact - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v4 with: name: loopback-fw path: ./nrf52-code/loopback-fw/target/thumbv7em-none-eabihf/release/ - - - name: Find slug name - run: | + - run: | slug=$(./describe.sh "${GITHUB_REF}") echo "Building with slug '${slug}'" echo "slug=${slug}" >> "${GITHUB_ENV}" - - - name: Build and test - env: # Or as an environment variable - HIDDEN_MESSAGE: ${{ secrets.HIDDEN_MESSAGE }} - run: | - . ${{github.workspace}}/build_fns.sh - zip_output "./rust-exercises-${{ env.slug }}" - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 + - run: just assemble ${{ env.slug }} + - uses: actions/upload-artifact@v4 if: ${{success()}} with: name: Artifacts if-no-files-found: error path: | ./rust-exercises-* - - - name: Create and Upload Release - if: github.event_name == 'push' && startswith(github.ref, 'refs/tags/') + - if: github.event_name == 'push' && startswith(github.ref, 'refs/tags/') id: create_release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/weekly-canary-build.yml b/.github/workflows/weekly-canary-build.yml index a52aeef4..6ac7ea33 100644 --- a/.github/workflows/weekly-canary-build.yml +++ b/.github/workflows/weekly-canary-build.yml @@ -18,30 +18,34 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - - name: Install tools + - uses: ./.github/actions/setup + with: + cache: exercise-book + channel: ${{ matrix.rust-channel }} + - name: Install mdbook, mdbook-mermaid uses: taiki-e/install-action@v2 with: - tool: mdslides@0.3,mdbook@0.4,mdbook-mermaid@0.12,flip-link@0.1.10 - - # `minimal` profile avoids downloading `rustdocs`, `clippy`, etc. - - name: Install targets, update, set default Rust - run: | - rustup set profile minimal - rustup update ${{ matrix.rust-channel }} - rustup default ${{ matrix.rust-channel }} - rustup component add rust-src - rustup component add rustfmt - rustup target add thumbv7em-none-eabihf - - - name: Find slug name - run: | - slug=$(./describe.sh "${GITHUB_REF}") - echo "Building with slug '${slug}'" - echo "slug=${slug}" >> "${GITHUB_ENV}" + tool: mdbook@0.4,mdbook-mermaid@0.12 + - run: just test-mdbook + - run: just build-mdbook + - name: Upload mdbook artifacts + uses: actions/upload-artifact@v4 + with: + name: mdbook-dir + path: exercise-book/book/ + if-no-files-found: error - - name: Build and test - env: # Or as an environment variable - HIDDEN_MESSAGE: ${{ secrets.HIDDEN_MESSAGE }} - run: | - ./build.sh "./rust-exercises-${{ env.slug }}" + build-nrf52-code: + strategy: + fail-fast: false + matrix: + rust-channel: [stable, beta, nightly] + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup + with: + channel: ${{ matrix.rust-channel }} + cache: nrf52-code + target: thumbv7em-none-eabihf + - run: just build-nrf52-code diff --git a/build.sh b/build.sh deleted file mode 100755 index c3bc2927..00000000 --- a/build.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - - -# This file is a helper file to help build and test local builds of this repository. - -# Load all build functions -# All of the build/testing logic should be defined inside build_fns.sh -. ./build_fns.sh - - -# Check the formatting -check_fmt - -# Build and test the solutions -pushd exercise-solutions -test_examples -pushd connected-mailbox -test_standalone -popd -pushd multi-threaded-mailbox -test_standalone -popd -popd - -# Build from source because armv8r-none-eabihf isn't Tier 2 -pushd qemu-code -pushd uart-driver -build_qemu_core -popd -popd - -pushd nrf52-code -pushd boards/dk -build_thumbv7em -popd -pushd boards/dk-solution -build_thumbv7em -popd -pushd boards/dongle -build_thumbv7em -popd -pushd radio-app -build_thumbv7em -popd -for i in usb-lib-solutions/*; do - pushd "$i" - build_test_thumbv7em - popd -done -pushd usb-lib -build_thumbv7em -popd -pushd usb-app -build_thumbv7em -popd -pushd usb-app-solutions -build_thumbv7em -popd -pushd consts -build_thumbv7em -popd -pushd puzzle-fw -build_thumbv7em -popd -pushd loopback-fw -build_thumbv7em -popd -popd - -# Only check the templates (they will panic at run-time due to the use of todo!) -pushd exercise-templates -check_templates -popd - -# Build and test the mdbook build -pushd exercise-book -mdbook_test_build -popd - -# Zip the output -zip_output \ No newline at end of file diff --git a/build_fns.sh b/build_fns.sh deleted file mode 100755 index 95046c23..00000000 --- a/build_fns.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash - -# -# Ferrous Systems CI deployment setup -# -# Copyright (c) Ferrous Systems, 2025 -# -# This script will define functions for testing this repo. -# -set -euo pipefail - -# Build and test the solutions -# exercise-solutions -function test_examples() { - cargo test --locked - cargo test --examples --locked - return 0 -} - -# exercise-solutions/connected-mailbox -# exercise-solutions/multi-threaded-mailbox -function test_standalone() { - cargo test --locked - return 0 -} - -# qemu-code/uart-driver -function build_qemu_core() { - RUSTC_BOOTSTRAP=1 cargo build -Zbuild-std=core --locked - return 0 -} - -# nrf52-code/boards/dk -# nrf52-code/boards/dk-solution -# nrf52-code/boards/dongle -# nrf52-code/boards/radio-app -# nrf52-code/usb-app -# nrf52-code/usb-app-solutions -# nrf52-code/consts -# nrf52-code/puzzle-fw -# nrf52-code/loopback-fw -function build_thumbv7em() { - cargo build --target=thumbv7em-none-eabihf --locked --release - return 0 -} - -# nrf52-code/usb-lib-solutions/complete -# nrf52-code/usb-lib-solutions/get-descriptor-config -# nrf52-code/usb-lib-solutions/get-device -# nrf52-code/usb-lib-solutions/set-config -function build_test_thumbv7em() { - cargo build --target=thumbv7em-none-eabihf --locked --release - cargo test --locked - return 0 -} - -# exercise-templates -function check_templates() { - cargo check --locked - return 0 -} - -function mdbook_test_build() { - mdbook test - mdbook build - return 0 -} - -function zip_output() { - OUTPUT_NAME=${1:-./output} - rm -rf "${OUTPUT_NAME}" - mkdir -p "${OUTPUT_NAME}" - mkdir -p "${OUTPUT_NAME}/exercise-book" - # Note: the use of the html subdirectory here is deliberate. - # a) it allows the book to be provided as PDF in the future - # b) it ensures the `../../exercise-solutions` links in the markdown also work - # when loaded from this output folder. The `../..` comes about - # because the Markdown book source lives in the `src` subfolder and so you - # have to go up one extra level. Adding an extra level in the output - # is easier than re-writing all the links at build time. - mv ./exercise-book/book "${OUTPUT_NAME}/exercise-book/html" - cp -r ./exercise-templates "${OUTPUT_NAME}/" - cp -r ./exercise-solutions "${OUTPUT_NAME}/" - cp -r ./nrf52-code "${OUTPUT_NAME}/" - cp -r ./qemu-code "${OUTPUT_NAME}/" - cp -r ./xtask "${OUTPUT_NAME}/" - cp -r ./.cargo "${OUTPUT_NAME}/" - cp -r ./tools "${OUTPUT_NAME}/" - cp ./nrf52-code/puzzle-fw/target/thumbv7em-none-eabihf/release/puzzle-fw "${OUTPUT_NAME}/nrf52-code/boards/dongle-fw/puzzle-fw" - cp ./nrf52-code/loopback-fw/target/thumbv7em-none-eabihf/release/loopback-fw "${OUTPUT_NAME}/nrf52-code/boards/dongle-fw/loopback-fw" - find "${OUTPUT_NAME}" -name target -type d -print0 | xargs -0 rm -rf - zip -r "${OUTPUT_NAME}.zip" "${OUTPUT_NAME}" - return 0 -} - - -FAILURE=0 - -fail() { - echo "********************************************************" - echo "cargo fmt failed: dir $1 did not pass 'cargo fmt --check'" - echo "********************************************************" - FAILURE=1 -} - -function check_fmt() { -dirs=("exercise-solutions" - "exercise-solutions/connected-mailbox" - "exercise-solutions/multi-threaded-mailbox" - "qemu-code/uart-driver" - "nrf52-code/boards/dk" - "nrf52-code/boards/dk-solution" - "nrf52-code/boards/dongle" - "nrf52-code/radio-app" - "nrf52-code/usb-app" - "nrf52-code/usb-app-solutions" - "nrf52-code/consts" - "nrf52-code/puzzle-fw" - "nrf52-code/loopback-fw" - "nrf52-code/usb-lib-solutions/complete" - "nrf52-code/usb-lib-solutions/get-descriptor-config" - "nrf52-code/usb-lib-solutions/get-device" - "nrf52-code/usb-lib-solutions/set-config" - "exercise-templates" -) - - -for dir in "${dirs[@]}"; do - pushd "$dir" || exit - cargo fmt --check || fail "$dir" - popd || exit -done - -if [ "$FAILURE" == "1" ]; then - echo "***************************************************" - echo " ❌ cargo fmt has failed! ❌" - echo "***************************************************" - exit 1 -else - echo "***************************************************" - echo " ✅ cargo fmt has passed! ✅ " - echo "***************************************************" -fi -} diff --git a/exercise-templates/rustlatin/step1/src/lib.rs b/exercise-templates/rustlatin/step1/src/lib.rs index 26669733..08d549c0 100644 --- a/exercise-templates/rustlatin/step1/src/lib.rs +++ b/exercise-templates/rustlatin/step1/src/lib.rs @@ -19,10 +19,11 @@ fn rustlatin(sentence: &str) -> Vec<()> { collection_of_words } -#[test] -fn correct_splitting() { - assert_eq!( - vec!["This", "sentence", "needs", "to", "be", "split"], - rustlatin("This sentence needs to be split") - ) -} +// Uncomment this: +// #[test] +// fn correct_splitting() { +// assert_eq!( +// vec!["This", "sentence", "needs", "to", "be", "split"], +// rustlatin("This sentence needs to be split") +// ) +// } diff --git a/exercise-templates/rustlatin/step2/src/lib.rs b/exercise-templates/rustlatin/step2/src/lib.rs index cef46459..21750f0f 100644 --- a/exercise-templates/rustlatin/step2/src/lib.rs +++ b/exercise-templates/rustlatin/step2/src/lib.rs @@ -14,10 +14,10 @@ fn rustlatin(sentence: &str) -> Vec<()> { collection_of_words } -#[test] -fn concatenated() { - assert_eq!( - vec!["dors", "yours", "likers", "rustrs"], - rustlatin("do you like rust") - ) -} +// #[test] +// fn concatenated() { +// assert_eq!( +// vec!["dors", "yours", "likers", "rustrs"], +// rustlatin("do you like rust") +// ) +// } diff --git a/exercise-templates/rustlatin/step3/src/lib.rs b/exercise-templates/rustlatin/step3/src/lib.rs index beb77ee0..ed4f80cb 100644 --- a/exercise-templates/rustlatin/step3/src/lib.rs +++ b/exercise-templates/rustlatin/step3/src/lib.rs @@ -14,10 +14,11 @@ fn rustlatin(sentence: &str) -> Vec<()> { collection_of_chars } -#[test] -fn return_the_char() { - assert_eq!( - vec!['n', 't', 'd', 'b', 'i', 'a', 'r', 'v'], - rustlatin("note the difference between iterator and return values") - ) -} +// Uncomment this: +// #[test] +// fn return_the_char() { +// assert_eq!( +// vec!['n', 't', 'd', 'b', 'i', 'a', 'r', 'v'], +// rustlatin("note the difference between iterator and return values") +// ) +// } diff --git a/exercise-templates/rustlatin/step4/src/lib.rs b/exercise-templates/rustlatin/step4/src/lib.rs index e2dc943d..755e9a24 100644 --- a/exercise-templates/rustlatin/step4/src/lib.rs +++ b/exercise-templates/rustlatin/step4/src/lib.rs @@ -38,8 +38,10 @@ fn test_latinizer() { fn correct_translation() { // Why can we compare `&str` and `String` here? // https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-PartialEq%3C%26%27a%20str%3E - assert_eq!( - "rustrs helpsrs yours sravoid sra lotrs srof srirritating bugsrs", - rustlatin("rust helps you avoid a lot of irritating bugs") - ) + + // Uncomment this: + // assert_eq!( + // "rustrs helpsrs yours sravoid sra lotrs srof srirritating bugsrs", + // rustlatin("rust helps you avoid a lot of irritating bugs") + // ) } diff --git a/justfile b/justfile new file mode 100644 index 00000000..1bc44dfe --- /dev/null +++ b/justfile @@ -0,0 +1,130 @@ +# Justfile for the Ferrous Systems Rust Exercises +# +# Copyright (c) Ferrous Systems, 2025 + +set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] + +package_list := " \ + exercise-solutions \ + exercise-solutions/connected-mailbox\ + exercise-solutions/multi-threaded-mailbox\ + exercise-templates \ + qemu-code/uart-driver\ + nrf52-code/boards/dk \ + nrf52-code/boards/dk-solution \ + nrf52-code/boards/dongle \ + nrf52-code/radio-app \ + nrf52-code/usb-app \ + nrf52-code/usb-app-solutions \ + nrf52-code/consts \ + nrf52-code/puzzle-fw \ + nrf52-code/loopback-fw \ + nrf52-code/usb-lib-solutions/complete \ + nrf52-code/usb-lib-solutions/get-descriptor-config \ + nrf52-code/usb-lib-solutions/get-device \ + nrf52-code/usb-lib-solutions/set-config \ + xtask \ + tools/tcp-client \ +" + +default: + @just --choose + +everything: test-mdbook build-mdbook test-exercise-templates test-exercise-solutions test-connected-mailbox test-multi-threaded-mailbox build-qemu-uart-driver build-radio-app build-usb-app test-usb-lib build-puzzle-fw build-loopback-fw format + +format-check: format-check-rust + +format: format-rust + +clean: clean-rust + rm -rf ./training-book/book + +serve: + cd training-book && mdbook serve + +build-mdbook: + cd exercise-book && RUST_LOG=info mdbook build + +test-mdbook: + cd exercise-book && RUST_LOG=info mdbook test + +test-exercise-templates: + cd exercise-templates && cargo build + cd exercise-templates && cargo test + +test-exercise-solutions: + cd exercise-solutions && cargo build + cd exercise-solutions && cargo test + +test-connected-mailbox: + cd exercise-solutions/connected-mailbox && cargo build + cd exercise-solutions/connected-mailbox && cargo test + +test-multi-threaded-mailbox: + cd exercise-solutions/multi-threaded-mailbox && cargo build + cd exercise-solutions/multi-threaded-mailbox && cargo test + +build-qemu-uart-driver: + cd qemu-code/uart-driver && RUSTC_BOOTSTRAP=1 cargo build --release -Zbuild-std=core + +build-radio-app: + cd nrf52-code/radio-app && cargo build --release + +build-usb-app: + cd nrf52-code/usb-app && cargo build --release + cd nrf52-code/usb-app-solutions && cargo build --release + +test-usb-lib: + cd nrf52-code/usb-lib && cargo build --release + cd nrf52-code/usb-lib-solutions/complete && cargo build --release + cd nrf52-code/usb-lib-solutions/get-descriptor-config && cargo build --release + cd nrf52-code/usb-lib-solutions/get-device && cargo build --release + cd nrf52-code/usb-lib-solutions/set-config && cargo build --release + +build-puzzle-fw: + cd nrf52-code/puzzle-fw && cargo build --release + +build-loopback-fw: + cd nrf52-code/loopback-fw && cargo build --release + +build-nrf52-code: build-qemu-uart-driver build-radio-app build-usb-app test-usb-lib build-puzzle-fw build-loopback-fw + +assemble version: + echo "Making ./rust-exercises-{{ version }}..." + rm -rf ./rust-exercises-{{ version }} + mkdir -p ./rust-exercises-{{ version }}/exercise-book + mv ./exercise-book/book ./rust-exercises-{{ version }}/exercise-book/html + cp -r ./exercise-templates ./rust-exercises-{{ version }} + cp -r ./exercise-solutions ./rust-exercises-{{ version }} + cp -r ./nrf52-code ./rust-exercises-{{ version }} + cp -r ./qemu-code ./rust-exercises-{{ version }} + cp -r ./xtask ./rust-exercises-{{ version }} + cp -r ./.cargo ./rust-exercises-{{ version }} + cp -r ./tools ./rust-exercises-{{ version }} + cp ./nrf52-code/puzzle-fw/target/thumbv7em-none-eabihf/release/puzzle-fw "./rust-exercises-{{ version }}/nrf52-code/boards/dongle-fw/puzzle-fw" + cp ./nrf52-code/loopback-fw/target/thumbv7em-none-eabihf/release/loopback-fw "./rust-exercises-{{ version }}/nrf52-code/boards/dongle-fw/loopback-fw" + echo "Compressing ./rust-exercises-{{ version }}.zip..." + zip -r ./rust-exercises-{{ version }}.zip ./rust-exercises-{{ version }} + +format-check-rust: + #!/bin/sh + FAIL=0 + for package in {{ package_list }}; do + echo "Checking ${package}..." + ( cd ${package} && cargo fmt --check ) || FAIL=1 + done + if [[ "$FAIL" == 1 ]]; then exit 1; else echo "Formatting all OK"; fi + +format-rust: + #!/bin/sh + for package in {{ package_list }}; do + echo "Formatting ${package}..." + ( cd ${package} && cargo fmt ) + done + +clean-rust: + #!/bin/sh + for package in {{ package_list }}; do + echo "Cleaning ${package}..." + ( cd ${package} && cargo clean ) + done