diff --git a/.github/workflows/deploy-mdbook.yml b/.github/workflows/deploy-mdbook.yml deleted file mode 100644 index 351e4ad55..000000000 --- a/.github/workflows/deploy-mdbook.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Deploy Sysand Users Guide to GitHub Pages - -on: - release: - types: [published] - workflow_dispatch: - -permissions: - contents: read - pages: write - id-token: write - -jobs: - build: - if: github.event_name == 'workflow_dispatch' || !github.event.release.prerelease - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v6 - - name: Install mdBook - uses: peaceiris/actions-mdbook@v2 - with: - mdbook-version: "latest" - - - run: mdbook build docs - - - name: Upload Pages Artifact - uses: actions/upload-pages-artifact@v4 - with: - path: ./docs/book - - deploy: - needs: [build] - runs-on: ubuntu-24.04 - environment: - name: github-pages - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml deleted file mode 100644 index 7351eebfd..000000000 --- a/.github/workflows/java.yml +++ /dev/null @@ -1,296 +0,0 @@ -name: Java (Bindings) - -on: - push: - branches: [main] - tags: ["*"] - pull_request: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash - -env: - RUST_BACKTRACE: 1 - CARGO_TERM_COLOR: always - CARGO_NET_RETRY: 10 - RUSTUP_MAX_RETRIES: 10 - UV_HTTP_RETRIES: 5 - UV_HTTP_TIMEOUT: 60 - -jobs: - plan: - runs-on: ubuntu-slim - outputs: - test: ${{ steps.decisions.outputs.test }} - gate: ${{ steps.decisions.outputs.gate }} - steps: - - uses: dorny/paths-filter@v4 - id: filter - with: - filters: | - src: - - 'core/**' - - 'bindings/java/**' - - 'Cargo.*' - - '.github/workflows/java.yml' - - id: decisions - run: | - test=${{ steps.filter.outputs.src == 'true' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} - gate=${{ github.event_name == 'pull_request' }} - echo "test=$test" >> "$GITHUB_OUTPUT" - echo "gate=$gate" >> "$GITHUB_OUTPUT" - - compile-bindings: - needs: [plan] - if: needs.plan.outputs.test == 'true' - name: Compile native bindings - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-24.04 - - ubuntu-24.04-arm - - windows-latest - - windows-11-arm - - macos-15-intel # x86 - - macos-latest # arm64 - - steps: - - uses: actions/checkout@v6 - - uses: actions/cache@v5 - with: - path: | - ~/.cargo/bin - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-cargo- - - - name: cargo build ... - run: cargo build --locked --package sysand-java --release - - - uses: actions/setup-python@v6 - if: matrix.os == 'ubuntu-24.04' - with: - python-version: "3.14" - - name: Create version.txt - if: matrix.os == 'ubuntu-24.04' - run: python bindings/java/scripts/java-builder.py create-version-file - env: - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE }} - - name: Upload version.txt - uses: actions/upload-artifact@v7 - if: matrix.os == 'ubuntu-24.04' - with: - name: version - path: version.txt - if-no-files-found: error - - - name: Upload native bindings - uses: actions/upload-artifact@v7 - with: - name: native-bindings-${{ matrix.os }} - path: | - target/release/*.so - target/release/*.dylib - target/release/*.dll - if-no-files-found: error - retention-days: 5 # lower than default, many ~5 MB files - - build-jar: - name: Build Java JAR - needs: [compile-bindings] - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - uses: actions/setup-java@v5 - with: - java-version: "21" # to support JRE 21+ - distribution: temurin - gpg-private-key: ${{ secrets.MAVEN_CENTRAL_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Download version.txt - uses: actions/download-artifact@v8 - with: - name: version - - name: Download native bindings - uses: actions/download-artifact@v8 - with: - path: native-bindings - - name: List native bindings - run: ls -la native-bindings/* - - - name: Build JAR - run: | - python bindings/java/scripts/java-builder.py \ - ${{ startsWith(github.ref, 'refs/tags/') && '--release-jar-version' || '' }} \ - build \ - --use-existing-native-libs native-bindings \ - --use-release-build \ - ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE && '--sign-artifacts' || '' }} - env: - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE }} - - - name: Build Sysand Maven plugin and run integration tests - run: | - python bindings/java/scripts/java-builder.py \ - ${{ startsWith(github.ref, 'refs/tags/') && '--release-jar-version' || '' }} \ - build-plugin \ - ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE && '--sign-artifacts' || '' }} - env: - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE }} - - - name: Upload JARs - uses: actions/upload-artifact@v7 - with: - name: jars - path: target/java - if-no-files-found: error - retention-days: 5 # lower than default, a ~160 MB file - - name: Upload Maven plugin JAR - uses: actions/upload-artifact@v7 - with: - name: maven-plugin-jar - path: target/java-plugin - if-no-files-found: error - # We need to include hidden files because integration tests use - # .meta.json and .project.json files. - include-hidden-files: true - - test-jar: - name: Test Java JAR - needs: [build-jar] - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-24.04 - - ubuntu-24.04-arm - - windows-latest - - windows-11-arm - - macos-15-intel # x86 - - macos-latest # arm64 - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - uses: actions/setup-java@v5 - with: - java-version: "21" # to support JRE 21+ - distribution: temurin - gpg-private-key: ${{ secrets.MAVEN_CENTRAL_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Download JARs - uses: actions/download-artifact@v8 - with: - name: jars - path: target/java - - name: Download version.txt - uses: actions/download-artifact@v8 - with: - name: version - - name: List .jar files and more - run: | - find . -iname "*.jar" - ls -la * - ls -la target/* - ls -la target/java/* - ls -la target/java/target/* - - - name: Test Java JAR - run: | - python bindings/java/scripts/java-builder.py \ - ${{ startsWith(github.ref, 'refs/tags/') && '--release-jar-version' || '' }} \ - test - env: - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE }} - - ci-gate: - name: Java CI Gate - needs: [plan, compile-bindings, build-jar, test-jar] - if: needs.plan.outputs.gate == 'true' && !cancelled() - runs-on: ubuntu-slim - steps: - - run: | - if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then - exit 1 - fi - - release: - # Nightly tags do not trigger CI since they are created in CI - name: Release - needs: [build-jar, test-jar] - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-24.04 - permissions: - id-token: write # for signing release artifacts - contents: write # for uploading release artifacts - attestations: write # for release artifact attestation - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - uses: actions/setup-java@v5 - with: - java-version: "21" # to support JRE 21+ - distribution: temurin - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.MAVEN_CENTRAL_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Download native bindings - uses: actions/download-artifact@v8 - with: - name: jars - path: target/java - - name: Download Maven plugin JAR - uses: actions/download-artifact@v8 - with: - name: maven-plugin-jar - path: target/java-plugin - - name: Download version.txt - uses: actions/download-artifact@v8 - with: - name: version - - name: List .jar files and more - run: | - find . -iname "*.jar" - find target/java-plugin/target/it/ - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-path: "target/java/target/*.jar" - - - name: Deploy Java bindings - run: python bindings/java/scripts/java-builder.py deploy - env: - MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_TOKEN_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_TOKEN_PASSWORD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE }} diff --git a/.github/workflows/js-wasm.yml b/.github/workflows/js-wasm.yml deleted file mode 100644 index 4f5a6ce8c..000000000 --- a/.github/workflows/js-wasm.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: JS/WASM (Bindings) - -on: - push: - branches: [main] - tags: ["*"] - pull_request: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash - -env: - RUST_BACKTRACE: 1 - CARGO_TERM_COLOR: always - CARGO_NET_RETRY: 10 - RUSTUP_MAX_RETRIES: 10 - UV_HTTP_RETRIES: 5 - UV_HTTP_TIMEOUT: 60 - -jobs: - plan: - runs-on: ubuntu-slim - outputs: - test: ${{ steps.decisions.outputs.test }} - gate: ${{ steps.decisions.outputs.gate }} - steps: - - uses: dorny/paths-filter@v4 - id: filter - with: - filters: | - src: - - 'core/**' - - 'bindings/js/**' - - 'Cargo.*' - - '.github/workflows/js-wasm.yml' - - id: decisions - run: | - test=${{ steps.filter.outputs.src == 'true' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} - gate=${{ github.event_name == 'pull_request' }} - echo "test=$test" >> "$GITHUB_OUTPUT" - echo "gate=$gate" >> "$GITHUB_OUTPUT" - - test: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 - with: - node-version: 24 - - - name: Install wasm-pack - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - - - name: Test in Firefox - run: | - cd bindings/js - export WASM_BINDGEN_USE_BROWSER=1 - wasm-pack test --headless --firefox - - - name: Test in Chrome - run: | - cd bindings/js - export WASM_BINDGEN_USE_BROWSER=1 - wasm-pack test --headless --chrome - - - name: Build for Node.js and test - run: | - cd bindings/js - npm install - npm run test:browser - - ci-gate: - name: JS/WASM CI Gate - needs: [plan, test] - if: needs.plan.outputs.gate == 'true' && !cancelled() - runs-on: ubuntu-slim - steps: - - run: | - if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then - exit 1 - fi diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml deleted file mode 100644 index cac61f877..000000000 --- a/.github/workflows/python.yml +++ /dev/null @@ -1,388 +0,0 @@ -# This file evolved from being autogenerated with maturin and then **heavily -# manually** edited. You can regenerate it as below for comparative reference. -# Last time this was done was with maturin v1.12.6 at 2026-03-17. -# -# maturin generate-ci github --pytest --manifest-path bindings/py/Cargo.toml -# -name: Python (Bindings) - -on: - push: - branches: [main] - tags: ["*"] - pull_request: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash - -env: - RUST_BACKTRACE: 1 - CARGO_TERM_COLOR: always - CARGO_NET_RETRY: 10 - RUSTUP_MAX_RETRIES: 10 - UV_HTTP_RETRIES: 5 - UV_HTTP_TIMEOUT: 60 - -jobs: - plan: - runs-on: ubuntu-slim - outputs: - test: ${{ steps.decisions.outputs.test }} - gate: ${{ steps.decisions.outputs.gate }} - steps: - - uses: dorny/paths-filter@v4 - id: filter - with: - filters: | - src: - - 'bindings/py/**' - - 'core/**' - - 'sysand/**' - - 'Cargo.*' - - '.github/workflows/python.yml' - - '.github/scripts/*' - - id: decisions - run: | - test=${{ steps.filter.outputs.src == 'true' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} - gate=${{ github.event_name == 'pull_request' }} - echo "test=$test" >> "$GITHUB_OUTPUT" - echo "gate=$gate" >> "$GITHUB_OUTPUT" - - lint: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ubuntu-24.04 - defaults: - run: - working-directory: bindings/py - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - uses: astral-sh/setup-uv@v7 - - - name: Setup environment - run: | - uv sync --group linters --active --no-install-project --locked - echo "$(pwd)/.venv/bin" >> "$GITHUB_PATH" - - - name: ruff format ... - run: ruff format --check python tests - - - name: ruff check ... - run: ruff check python - - - name: mypy ... - run: mypy --strict python - - windows: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ${{ matrix.platform.runner }} - strategy: - matrix: - platform: - - runner: windows-latest - target: x64 - rust_target: x86_64-pc-windows-msvc - - runner: windows-11-arm - target: arm64 # not aarch64 because expected by setup-python - rust_target: aarch64-pc-windows-msvc - # It is sufficient to build wheels for the lowest supported Python - # version, but we need to build wheels for each supported free-threaded - # version. - python: - - version: "3.14t" - label: 3.14-free-threaded - args_suffix: --interpreter python3.14t - include: - # Since Python 3.10 isn't available on the arm runners, we need to - # provide a 3.10 job for x64 and a 3.11 job for arm64. - - platform: - runner: windows-latest - target: x64 - rust_target: x86_64-pc-windows-msvc - python: - version: "3.10" - label: "3.10" - args_suffix: "" - - platform: - runner: windows-11-arm - target: arm64 # not aarch64 because expected by setup-python - rust_target: aarch64-pc-windows-msvc - python: - version: "3.11" - label: "3.11" - args_suffix: "" - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python.version }} - architecture: ${{ matrix.platform.target }} - - uses: astral-sh/setup-uv@v7 - - - uses: actions/cache@v5 - with: - path: | - ~/.cargo/bin - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-cargo- - - - name: cargo test ... (Python bindings) - run: | - cd bindings/py - cargo test --locked --package sysand-py --no-default-features --target ${{ matrix.platform.rust_target }} - - - name: Build wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.rust_target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi ${{ matrix.python.args_suffix }} - - - name: Upload wheels - uses: actions/upload-artifact@v7 - with: - name: wheels-windows-${{ matrix.platform.target }}-${{ matrix.python.label }} - path: dist - if-no-files-found: error - - - name: pytest - run: | - export UV_PYTHON=${{ matrix.python.version }} - export ACTIVATION_SCRIPT=.venv/Scripts/activate - .github/scripts/run-pytest.sh ${{ matrix.python.version }} - - linux: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ${{ matrix.platform.runner }} - strategy: - fail-fast: false - matrix: - platform: - - runner: ubuntu-24.04 - target: x86_64 - - runner: ubuntu-24.04-arm - target: aarch64 - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - uses: astral-sh/setup-uv@v7 - - - uses: actions/cache@v5 - with: - path: | - ~/.cargo/bin - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-cargo- - - - name: cargo test ... (Python bindings) - run: cargo test --locked --package sysand-py --no-default-features - - - name: Build wheels (manylinux) - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi - manylinux: manylinux2014 - - name: Build wheels (musllinux) - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi - manylinux: musllinux_1_2 - - - name: Build free-threaded wheels (manylinux) - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi --interpreter python3.14t - manylinux: manylinux2014 # TODO: don't use default cross-compile containers for aarch64 - - name: Build free-threaded wheels (musllinux) - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi --interpreter python3.14t - manylinux: musllinux_1_2 - - - name: Upload wheels - uses: actions/upload-artifact@v7 - with: - name: wheels-linux-${{ matrix.platform.target }} - path: dist - if-no-files-found: error - - - name: pytest (manylinux) - run: .github/scripts/run-pytest.sh - - - name: pytest (musllinux) - run: | - docker run --rm -v ${{ github.workspace }}:/io -w /io \ - alpine:latest \ - sh -c ' - apk add -q curl bash python3 - curl -LsSf https://astral.sh/uv/install.sh | sh - export PATH=$PATH:$HOME/.local/bin - /bin/bash .github/scripts/run-pytest.sh - ' - - macos: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ${{ matrix.platform.runner }} - strategy: - matrix: - platform: - - runner: macos-15-intel - target: x86_64 - - runner: macos-latest - target: aarch64 - - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - uses: astral-sh/setup-uv@v7 - - - uses: actions/cache@v5 - with: - path: | - ~/.cargo/bin - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-cargo- - - - name: cargo test ... (Python bindings) - run: cargo test --locked --package sysand-py --no-default-features - - - name: Build wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi - - - name: Build free-threaded wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.platform.target }} - working-directory: bindings/py - args: --release --out ../../dist --compatibility pypi --interpreter python3.14t - - - name: Upload wheels - uses: actions/upload-artifact@v7 - with: - name: wheels-macos-${{ matrix.platform.target }} - path: dist - if-no-files-found: error - - - name: pytest - run: .github/scripts/run-pytest.sh - - sdist: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v6 - - - name: Maturin workaround - # Maturin-action blindly downloads the specified toolchain without - # checking that it won't be needed at all for sdist - # TODO: fix maturin so that this isn't needed - run: rm rust-toolchain.toml - - - name: Build sdist - uses: PyO3/maturin-action@v1 - with: - command: sdist - working-directory: bindings/py - args: --out ../../dist - - - name: Upload sdist - uses: actions/upload-artifact@v7 - with: - name: wheels-sdist - path: dist - if-no-files-found: error - - ci-gate: - name: Python CI Gate - needs: [plan, lint, windows, linux, macos, sdist] - if: needs.plan.outputs.gate == 'true' && !cancelled() - runs-on: ubuntu-slim - steps: - - run: | - if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then - exit 1 - fi - - release: - name: Release to PyPI - environment: pypi-publish - needs: [lint, linux, macos, windows, sdist] - if: startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-slim - permissions: - id-token: write # for trusted publishing, and signing release artifacts - contents: write # for uploading release artifacts - attestations: write # for release artifact attestation - - steps: - - uses: actions/download-artifact@v8 - - - name: Generate artifact attestation - id: attest - uses: actions/attest-build-provenance@v3 - with: - subject-path: "wheels-*/*" - - - name: Prepare attestations for uv - run: | - # The action creates one attestation bundle for all artifacts, but - # uv expects a separate .publish.attestation file for each artifact - for file in wheels-*/*; do - cp "${{ steps.attest.outputs.bundle-path }}" "$file.publish.attestation" - done - - - uses: astral-sh/setup-uv@v7 - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') - - - name: Publish to PyPI - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') - run: | - uv publish -v --trusted-publishing always wheels-*/* diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 043f11ef4..a3bcbec66 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,10 +2,10 @@ name: Rust (Library & CLI) on: push: - branches: [main] + branches: ["*"] tags: ["*"] pull_request: - branches: [main] + branches: ["*"] workflow_dispatch: permissions: @@ -28,104 +28,13 @@ env: UV_HTTP_TIMEOUT: 60 jobs: - plan: - runs-on: ubuntu-slim - outputs: - test: ${{ steps.decisions.outputs.test }} - gate: ${{ steps.decisions.outputs.gate }} - steps: - - uses: dorny/paths-filter@v4 - id: filter - with: - filters: | - src: - - 'core/**' - - 'sysand/**' - - 'Cargo.*' - - '.github/workflows/rust.yml' - - id: decisions - run: | - test=${{ steps.filter.outputs.src == 'true' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} - gate=${{ github.event_name == 'pull_request' }} - echo "test=$test" >> "$GITHUB_OUTPUT" - echo "gate=$gate" >> "$GITHUB_OUTPUT" - - lint-and-format: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v6 - - uses: actions/cache@v5 - with: - path: | - ~/.cargo/bin - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-cargo- - - - uses: taiki-e/install-action@cargo-hack - - - name: cargo hack clippy ... - run: cargo hack clippy --each-feature --no-dev-deps --features std --ignore-unknown-features -- --deny warnings - - - name: cargo clippy ... - run: cargo clippy --locked --all-targets --all-features -- --deny warnings - - - name: cargo fmt ... - run: cargo fmt --check - - test: - needs: [plan] - if: needs.plan.outputs.test == 'true' - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-24.04 - - ubuntu-24.04-arm - - windows-latest - - windows-11-arm - - macos-15-intel # x86 - - macos-latest # arm64 - - steps: - - uses: actions/checkout@v6 - - uses: actions/cache@v5 - with: - path: | - ~/.cargo/bin - ~/.cargo/registry/index - ~/.cargo/registry/cache - ~/.cargo/git/db - key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-cargo- - - - name: cargo test ... (Rust library & CLI) - run: >- - cargo test --locked - --package sysand-core - --package sysand - --features sysand-core/filesystem,sysand-core/networking,sysand-core/js,sysand-core/python,alltests,kpar-bzip2,kpar-zstd,kpar-xz,kpar-ppmd - build: - needs: [test] runs-on: ${{ matrix.os }} strategy: matrix: os: - - ubuntu-24.04 - - ubuntu-24.04-arm - windows-latest - windows-11-arm - - macos-15-intel # x86 - - macos-latest # arm64 steps: - uses: actions/checkout@v6 - uses: actions/cache@v5 @@ -142,108 +51,15 @@ jobs: - name: cargo build ... run: cargo build --locked --bin sysand --release - - name: Relocate binaries + - name: Check vcruntime linking + if: runner.os == 'Windows' + shell: pwsh run: | - mkdir -p dist - ext=${{ (matrix.os == 'windows-latest' || matrix.os == 'windows-11-arm') && '.exe' || '' }} - cp target/release/sysand${ext} dist/sysand-${{ matrix.os }}${ext} - - - name: Upload binaries - uses: actions/upload-artifact@v7 - with: - name: sysand-cli-${{ matrix.os }} - path: dist - if-no-files-found: error - - ci-gate: - name: Rust CI Gate - needs: [plan, lint-and-format, test, build] - if: needs.plan.outputs.gate == 'true' && !cancelled() - runs-on: ubuntu-slim - steps: - - run: | - if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then + $vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath + $dumpbin = Resolve-Path (Join-Path $vsPath "VC\Tools\MSVC\*\bin\Hostx64\x64\dumpbin.exe") | Select-Object -Last 1 + $deps = & $dumpbin /dependents target\release\sysand.exe + echo $deps + if ($deps -match "VCRUNTIME140.dll") { + Write-Error "vcruntime140.dll is dynamically linked — static linking failed" exit 1 - fi - - nightly-release: - name: Nightly Release - needs: [test, build] - if: github.ref == 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-24.04 - permissions: - id-token: write # for signing release artifacts - contents: write # for uploading release artifacts - attestations: write # for release artifact attestation - - steps: - - uses: actions/download-artifact@v8 - with: - path: artifacts - merge-multiple: true - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-path: "artifacts/*" - - - name: Rename artifacts - run: | - mv artifacts/sysand-ubuntu-24.04 artifacts/sysand-linux-x86_64 - mv artifacts/sysand-ubuntu-24.04-arm artifacts/sysand-linux-arm64 - mv artifacts/sysand-windows-latest.exe artifacts/sysand-windows-x86_64.exe - mv artifacts/sysand-windows-11-arm.exe artifacts/sysand-windows-arm64.exe - mv artifacts/sysand-macos-15-intel artifacts/sysand-macos-x86_64 - mv artifacts/sysand-macos-latest artifacts/sysand-macos-arm64 - - - name: Create release tag - run: echo "TAG_NAME=$(date +v-%Y-%m-%d-%H%M)" >> $GITHUB_ENV - - - name: Create a nightly release - uses: softprops/action-gh-release@v2 - with: - prerelease: true - files: | - artifacts/* - overwrite_files: false - tag_name: ${{ env.TAG_NAME }} - name: Nightly Release ${{ env.TAG_NAME }} - - release: - name: Release - needs: [test, build] - if: startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-24.04 - permissions: - id-token: write # for signing release artifacts - contents: write # for uploading release artifacts - attestations: write # for release artifact attestation - - steps: - - uses: actions/download-artifact@v8 - with: - path: artifacts - merge-multiple: true - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-path: "artifacts/*" - - - name: Rename artifacts - run: | - mv artifacts/sysand-ubuntu-24.04 artifacts/sysand-linux-x86_64 - mv artifacts/sysand-ubuntu-24.04-arm artifacts/sysand-linux-arm64 - mv artifacts/sysand-windows-latest.exe artifacts/sysand-windows-x86_64.exe - mv artifacts/sysand-windows-11-arm.exe artifacts/sysand-windows-arm64.exe - mv artifacts/sysand-macos-15-intel artifacts/sysand-macos-x86_64 - mv artifacts/sysand-macos-latest artifacts/sysand-macos-arm64 - - - name: Create a release - uses: softprops/action-gh-release@v2 - with: - make_latest: true - files: | - artifacts/* - overwrite_files: false - name: Release ${{ github.event.inputs.tag_name }} + }