name: Ruby SDK

on:
  push:
    branches: [main]
    paths:
      - "sdk/ruby/**"
      - ".github/workflows/ruby.yml"
  pull_request:
    branches: [main]
    paths:
      - "sdk/ruby/**"
      - ".github/workflows/ruby.yml"

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

env:
  CARGO_TERM_COLOR: always
  CARGO_NET_RETRY: "10"
  CARGO_HTTP_TIMEOUT: "120"

jobs:
  build:
    name: Ruby ${{ matrix.ruby }} / Linux x86_64
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        ruby: ["3.1", "3.2", "3.3", "3.4"]

    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
        with:
          ruby-version: ${{ matrix.ruby }}

      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
        with:
          components: clippy, rustfmt

      # The Ruby extension is its own Cargo project and must keep an exact crates.io
      # dependency for source-gem releases. Until the matching core crate is published,
      # patch CI to the checkout so new Ruby bindings can be tested in the same PR.
      - name: Use checkout Rust SDK
        shell: bash
        run: |
          ruby_cargo_home="$RUNNER_TEMP/microsandbox-ruby-cargo"
          standalone_lock="$RUNNER_TEMP/microsandbox-ruby-standalone.lock"
          mkdir -p "$ruby_cargo_home"
          printf '[patch.crates-io]\nmicrosandbox = { path = "%s/sdk/rust" }\n' "$GITHUB_WORKSPACE" > "$ruby_cargo_home/config.toml"
          mv "$GITHUB_WORKSPACE/sdk/ruby/ext/microsandbox/Cargo.lock" "$standalone_lock"
          cp "$GITHUB_WORKSPACE/Cargo.lock" "$GITHUB_WORKSPACE/sdk/ruby/ext/microsandbox/Cargo.lock"
          echo "CARGO_HOME=$ruby_cargo_home" >> "$GITHUB_ENV"
          echo "MICROSANDBOX_RUBY_STANDALONE_LOCK=$standalone_lock" >> "$GITHUB_ENV"

      - uses: Swatinem/rust-cache@258712b0b7b1ddf8bddc9fc3b0faca682b2736c3 # v2
        with:
          workspaces: sdk/ruby/ext/microsandbox
          cache-bin: false

      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y libcap-ng-dev musl-tools

      - name: Install Ruby build dependencies
        run: gem install rake rake-compiler test-unit rb_sys --no-document

      # Ruby deliberately compiles the Rust SDK without its prebuilt feature.
      # Stage the guest agent from this checkout so the filesystem crate can
      # embed it without reaching for an unpublished GitHub release asset.
      - name: Build agentd for local SDK checks
        run: |
          rustup target add x86_64-unknown-linux-musl
          cargo build --profile ci --manifest-path crates/agentd/Cargo.toml --target x86_64-unknown-linux-musl
          mkdir -p build
          cp target/x86_64-unknown-linux-musl/ci/agentd build/agentd

      - name: Check Rust extension
        working-directory: sdk/ruby/ext/microsandbox
        run: |
          cargo fmt -- --check
          cargo check
          cargo clippy -- -D warnings

      - name: Compile and test source tree
        working-directory: sdk/ruby
        run: rake clean compile test

      # The temporary Cargo patch is outside the gem, so the artifact keeps its
      # exact crates.io pin while this source-tree check uses the matching local API.
      - name: Build and install source gem against checkout
        working-directory: sdk/ruby
        run: |
          gem build microsandbox.gemspec
          gem install --local microsandbox-*.gem --no-document
          ruby --disable-gems -e 'require "rubygems"; require "microsandbox"; abort unless Microsandbox.version == "0.6.9"'

      - name: Restore standalone Ruby lockfile
        if: always()
        shell: bash
        run: mv "$MICROSANDBOX_RUBY_STANDALONE_LOCK" "$GITHUB_WORKSPACE/sdk/ruby/ext/microsandbox/Cargo.lock"
