mirror of
https://github.com/lahfir/agent-desktop.git
synced 2026-07-26 17:12:15 +00:00
Add locked Rust verification, binary command tests, npm package surface checks, dependency policy scanning, workflow security auditing, and Dependabot updates so PR and release gates cover the package surfaces that are shipped.
156 lines
5.6 KiB
YAML
156 lines
5.6 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master]
|
|
pull_request:
|
|
workflow_dispatch:
|
|
|
|
# Cancel in-progress runs for the same ref so stale PR builds don't burn minutes.
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
# Deny all permissions at workflow level; each job declares only what it needs.
|
|
permissions: {}
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
RUST_BACKTRACE: 1
|
|
|
|
jobs:
|
|
fmt:
|
|
name: Format
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
- run: rustup component add rustfmt
|
|
- run: cargo fmt --all -- --check
|
|
|
|
test:
|
|
name: Test
|
|
runs-on: macos-latest
|
|
timeout-minutes: 30
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Install Rust toolchain
|
|
run: rustup show
|
|
|
|
- name: Cache cargo registry
|
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
with:
|
|
path: |
|
|
~/.cargo/registry/index/
|
|
~/.cargo/registry/cache/
|
|
~/.cargo/git/db/
|
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml', 'Cargo.lock') }}
|
|
restore-keys: ${{ runner.os }}-cargo-
|
|
|
|
- name: Cache build artifacts
|
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
with:
|
|
path: target/
|
|
key: ${{ runner.os }}-build-ci-${{ hashFiles('**/Cargo.toml', 'Cargo.lock') }}-${{ hashFiles('**/*.rs') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-build-ci-${{ hashFiles('**/Cargo.toml', 'Cargo.lock') }}-
|
|
${{ runner.os }}-build-ci-
|
|
|
|
- name: Check dependency isolation
|
|
run: |
|
|
if cargo tree --locked -p agent-desktop-core 2>/dev/null | grep -E 'agent-desktop-(macos|windows|linux)'; then
|
|
echo "FAIL: core crate depends on platform crates"
|
|
exit 1
|
|
fi
|
|
echo "OK: core crate has no platform dependencies"
|
|
|
|
- name: Clippy
|
|
run: cargo clippy --locked --all-targets -- -D warnings
|
|
|
|
- name: Unit tests
|
|
run: cargo test --locked --lib --workspace
|
|
|
|
- name: Binary command tests
|
|
run: cargo test --locked -p agent-desktop
|
|
|
|
# The FFI crate ships integration harnesses under crates/ffi/tests/ that
|
|
# exercise the C-ABI from outside the crate (raw extern "C" decls, enum
|
|
# fuzzing, out-param zeroing, last-error lifetimes). The workspace --lib
|
|
# run skips them, so wire them in explicitly so regressions fail PR CI.
|
|
- name: FFI integration tests
|
|
run: cargo test --locked -p agent-desktop-ffi --tests
|
|
|
|
# Use the ci profile (no LTO, opt-level 1) — fast compile, still checks the binary builds.
|
|
- name: Build binary (ci profile)
|
|
run: cargo build --locked --profile ci
|
|
|
|
- name: Check binary size
|
|
run: |
|
|
SIZE=$(stat -f%z target/ci/agent-desktop)
|
|
LIMIT=$((15 * 1024 * 1024))
|
|
echo "Binary size: $(du -sh target/ci/agent-desktop | cut -f1)"
|
|
if [ "$SIZE" -gt "$LIMIT" ]; then
|
|
echo "FAIL: binary exceeds 15MB limit (${SIZE} bytes)"
|
|
exit 1
|
|
fi
|
|
echo "OK: binary within 15MB limit"
|
|
|
|
- name: FFI cdylib build (release-ffi profile)
|
|
run: cargo build --locked --profile release-ffi -p agent-desktop-ffi
|
|
|
|
- name: FFI header drift check
|
|
run: |
|
|
# build.rs stamps target/ffi-header-path.txt with the absolute path
|
|
# to the header produced by the most recent build, so the drift
|
|
# check always compares against the just-generated artifact rather
|
|
# than an arbitrary match from `find | head -1` over a warm cache.
|
|
STAMP=target/ffi-header-path.txt
|
|
if [ ! -f "$STAMP" ]; then
|
|
echo "FAIL: $STAMP missing; build.rs did not stamp header path"
|
|
exit 1
|
|
fi
|
|
GENERATED=$(cat "$STAMP")
|
|
if [ ! -f "$GENERATED" ]; then
|
|
echo "FAIL: stamped header path does not exist: $GENERATED"
|
|
exit 1
|
|
fi
|
|
if ! diff -u crates/ffi/include/agent_desktop.h "$GENERATED"; then
|
|
echo "FAIL: crates/ffi/include/agent_desktop.h is out of date"
|
|
echo "Run 'scripts/update-ffi-header.sh' locally and commit the regenerated header."
|
|
exit 1
|
|
fi
|
|
echo "OK: FFI header is in sync with source"
|
|
|
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
|
with:
|
|
node-version: '24'
|
|
|
|
- name: NPM package contents
|
|
run: node scripts/check-npm-package.js
|
|
|
|
- name: NPM wrapper smoke
|
|
run: |
|
|
case "$(uname -s)-$(uname -m)" in
|
|
Darwin-arm64) NAME=agent-desktop-darwin-arm64 ;;
|
|
Darwin-x86_64) NAME=agent-desktop-darwin-x64 ;;
|
|
*)
|
|
echo "Unsupported smoke-test platform: $(uname -s)-$(uname -m)"
|
|
exit 1
|
|
;;
|
|
esac
|
|
trap 'rm -f "npm/bin/${NAME}"' EXIT
|
|
cp target/ci/agent-desktop "npm/bin/${NAME}"
|
|
chmod +x "npm/bin/${NAME}"
|
|
node npm/bin/agent-desktop.js version --json > /tmp/agent-desktop-version.json
|
|
node -e "
|
|
const out = require('fs').readFileSync('/tmp/agent-desktop-version.json', 'utf8');
|
|
const json = JSON.parse(out);
|
|
if (json.ok !== true || !json.data || typeof json.data.version !== 'string') {
|
|
throw new Error('agent-desktop npm wrapper did not return version JSON');
|
|
}
|
|
"
|