bzr 0.4.0

A CLI for Bugzilla, inspired by gh
Documentation
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

jobs:
  msrv:
    name: MSRV
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - name: Install libdbus-1-dev
        run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # 1.88.0
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
        with:
          key: msrv-1.88.0
      - run: cargo test --locked

  fmt:
    name: Format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
        with:
          components: rustfmt
      - run: cargo fmt --check

  test-layout:
    name: Test Layout
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - run: make check-test-layout

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - name: Install libdbus-1-dev
        run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
      - run: cargo clippy --locked -- -D warnings

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - name: Install libdbus-1-dev
        run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
      - run: cargo test --locked

  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - name: Install libdbus-1-dev
        run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
      - run: cargo build --release --locked

  manpages:
    name: Manpages
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
        with:
          key: manpages
      - name: Generate manpages
        run: cargo run -p xtask --no-default-features --release --locked -- man --out man/man1
      - name: Verify expected pages exist
        run: |
          set -euo pipefail
          test -s man/man1/bzr.1
          test -s man/man1/bzr-bug.1
          test -s man/man1/bzr-bug-list.1
          test -s man/man1/bzr-config-set-server.1
      - name: Render with groff (catches malformed roff)
        run: |
          set -euo pipefail
          sudo apt-get update && sudo apt-get install -y groff
          for page in man/man1/*.1; do
            groff -man -Tutf8 "$page" > /dev/null
          done

  cross-check:
    name: Cross-check ${{ matrix.target }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target:
          - aarch64-unknown-linux-gnu
          - powerpc64le-unknown-linux-gnu
          - s390x-unknown-linux-gnu
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
        with:
          key: ${{ matrix.target }}
      - name: Install cross
        run: cargo install cross --locked
      - name: Check
        env:
          PKG_CONFIG_ALLOW_CROSS: "1"
        run: cross check --locked --target ${{ matrix.target }}

  windows-cross-check:
    name: Cross-check aarch64-pc-windows-msvc
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
        with:
          targets: aarch64-pc-windows-msvc
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
        with:
          key: aarch64-pc-windows-msvc
      - name: Check
        run: cargo check --locked --target aarch64-pc-windows-msvc
  sonarqube:
    name: SonarQube
    # Skip on forked PRs and Dependabot PRs (neither has access to SONAR_TOKEN).
    # Clippy (above) provides unconditional SAST coverage on all PRs including
    # Dependabot, satisfying OpenSSF Scorecard's SAST check.
    if: |
      (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false)
      && github.actor != 'dependabot[bot]'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          fetch-depth: 0  # Shallow clones should be disabled for a better relevancy of analysis
      - name: Install libdbus-1-dev
        run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config
      - uses: dtolnay/rust-toolchain@98e1b82157cd469e843cb7f524c1313b4ad9492c  # stable
        with:
          components: llvm-tools-preview
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2
        with:
          key: sonarqube
      - uses: taiki-e/install-action@49ba71bf46962339e6e5c0a7a4ec3ed4c8af28ac  # cargo-llvm-cov
      - name: Generate coverage report
        run: cargo llvm-cov --locked --workspace --all-features --lcov --output-path lcov.info
      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@59db25f34e16620e48ab4bb9e4a5dce155cb5432  # v8.0.0
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

  installer-lint:
    name: Lint installer scripts
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6

      - name: Install shellcheck and shfmt
        run: |
          sudo apt-get update
          sudo apt-get install -y shellcheck
          curl -fsSL https://github.com/mvdan/sh/releases/download/v3.7.0/shfmt_v3.7.0_linux_amd64 -o /tmp/shfmt
          sudo install -m 0755 /tmp/shfmt /usr/local/bin/shfmt

      - name: Run shellcheck
        run: shellcheck -s sh install.sh tests/installer/smoke.sh

      - name: Run shfmt (check only)
        run: shfmt -d -ln posix -i 2 install.sh tests/installer/smoke.sh

      - name: Run PSScriptAnalyzer
        shell: pwsh
        run: |
          Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
          $diagnostics = @()
          $diagnostics += Invoke-ScriptAnalyzer -Path install.ps1 -Severity Warning
          $diagnostics += Invoke-ScriptAnalyzer -Path tests/installer/smoke.ps1 -Severity Warning
          if ($diagnostics) {
            $diagnostics | Format-Table
            exit 1
          }

  installer-test:
    name: Smoke ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-14, windows-latest]
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6

      - name: Smoke (bash)
        if: matrix.os != 'windows-latest'
        run: sh tests/installer/smoke.sh

      - name: Smoke (powershell)
        if: matrix.os == 'windows-latest'
        shell: pwsh
        run: ./tests/installer/smoke.ps1