name: release

on:
  workflow_dispatch:
    inputs:
      tag:
        description: "Git tag (leave empty for dry run)"
        required: false
      latest:
        description: "Release as latest?"
        required: true
        type: boolean
      prerelease:
        description: "Release as prerelease?"
        required: true
        type: boolean

jobs:
  release:
    name: Release
    runs-on: larger-runners
    environment: gpg
    permissions:
      contents: write
      id-token: write
      packages: write

    steps:
      - name: Set up QEMU cross build support
        uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0

      - name: Login to Github Container Registry
        uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
        if: startsWith(inputs.tag, 'v')
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Checkout
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          fetch-depth: 0
          ref: ${{ inputs.tag }}

      - name: Fetch tags
        run: git fetch --force --tags

      - name: Compare versions
        if: startsWith(inputs.tag, 'v')
        run: ./.github/scripts/compare-release-version.sh
        env:
          TARGET_VERSION: ${{inputs.tag}}

      - name: Check if tag is on main branch or version branch
        id: validate_tag
        env:
          INPUT_TAG: ${{ inputs.tag }}
        run: |
          IS_TAG_ON_MAIN=$(git branch -a --contains "$INPUT_TAG" | grep -q "main" && echo true || echo false)
          IS_TAG_ON_VERSION=$(git branch -a --contains "$INPUT_TAG" | grep -E "^v[0-9]+\.[0-9]+" && echo true || echo false)
          echo "IS_TAG_ON_MAIN=${IS_TAG_ON_MAIN}" >> $GITHUB_OUTPUT
          echo "IS_TAG_ON_VERSION=${IS_TAG_ON_VERSION}" >> $GITHUB_OUTPUT

      - name: Check if release is allowed or not
        id: validate_release
        env:
          IS_PRERELEASE: ${{ inputs.prerelease }}
          IS_TAG_ON_MAIN: ${{ steps.validate_tag.outputs.IS_TAG_ON_MAIN }}
        run: |
          if [[ "$IS_PRERELEASE" == "false" && "$IS_TAG_ON_MAIN" == "true" ]]; then
            echo "ERROR: Creating stable release from a tag on main is not allowed."
            exit 1
          fi

      - name: Set up Go
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version-file: 'go.mod'

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0

      - name: Install cosign
        uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
        with:
          cosign-release: v2.2.0

      - name: Setup snapcraft
        run: |
          sudo snap install snapcraft --classic --channel=7.x/stable

          # See https://github.com/goreleaser/goreleaser/issues/1715
          mkdir -p "$HOME/.cache/snapcraft/download"
          mkdir -p "$HOME/.cache/snapcraft/stage-packages"
        env:
          SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_TOKEN }}

      - name: Import GPG key
        if: startsWith(inputs.tag, 'v')
        run: |
          GPG_KEY_FILE=/tmp/signing-key.gpg
          echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode > "${GPG_KEY_FILE}"
          
          echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --import
          GPG_FINGERPRINT=$(gpg --list-secret-keys --keyid-format LONG | awk '/^sec/{sub(/.*\//, "", $2); print $2; exit}')
          
          echo "GPG_FINGERPRINT=${GPG_FINGERPRINT}" >>"${GITHUB_ENV}"
          echo "GPG_KEY_FILE=${GPG_KEY_FILE}" >> "${GITHUB_ENV}"
        env:
          GPG_TTY: /dev/ttys000  # Set the GPG_TTY to avoid issues with pinentry

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811 # v5.1.0
        with:
          version: v1.21.2
          distribution: goreleaser-pro
          args: release --clean --timeout=60m --snapshot=${{ !startsWith(inputs.tag, 'v') }}
        env:
          # Note: the GPG_FINGERPRINT and GPG_KEY_FILE are defined in the task above. If they are not set,
          # goreleaser won't sign the packages.
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
          SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_TOKEN }}
          RELEASE_FLAG_LATEST: ${{ inputs.latest }}
          RELEASE_FLAG_PRERELEASE: ${{ inputs.prerelease }}

      - name: Remove GPG key
        if: always()
        run: |
          rm -rf ~/.gnupg
          if [ -n "${GPG_KEY_FILE}" ]; then
            rm -rf "${GPG_KEY_FILE}"
          fi

      - name: Upload artifacts
        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
        with:
          name: dist
          path: dist

      - name: Upload Debian packages to PackageCloud
        if: startsWith(inputs.tag, 'v') && ! inputs.prerelease
        uses: computology/packagecloud-github-action@3a3116159414e57767827ed264a6de29a1f86d4c # v0.6
        with:
                PACKAGE-NAME: dist/*.deb
                PACKAGECLOUD-USERNAME: opentofu
                PACKAGECLOUD-REPONAME: tofu
                PACKAGECLOUD-DISTRO: any/any
                PACKAGECLOUD-TOKEN: ${{ secrets.PACKAGECLOUD_TOKEN }}
      - name: Upload RPM packages to PackageCloud
        if: startsWith(inputs.tag, 'v') && ! inputs.prerelease
        uses: computology/packagecloud-github-action@3a3116159414e57767827ed264a6de29a1f86d4c # v0.6
        with:
                PACKAGE-NAME: dist/*.rpm
                PACKAGECLOUD-USERNAME: opentofu
                PACKAGECLOUD-REPONAME: tofu
                PACKAGECLOUD-DISTRO: rpm_any/rpm_any
                PACKAGECLOUD-TOKEN: ${{ secrets.PACKAGECLOUD_TOKEN }}
