mqi 0.3.0

Idiomatic IBM® MQ Interface (MQI) and MQ Administration Interface (MQAI) APIs
Documentation
name: Continuous Integration

on:
  workflow_dispatch:
  push:
    branches:
      - develop
  pull_request:
    branches:
      - develop
  schedule: [cron: "40 4 * * 5"]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  CARGO_TERM_COLOR: always

permissions: {}

jobs:
  client_check:
    strategy:
      fail-fast: false
      matrix:
        version:
          - client-version: 9.2
            feature: mqc_9_2_0_0
          - client-version: 9.3
            feature: mqc_9_3_5_0
          - client-version: 9.4
            feature: mqc_9_4_3_0
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: advantic-au/action-mq-client@stable
        id: mq-client
        with:
          client-version: ${{ matrix.version.client-version }}
      - name: Install stable
        uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
        with:
          shared-key: "build"
      - name: Check
        run: cargo check --features ${{ matrix.version.feature }},exits,mqai,dlopen2
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}

  test_server:
    name: "MQ server integration test"
    needs: test
    runs-on: ubuntu-24.04
    services:
      mq:
        image: icr.io/ibm-messaging/mq:9.4.3.0-r1
        env:
          MQ_ENABLE_EMBEDDED_WEB_SERVER: false
          LICENSE: accept
          MQ_APP_PASSWORD: app
        ports:
          - 1414:1414
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: advantic-au/action-mq-client@stable
        id: mq-client
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: stable
      - uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3 # v2.56.13
        with:
          tool: nextest
      - name: Test
        run: cargo nextest run --profile ci --no-default-features --features link,mqai,exits,mqc_latest
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}
          MQSERVER: DEV.APP.SVRCONN/TCP/localhost(1414)
          MQ_USER: app
          MQ_PASSWORD: app

  test:
    name: "test (${{ matrix.toolchain }}, ${{ matrix.os }})"
    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - stable
          - nightly
        os: [ubuntu-24.04]
        include:
          - toolchain: stable
            os: ubuntu-24.04-arm
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: advantic-au/action-mq-client@stable
        id: mq-client
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: ${{matrix.toolchain}}
      - name: Enable type layout randomization
        run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV
        if: matrix.toolchain == 'nightly'
      - uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3 # v2.56.13
        with:
          tool: nextest
      - name: Test all features
        run: |
          cargo nextest run --profile ci --all-features
          cargo test --all-features --doc
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}
      - name: Test default features
        run: |
          cargo nextest run --profile ci --features mock
          cargo test --doc
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}
      - name: Test no default features
        run: |
          cargo nextest run --profile ci --no-default-features --features mock
          cargo test --no-default-features --doc
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}

  miri:
    strategy:
      fail-fast: false
      matrix:
        target:
          - s390x-unknown-linux-gnu
          - x86_64-unknown-linux-gnu
    runs-on: ubuntu-24.04
    needs: test
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: nightly
          components: miri, rust-src
      - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
        with:
          shared-key: "build"
      - uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3 # v2.56.13
        with:
          tool: nextest
      - name: Execute miri tests
        env:
          MIRIFLAGS: -Zmiri-strict-provenance -Zmiri-env-forward=PROPTEST_DISABLE_FAILURE_PERSISTENCE -Zmiri-env-forward=PROPTEST_CASES
          PROPTEST_CASES: 64
          PROPTEST_DISABLE_FAILURE_PERSISTENCE: true
        run: cargo miri nextest run --profile ci --no-default-features --features mock,mqai,exits,mqc_latest --target ${{ matrix.target }}

  incremental_mutants:
    runs-on: ubuntu-24.04
    needs: test
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
          fetch-depth: 0
      - uses: advantic-au/action-mq-client@stable
        id: mq-client
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: stable
      - name: Relative diff
        run: |
          git branch -av
          git diff origin/"${GITHUB_BASE_REF}".. > git.diff
        env:
          GITHUB_BASE_REF: ${{ github.base_ref }}
      - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
      - uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3 # v2.56.13
        with:
          tool: cargo-mutants
      - name: Mutant testing
        run: |
          cargo mutants --no-shuffle -vV --in-diff git.diff --all-features
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}
        continue-on-error: true
      - name: Artefact mutants-incremental.out
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: mutants-incremental.out
          path: mutants.out

  rustfmt:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Install stable
        uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: stable
          components: rustfmt
      - name: Lint with rustfmt
        run: cargo fmt -- --check

  clippy:
    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - stable
          - beta
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: advantic-au/action-mq-client@stable
        id: mq-client
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: ${{ matrix.toolchain }}
          components: clippy
      - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
        with:
          shared-key: "build"
      - name: Run clippy
        run: |
          set -x
          cargo clippy --tests --examples --all-features --
          cargo clippy --tests --examples --
          cargo clippy --tests --examples --no-default-features --features mock,exits,link --
          cargo clippy --tests --examples --no-default-features --features mock,mqai,link --
          cargo clippy --tests --examples --no-default-features --features mock,mqai,exits,dlopen2 --
          cargo clippy --tests --examples --no-default-features --features mock,link --
        env:
          RUSTFLAGS: -Dwarnings
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}

  minimum:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: advantic-au/action-mq-client@stable
        id: mq-client
      # Re-resolve Cargo.lock with minimal versions
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: nightly # -Z option only available on nightly
      - run: cargo generate-lockfile -Z minimal-versions
      # Now verify that `cargo check` works with respect to the oldest possible
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: 1.87
      - run: cargo check --locked --all-features
        env:
          RUSTFLAGS: -Dwarnings
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}
      - uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3 # v2.56.13
        with:
          tool: nextest
      - run: |
          cargo nextest run --profile ci --locked --all-features
          cargo test --locked --all-features --doc
        env:
          MQ_HOME: ${{ steps.mq-client.outputs.client-install-path }}
  docs:
    runs-on: ubuntu-24.04
    env:
      RUSTDOCFLAGS: -Dwarnings
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
        with:
          toolchain: nightly
      - uses: taiki-e/install-action@c07504cae06f832dc8de08911c9a9c5cddb0d2d3 # v2.56.13
        with:
          tool: cargo-docs-rs
      - run: cargo docs-rs

  clippy_outcome:
    if: ${{ always() }}
    runs-on: ubuntu-24.04
    name: Clippy outcome
    needs: [clippy]
    steps:
      - run: |
          result="${NEEDS_RESULT}"
          if [[ $result == "success" || $result == "skipped" ]]; then
            exit 0
          else
            exit 1
          fi
        env:
          NEEDS_RESULT: ${{ needs.clippy.result }}

  miri_outcome:
    if: ${{ always() }}
    runs-on: ubuntu-24.04
    name: Miri outcome
    needs: [miri]
    steps:
      - run: |
          result="${NEEDS_RESULT}"
          if [[ $result == "success" || $result == "skipped" ]]; then
            exit 0
          else
            exit 1
          fi
        env:
          NEEDS_RESULT: ${{ needs.miri.result }}

  test_outcome:
    if: ${{ always() }}
    runs-on: ubuntu-24.04
    name: Test outcome
    needs: [test]
    steps:
      - run: |
          result="${NEEDS_RESULT}"
          if [[ $result == "success" || $result == "skipped" ]]; then
            exit 0
          else
            exit 1
          fi
        env:
          NEEDS_RESULT: ${{ needs.test.result }}