# This workflow is modified from Lighthouse:
# https://github.com/sigp/lighthouse/blob/441fc1691b69f9edc4bbdc6665f3efab16265c9b/.github/workflows/release.yml

name: release

on:
  push:
    tags:
      - v*

env:
  REPO_NAME: ${{ github.repository_owner }}/reth
  OP_IMAGE_NAME: ${{ github.repository_owner }}/op-reth
  IMAGE_NAME: ${{ github.repository_owner }}/reth
  CARGO_TERM_COLOR: always
  DOCKER_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/reth
  DOCKER_REPRODUCIBLE_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/reth-reproducible

jobs:
  extract-version:
    name: extract version
    runs-on: ubuntu-latest
    steps:
      - name: Extract version
        run: echo "VERSION=$(echo ${GITHUB_REF#refs/tags/})" >> $GITHUB_OUTPUT
        id: extract_version
    outputs:
      VERSION: ${{ steps.extract_version.outputs.VERSION }}

  build:
    name: build release
    runs-on: ${{ matrix.configs.os }}
    needs: extract-version
    strategy:
      matrix:
        configs:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-20.04
            profile: maxperf
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-20.04
            profile: maxperf
          - target: x86_64-apple-darwin
            os: macos-13
            profile: maxperf
          - target: aarch64-apple-darwin
            os: macos-14
            profile: maxperf
          - target: x86_64-pc-windows-gnu
            os: ubuntu-20.04
            profile: maxperf
        build:
          - command: build
            binary: reth
          - command: op-build
            binary: op-reth
    steps:
      - uses: actions/checkout@v4
      - uses: rui314/setup-mold@v1
      - uses: dtolnay/rust-toolchain@stable
        with:
          target: ${{ matrix.configs.target }}
      - uses: taiki-e/install-action@cross
      - uses: Swatinem/rust-cache@v2
        with:
          cache-on-failure: true

      - name: Apple M1 setup
        if: matrix.configs.target == 'aarch64-apple-darwin'
        run: |
          echo "SDKROOT=$(xcrun -sdk macosx --show-sdk-path)" >> $GITHUB_ENV
          echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version)" >> $GITHUB_ENV

      - name: Build Reth
        run: make PROFILE=${{ matrix.configs.profile }} ${{ matrix.build.command }}-${{ matrix.configs.target }}
      - name: Move binary
        run: |
          mkdir artifacts
          [[ "${{ matrix.configs.target }}" == *windows* ]] && ext=".exe"
          mv "target/${{ matrix.configs.target }}/${{ matrix.configs.profile }}/${{ matrix.build.binary }}${ext}" ./artifacts

      - name: Configure GPG and create artifacts
        env:
          GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
          GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
        run: |
          export GPG_TTY=$(tty)
          echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --batch --import
          cd artifacts
          tar -czf ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz ${{ matrix.build.binary }}*
          echo "$GPG_PASSPHRASE" | gpg --passphrase-fd 0 --pinentry-mode loopback --batch -ab ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz
          mv *tar.gz* ..
        shell: bash

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz
          path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz

      - name: Upload signature
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz.asc
          path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz.asc

  build-reproducible:
    name: build and push reproducible image
    runs-on: ubuntu-latest
    needs: extract-version
    permissions:
      packages: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push reproducible image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./Dockerfile.reproducible
          push: true
          tags: |
            ${{ env.DOCKER_REPRODUCIBLE_IMAGE_NAME }}:${{ needs.extract-version.outputs.VERSION }}
            ${{ env.DOCKER_REPRODUCIBLE_IMAGE_NAME }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max
          provenance: false

  draft-release:
    name: draft release
    needs: [build, build-reproducible, extract-version]
    runs-on: ubuntu-latest
    env:
      VERSION: ${{ needs.extract-version.outputs.VERSION }}
    permissions:
      # Required to post the release
      contents: write
    steps:
      # This is necessary for generating the changelog.
      # It has to come before "Download Artifacts" or else it deletes the artifacts.
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Download artifacts
        uses: actions/download-artifact@v4
      - name: Generate full changelog
        id: changelog
        run: |
          echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
          echo "$(git log --pretty=format:"- %s" $(git describe --tags --abbrev=0 ${{ env.VERSION }}^)..${{ env.VERSION }})" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
      - name: Create release draft
        env:
          GITHUB_USER: ${{ github.repository_owner }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        # The formatting here is borrowed from Lighthouse (which is borrowed from OpenEthereum):
        # https://github.com/openethereum/openethereum/blob/6c2d392d867b058ff867c4373e40850ca3f96969/.github/workflows/build.yml
        run: |
          body=$(cat <<- "ENDBODY"
          ![image](https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-prod.png)

          ## Testing Checklist (DELETE ME)

          - [ ] Run on testnet for 1-3 days.
          - [ ] Resync a mainnet node.
          - [ ] Ensure all CI checks pass.

          ## Release Checklist (DELETE ME)

          - [ ] Ensure all crates have had their versions bumped.
          - [ ] Write the summary.
          - [ ] Fill out the update priority.
          - [ ] Ensure all binaries have been added.
          - [ ] Prepare release posts (Twitter, ...).

          ## Summary

          Add a summary, including:

          - Critical bug fixes
          - New features
          - Any breaking changes (and what to expect)

          ## Update Priority

          This table provides priorities for which classes of users should update particular components.

          | User Class           | Priority        |
          |----------------------|-----------------|
          | Payload Builders     | <TODO> |
          | Non-Payload Builders | <TODO>    |

          *See [Update Priorities](https://paradigmxyz.github.io/reth/installation/priorities.html) for more information about this table.*

          ## All Changes

          ${{ steps.changelog.outputs.CHANGELOG }}

          ## Binaries

          [See pre-built binaries documentation.](https://paradigmxyz.github.io/reth/installation/binaries.html)

          The binaries are signed with the PGP key: `50FB 7CC5 5B2E 8AFA 59FE 03B7 AA5E D56A 7FBF 253E`

          | System | Architecture | Binary | PGP Signature |
          |:---:|:---:|:---:|:---|
          | <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | x86_64 | [reth-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz.asc) |
          | <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | aarch64 | [reth-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz.asc) |
          | <img src="https://simpleicons.org/icons/windows.svg" style="width: 32px;"/> | x86_64 | [reth-${{ env.VERSION }}-x86_64-pc-windows-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-x86_64-pc-windows-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-x86_64-pc-windows-gnu.tar.gz.asc) |
          | <img src="https://simpleicons.org/icons/apple.svg" style="width: 32px;"/> | x86_64 | [reth-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz.asc) |
          | <img src="https://simpleicons.org/icons/apple.svg" style="width: 32px;"/> | aarch64 | [reth-${{ env.VERSION }}-aarch64-apple-darwin.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-aarch64-apple-darwin.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/reth-${{ env.VERSION }}-aarch64-apple-darwin.tar.gz.asc) |
          | | | | |
          | **System** | **Option** | - | **Resource** |
          | <img src="https://simpleicons.org/icons/docker.svg" style="width: 32px;"/> | Docker | | [${{ env.IMAGE_NAME }}](https://github.com/paradigmxyz/reth/pkgs/container/reth) |
          | <img src="https://simpleicons.org/icons/docker.svg" style="width: 32px;"/> | Docker (Reproducible) | | [${{ env.IMAGE_NAME }}-reproducible](https://github.com/paradigmxyz/reth/pkgs/container/reth-reproducible) |
          ENDBODY
          )
          assets=()
          for asset in ./*reth-*.tar.gz*; do
              assets+=("$asset/$asset")
          done
          tag_name="${{ env.VERSION }}"
          echo "$body" | gh release create --draft -t "Reth $tag_name" -F "-" "$tag_name" "${assets[@]}"
