diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 5aede7a1dbea..265d931490de 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -78,29 +78,17 @@ jobs: if: matrix.use-cross run: source ./bin/activate-hermit && cargo install cross --git https://github.com/cross-rs/cross - # Cache Cargo registry and git dependencies for Windows builds - - name: Cache Cargo registry (Windows) - if: matrix.use-docker - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f + - name: Cache Cargo artifacts (Linux/macOS) + if: matrix.use-cross + uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: - path: | - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-registry- - - # Cache compiled dependencies (target/release/deps) for Windows builds - - name: Cache Cargo build (Windows) + key: ${{ matrix.architecture }}-${{ matrix.target-suffix }} + + - name: Cache Cargo artifacts (Windows) if: matrix.use-docker - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f + uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: - path: target - key: ${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}-${{ hashFiles('rust-toolchain.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}- - ${{ runner.os }}-cargo-build-release- + key: ${{ matrix.architecture }}-${{ matrix.target-suffix }} - name: Build CLI (Linux/macOS) if: matrix.use-cross diff --git a/.github/workflows/bundle-desktop-intel.yml b/.github/workflows/bundle-desktop-intel.yml index a8d698b8259a..95e322deed43 100644 --- a/.github/workflows/bundle-desktop-intel.yml +++ b/.github/workflows/bundle-desktop-intel.yml @@ -63,29 +63,10 @@ jobs: cd ui/desktop npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version - - name: Cache Cargo registry - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-intel-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-intel-cargo-registry- - - - name: Cache Cargo index - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: - path: ~/.cargo/index - key: ${{ runner.os }}-intel-cargo-index - restore-keys: | - ${{ runner.os }}-intel-cargo-index - - - name: Cache Cargo build - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: target - key: ${{ runner.os }}-intel-cargo-build-release-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-intel-cargo-build-release- + key: intel - name: Build goose-server for Intel macOS (x86_64) diff --git a/.github/workflows/bundle-desktop-linux.yml b/.github/workflows/bundle-desktop-linux.yml index 8d24787c9d57..945b414b376e 100644 --- a/.github/workflows/bundle-desktop-linux.yml +++ b/.github/workflows/bundle-desktop-linux.yml @@ -87,17 +87,10 @@ jobs: - name: Install cross run: source ./bin/activate-hermit && cargo install cross --git https://github.com/cross-rs/cross - - name: Cache Cargo artifacts - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: - path: | - ${{ env.CARGO_HOME }}/bin/ - ${{ env.CARGO_HOME }}/registry/index/ - ${{ env.CARGO_HOME }}/registry/cache/ - ${{ env.CARGO_HOME }}/git/db/ - key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-release- + key: linux - name: Build goosed binary env: @@ -164,21 +157,21 @@ jobs: find ui/desktop/out/ -name "*.deb" -o -name "*.rpm" -exec ls -lh {} \; - name: Upload .deb package - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Goose-linux-x64-deb path: ui/desktop/out/make/deb/x64/*.deb if-no-files-found: error - name: Upload .rpm package - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Goose-linux-x64-rpm path: ui/desktop/out/make/rpm/x64/*.rpm if-no-files-found: error - name: Upload combined Linux packages - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Goose-linux-x64 path: | diff --git a/.github/workflows/bundle-desktop-windows.yml b/.github/workflows/bundle-desktop-windows.yml index bbde5345f659..68e589dc70dc 100644 --- a/.github/workflows/bundle-desktop-windows.yml +++ b/.github/workflows/bundle-desktop-windows.yml @@ -1,7 +1,7 @@ name: "Bundle Desktop (Windows)" on: -# push: +# push: # branches: [ "main" ] # pull_request: # branches: [ "main" ] @@ -41,15 +41,12 @@ jobs: runs-on: ubuntu-latest # Use Ubuntu for cross-compilation steps: - # 1) Check out source - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 with: - # Only pass ref if it's explicitly set, otherwise let checkout action use its default behavior ref: ${{ inputs.ref != '' && inputs.ref || '' }} fetch-depth: 0 - # 2) Configure AWS credentials for code signing - name: Configure AWS credentials if: inputs.signing && inputs.signing == true uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # ratchet:aws-actions/configure-aws-credentials@v4 @@ -57,13 +54,11 @@ jobs: role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.WINDOW_SIGNING_ROLE || secrets.WINDOW_SIGNING_ROLE_TAG }} aws-region: us-west-2 - # 2) Set up Node.js - name: Set up Node.js uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # pin@v3 with: node-version: 22 - # 3) Cache dependencies - name: Cache node_modules uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 with: @@ -75,36 +70,18 @@ jobs: restore-keys: | windows-npm-cache-v1-${{ runner.os }}-node22- - # Cache Cargo registry and git dependencies - - name: Cache Cargo registry - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 with: - path: | - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-registry- - - # Cache compiled dependencies (target/release/deps) - - name: Cache Cargo build - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f - with: - path: target - key: ${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}-${{ hashFiles('rust-toolchain.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}- - ${{ runner.os }}-cargo-build-release- + key: windows - # 4) Build Rust for Windows using Docker (cross-compilation with enhanced caching) - name: Build Windows executable using Docker cross-compilation with enhanced caching run: | echo "🚀 Building Windows executable with enhanced GitHub Actions caching..." - + # Create cache directories mkdir -p ~/.cargo/registry ~/.cargo/git - + # Use enhanced caching with GitHub Actions cache mounts docker run --rm \ -v "$(pwd)":/usr/src/myapp \ @@ -117,7 +94,7 @@ jobs: echo '=== Setting up Rust environment with caching ===' export CARGO_HOME=/usr/local/cargo export PATH=/usr/local/cargo/bin:\$PATH - + # Check if Windows target is already installed in cache if rustup target list --installed | grep -q x86_64-pc-windows-gnu; then echo '✅ Windows cross-compilation target already installed' @@ -125,11 +102,11 @@ jobs: echo '📦 Installing Windows cross-compilation target...' rustup target add x86_64-pc-windows-gnu fi - + echo '=== Setting up build dependencies ===' apt-get update apt-get install -y mingw-w64 protobuf-compiler cmake time - + echo '=== Setting up cross-compilation environment ===' export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++ @@ -137,7 +114,7 @@ jobs: export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc export PKG_CONFIG_ALLOW_CROSS=1 export PROTOC=/usr/bin/protoc - + echo '=== Optimized Cargo configuration ===' mkdir -p .cargo echo '[build]' > .cargo/config.toml @@ -159,7 +136,7 @@ jobs: echo '' >> .cargo/config.toml echo '[registries.crates-io]' >> .cargo/config.toml echo 'protocol = \"sparse\"' >> .cargo/config.toml - + echo '=== Building with cached dependencies ===' # Check if we have cached build artifacts if [ -d target/x86_64-pc-windows-gnu/release/deps ] && [ \"\$(ls -A target/x86_64-pc-windows-gnu/release/deps)\" ]; then @@ -169,51 +146,50 @@ jobs: echo '🔨 No cached artifacts found, performing full build...' CARGO_INCREMENTAL=0 fi - + echo '🔨 Building Windows executable...' CARGO_INCREMENTAL=\$CARGO_INCREMENTAL \ CARGO_NET_RETRY=3 \ CARGO_HTTP_TIMEOUT=60 \ RUST_BACKTRACE=1 \ cargo build --release --target x86_64-pc-windows-gnu --jobs 4 - + echo '=== Copying Windows runtime DLLs ===' GCC_DIR=\$(ls -d /usr/lib/gcc/x86_64-w64-mingw32/*/ | head -n 1) cp \"\$GCC_DIR/libstdc++-6.dll\" target/x86_64-pc-windows-gnu/release/ cp \"\$GCC_DIR/libgcc_s_seh-1.dll\" target/x86_64-pc-windows-gnu/release/ cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll target/x86_64-pc-windows-gnu/release/ - + echo '✅ Build completed successfully!' ls -la target/x86_64-pc-windows-gnu/release/ " - + # Verify build succeeded if [ ! -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then echo "❌ Windows binary not found." ls -la ./target/x86_64-pc-windows-gnu/release/ || echo "Release directory doesn't exist" exit 1 fi - + echo "✅ Windows binary found!" ls -la ./target/x86_64-pc-windows-gnu/release/goosed.exe ls -la ./target/x86_64-pc-windows-gnu/release/*.dll - # 5) Prepare Windows binary and DLLs - name: Prepare Windows binary and DLLs run: | if [ ! -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then echo "Windows binary not found." exit 1 fi - + echo "Cleaning destination directory..." rm -rf ./ui/desktop/src/bin mkdir -p ./ui/desktop/src/bin - + echo "Copying Windows binary and DLLs..." cp -f ./target/x86_64-pc-windows-gnu/release/goosed.exe ./ui/desktop/src/bin/ cp -f ./target/x86_64-pc-windows-gnu/release/*.dll ./ui/desktop/src/bin/ - + # Copy Windows platform files (tools, scripts, etc.) if [ -d "./ui/desktop/src/platform/windows/bin" ]; then echo "Copying Windows platform files..." @@ -222,7 +198,7 @@ jobs: cp -f "$file" ./ui/desktop/src/bin/ fi done - + if [ -d "./ui/desktop/src/platform/windows/bin/goose-npm" ]; then echo "Setting up npm environment..." rsync -a --delete ./ui/desktop/src/platform/windows/bin/goose-npm/ ./ui/desktop/src/bin/goose-npm/ @@ -230,56 +206,53 @@ jobs: echo "Windows-specific files copied successfully" fi - # 6) Install & build UI desktop - name: Build desktop UI with npm run: | cd ui/desktop - + npm install npm run bundle:windows - # 7) Copy exe/dll to final out folder and prepare flat distribution - name: Copy exe/dll to final out folder and prepare flat distribution run: | cd ui/desktop mkdir -p ./out/Goose-win32-x64/resources/bin rsync -av src/bin/ out/Goose-win32-x64/resources/bin/ - + # Create flat distribution structure mkdir -p ./dist-windows cp -r ./out/Goose-win32-x64/* ./dist-windows/ - + # Verify the final structure echo "📋 Final flat distribution structure:" ls -la ./dist-windows/ echo "📋 Binary files in resources/bin:" ls -la ./dist-windows/resources/bin/ - # 8) Sign Windows executables with jsign + AWS KMS - name: Sign Windows executables with jsign + AWS KMS if: inputs.signing && inputs.signing == true run: | set -exuo pipefail echo "🔐 Starting Windows code signing with jsign + AWS KMS..." - + # Create certificate file from secret echo "📝 Creating certificate file from GitHub secret..." echo "${{ secrets.WINDOWS_CODESIGN_CERTIFICATE }}" > block-codesign-cert.pem - + # Install Java (required for jsign) echo "☕ Installing Java runtime..." sudo apt-get update sudo apt-get install -y openjdk-11-jre-headless osslsigncode - + # Download jsign echo "📥 Downloading jsign..." wget -q https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar -O jsign.jar echo "05ca18d4ab7b8c2183289b5378d32860f0ea0f3bdab1f1b8cae5894fb225fa8a jsign.jar" | sha256sum -c - + # Sign the main Electron executable (Goose.exe) echo "🔐 Signing main Electron executable: Goose.exe" cd ui/desktop/dist-windows/ - + java -jar ${GITHUB_WORKSPACE}/jsign.jar \ --storetype AWS \ --keystore us-west-2 \ @@ -293,11 +266,11 @@ jobs: osslsigncode verify Goose.exe echo "✅ Main executable Goose.exe signed successfully" - + # Sign the backend executable (goosed.exe) echo "🔐 Signing backend executable: goosed.exe" cd resources/bin/ - + java -jar ${GITHUB_WORKSPACE}/jsign.jar \ --storetype AWS \ --keystore us-west-2 \ @@ -319,11 +292,10 @@ jobs: sha256sum Goose.exe ls -la resources/bin/goosed.exe sha256sum resources/bin/goosed.exe - + # Clean up certificate file rm -f ${GITHUB_WORKSPACE}/block-codesign-cert.pem - # 9) Verify signed executables are in final distribution - name: Verify signed executables are in final distribution if: inputs.signing && inputs.signing == true run: | @@ -332,29 +304,27 @@ jobs: ls -la ui/desktop/dist-windows/Goose.exe osslsigncode verify ui/desktop/dist-windows/Goose.exe echo "✅ Main executable signature verification passed" - + echo "Backend executable:" ls -la ui/desktop/dist-windows/resources/bin/goosed.exe osslsigncode verify ui/desktop/dist-windows/resources/bin/goosed.exe echo "✅ Backend executable signature verification passed" - # 10) Create Windows zip package - name: Create Windows zip package run: | cd ui/desktop echo "📦 Creating Windows zip package..." - + # Create a zip file from the dist-windows directory zip -r "Goose-win32-x64.zip" dist-windows/ - + echo "✅ Windows zip package created:" ls -la Goose-win32-x64.zip - + # Also create the zip in the expected output structure for consistency mkdir -p out/Goose-win32-x64/ cp Goose-win32-x64.zip out/Goose-win32-x64/ - # 11) Upload the final Windows build - name: Upload Windows build artifacts uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # pin@v4 with: diff --git a/.github/workflows/bundle-desktop.yml b/.github/workflows/bundle-desktop.yml index dd9f58cc6b32..ca85f2fc4ec5 100644 --- a/.github/workflows/bundle-desktop.yml +++ b/.github/workflows/bundle-desktop.yml @@ -108,29 +108,8 @@ jobs: cd ui/desktop npm version "${VERSION}" --no-git-tag-version --allow-same-version - - name: Cache Cargo registry - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-registry- - - - name: Cache Cargo index - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: ~/.cargo/index - key: ${{ runner.os }}-cargo-index - restore-keys: | - ${{ runner.os }}-cargo-index - - - name: Cache Cargo build - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-release-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-build-release- + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 # Build the project - name: Build goosed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a3395fccc7a..646e918a85b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,3 +1,5 @@ +name: CI + on: push: branches: @@ -10,8 +12,6 @@ on: - main workflow_dispatch: -name: CI - jobs: changes: runs-on: ubuntu-latest @@ -41,23 +41,21 @@ jobs: - name: Checkout Code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Run cargo fmt - run: source ./bin/activate-hermit && cargo fmt --check + run: cargo fmt --check rust-build-and-test: name: Build and Test Rust Project - runs-on: goose + runs-on: ubuntu-latest needs: changes if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request' steps: - name: Checkout Code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 - - name: Activate hermit and set CARGO_HOME - run: | - source bin/activate-hermit - echo "CARGO_HOME=$CARGO_HOME" >> $GITHUB_ENV - echo "RUSTUP_HOME=$RUSTUP_HOME" >> $GITHUB_ENV + - uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install Dependencies run: | @@ -65,32 +63,52 @@ jobs: sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev - name: Cache Cargo artifacts - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: | - ${{ env.CARGO_HOME }}/bin/ - ${{ env.CARGO_HOME }}/registry/index/ - ${{ env.CARGO_HOME }}/registry/cache/ - ${{ env.CARGO_HOME }}/git/db/ - target/ - key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-debug- + uses: Swatinem/rust-cache@v2 - name: Build and Test run: | gnome-keyring-daemon --components=secrets --daemonize --unlock <<< 'foobar' - source ../bin/activate-hermit export CARGO_INCREMENTAL=0 - cargo test --jobs 2 + cargo test -- --skip scenario_tests::scenarios::tests + cargo test --jobs 1 scenario_tests::scenarios::tests working-directory: crates + + rust-lint: + name: Lint Rust Code + runs-on: ubuntu-latest + needs: changes + if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request' + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - uses: Swatinem/rust-cache@v2 + - name: Lint run: | source ./bin/activate-hermit + # use the non-hermit rust toolchain because the rust-cache action does not + # play nicely with hermit-managed rust + hermit uninstall rustup export CARGO_INCREMENTAL=0 ./scripts/clippy-lint.sh + openapi-schema-check: + name: Check OpenAPI Schema is Up-to-Date + runs-on: ubuntu-latest + needs: changes + if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request' + steps: + - name: Checkout Code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Cache Cargo artifacts + uses: Swatinem/rust-cache@v2 + - name: Install Node.js Dependencies for OpenAPI Check run: source ../../bin/activate-hermit && npm ci working-directory: ui/desktop @@ -98,6 +116,7 @@ jobs: - name: Check OpenAPI Schema is Up-to-Date run: | source ./bin/activate-hermit + hermit uninstall rustup just check-openapi-schema desktop-lint: @@ -130,5 +149,3 @@ jobs: - name: Run Tests run: source ../../bin/activate-hermit && npm run test:run working-directory: ui/desktop - - diff --git a/.github/workflows/pr-smoke-test.yml b/.github/workflows/pr-smoke-test.yml index af1100bb83fa..0a14db7359b2 100644 --- a/.github/workflows/pr-smoke-test.yml +++ b/.github/workflows/pr-smoke-test.yml @@ -55,33 +55,18 @@ jobs: with: ref: ${{ github.event.inputs.branch || github.ref }} - - name: Activate hermit and set CARGO_HOME - run: | - source bin/activate-hermit - echo "CARGO_HOME=$CARGO_HOME" >> $GITHUB_ENV - echo "RUSTUP_HOME=$RUSTUP_HOME" >> $GITHUB_ENV + - uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install Dependencies run: | sudo apt update -y sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev - - name: Cache Cargo artifacts - uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 - with: - path: | - ${{ env.CARGO_HOME }}/bin/ - ${{ env.CARGO_HOME }}/registry/index/ - ${{ env.CARGO_HOME }}/registry/cache/ - ${{ env.CARGO_HOME }}/git/db/ - target/ - key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-release- + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 - name: Build Release Binary for Smoke Tests run: | - source ./bin/activate-hermit cargo build --release - name: Upload Binary for Smoke Tests diff --git a/scripts/clippy-baseline.sh b/scripts/clippy-baseline.sh index fcee8ab8cf51..e0ed230f874c 100755 --- a/scripts/clippy-baseline.sh +++ b/scripts/clippy-baseline.sh @@ -1,11 +1,11 @@ #!/bin/bash # Baseline clippy rules - only fail on NEW violations -# +# # Format: "rule_name|violation_parser" # # Violation parsers (run clippy on your rule to see which fits): -# function_name - When spans show: "fn my_function(..." +# function_name - When spans show: "fn my_function(..." # type_name - When spans show: "struct MyStruct" or "enum MyEnum" # file_only - When spans show file-level issues # @@ -23,18 +23,18 @@ BASELINE_RULES=( parse_violation() { local rule_code="$1" local violation_parser="$2" - + case "$violation_parser" in "function_name") - jq -r 'select(.message.code.code == "'"$rule_code"'") | + jq -r 'select(.message.code.code == "'"$rule_code"'") | "\(.message.spans[0].file_name)::\(.message.spans[0].text[0].text | split("fn ")[1] | split("(")[0])"' ;; "type_name") - jq -r 'select(.message.code.code == "'"$rule_code"'") | + jq -r 'select(.message.code.code == "'"$rule_code"'") | "\(.message.spans[0].file_name)::\(.message.spans[0].text[0].text | split(" ")[1] | split(" ")[0])"' ;; "file_only") - jq -r 'select(.message.code.code == "'"$rule_code"'") | + jq -r 'select(.message.code.code == "'"$rule_code"'") | "\(.message.spans[0].file_name)"' ;; *) @@ -53,22 +53,22 @@ get_baseline_file() { generate_baseline() { local rule_name="$1" - + [[ -z "$rule_name" ]] && { echo "Missing rule name"; return 1; } - + local violation_parser="" for rule in "${BASELINE_RULES[@]}"; do [[ "${rule%|*}" == "$rule_name" ]] && { violation_parser="${rule#*|}"; break; } done - + [[ -z "$violation_parser" ]] && { echo "Unknown rule: $rule_name"; return 1; } - + local baseline_file=$(get_baseline_file "$rule_name") - + cargo clippy --jobs 2 --message-format=json -- -W "$rule_name" | \ parse_violation "$rule_name" "$violation_parser" | \ sort > "$baseline_file" - + echo "✅ Generated baseline for $rule_name ($(wc -l < "$baseline_file") violations)" } @@ -79,23 +79,23 @@ check_rule_from_json() { local rule_name="$2" local violation_parser="$3" local baseline_file="$4" - + echo " → Checking $rule_name" - + if [[ ! -f "$baseline_file" ]]; then echo " ❌ $rule_name: baseline file not found" return 1 fi - + local temp_parsed=$(mktemp) cat "$temp_json" | parse_violation "$rule_name" "$violation_parser" | sort > "$temp_parsed" - + local new_violations_file=$(mktemp) diff <(sort "$baseline_file") <(sort "$temp_parsed") | grep "^>" | cut -c3- > "$new_violations_file" - + if [[ -s "$new_violations_file" ]]; then echo " ❌ $rule_name: NEW violations found:" - + while IFS= read -r violation; do # Extract all violations for this rule and find the matching one cat "$temp_json" | jq -c 'select(.message.code.code == "'"$rule_name"'")' 2>/dev/null | while read -r json_line; do @@ -105,13 +105,13 @@ check_rule_from_json() { fi done done < "$new_violations_file" - + rm "$temp_parsed" "$new_violations_file" return 1 fi - + rm "$new_violations_file" - + echo " ✅ $rule_name: ok" rm "$temp_parsed" return 0 @@ -119,31 +119,31 @@ check_rule_from_json() { check_all_baseline_rules() { echo "🔍 Checking baseline clippy rules..." - + local clippy_flags="" for rule in "${BASELINE_RULES[@]}"; do local rule_name="${rule%|*}" clippy_flags="$clippy_flags -W $rule_name" done - + local temp_json=$(mktemp) - cargo clippy --jobs 2 --message-format=json -- $clippy_flags > "$temp_json" - + cargo clippy --jobs 2 --message-format=json -- $clippy_flags | tee "$temp_json" + local failed_rules=() - + # Check each rule against its baseline for rule in "${BASELINE_RULES[@]}"; do local rule_name="${rule%|*}" local violation_parser="${rule#*|}" local baseline_file=$(get_baseline_file "$rule_name") - + if ! check_rule_from_json "$temp_json" "$rule_name" "$violation_parser" "$baseline_file"; then failed_rules+=("$rule_name") fi done - + rm "$temp_json" - + if [[ ${#failed_rules[@]} -gt 0 ]]; then echo "" echo "❌ Failed baseline checks for: ${failed_rules[*]}" @@ -156,4 +156,4 @@ check_all_baseline_rules() { if [[ "$1" == "generate" ]]; then generate_baseline "$2" -fi \ No newline at end of file +fi