Bug fixes #4
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: [dev] # CI runs on dev pushes only | |
| pull_request: | |
| branches: [main] # safety net: CI runs on PRs to main | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| # ── Rust: audit + lint + test + smoke ───────────────────────────────────── | |
| rust: | |
| name: Rust (audit + lint + test) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| token: ${{ secrets.PRIVATE_REPO_TOKEN }} | |
| - name: Configure Cargo for private dependencies | |
| run: cp .cargo/config.toml.example .cargo/config.toml | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy, rustfmt | |
| - name: Install cargo-audit | |
| run: cargo install cargo-audit --locked | |
| - name: Security audit | |
| run: cargo audit | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Format check | |
| run: cargo fmt --all -- --check | |
| - name: Clippy | |
| run: cargo clippy -p anya-security-core -- -D warnings | |
| - name: Run tests | |
| run: cargo test -p anya-security-core --verbose | |
| - name: Smoke test binary | |
| run: | | |
| ./target/debug/anya --version | |
| ./target/debug/anya --help | |
| ./target/debug/anya --file tests/fixtures/simple.exe --json --no-color | jq .file_format | |
| # ── Frontend: tsc + build + Vitest (single job) ──────────────────────────── | |
| frontend: | |
| name: Frontend (tsc + build + test) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node 22 | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: TypeScript check | |
| run: npx tsc --noEmit | |
| - name: Vite build | |
| run: npm run build | |
| - name: Run unit tests | |
| run: npm run test:unit | |
| # ── E2E: WebdriverIO + Tauri ─────────────────────────────────────────────── | |
| # Disabled: Tauri 2 + WebdriverIO 9 + tauri-driver 2.0.5 does not work | |
| # reliably in GitHub Actions headless environments. The capability matching | |
| # fails because the binary path and WebKit automation mode don't align in CI. | |
| # Re-enable when Tauri ships stable E2E support for CI. | |
| # Tests are still runnable locally with: | |
| # TAURI_WEBVIEW_AUTOMATION=true npm run tauri build -- --debug | |
| # xvfb-run --auto-servernum npm run test:e2e | |
| # ── Build CLI + GUI artifacts for testing ───────────────────────────────── | |
| # Runs in PARALLEL with test jobs — no needs: dependency. | |
| # Artifacts are available even if tests fail (useful for debugging). | |
| build-artifacts: | |
| name: Build — ${{ matrix.platform }} | |
| runs-on: ${{ matrix.platform }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: ubuntu-22.04 | |
| tauri_args: "" | |
| artifact: anya-linux-x64 | |
| - platform: macos-latest | |
| tauri_args: "--target universal-apple-darwin" | |
| artifact: anya-macos-universal | |
| - platform: windows-latest | |
| tauri_args: "" | |
| artifact: anya-windows-x64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| token: ${{ secrets.PRIVATE_REPO_TOKEN }} | |
| - name: Configure Cargo for private dependencies | |
| run: cp .cargo/config.toml.example .cargo/config.toml | |
| - name: Setup Node 22 | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| cache: "npm" | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Install Linux system dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libappindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf \ | |
| libsoup-3.0-dev \ | |
| libssl-dev | |
| - name: Install npm dependencies | |
| run: npm ci | |
| # tauri-action builds the full workspace (CLI binary is produced as a | |
| # side effect), so we don't need a separate cargo build step. | |
| - name: Build Tauri GUI + CLI | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| args: ${{ matrix.tauri_args }} | |
| # ── Upload CLI binary (extracted from tauri build) ────────────────── | |
| - name: Upload CLI artifact (Linux) | |
| if: runner.os == 'Linux' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }}-cli | |
| path: target/release/anya | |
| retention-days: 14 | |
| - name: Upload CLI artifact (macOS) | |
| if: runner.os == 'macOS' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }}-cli | |
| path: target/universal-apple-darwin/release/anya | |
| retention-days: 14 | |
| - name: Upload CLI artifact (Windows) | |
| if: runner.os == 'Windows' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }}-cli | |
| path: target/release/anya.exe | |
| retention-days: 14 | |
| # ── Upload GUI installers ─────────────────────────────────────────── | |
| - name: Upload GUI artifacts (Linux) | |
| if: runner.os == 'Linux' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }}-gui | |
| path: | | |
| target/release/bundle/appimage/*.AppImage | |
| target/release/bundle/deb/*.deb | |
| retention-days: 14 | |
| - name: Upload GUI artifacts (macOS) | |
| if: runner.os == 'macOS' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }}-gui | |
| path: target/universal-apple-darwin/release/bundle/dmg/*.dmg | |
| retention-days: 14 | |
| - name: Upload GUI artifacts (Windows) | |
| if: runner.os == 'Windows' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }}-gui | |
| path: target/release/bundle/nsis/*.exe | |
| retention-days: 14 | |
| # ── Docker: validate the Dockerfile builds correctly ───────────────────── | |
| # Build-only (no push). Catches Dockerfile issues before they hit release. | |
| docker-validate: | |
| name: Docker — build validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| token: ${{ secrets.PRIVATE_REPO_TOKEN }} | |
| - name: Configure Cargo for private dependencies | |
| run: cp .cargo/config.toml.example .cargo/config.toml | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image (no push) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| push: false | |
| platforms: linux/amd64 | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| build-args: | | |
| VERSION=ci-${{ github.sha }} | |
| # ── CLI cross-compilation: validate musl build ────────────────────────── | |
| # Catches musl cross-compile failures before they hit release. | |
| cli-musl-build: | |
| name: CLI — x86_64-musl | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| token: ${{ secrets.PRIVATE_REPO_TOKEN }} | |
| - name: Configure Cargo for private dependencies | |
| run: cp .cargo/config.toml.example .cargo/config.toml | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: x86_64-unknown-linux-musl | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: musl | |
| - name: Install musl tools | |
| run: sudo apt-get update && sudo apt-get install -y musl-tools | |
| - name: Build CLI binary | |
| run: cargo build --release --target x86_64-unknown-linux-musl -p anya-security-core | |
| - name: Upload static CLI artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: anya-linux-x64-static | |
| path: target/x86_64-unknown-linux-musl/release/anya | |
| retention-days: 14 | |
| # ── Version consistency check ──────────────────────────────────────── | |
| # Ensures all 4 version files are in sync before any release. | |
| version-check: | |
| name: Version consistency | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check all version files match | |
| run: | | |
| V_CARGO=$(grep '^version' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') | |
| V_TAURI_CARGO=$(grep '^version' src-tauri/Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') | |
| V_TAURI_JSON=$(grep '"version"' src-tauri/tauri.conf.json | head -1 | sed 's/.*"version": "\(.*\)".*/\1/') | |
| V_PACKAGE=$(grep '"version"' package.json | head -1 | sed 's/.*"version": "\(.*\)".*/\1/') | |
| echo "Cargo.toml: $V_CARGO" | |
| echo "src-tauri/Cargo.toml: $V_TAURI_CARGO" | |
| echo "tauri.conf.json: $V_TAURI_JSON" | |
| echo "package.json: $V_PACKAGE" | |
| if [ "$V_CARGO" != "$V_TAURI_CARGO" ] || [ "$V_CARGO" != "$V_TAURI_JSON" ] || [ "$V_CARGO" != "$V_PACKAGE" ]; then | |
| echo "::error::Version mismatch! All 4 files must have the same version." | |
| echo "Use: ./scripts/bump-version.sh $V_CARGO or the Create Release workflow." | |
| exit 1 | |
| fi | |
| echo "All versions match: $V_CARGO" | |
| # ── Chocolatey package validation ──────────────────────────────────── | |
| # Validates the .nuspec and install scripts parse correctly (no push). | |
| choco-validate: | |
| name: Chocolatey — dry run | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate nuspec | |
| shell: pwsh | |
| run: | | |
| # Verify required files exist | |
| $files = @( | |
| '.choco/anya.nuspec', | |
| '.choco/tools/chocolateyinstall.ps1', | |
| '.choco/tools/chocolateyuninstall.ps1', | |
| '.choco/tools/VERIFICATION.txt', | |
| '.choco/tools/LICENSE.txt' | |
| ) | |
| foreach ($f in $files) { | |
| if (!(Test-Path $f)) { | |
| Write-Error "Missing: $f" | |
| exit 1 | |
| } | |
| Write-Host "OK: $f" | |
| } | |
| - name: Dry-run pack | |
| shell: pwsh | |
| run: | | |
| $version = (Select-String -Path Cargo.toml -Pattern '^version = "(.+)"' | Select-Object -First 1).Matches.Groups[1].Value | |
| Write-Host "Packing version: $version" | |
| choco pack .choco/anya.nuspec --version $version | |
| if (!(Test-Path "anya.${version}.nupkg")) { | |
| Write-Error "choco pack failed — no .nupkg produced" | |
| exit 1 | |
| } | |
| Write-Host "Pack successful: anya.${version}.nupkg" |