name: Per merge CI

on: # rebuild any PRs and main branch changes
  pull_request:
  push:
    branches:
      - master

permissions:
  contents: read
  actions: write

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-lint:
    name: "Format, docs, and lint"
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: 1.90.0
      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          # TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
          version: "23.x"
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - run: rustup component add rustfmt clippy
      - uses: Swatinem/rust-cache@v2
      - run: cargo fmt --all --check
      - run: cargo doc --workspace --all-features --no-deps
        env:
          RUSTDOCFLAGS: "-D warnings"
      - run: cargo lint
      - run: cargo test-lint
      - run: cargo check
      - run: git diff --exit-code

  test:
    name: Unit Tests
    timeout-minutes: 15
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, ubuntu-arm, macos-intel, macos-arm, windows-latest]
        include:
          - os: windows-latest
          - os: ubuntu-latest
          - os: ubuntu-arm
            runsOn: ubuntu-24.04-arm64-2-core
          - os: macos-arm
            runsOn: macos-14
          - os: macos-intel
            runsOn: macos-15-intel
    runs-on: ${{ matrix.runsOn || matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: 1.90.0
      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          # TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
          version: "23.x"
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      # Workaround for https://github.com/actions/runner-images/issues/12432
      # from https://github.com/rust-lang/rust/issues/141626#issuecomment-2919419236
      # Visual Studio bug tracker https://developercommunity.visualstudio.com/t/Regression-from-1943:-linkexe-crashes/10912960
      - name: Setup RUSTFLAGS (Windows)
        if: runner.os == 'Windows'
        uses: actions/github-script@v7
        with:
          script: |
            core.exportVariable('RUSTFLAGS', '-Csymbol-mangling-version=v0');
      - uses: Swatinem/rust-cache@v2
      - run: cargo test -- --include-ignored --nocapture
      - name: Find test executable for cgroup tests
        id: find-cgroup-test
        if: runner.os == 'Linux' && runner.arch == 'X64'
        run: |
          test_executable=$(cargo build --tests --message-format json | jq -r 'select(.profile?.test == true and .target?.name == "temporalio_sdk_core" and .executable) | .executable')
          cp $test_executable ./core-tests
      - name: Upload cgroup test executable
        uses: actions/upload-artifact@v4
        if: runner.os == 'Linux' && runner.arch == 'X64'
        with:
          name: cgroup-tests-linux-x86_64
          path: ./core-tests
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: tarpaulin-report.html
      - uses: actions/upload-artifact@v4
        with:
          name: state-machine-coverage
          path: machine_coverage/

  cgroup-tests:
    name: cgroup tests
    needs: test
    runs-on: ubuntu-latest
    container:
      image: ubuntu
      options: --cpus=1 --memory=512m
    env:
      CGROUP_TESTS_ENABLED: true
    steps:
      - name: Download cgroup test executable
        uses: actions/download-artifact@v5
        with:
          name: cgroup-tests-linux-x86_64
      - name: Run tests
        run: |
          chmod +x ./core-tests
          ./core-tests cgroup_ --nocapture

  integ-tests:
    name: Integ tests
    timeout-minutes: 25
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, ubuntu-arm, macos-intel, macos-arm, windows-latest]
        include:
          - os: windows-latest
          - os: ubuntu-latest
          - os: ubuntu-arm
            runsOn: ubuntu-24.04-arm64-2-core
          - os: macos-arm
            runsOn: macos-14
          - os: macos-intel
            runsOn: macos-15-intel
    runs-on: ${{ matrix.runsOn || matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: 1.90.0
      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          # TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
          version: "23.x"
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      # Workaround for https://github.com/actions/runner-images/issues/12432
      # from https://github.com/rust-lang/rust/issues/141626#issuecomment-2919419236
      # Visual Studio bug tracker https://developercommunity.visualstudio.com/t/Regression-from-1943:-linkexe-crashes/10912960
      - name: Setup RUSTFLAGS (Windows)
        if: runner.os == 'Windows'
        uses: actions/github-script@v7
        with:
          script: |
            core.exportVariable('RUSTFLAGS', '-Csymbol-mangling-version=v0');
      - uses: Swatinem/rust-cache@v2
      - run: cargo integ-test

  cloud-tests:
    if: github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-core'
    name: Cloud tests
    env:
      TEMPORAL_CLOUD_ADDRESS: https://${{ vars.TEMPORAL_CLIENT_NAMESPACE }}.tmprl.cloud:7233
      TEMPORAL_NAMESPACE: ${{ vars.TEMPORAL_CLIENT_NAMESPACE }}
      TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }}
      TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }}
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: 1.90.0
      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          # TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
          version: "23.x"
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - uses: Swatinem/rust-cache@v2
      - run: cargo test --features=test-utilities --test cloud_tests

  docker-integ-tests:
    name: Docker integ tests
    env:
      TEMPORAL_CLOUD_ADDRESS: https://${{ vars.TEMPORAL_CLIENT_NAMESPACE }}.tmprl.cloud:7233
      TEMPORAL_CLOUD_NAMESPACE: ${{ vars.TEMPORAL_CLIENT_NAMESPACE }}
      TEMPORAL_CLIENT_CERT: ${{ secrets.TEMPORAL_CLIENT_CERT }}
      TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }}
      DOCKER_PROMETHEUS_RUNNING: true
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: 1.90.0
      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          # TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
          version: "23.x"
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - name: Start container for otel-collector and prometheus
        uses: hoverkraft-tech/compose-action@v2.0.1
        with:
          compose-file: ./etc/docker/docker-compose-ci.yaml
      - uses: Swatinem/rust-cache@v2
      - run: cargo integ-test docker_

  c-bridge-static-link-test:
    name: "C bridge static link test"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: 1.90.0
      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          # TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
          version: "23.x"
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Build crate as static library
        run: cargo rustc --package temporalio-sdk-core-c-bridge --features xz2-static -- --crate-type=staticlib

      - name: Build C test program
        run: gcc -I./crates/sdk-core-c-bridge/include crates/sdk-core/tests/c_bridge_smoke_test.c target/debug/deps/libtemporalio_sdk_core_c_bridge.a -lpthread -ldl -lm -o test

      - name: Run C test program
        run: ./test
