name: Publish release candidate

# only one can tun at a time
concurrency: cd-publish-rc

# See for rationale https://github.com/ChainSafe/lodestar/blob/unstable/RELEASE.md
on:
  push:
    tags:
      - v*

jobs:
  tag:
    name: Check tag
    runs-on: buildjet-4vcpu-ubuntu-2204
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get tag
        id: get_tag
        run: echo "tag=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT

      - name: Get previous tag
        id: get_prev_tag
        run: node scripts/get_prev_tag.js
        env:
          CURRENT_TAG: ${{ steps.get_tag.outputs.tag }}
          IGNORE_PATTERN: rc

      - name: Determine release type
        id: is_rc
        run: scripts/release/assert_valid_rc.sh
        env:
          TAG: ${{ steps.get_tag.outputs.tag }}

    outputs:
      is_rc: ${{ steps.is_rc.outputs.is_rc }}
      version: ${{ steps.is_rc.outputs.version }}
      tag: ${{ steps.get_tag.outputs.tag }}
      prev_tag: ${{ steps.get_prev_tag.outputs.prev_tag }}

  binaries:
    name: Build lodestar binaries
    uses: ./.github/workflows/binaries.yml
    needs: tag
    with:
      version: ${{ needs.tag.outputs.tag }}

  npm:
    name: Publish to NPM & Github
    runs-on: buildjet-4vcpu-ubuntu-2204
    needs: [tag, binaries]
    if: needs.tag.outputs.is_rc == 'true'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Needs full depth for changelog generation

      - uses: "./.github/actions/setup-and-build"
        with:
          node: 22

      - name: Generate changelog
        run: node scripts/generate_changelog.mjs ${{ needs.tag.outputs.prev_tag }} ${{ needs.tag.outputs.tag }} CHANGELOG.md

      - name: Get binaries
        uses: actions/download-artifact@v4
        with:
          path: dist/
          merge-multiple: true

      - name: Create Release
        id: create_release
        uses: softprops/action-gh-release@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          files: dist/*
          fail_on_unmatched_files: true
          tag_name: ${{ needs.tag.outputs.tag }}
          body_path: "CHANGELOG.md"
          name: Release ${{ needs.tag.outputs.tag }}
          prerelease: true

      - name: Change and commit version
        # Write version before publishing so it's picked up by `lerna publish from-package`.
        # It must also be committed to ensure a clean git tree, otherwise `lerna publish` errors.
        # This "temp" commit doesn't change the actually release commit which is captured above.
        # git-data is also correct, since it's generated at build time, before `lerna version` run.
        run: |
          node_modules/.bin/lerna version ${{ needs.tag.outputs.version }} \
          --force-publish \
          --exact \
          --yes \
          --no-git-tag-version

          git config user.name 'temp'
          git config user.email 'temp@github.com'
          git commit -am "${{ needs.tag.outputs.version }}"

      # From https://github.com/lerna/lerna/issues/2404
      - run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Publish to npm registry
        run: yarn run release:publish --dist-tag rc
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      # In case of failure
      - name: Rollback on failure
        if: failure()
        uses: author/action-rollback@1.0.4
        with:
          release_id: ${{ steps.create_release.outputs.id }}
          tag: ${{ needs.tag.outputs.tag }}
          delete_orphan_tag: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  docker:
    name: Publish to Docker Hub
    runs-on: buildjet-4vcpu-ubuntu-2204
    needs: [tag, npm]
    if: needs.tag.outputs.is_rc == 'true'
    steps:
      - uses: actions/checkout@v4
      - run: scripts/await-release.sh ${{ needs.tag.outputs.tag }} rc 900
      # https://github.com/docker/setup-qemu-action
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      # https://github.com/docker/setup-buildx-action
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        run: >
          docker buildx build . --push
          --tag chainsafe/lodestar:rc
          --tag chainsafe/lodestar:${{ needs.tag.outputs.tag }}
          --platform linux/amd64,linux/arm64
          --build-arg COMMIT=$(git rev-parse HEAD)

      - run: docker run chainsafe/lodestar:${{ needs.tag.outputs.tag }} --help
      # Display history to know byte size of each layer
      # Image is available only because of the previous `docker run` command
      - run: docker image history chainsafe/lodestar:${{ needs.tag.outputs.tag }}

      - name: Build and push custom Grafana
        run: >
          docker buildx build ./docker/grafana/ --push
          --file ./docker/grafana/Dockerfile
          --build-context dashboards=./dashboards
          --tag chainsafe/lodestar-grafana:${{ needs.tag.outputs.tag }}
          --platform linux/amd64,linux/arm64

      - name: Build and push custom Prometheus
        run: >
          docker buildx build ./docker/prometheus/ --push
          --file ./docker/prometheus/Dockerfile
          --tag chainsafe/lodestar-prometheus:${{ needs.tag.outputs.tag }}
          --platform linux/amd64,linux/arm64
