name: Release

on:
  push:
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+'
      - 'v[0-9]+.[0-9]+.[0-9]+-*'

permissions:
  contents: write
  actions: read
  id-token: write

jobs:
  # ===========================================================================
  # Build C API binary packages for Linux x86_64 and aarch64
  # ===========================================================================
  build-c-api:
    name: Build C API (${{ matrix.arch }})
    runs-on: ${{ matrix.runner }}
    strategy:
      matrix:
        include:
          - arch: x86_64
            runner: ubuntu-22.04
          - arch: aarch64
            runner: ubuntu-22.04-arm
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

      - name: Install Rust toolchain
        run: rustup toolchain install stable --profile minimal

      - name: Build release
        run: cargo build --release

      - name: Extract version from tag
        id: version
        run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Package C API
        run: |
          VERSION=${{ steps.version.outputs.version }}
          MAJOR=$(echo "$VERSION" | cut -d. -f1)
          MINOR=$(echo "$VERSION" | cut -d. -f2)
          PATCH=$(echo "$VERSION" | cut -d. -f3)
          PKG_NAME="edgefirst-schemas-linux_${{ matrix.arch }}-${VERSION}"
          mkdir -p "${PKG_NAME}/lib/pkgconfig" "${PKG_NAME}/include/edgefirst"
          cp README.md LICENSE "${PKG_NAME}/"
          cp include/edgefirst/schemas.h "${PKG_NAME}/include/edgefirst/"

          # Versioned shared library with symlinks (GNU/Linux convention)
          cp target/release/libedgefirst_schemas.so "${PKG_NAME}/lib/libedgefirst_schemas.so.${MAJOR}.${MINOR}.${PATCH}"
          ln -s "libedgefirst_schemas.so.${MAJOR}.${MINOR}.${PATCH}" "${PKG_NAME}/lib/libedgefirst_schemas.so.${MAJOR}.${MINOR}"
          ln -s "libedgefirst_schemas.so.${MAJOR}.${MINOR}.${PATCH}" "${PKG_NAME}/lib/libedgefirst_schemas.so.${MAJOR}"
          ln -s "libedgefirst_schemas.so.${MAJOR}.${MINOR}.${PATCH}" "${PKG_NAME}/lib/libedgefirst_schemas.so"

          cp target/release/libedgefirst_schemas.a "${PKG_NAME}/lib/"
          sed "s/@VERSION@/${VERSION}/" \
            edgefirst-schemas.pc.in > "${PKG_NAME}/lib/pkgconfig/edgefirst-schemas.pc"
          zip -r --symlinks "${PKG_NAME}.zip" "${PKG_NAME}"

      - name: Upload C API artifact
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: c-api-${{ matrix.arch }}
          path: edgefirst-schemas-linux_${{ matrix.arch }}-${{ steps.version.outputs.version }}.zip

  # ===========================================================================
  # Collect Debian packages from ROS workflow
  # ===========================================================================
  collect-debian:
    name: Collect Debian Packages
    runs-on: ubuntu-latest
    steps:
      - name: Wait for ROS workflow
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          echo "Waiting for ROS workflow on commit ${GITHUB_SHA}..."
          for i in $(seq 1 30); do
            RUN_ID=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow ros.yml \
              --commit "$GITHUB_SHA" --json databaseId --jq '.[0].databaseId')
            if [ -n "$RUN_ID" ]; then
              break
            fi
            echo "  Attempt $i/30 — ROS workflow not found yet, retrying in 10s..."
            sleep 10
          done

          if [ -z "$RUN_ID" ]; then
            echo "::error::ROS workflow run not found for commit ${GITHUB_SHA}"
            exit 1
          fi

          echo "Found ROS workflow run: ${RUN_ID}"
          gh run watch "$RUN_ID" --repo "$GITHUB_REPOSITORY" --exit-status

      - name: Download Debian packages
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          RUN_ID=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow ros.yml \
            --commit "$GITHUB_SHA" --json databaseId --jq '.[0].databaseId')
          gh run download "$RUN_ID" --repo "$GITHUB_REPOSITORY" \
            --pattern 'ros-*-edgefirst-msgs_*' --dir packages
          find packages -name '*.deb' -exec mv {} . \;
          echo "Downloaded Debian packages:"
          ls -lh *.deb

      - name: Upload Debian artifacts
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: debian-packages
          path: "*.deb"

  # ===========================================================================
  # Create GitHub Release (waits for all artifacts, publishes in one shot)
  # ===========================================================================
  create-release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: [build-c-api, collect-debian]
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
        with:
          fetch-depth: 0

      - name: Extract version from tag
        id: version
        run: |
          VERSION=${GITHUB_REF#refs/tags/}
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Version: $VERSION"

      - name: Extract changelog for version
        run: |
          # Strip 'v' prefix — CHANGELOG.md uses bare version numbers
          VERSION="${{ steps.version.outputs.version }}"
          BARE_VERSION="${VERSION#v}"

          # Extract the section for this version from CHANGELOG.md
          CHANGELOG_CONTENT=$(awk "/## \[$BARE_VERSION\]/,/## \[/" CHANGELOG.md | sed '$d' | tail -n +2)

          if [ -z "$CHANGELOG_CONTENT" ]; then
            CHANGELOG_CONTENT="Release $VERSION"
          fi

          echo "$CHANGELOG_CONTENT" > release_notes.md

      - name: Generate SBOM
        run: |
          bash .github/scripts/generate_sbom.sh || echo "SBOM generation skipped"

      - name: Download all artifacts
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
        with:
          path: release-assets

      - name: Collect release files
        run: |
          mkdir -p release-files
          find release-assets -type f \( -name '*.zip' -o -name '*.deb' \) -exec mv {} release-files/ \;
          [ -f sbom.json ] && cp sbom.json release-files/
          echo "Release files:"
          ls -lh release-files/

      - name: Create GitHub Release
        uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
        with:
          name: ${{ steps.version.outputs.version }}
          body_path: release_notes.md
          draft: false
          prerelease: ${{ contains(steps.version.outputs.version, '-') }}
          files: release-files/*
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # ===========================================================================
  # Publish to crates.io
  # ===========================================================================
  publish-crates:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

      - name: Install Rust toolchain
        run: rustup toolchain install stable --profile minimal

      - name: Install cargo-workspaces
        uses: taiki-e/install-action@0bc4cd8a3e21db4cb9519857377b0c8c5e150de5 # v2.67.2
        with:
          tool: cargo-workspaces

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo workspaces publish --from-git

  # ===========================================================================
  # Publish to PyPI
  # ===========================================================================
  publish-pypi:
    name: Publish to PyPI
    runs-on: ubuntu-latest
    environment: pypi
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
        with:
          fetch-depth: 0

      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: '3.10'

      - name: Build package
        run: |
          python -m pip install build
          python -m build

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
