feat(session): implement persistent command logging #773
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: [ master, main, develop ] | |
| pull_request: | |
| branches: [ master, main, develop ] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| check: | |
| name: Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@1.95.0 | |
| with: | |
| components: rustfmt, clippy | |
| - name: Setup protoc | |
| uses: arduino/setup-protoc@v3 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install ripgrep and ast-grep | |
| run: | | |
| cargo install ripgrep --locked | |
| cargo install ast-grep --locked | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Run cargo check | |
| run: cargo check --all-targets --all-features | |
| fmt: | |
| name: Rustfmt | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@1.95.0 | |
| with: | |
| components: rustfmt | |
| - name: Run cargo fmt | |
| run: cargo fmt --all -- --check | |
| clippy: | |
| name: Clippy | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@1.95.0 | |
| with: | |
| components: clippy | |
| - name: Setup protoc | |
| uses: arduino/setup-protoc@v3 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install ripgrep and ast-grep | |
| run: | | |
| cargo install ripgrep --locked | |
| cargo install ast-grep --locked | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Run cargo clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| test: | |
| name: Test Suite | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| rust: [1.95.0] | |
| include: | |
| - os: ubuntu-latest | |
| rust: beta | |
| - os: ubuntu-latest | |
| rust: nightly | |
| continue-on-error: ${{ matrix.rust == 'nightly' }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ matrix.rust }} | |
| - name: Setup protoc | |
| uses: arduino/setup-protoc@v3 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install ripgrep and ast-grep | |
| run: | | |
| cargo install ripgrep --locked | |
| cargo install ast-grep --locked | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-${{ matrix.rust }}-cargo- | |
| ${{ runner.os }}-cargo- | |
| # Cache the HuggingFace model weights fetched by smoke tests | |
| # (`muvon/octomind-embed`, ~130MB safetensors). octolib stores them via | |
| # `dirs::cache_dir()/octolib/huggingface`, which expands to: | |
| # Linux: ~/.cache/octolib/huggingface | |
| # macOS: ~/Library/Caches/octolib/huggingface | |
| # Windows: ~/AppData/Local/octolib/huggingface | |
| # Cache key invalidates when src/embeddings/mod.rs changes (e.g. MODEL_NAME). | |
| - name: Cache HuggingFace model weights | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/octolib/huggingface | |
| ~/Library/Caches/octolib/huggingface | |
| ~/AppData/Local/octolib/huggingface | |
| key: ${{ runner.os }}-octolib-hf-${{ hashFiles('src/embeddings/mod.rs') }} | |
| restore-keys: | | |
| ${{ runner.os }}-octolib-hf- | |
| # Linux: csukuangfj ships a single bundled libonnxruntime.a — ort-sys's | |
| # single-file shortcut links it directly. Just point ORT_LIB_LOCATION at | |
| # the extracted lib/ dir. | |
| # Windows MSVC: nothing to do — ort-sys's download-binaries feature pulls | |
| # pyke's prebuilts automatically when ORT_LIB_LOCATION is unset. | |
| - name: Download ONNX Runtime static library (Linux) | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| ORT_VERSION="1.24.2" | |
| ORT_ASSET="onnxruntime-linux-x64-static_lib-${ORT_VERSION}-glibc2_17" | |
| curl -sL "https://github.com/csukuangfj/onnxruntime-libs/releases/download/v${ORT_VERSION}/${ORT_ASSET}.zip" -o /tmp/ort.zip | |
| unzip -q /tmp/ort.zip -d /tmp/ort | |
| echo "ORT_LIB_LOCATION=/tmp/ort/${ORT_ASSET}/lib" >> "$GITHUB_ENV" | |
| # Windows: ORT prebuilts (pyke download-binaries) are compiled with /MD | |
| # (dynamic CRT). Rust on MSVC defaults to /MT (static CRT), causing | |
| # __imp_* unresolved-symbol link errors. Switch to dynamic CRT to match. | |
| # vcruntime140.dll is present on all GitHub Windows runners. | |
| - name: Run tests | |
| shell: bash | |
| env: | |
| RUSTFLAGS: ${{ runner.os == 'Windows' && '-C target-feature=-crt-static' || '' }} | |
| run: cargo test --verbose | |
| musl-build: | |
| name: Musl Build (x86_64 + aarch64) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: true | |
| matrix: | |
| include: | |
| - target: x86_64-unknown-linux-musl | |
| os: ubuntu-latest | |
| - target: aarch64-unknown-linux-musl | |
| os: ubuntu-22.04-arm | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # Cache the static ONNX Runtime build (45–60 min cold) between runs. | |
| # Cache the full source+build tree because ort-sys's full static-link | |
| # branch needs to walk build/_deps/ for re2, abseil, protobuf, etc. | |
| # Flattening the .a files into one dir breaks linking. | |
| # Keyed by ORT version + target so a version bump invalidates correctly. | |
| - name: Cache ONNX Runtime static build | |
| uses: actions/cache@v4 | |
| with: | |
| path: onnxruntime-src | |
| key: onnxruntime-1.24.2-${{ matrix.target }}-alpine3.22-v6 | |
| - name: Cache cargo registry and target | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: docker-alpine-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| docker-alpine-${{ matrix.target }}-cargo- | |
| - name: Build in Alpine (mirrors release pipeline) | |
| run: | | |
| # Pre-create the cache dir on the host so Docker volume-mount inherits | |
| # writable permissions. | |
| mkdir -p onnxruntime-src | |
| chmod -R 777 onnxruntime-src | |
| docker run --rm \ | |
| --user 0:0 \ | |
| -v "$(pwd):/workspace" \ | |
| -w /workspace \ | |
| rust:1.95.0-alpine3.22 \ | |
| sh -c ' | |
| set -eu | |
| # No protobuf-dev: it pulls in abseil-cpp-dev transitively, which | |
| # makes ORT'\''s CMake skip its bundled abseil and (because re2 | |
| # depends on bundled absl targets) drop re2 from the build entirely. | |
| # ort-sys 2.0.0-rc.12 hardcodes static links to ~25 absl_*, re2, | |
| # protobuf libs at fixed _deps/ paths, so all three must be built | |
| # by ORT, not the system. Without the system packages ORT | |
| # FetchContent'\''s and compiles all three from source. | |
| apk add --no-cache \ | |
| git perl bash musl-dev openssl-dev openssl-libs-static \ | |
| pkgconfig gcc g++ \ | |
| cmake make linux-headers python3 py3-pip patch | |
| # Provide stub execinfo.h — musl lacks it and Alpine 3.17+ removed | |
| # libexecinfo. ORT'\''s stacktrace.cc unconditionally includes it on | |
| # non-Android POSIX. The stub provides no-op backtrace functions. | |
| mkdir -p /tmp/include | |
| cat > /tmp/include/execinfo.h << "EOF" | |
| #ifndef _EXECINFO_H | |
| #define _EXECINFO_H | |
| #include <stddef.h> | |
| static inline int backtrace(void **buffer, int size) { (void)buffer; (void)size; return 0; } | |
| static inline char **backtrace_symbols(void *const *buffer, int size) { (void)buffer; (void)size; return NULL; } | |
| static inline void backtrace_symbols_fd(void *const *buffer, int size, int fd) { (void)buffer; (void)size; (void)fd; } | |
| #endif | |
| EOF | |
| export C_INCLUDE_PATH=/tmp/include | |
| export CPLUS_INCLUDE_PATH=/tmp/include | |
| rustup target add ${{ matrix.target }} | |
| ORT_SRC=/workspace/onnxruntime-src | |
| ORT_LIB_LOCATION="$ORT_SRC/build/Release" | |
| # libre2.a is the late marker — re2 is built last in the bundled | |
| # dep graph (after abseil + protobuf), so its presence proves the | |
| # full static tree is in place. A partial cache that only has | |
| # libonnxruntime_common.a but no libre2.a triggers a clean rebuild. | |
| if [ ! -f "$ORT_LIB_LOCATION/_deps/re2-build/libre2.a" ]; then | |
| echo "==> Building ONNX Runtime 1.24.2 from source (static, musl)" | |
| rm -rf "$ORT_SRC" | |
| git clone --single-branch --branch v1.24.2 --recursive \ | |
| https://github.com/microsoft/onnxruntime.git "$ORT_SRC" | |
| cd "$ORT_SRC" | |
| ./build.sh \ | |
| --config Release \ | |
| --build_dir build \ | |
| --parallel \ | |
| --skip_tests \ | |
| --skip_submodule_sync \ | |
| --allow_running_as_root \ | |
| --compile_no_warning_as_error \ | |
| --no_kleidiai \ | |
| --no_sve \ | |
| --cmake_extra_defines \ | |
| CMAKE_POSITION_INDEPENDENT_CODE=ON \ | |
| onnxruntime_BUILD_UNIT_TESTS=OFF \ | |
| onnxruntime_BUILD_SHARED_LIB=OFF \ | |
| onnxruntime_USE_KLEIDIAI=OFF | |
| # ORT'\''s static build (.a archives, --skip_tests) never link an | |
| # executable, so target_link_libraries deps like re2::re2 don'\''t | |
| # trigger compilation — re2 is FetchContent-populated but its | |
| # CMake target stays unbuilt. ort-sys 2.0.0-rc.12 hardcodes a | |
| # static link to it. Explicitly drive the re2 target inside ORT'\''s | |
| # configured build tree (uses bundled abseil from the same tree). | |
| cmake --build "$ORT_LIB_LOCATION" --target re2 -j | |
| cd /workspace | |
| else | |
| echo "==> Using cached ONNX Runtime static build" | |
| fi | |
| # ort-sys static_config #1 with empty profile detection. | |
| # ORT_LIB_LOCATION = build/Release (where libonnxruntime_common.a lives directly). | |
| # Profile detection iterates build/Release/{Release,RelWithDebInfo,...}, | |
| # none exist → profile="" → transform_dep adds no suffix. | |
| # lib_dir = base ✓, external_lib_dir = base/_deps = build/Release/_deps | |
| # which is where cmake actually places onnx-build/, re2-build/, abseil_cpp-build/, etc. | |
| # | |
| # DO NOT use ORT_LIB_LOCATION="$ORT_SRC/build": that triggers profile=Release | |
| # detection, which makes transform_dep append /Release to every _deps path, | |
| # so search paths land at build/_deps/onnx-build/Release (non-existent) and | |
| # linking fails with "could not find native static library 'onnx'". | |
| export ORT_LIB_LOCATION="$ORT_LIB_LOCATION" | |
| # GCC 15 (Alpine 3.23) introduced __cpu_features2 in libgcc. | |
| # ORT'\''s cpuid_info.cc.o references it; musl static link needs | |
| # libgcc.a explicitly or the symbol is undefined at link time. | |
| export RUSTFLAGS="-C link-arg=-lgcc" | |
| cargo build --target ${{ matrix.target }} | |
| ' | |
| security: | |
| name: Security Audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@1.95.0 | |
| - name: Setup protoc | |
| uses: arduino/setup-protoc@v3 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install ripgrep and ast-grep | |
| run: | | |
| cargo install ripgrep --locked | |
| cargo install ast-grep --locked | |
| - name: Install cargo-audit | |
| run: cargo install cargo-audit --locked | |
| - name: Run security audit | |
| run: cargo audit | |
| coverage: | |
| name: Code Coverage | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@1.95.0 | |
| - name: Setup protoc | |
| uses: arduino/setup-protoc@v3 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install ripgrep and ast-grep | |
| run: | | |
| cargo install ripgrep --locked | |
| cargo install ast-grep --locked | |
| - name: Install cargo-tarpaulin | |
| run: cargo install cargo-tarpaulin --locked | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-coverage- | |
| ${{ runner.os }}-cargo- | |
| - name: Generate code coverage | |
| run: cargo tarpaulin --engine llvm --verbose --workspace --timeout 120 --out xml | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| file: ./cobertura.xml | |
| fail_ci_if_error: false | |
| brief: | |
| uses: muvon/ci-workflow/.github/workflows/brief.yml@master | |
| secrets: inherit |