From c9bf7f42a576fce75e3b3882ffb46c7e70ca16cd Mon Sep 17 00:00:00 2001 From: Loi Chyan Date: Sat, 13 Jul 2024 22:28:00 +0800 Subject: [PATCH 1/2] ci: rewrite --- .github/workflows/ci.yml | 121 -------------------- .github/workflows/cicd.yml | 221 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + 3 files changed, 222 insertions(+), 121 deletions(-) delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/cicd.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 48eda01..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: CI - -on: - release: - types: [published] - pull_request: - # workflow_dispatch: - -permissions: - contents: write - -defaults: - run: - shell: bash - -jobs: - ci: - strategy: - fail-fast: false - matrix: - # prettier-ignore - cfg: - - { os: macos-latest , target: x86_64-apple-darwin } - - { os: ubuntu-latest , target: x86_64-unknown-linux-musl } - - { os: windows-latest, target: x86_64-pc-windows-msvc } - runs-on: ${{ matrix.cfg.os }} - env: - CARGO: cargo - RUST_TOOLCHAIN: "1.70" - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Initialize - id: init - run: | - echo "$HOME/.cargo/bin" >>$GITHUB_PATH - echo "cargo-dependencies=${{ hashFiles('**/Cargo.lock') }}" >>$GITHUB_OUTPUT - - - name: Install Just - uses: extractions/setup-just@v1 - - - name: Cache Rust toolchain - id: cache-rust-toolchain - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/ - ~/.rustup/ - key: rust-toolchain-${{ matrix.cfg.target }}-${{ env.RUST_TOOLCHAIN }} - - - name: Set up Rust toolchain - uses: dtolnay/rust-toolchain@v1 - if: steps.cache-rust-toolchain.outputs.cache-hit != 'true' - with: - toolchain: ${{ env.RUST_TOOLCHAIN }} - targets: ${{ matrix.cfg.target }} - components: rustfmt,clippy - - - name: Override Rust toolchain - run: | - rustup override set ${{ env.RUST_TOOLCHAIN }} - echo "CARGO_BUILD_TARGET=${{ matrix.cfg.target }}" >>$GITHUB_ENV - - - name: Cache Cargo dependencies - id: cache-cargo-dependencies - uses: actions/cache@v3 - with: - path: | - .cargo/config - vendor/ - target/ - # prettier-ignore - key: cargo-dependencies-${{ matrix.cfg.target }}-${{ steps.init.outputs.cargo-dependencies }} - - - name: Vendor Cargo dependencies - if: steps.cache-cargo-dependencies.outputs.cache-hit != 'true' - run: just vendor - - - name: Build Cargo dependencies - run: $CARGO build - - - name: Run format check - run: $CARGO fmt --check --all - - - name: Run tests - run: $CARGO test --workspace - - - name: Build release binary - if: github.event_name == 'release' && github.event.action == 'published' - run: | - $CARGO build --verbose --release - echo "RELEASE=true" >>$GITHUB_ENV - echo "RELEASE_DIR=target/$CARGO_BUILD_TARGET/release" >>$GITHUB_ENV - - - name: Pack assets (*nix) - if: env.RELEASE && matrix.cfg.os != 'windows-latest' - run: | - asset="nerdfix-$CARGO_BUILD_TARGET.tar.gz" - cp "$RELEASE_DIR/nerdfix" nerdfix - tar -czvf "$asset" nerdfix - echo "ASSET=$asset" >>$GITHUB_ENV - - - name: Pack assets (Windows) - if: env.RELEASE && matrix.cfg.os == 'windows-latest' - run: | - asset="nerdfix-$CARGO_BUILD_TARGET.zip" - cp "$RELEASE_DIR/nerdfix.exe" nerdfix.exe - 7z a "$asset" nerdfix.exe - echo "ASSET=$asset" >>$GITHUB_ENV - - # NOTE: don't save release build dependencies to cache - - name: Clean release build - if: env.RELEASE - run: rm -rf "$RELEASE_DIR" - - - name: Upload release asset - uses: softprops/action-gh-release@v1 - if: env.RELEASE && startsWith(github.ref, 'refs/tags/') - with: - files: ${{ env.ASSET }} diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..8ff10a1 --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,221 @@ +# Adapted from: +# - https://github.com/starship/starship/blob/27cc4bc/.github/workflows/release.yml +# - https://github.com/sharkdp/bat/blob/6fc5882/.github/workflows/CICD.yml +name: CICD +on: + push: + branches: [main] + paths-ignore: ["**.md"] + pull_request: + paths-ignore: ["**.md"] + +permissions: + contents: read + +defaults: + run: + shell: bash + +jobs: + metadata: + name: Extract crate metadata + runs-on: ubuntu-latest + steps: + - name: Setup | Checkout + uses: actions/checkout@v4 + + - name: Setup | Rust + id: setup-rust + uses: dtolnay/rust-toolchain@stable + - run: rustup override set '${{ steps.setup-rust.outputs.name }}' + + - name: Setup | Extract crate metadata + id: metadata + run: | + cargo metadata --no-deps --format-version=1 \ + | jq -r '.packages[0] + | {name, version, rust_version} + | to_entries + | map("\(.key)=\(.value)") + | join("\n")' \ + | tee -a $GITHUB_OUTPUT + outputs: + name: ${{ steps.metadata.outputs.name }} + version: ${{ steps.metadata.outputs.version }} + rust_version: ${{ steps.metadata.outputs.rust_version }} + + check: + name: Run tests and checks + needs: [metadata] + strategy: + fail-fast: false + matrix: + # prettier-ignore + include: + - { os: ubuntu-20.04, toolchain: "${{ needs.metadata.outputs.rust_version }}" } # MSRV + - { os: ubuntu-20.04, toolchain: nightly } # Nightly + - { os: ubuntu-20.04, toolchain: stable } + - { os: macos-12, toolchain: stable } + - { os: windows-2019, toolchain: stable } + runs-on: ${{ matrix.os }} + steps: + - name: Setup | Checkout + uses: actions/checkout@v4 + + - name: Setup | Rust + id: setup-rust + uses: dtolnay/rust-toolchain@stable # avoid frequent cache updates + with: + toolchain: ${{ matrix.toolchain }} + components: clippy,rustfmt + - run: rustup override set '${{ steps.setup-rust.outputs.name }}' + + - name: Setup | Install cargo-audit + uses: taiki-e/install-action@cargo-audit + + - name: Setup | Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Post Setup | Show information + run: | + gcc --version || true + rustup --version + rustup toolchain list + rustup default + cargo --version + rustc --version + + - name: Check | Audit + run: cargo audit + + - name: Check | Formatting + run: cargo fmt --check + + - name: Check | Clippy + run: cargo clippy --locked + + - name: Check | Test suite + run: cargo test --locked + + - name: Check | Build + run: cargo build --locked + + build: + name: Build release binaries + needs: [metadata, check] + if: startsWith(github.head_ref, 'release/') + strategy: + fail-fast: false + matrix: + # prettier-ignore + include: + - { target: x86_64-unknown-linux-musl, os: ubuntu-20.04, cross: true } + - { target: aarch64-unknown-linux-musl, os: ubuntu-20.04, cross: true } + - { target: x86_64-unknown-freebsd, os: ubuntu-20.04, cross: true } + - { target: x86_64-apple-darwin, os: macOS-12 } + - { target: aarch64-apple-darwin, os: macOS-12 } + - { target: x86_64-pc-windows-msvc, os: windows-2019 } + - { target: aarch64-pc-windows-msvc, os: windows-2019 } + runs-on: ${{ matrix.os }} + env: + CARGO_INCREMENTAL: 0 + RUST_BACKTRACE: short + steps: + - name: Setup | Checkout + uses: actions/checkout@v4 + + - name: Setup | Rust + id: setup-rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + - run: rustup override set '${{ steps.setup-rust.outputs.name }}' + + - name: Setup | Install cross + if: matrix.cross + uses: taiki-e/install-action@cross + - run: echo CARGO=${{ matrix.cross && 'cross' || 'cargo' }} >>$GITHUB_ENV + + - name: Build | Build release + run: $CARGO build --release --locked --target '${{ matrix.target }}' + + - name: Post Build | Pack artifacts + id: pack + run: | + mkdir build + cp README.md LICENSE* build/ + basename='${{ needs.metadata.outputs.name }}-${{ matrix.target }}' + binpath='target/${{ matrix.target }}/release/${{ needs.metadata.outputs.name }}' + case '${{ matrix.os }}' in + windows-*) + cp "$binpath.exe" build/ + cd build && 7z a "../$basename.zip" * + echo name="$basename.zip" >>$GITHUB_OUTPUT + ;; + *) + cp "$binpath" build/ + cd build && tar czvf "../$basename.tar.gz" * + echo name="$basename.tar.gz" >>$GITHUB_OUTPUT + ;; + esac + + - name: Post Build | Generate checksums + # prettier-ignore + run: > + openssl dgst -sha256 -r '${{ steps.pack.outputs.name }}' + | cut -d' ' -f1 >'${{ steps.pack.outputs.name }}.sha256' + + - name: Pre Release | Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ needs.metadata.outputs.name }}-${{ matrix.target }} + path: ${{ steps.pack.outputs.name }}* + + release: + name: Create GitHub release + needs: [metadata, build] + if: github.repository == 'loichyan/test' + permissions: + contents: write # need to update release + runs-on: ubuntu-latest + steps: + - name: Setup | Checkout + uses: actions/checkout@v4 + + # For a PR from "release/v1.0.0", the release tag is set to "v1.0.0" + - name: Setup | Configure + id: configure + run: echo tag="${GITHUB_HEAD_REF#release/}" >$GITHUB_OUTPUT + + - name: Setup | Download artifacts + uses: actions/download-artifact@v4 + with: + path: build/ + pattern: ${{ needs.metadata.outputs.name }}-* + merge-multiple: true + + # Release notes are taken from the PR's body + - name: Release | Create Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + release_tag: ${{ steps.configure.outputs.tag }} + release_body: ${{ github.event.pull_request.body }} + run: | + if gh release view --json= "$release_tag" &>/dev/null; then + echo "update existed release $release_tag" + command=edit + else + echo "create new release $release_tag" + command=create + fi + gh release "$command" "$release_tag" \ + --target="$GITHUB_BASE_REF" \ + --draft=true \ + --title="$release_tag ($(date +'%Y-%m-%d'))" \ + --notes="$release_body" + + - name: Release | Upload artifacts + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + release_tag: ${{ steps.configure.outputs.tag }} + run: gh release upload --clobber "$release_tag" build/* diff --git a/Cargo.toml b/Cargo.toml index 9c53f9d..c2851b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ version = "0.4.0" authors = ["Loi Chyan "] license = "MIT OR Apache-2.0" edition = "2021" +rust-version = "1.70" [dependencies] bytesize = "1.3" From c7f33344c5a1649ef1932ac47613bbd6605d2026 Mon Sep 17 00:00:00 2001 From: Loi Chyan Date: Sun, 14 Jul 2024 12:49:35 +0800 Subject: [PATCH 2/2] ci: report Cargo check results --- .github/workflows/cicd.yml | 4 ++-- scripts/cargo-check-report | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100755 scripts/cargo-check-report diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 8ff10a1..e8c90eb 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -92,7 +92,7 @@ jobs: run: cargo fmt --check - name: Check | Clippy - run: cargo clippy --locked + run: cargo clippy --locked --message-format=json | ./scripts/cargo-check-report - name: Check | Test suite run: cargo test --locked @@ -174,7 +174,7 @@ jobs: release: name: Create GitHub release needs: [metadata, build] - if: github.repository == 'loichyan/test' + if: github.repository == 'loichyan/nerdfix' permissions: contents: write # need to update release runs-on: ubuntu-latest diff --git a/scripts/cargo-check-report b/scripts/cargo-check-report new file mode 100755 index 0000000..14a124b --- /dev/null +++ b/scripts/cargo-check-report @@ -0,0 +1,39 @@ +#!/usr/bin/env -S jq -srf + +# Sanitize some strings so they can be parsed safely: +# - https://github.com/actions/toolkit/blob/1db7362/packages/core/src/command.ts#L80 +def escapeData: + gsub("%"; "%25") + | gsub("\r"; "%0D") + | gsub("\n"; "%0A") +; +def escapeProperty: + escapeData + | gsub(":"; "%3A") + | gsub(","; "%2C") +; + +.[] +| select( + .reason == "compiler-message" + and (.message.level == "error" or .message.level == "warning") + and (.message.spans | length) > 0 + ) +| .message + .message.spans[0] +| { + level, + properties: { + title: .message | escapeProperty, + file: .file_name | escapeProperty, + line: .line_start, + endLine: .line_end, + col: .column_start, + endColumn: .column_end, + }, + message: .rendered | escapeData, + } +| "::\(.level)" + + " " + + (.properties | to_entries | map("\(.key)=\(.value)") | join(",")) + + "::" + + .message