# Copyright (c) 2024 Hemi Labs, Inc.
# Use of this source code is governed by the MIT License,
# which can be found in the LICENSE file.

# GitHub Actions workflow to create releases.
# Releases are published from tags matching "v*.*.*".
name: "Release"
on:
  push:
    tags: [ "v*.*.*" ]

concurrency:
  group: "release-${{ github.ref }}"
  cancel-in-progress: true

env:
  GO_VERSION: "1.23.x"
  PNPM_VERSION: "9.4.x"
  GO_LDFLAGS: >-
    -X 'github.com/hemilabs/heminetwork/version.Brand=Hemi Labs'
    -X github.com/hemilabs/heminetwork/version.PreRelease=

jobs:
  # Build and test
  test-go:
    name: "Test (Go)"
    uses: ./.github/workflows/go.yml

  # Prepare to release
  prepare:
    name: "Prepare"
    runs-on: "ubuntu-latest"
    permissions:
      contents: read
    outputs:
      version: "${{ steps.version.outputs.version }}"
      tag: "${{ steps.version.outputs.tag }}"
      version_type: "${{ steps.version.outputs.type }}"
    steps:
      - name: "Determine version type"
        id: version
        env:
          RAW_VERSION: "${{ github.ref_name }}"
        # This script determines the version type (stability), e.g.
        #  1.0.0 = stable, 1.1.0-rc.1 = unstable, 0.1.0 = unstable
        run: |
          VERSION=$(echo "$RAW_VERSION" | sed -e 's/^v//')
          TAG=$(echo "$RAW_VERSION" | sed -E 's/^([^v])/v\1/g')
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"
          echo "tag=$TAG" >> "$GITHUB_OUTPUT"

          TYPE=unstable
          if echo "$VERSION" | grep -Eq '^[1-9][0-9]*\.[0-9]+\.[0-9]+$'; then
            TYPE=stable
          fi
          echo "Detected that $TAG is $TYPE"
          echo "type=$TYPE" >> "$GITHUB_OUTPUT"

  # Publish NPM packages
  npm:
    name: "npm"
    runs-on: "ubuntu-latest"
    needs: [ "prepare" ]
    permissions:
      contents: read
    steps:
      - name: "Checkout repository"
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: "Setup Go ${{ env.GO_VERSION }}"
        uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
        with:
          go-version: "${{ env.GO_VERSION }}"
          cache: true
          check-latest: true

      - name: "Setup pnpm ${{ env.PNPM_VERSION }}"
        uses: pnpm/action-setup@0c17529a66aca453f9227af23103ed11469b1e47 # v4.0.0
        with:
          version: "${{ env.PNPM_VERSION }}"

      - name: "Setup Node"
        uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
        with:
          node-version-file: "web/.nvmrc"
          check-latest: true
          cache: "pnpm"
          cache-dependency-path: "web/**/pnpm-lock.yaml"
          registry-url: "https://registry.npmjs.org"

      - name: "Install dependencies"
        working-directory: "web/"
        run: pnpm install --frozen-lockfile

      - name: "Install Go dependencies"
        working-directory: "web/"
        run: make deps

      - name: "Set package.json versions"
        working-directory: "web/"
        env:
          VERSION: "${{ needs.prepare.outputs.version }}"
        run: |
          # Prints all package.json files
          PACKAGE_FILES=$(find . -path '**/node_modules' -prune -o -name 'package.json' -print)
          for file in $PACKAGE_FILES; do
            # Set "version" in package.json file to $VERSION.
            TMP_FILE="$(mktemp)"
            jq --arg v "$VERSION" '.version = $v' "$file" > "$TMP_FILE"
            mv "$TMP_FILE" "$file"
          done

        # TODO(joshuasing): Install and use binaryen
      - name: "Build @hemilabs/pop-miner WebAssembly binary"
        working-directory: "web/"
        run: make wasm

      - name: "Build @hemilabs/pop-miner package"
        working-directory: "web/"
        run: pnpm build:pop-miner

      - name: "Publish @hemilabs/pop-miner package"
        working-directory: "web/"
        run: pnpm publish packages/pop-miner --access public --no-git-checks
        env:
          NODE_AUTH_TOKEN: "${{ secrets.NPM_TOKEN }}"

  # Create GitHub Release
  release:
    name: "Release"
    runs-on: "ubuntu-latest"
    needs: [ "test-go" ]
    permissions:
      # Required to create GitHub releases.
      contents: write
      # Required for Sigstore cosign authentication.
      id-token: write
      # Required to publish to GitHub Container Registry.
      packages: write
    steps:
      - name: "Checkout repository"
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          fetch-depth: 0

      - name: "Setup Go ${{ env.GO_VERSION }}"
        uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
        with:
          go-version: "${{ env.GO_VERSION }}"
          cache: true
          check-latest: true

      - name: "Install cosign"
        uses: sigstore/cosign-installer@1aa8e0f2454b781fbf0fbf306a4c9533a0c57409 # v3.7.0

      - name: "Install Syft"
        uses: anchore/sbom-action/download-syft@1ca97d9028b51809cf6d3c934c3e160716e1b605 # v0.17.5

      - name: "Setup QEMU"
        uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0

      - name: "Setup Docker Buildx"
        uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1

      - name: "Login to DockerHub"
        uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
        with:
          username: "${{ secrets.DOCKERHUB_USERNAME }}"
          password: "${{ secrets.DOCKERHUB_TOKEN }}"

      - name: "Login to GitHub Container Registry"
        uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
        with:
          registry: "ghcr.io"
          username: "${{ github.repository_owner }}"
          password: "${{ secrets.GITHUB_TOKEN }}"

      - name: "Release"
        uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
        with:
          distribution: "goreleaser"
          version: "~> v2"
          args: "release --clean"
        env:
          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"