name: Publish release files for CD native and non-cd-native environments

on:
  release:
    types: [ created ]
  # When a release failed, and there is something you need to fix in this
  # YML file, you can manually re-run the job via this event to re-do the
  # release. (Simply re-run the job through GitHub UI won't work as it would use
  # the old YML file, which needs a fix.)
  workflow_dispatch:
    inputs:
      # The GitHub Action (softprops/action-gh-release) used in this pipeline
      # needs a tag, you specify it through this parameter.
      #
      # In the case described above, it should be an existing tag. E.g., the
      # release of v16.0.4 failed, you should specify "v16.0.4" here.
      existing_tag:
        description: "The tag of the failed release that you wanna re-run and fix"
        required: true
        type: string

permissions:
  contents: read

jobs:
  # Publish release files for CD native environments
  native_build:
    permissions:
      # Use to sign the release artifacts
      id-token: write
      # Used to upload release artifacts
      contents: write
      # Used to generate artifact attestations
      attestations: write
    strategy:
      fail-fast: false
      matrix:
        # Use the Ubuntu 22.04 image to link with a low version of glibc
        #
        # https://github.com/topgrade-rs/topgrade/issues/1095
        platform: [ ubuntu-22.04, macos-latest, macos-13, windows-latest ]
    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v5.0.0

      - name: Install needed components
        run: |
          rustup component add rustfmt
          rustup component add clippy

      - name: Install cargo-deb
        run: cargo install cargo-deb
        if: ${{ startsWith(matrix.platform, 'ubuntu-') }}
        shell: bash

      - name: Check format
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --all-targets --locked -- -D warnings

      - name: Run clippy (All features)
        run: cargo clippy --all-targets --locked --all-features -- -D warnings

      - name: Run tests
        run: cargo test

      - name: Build in Release profile with all features enabled
        run: cargo build --release --all-features

      - name: Determine tag name
        id: determine_tag_name
        shell: bash # Or it won't work on Windows
        run: |
          if [ -n "${{ github.event.release.tag_name }}" ]; then
            echo "tag_name=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
          else
            echo "tag_name=${{ github.event.inputs.existing_tag }}" >> $GITHUB_OUTPUT
          fi

      - name: Rename Release (Unix)
        run: |
          cargo install default-target
          mkdir -p assets
          FILENAME=topgrade-${{ steps.determine_tag_name.outputs.tag_name }}-$(default-target)
          mv target/release/topgrade assets
          cd assets
          tar --format=ustar -czf $FILENAME.tar.gz topgrade
          rm topgrade
          ls .
        if: ${{ matrix.platform != 'windows-latest' }}
        shell: bash

      - name: Build Debian-based system binary and create package
        # First remove the binary built by previous steps
        # because we don't want the auto-update feature,
        # then build the new binary without auto-updating.
        run: |
          rm -rf target/release
          cargo build --release
          cargo deb --no-build --no-strip
        if: ${{ startsWith(matrix.platform, 'ubuntu-') }}
        shell: bash

      - name: Move Debian-based system package
        run: |
          mkdir -p assets
          mv target/debian/*.deb assets
        if: ${{ startsWith(matrix.platform, 'ubuntu-') }}
        shell: bash

      - name: Rename Release (Windows)
        run: |
          cargo install default-target
          mkdir assets
          FILENAME=topgrade-${{steps.determine_tag_name.outputs.tag_name}}-$(default-target)
          mv target/release/topgrade.exe assets/topgrade.exe
          cd assets
          powershell Compress-Archive -Path * -Destination ${FILENAME}.zip
          rm topgrade.exe
          ls .
        if: ${{ matrix.platform == 'windows-latest' }}
        shell: bash


      - name: Release
        uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2
        with:
          tag_name: ${{ steps.determine_tag_name.outputs.tag_name }}
          files: assets/*

      - name: Generate artifact attestations
        uses: actions/attest-build-provenance@v2.4.0
        with:
          subject-path: assets/*

  # Publish release files for non-CD-native environments
  cross_build:
    permissions:
      # Use to sign the release artifacts
      id-token: write
      # Used to upload release artifacts
      contents: write
      # Used to generate artifact attestations
      attestations: write
    strategy:
      fail-fast: false
      matrix:
        target:
          [
            "aarch64-unknown-linux-gnu",
            "armv7-unknown-linux-gnueabihf",
            "x86_64-unknown-linux-musl",
            "aarch64-unknown-linux-musl",
            "x86_64-unknown-freebsd",
          ]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5.0.0

      - name: Install needed components
        run: |
          rustup component add rustfmt
          rustup component add clippy

      - name: Install cargo-deb cross compilation dependencies
        run: sudo apt-get install libc6-arm64-cross libgcc-s1-arm64-cross
        if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' }}
        shell: bash

      - name: Install cargo-deb cross compilation dependencies for armv7
        run: sudo apt-get install libc6-armhf-cross libgcc-s1-armhf-cross
        if: ${{ matrix.target == 'armv7-unknown-linux-gnueabihf' }}
        shell: bash

      - name: Install cargo-deb
        run: cargo install cargo-deb
        if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'armv7-unknown-linux-gnueabihf' }}
        shell: bash

      - name: install targets
        run: rustup target add ${{ matrix.target }}

      - name: install cross
        uses: taiki-e/install-action@f63c33fd96cc1e69a29bafd06541cf28588b43a4 # v2.58.21
        with:
          tool: cross@0.2.5

      - name: Check format
        run: cross fmt --all -- --check

      - name: Run clippy
        run: cross clippy --all-targets --locked --target ${{matrix.target}} -- -D warnings

      - name: Run clippy (All features)
        run: cross clippy  --locked --all-features --target ${{matrix.target}} -- -D warnings

      - name: Run tests
        run: cross test --target ${{matrix.target}}

      - name: Build in Release profile with all features enabled
        run: cross build --release --all-features --target ${{matrix.target}}

      - name: Determine tag name
        id: determine_tag_name
        shell: bash # Or it won't work on Windows
        run: |
          if [ -n "${{ github.event.release.tag_name }}" ]; then
            echo "tag_name=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
          else
            echo "tag_name=${{ github.event.inputs.existing_tag }}" >> $GITHUB_OUTPUT
          fi

      - name: Rename Release
        run: |
          mkdir -p assets
          FILENAME=topgrade-${{steps.determine_tag_name.outputs.tag_name}}-${{matrix.target}}
          mv target/${{matrix.target}}/release/topgrade assets
          cd assets
          tar --format=ustar -czf $FILENAME.tar.gz topgrade
          rm topgrade
          ls .

      - name: Build Debian-based system package without autoupdate feature
        # First remove the binary built by previous steps
        # because we don't want the auto-update feature,
        # then build the new binary without auto-updating.
        run: |
          rm -rf target/${{matrix.target}}
          cross build --release --target ${{matrix.target}}
          cargo deb --target=${{matrix.target}} --no-build --no-strip
        if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'armv7-unknown-linux-gnueabihf' }}
        shell: bash

      - name: Move Debian-based system package
        run: |
          mkdir -p assets
          mv target/${{matrix.target}}/debian/*.deb assets
        if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'armv7-unknown-linux-gnueabihf' }}
        shell: bash


      - name: Release
        uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2
        with:
          tag_name: ${{ steps.determine_tag_name.outputs.tag_name }}
          files: assets/*

      - name: Generate artifact attestations
        uses: actions/attest-build-provenance@v2.4.0
        with:
          subject-path: assets/*
