Merge pull request #793 from HaoboGu/feat/ci #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| - run: .github/ci/format.sh | |
| check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ci-check | |
| - run: .github/ci/check.sh | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ci-test | |
| - 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: 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 | |
| base_dir="$worktree/${{ matrix.dir }}" | |
| if [[ -d "$base_dir" ]]; then | |
| (cd "$base_dir" && cargo build --release --target ${{ matrix.target }}) | |
| 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 | |
| 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" && 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: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ci-build-esp | |
| - run: .github/ci/build.sh |