name: Export source archive

on:
  workflow_dispatch:
    inputs:
      ref:
        description: Branch, tag, or commit to archive
        required: true
        default: dev
        type: string
      publish_release:
        description: Publish the tar.gz as a directly downloadable GitHub Release asset
        required: true
        default: true
        type: boolean

permissions:
  contents: write

jobs:
  export-source:
    name: Create source tar.gz
    runs-on: ubuntu-latest

    steps:
      - name: Check out requested revision
        uses: actions/checkout@v7
        with:
          ref: ${{ inputs.ref }}
          fetch-depth: 1
          persist-credentials: false

      - name: Create source archive
        id: archive
        shell: bash
        run: |
          set -euo pipefail

          commit="$(git rev-parse HEAD)"
          short_sha="$(git rev-parse --short=12 HEAD)"
          safe_ref="$(printf '%s' '${{ inputs.ref }}' | sed -E 's/[^A-Za-z0-9._-]+/-/g; s/^-+//; s/-+$//')"

          if [[ -z "$safe_ref" ]]; then
            safe_ref="source"
          fi

          base_name="purrfect-${safe_ref}-${short_sha}"
          archive_path="${RUNNER_TEMP}/${base_name}.tar.gz"

          # git archive includes tracked source files and omits .git metadata.
          git archive \
            --format=tar \
            --prefix="${base_name}/" \
            HEAD | gzip -9 > "$archive_path"

          sha256sum "$archive_path" > "${archive_path}.sha256"

          echo "archive_path=$archive_path" >> "$GITHUB_OUTPUT"
          echo "archive_name=${base_name}.tar.gz" >> "$GITHUB_OUTPUT"
          echo "commit=$commit" >> "$GITHUB_OUTPUT"
          echo "short_sha=$short_sha" >> "$GITHUB_OUTPUT"
          echo "safe_ref=$safe_ref" >> "$GITHUB_OUTPUT"

      - name: Upload workflow artifact
        uses: actions/upload-artifact@v7
        with:
          name: purrfect-source-${{ steps.archive.outputs.short_sha }}
          path: |
            ${{ steps.archive.outputs.archive_path }}
            ${{ steps.archive.outputs.archive_path }}.sha256
          if-no-files-found: error
          compression-level: 0
          retention-days: 30

      - name: Publish direct-download release asset
        if: ${{ inputs.publish_release }}
        env:
          GH_TOKEN: ${{ github.token }}
          GH_REPO: ${{ github.repository }}
          ARCHIVE_PATH: ${{ steps.archive.outputs.archive_path }}
          ARCHIVE_NAME: ${{ steps.archive.outputs.archive_name }}
          COMMIT: ${{ steps.archive.outputs.commit }}
          SHORT_SHA: ${{ steps.archive.outputs.short_sha }}
          REQUESTED_REF: ${{ inputs.ref }}
        shell: bash
        run: |
          set -euo pipefail

          tag="source-${SHORT_SHA}"
          checksum_path="${ARCHIVE_PATH}.sha256"

          if gh release view "$tag" >/dev/null 2>&1; then
            gh release upload "$tag" \
              "$ARCHIVE_PATH" \
              "$checksum_path" \
              --clobber
          else
            gh release create "$tag" \
              "$ARCHIVE_PATH" \
              "$checksum_path" \
              --target "$COMMIT" \
              --title "Purrfect source ${SHORT_SHA}" \
              --notes "Source archive generated from ref \`${REQUESTED_REF}\` at commit \`${COMMIT}\`."
          fi

          release_url="$(gh release view "$tag" --json url --jq '.url')"
          {
            echo "## Source archive"
            echo
            echo "- File: \`${ARCHIVE_NAME}\`"
            echo "- Commit: \`${COMMIT}\`"
            echo "- Release: ${release_url}"
          } >> "$GITHUB_STEP_SUMMARY"
