name: Release new version

on:
  workflow_dispatch:
    inputs:
      bumpLevel:
        description: "Bump level"
        default: "patch"
        type: choice
        options:
          - patch
          - minor
          - major
      profile:
        description: "Cargo profile"
        default: "release"
        type: choice
        options:
          - dev
          - release
          - test
          - bench
      enabledLintTests:
        description: "Execute lint tests"
        type: boolean
        default: true
      enabledIntegrationTests:
        description: "Execute integration tests"
        type: boolean
        default: true
      enabledBenchmarking:
        description: "Execute benchmarks"
        type: boolean
      enabledDeploymentDryRun:
        description: "Deploy in dry run mode"
        type: boolean
        default: true

env:
  RUSTFLAGS: "-Dwarnings"

permissions:
  contents: write

jobs:
  announce:
    name: Report
    runs-on: ubuntu-latest
    steps:
      - name: Print metadata
        run: |
          echo "Bump level: $BUMP_LEVEL"
          echo "Profile: $PROFILE"
          echo "Integration tests: $INTEGRATION_TESTS"
          echo "Benchmarking: $BENCHMARKING"
          echo "Dry run: $DRY_RUN"
        env:
          BUMP_LEVEL: ${{ inputs.bumpLevel }}
          PROFILE: ${{ inputs.profile }}
          INTEGRATION_TESTS: ${{ inputs.enabledIntegrationTests }}
          BENCHMARKING: ${{ inputs.enabledBenchmarking }}
          DRY_RUN: ${{ inputs.enabledDeploymentDryRun }}

  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Generate artifacts
        run: cargo build --${{ inputs.profile }} --verbose
      - name: Archive artifacts
        uses: actions/upload-artifact@v4
        with:
          name: crate-artifacts
          path: ./target
          retention-days: 1

  formatting-test:
    name: Formatting test
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Check code formatting
        run: cargo fmt --check

  unit-test:
    name: Unit test
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run unit tests
        run: cargo test --release --lib

  integration-test:
    name: Integration test
    runs-on: ubuntu-latest
    needs: [build]
    if: ${{ inputs.enabledIntegrationTests }}
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run integration tests
        run: cargo test --release --test integration_tests

  lint-test:
    name: Lint test
    runs-on: ubuntu-latest
    needs: [build]
    if: ${{ inputs.enabledLintTests }}
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run lint tests
        run: cargo clippy --all-targets --all-features --release

  benchmark:
    name: Benchmarking
    runs-on: ubuntu-latest
    needs: [build]
    if: ${{ inputs.enabledBenchmarking }}
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run benchmarks
        run: cargo bench --profile release

  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    needs: [formatting-test, unit-test, integration-test, lint-test, benchmark]
    if: ${{ !cancelled() && !failure() && !inputs.enabledDeploymentDryRun }}
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Fetch production artifacts
        uses: actions/download-artifact@v4
        with:
          name: crate-artifacts
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Install cargo-release from crates.io
        uses: baptiste0928/cargo-install@v3
        with:
          crate: cargo-release
          version: "0.25.17"
      - name: Setup git
        run: |
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git config user.name "github-actions[bot]"
      - name: Trigger new deployment
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
        run: cargo release ${{ inputs.bumpLevel }} --execute --no-confirm --no-verify

  deploy-dryrun:
    name: Deploy dry run
    runs-on: ubuntu-latest
    needs: [formatting-test, unit-test, integration-test, lint-test, benchmark]
    if: ${{ !failure() && inputs.enabledDeploymentDryRun }}
    steps:
      - name: Checkout latest changes
        uses: actions/checkout@v4
      - name: Fetch production artifacts
        uses: actions/download-artifact@v4
        with:
          name: crate-artifacts
      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Install cargo-release from crates.io
        uses: baptiste0928/cargo-install@v3
        with:
          crate: cargo-release
          version: "0.25.17"
      - name: Trigger new deployment
        run: cargo release ${{ inputs.bumpLevel }} --no-confirm --no-verify

  cleanup:
    name: Cleanup
    runs-on: ubuntu-latest
    needs: [build, deploy, deploy-dryrun]
    if: ${{ always() }}
    steps:
      - name: Delete all archived artifacts
        uses: geekyeggo/delete-artifact@v5
        with:
          failOnError: false
          name: crate-artifacts
