name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  # Release asset/label names embed the version (such as
  # kermit-linux-amd64-11.0), derived from the pushed tag by stripping
  # its leading "v" (tags are always "v*", see the push trigger above).
  # Computed once here since it is a run step's output, not something
  # that can be inlined directly into the matrix definitions below.
  version:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
    steps:
      - name: Derive version from tag
        id: version
        run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

  build-and-test:
    needs: version
    uses: ./.github/workflows/ci.yml
    with:
      upload-artifact: true
      version: ${{ needs.version.outputs.version }}

      # Release builds cover more platforms than the fast PR/push matrix
      # in ci.yml.  We build a full set of Linux binaries (dynamic and
      # static on amd64 and arm64), plus MacOS.  (BSDs are handled
      # elsewhere).  Every binary we release gets tested: the release
      # process is infrequent enough that the extra CI time is worth
      # it, so none of these set skip-tests (the fast PR/push matrix
      # in ci.yml is what stays single-platform for speed, not this
      # one).

      # The "static" binaries are built with linux+ssl+musl, not
      # linux+ssl+static, since  a musl-gcc static binary has no runtime
      # dependency on the exact glibc build used to link it. They set
      # skip-c-tests since we're not making a libcheck musl build.

      matrix: >-
        [
        {"os":"ubuntu-24.04","platform":"linux","arch":"amd64","make-target":"linux+ssl","label":"kermit-linux-amd64-${{ needs.version.outputs.version }}"},
        {"os":"ubuntu-24.04-arm","platform":"linux","arch":"arm64","make-target":"linux+ssl","label":"kermit-linux-arm64-${{ needs.version.outputs.version }}"},
        {"os":"ubuntu-24.04","platform":"linux","arch":"amd64","make-target":"linux+ssl+musl","label":"kermit-linux-amd64-static-${{ needs.version.outputs.version }}","skip-c-tests":true},
        {"os":"ubuntu-24.04-arm","platform":"linux","arch":"arm64","make-target":"linux+ssl+musl","label":"kermit-linux-arm64-static-${{ needs.version.outputs.version }}","skip-c-tests":true},
        {"os":"macos-latest","platform":"macos","arch":"arm64","make-target":"macos+ssl","label":"kermit-macos-arm64-${{ needs.version.outputs.version }}"}
        ]

  release:
    needs: [version, build-and-test]
    runs-on: ubuntu-latest
    # softprops/action-gh-release races itself when multiple matrix
    # legs create a release for the same tag at once: each leg sees no
    # release yet, so more than one tries to create it, and the
    # losers fail with "already_exists" on tag_name. This concurrency
    # group forces the legs to run one at a time
    # so only the first leg creates the release and the
    # rest just append their asset to it.
    concurrency:
      group: gh-release-${{ needs.version.outputs.version }}
      cancel-in-progress: false
    strategy:
      matrix:
        # Must match the labels in the build-and-test matrix above, plus
        # the freebsd-x86_64/netbsd-x86_64/openbsd-x86_64 jobs in ci.yml
        # (which aren't part of that JSON matrix, but upload artifacts
        # under these labels too when upload-artifact is true).
        include:
          - label: kermit-linux-amd64-${{ needs.version.outputs.version }}
          - label: kermit-linux-arm64-${{ needs.version.outputs.version }}
          - label: kermit-linux-amd64-static-${{ needs.version.outputs.version }}
          - label: kermit-linux-arm64-static-${{ needs.version.outputs.version }}
          - label: kermit-macos-arm64-${{ needs.version.outputs.version }}
          - label: kermit-freebsd-amd64-${{ needs.version.outputs.version }}
          - label: kermit-netbsd-amd64-${{ needs.version.outputs.version }}
          - label: kermit-openbsd-amd64-${{ needs.version.outputs.version }}
    steps:
      - uses: actions/checkout@v4

      - name: Download binaries
        uses: actions/download-artifact@v4
        with:
          name: ${{ matrix.label }}

      - name: Package
        run: |
          chmod +x kermit
          mkdir c${{ matrix.label }}
          mv kermit README.md COPYING.TXT ckermit.ini \
            c${{ matrix.label }}/
          tar czf \
            c${{ matrix.label }}.tar.gz \
            c${{ matrix.label }}

      - name: Upload release asset
        uses: softprops/action-gh-release@v2
        with:
          files: >-
            c${{ matrix.label }}.tar.gz
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # Runs once all binary release assets are uploaded ("needs: release"
  # waits for every release leg), so it can pull them straight
  # back down from the release instead of re-packaging anything
  # itself. Also covers GitHub's own auto-generated source archives,
  # fetched from their tag-keyed archive URL rather than regenerated
  # locally with git archive, since the two are not guaranteed to be
  # byte-identical.
  checksums:
    needs: [version, release]
    runs-on: ubuntu-latest
    steps:
      - name: Download binary release assets
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release download ${{ github.ref_name }} \
            --repo ${{ github.repository }} \
            --pattern 'ckermit-*.tar.gz' --dir dl

      - name: Download source archives
        run: |
          base="https://github.com/${{ github.repository }}"
          base="$base/archive/refs/tags/${{ github.ref_name }}"
          version="${{ needs.version.outputs.version }}"
          curl -sSfL -o "dl/ckermit-$version.tar.gz" \
            "$base.tar.gz"
          curl -sSfL -o "dl/ckermit-$version.zip" \
            "$base.zip"

      - name: Generate SHA256SUMS
        run: (cd dl && sha256sum *) > SHA256SUMS

      - name: Upload SHA256SUMS
        uses: softprops/action-gh-release@v2
        with:
          files: SHA256SUMS
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
