# This workflow is modified from Lighthouse: # https://github.com/sigp/lighthouse/blob/441fc1691b69f9edc4bbdc6665f3efab16265c9b/.github/workflows/release.yml name: release on: push: tags: - v* workflow_dispatch: inputs: dry_run: description: "Enable dry run mode (builds artifacts but skips uploads and release creation)" type: boolean default: false env: REPO_NAME: ${{ github.repository_owner }}/reth IMAGE_NAME: ${{ github.repository_owner }}/reth OP_IMAGE_NAME: ${{ github.repository_owner }}/op-reth REPRODUCIBLE_IMAGE_NAME: ${{ github.repository_owner }}/reth-reproducible CARGO_TERM_COLOR: always DOCKER_IMAGE_NAME_URL: https://ghcr.io/${{ github.repository_owner }}/reth DOCKER_OP_IMAGE_NAME_URL: https://ghcr.io/${{ github.repository_owner }}/op-reth RUSTC_WRAPPER: "sccache" jobs: dry-run: name: check dry run runs-on: ubuntu-latest steps: - run: | echo "Dry run value: ${{ github.event.inputs.dry_run }}" echo "Dry run enabled: ${{ github.event.inputs.dry_run == 'true'}}" echo "Dry run disabled: ${{ github.event.inputs.dry_run != 'true'}}" extract-version: name: extract version runs-on: ubuntu-latest steps: - name: Extract version run: echo "VERSION=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT id: extract_version outputs: VERSION: ${{ steps.extract_version.outputs.VERSION }} check-version: name: check version runs-on: ubuntu-latest needs: extract-version if: ${{ github.event.inputs.dry_run != 'true' }} steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - uses: mozilla-actions/sccache-action@v0.0.9 - name: Verify crate version matches tag # Check that the Cargo version starts with the tag, # so that Cargo version 1.4.8 can be matched against both v1.4.8 and v1.4.8-rc.1 run: | tag="${{ needs.extract-version.outputs.VERSION }}" tag=${tag#v} cargo_ver=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version') [[ "$tag" == "$cargo_ver"* ]] || { echo "Tag $tag doesn’t match the Cargo version $cargo_ver"; exit 1; } build: name: build release runs-on: ${{ matrix.configs.os }} needs: extract-version continue-on-error: ${{ matrix.configs.allow_fail }} strategy: fail-fast: true matrix: configs: - target: x86_64-unknown-linux-gnu os: ubuntu-24.04 profile: maxperf allow_fail: false - target: aarch64-unknown-linux-gnu os: ubuntu-24.04 profile: maxperf allow_fail: false - target: x86_64-apple-darwin os: macos-14 profile: maxperf allow_fail: false - target: aarch64-apple-darwin os: macos-14 profile: maxperf allow_fail: false - target: x86_64-pc-windows-gnu os: ubuntu-24.04 profile: maxperf allow_fail: false - target: riscv64gc-unknown-linux-gnu os: ubuntu-24.04 profile: maxperf allow_fail: true build: - command: build binary: reth - command: op-build binary: op-reth steps: - uses: actions/checkout@v6 - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@stable with: target: ${{ matrix.configs.target }} - uses: mozilla-actions/sccache-action@v0.0.9 - name: Install cross main id: cross_main run: | cargo install cross --git https://github.com/cross-rs/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 if: ${{ github.event.inputs.dry_run != 'true' }} uses: actions/upload-artifact@v6 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 if: ${{ github.event.inputs.dry_run != 'true' }} uses: actions/upload-artifact@v6 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 draft-release: name: draft release runs-on: ubuntu-latest needs: [build, extract-version] if: ${{ github.event.inputs.dry_run != 'true' }} 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@v6 with: fetch-depth: 0 - name: Download artifacts uses: actions/download-artifact@v7 - name: Generate full changelog id: changelog run: | echo "CHANGELOG<> $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: | prerelease_flag="" if [[ "${GITHUB_REF}" == *-rc* ]]; then prerelease_flag="--prerelease" fi 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 | | | Non-Payload Builders | | *See [Update Priorities](https://reth.rs/installation/priorities) for more information about this table.* ## All Changes ${{ steps.changelog.outputs.CHANGELOG }} ## Binaries [See pre-built binaries documentation.](https://reth.rs/installation/binaries) The binaries are signed with the PGP key: `50FB 7CC5 5B2E 8AFA 59FE 03B7 AA5E D56A 7FBF 253E` ### Reth | System | Architecture | Binary | PGP Signature | |:---:|:---:|:---:|:---| | | 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) | | | 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) | | | 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) | | | 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) | | | 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) | | | Docker | [${{ env.IMAGE_NAME }}](${{ env.DOCKER_IMAGE_NAME_URL }}) | - | ### OP-Reth | System | Architecture | Binary | PGP Signature | |:---:|:---:|:---:|:---| | | x86_64 | [op-reth-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-x86_64-unknown-linux-gnu.tar.gz.asc) | | | aarch64 | [op-reth-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz.asc) | | | x86_64 | [op-reth-${{ env.VERSION }}-x86_64-pc-windows-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-x86_64-pc-windows-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-x86_64-pc-windows-gnu.tar.gz.asc) | | | x86_64 | [op-reth-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-x86_64-apple-darwin.tar.gz.asc) | | | aarch64 | [op-reth-${{ env.VERSION }}-aarch64-apple-darwin.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-aarch64-apple-darwin.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/op-reth-${{ env.VERSION }}-aarch64-apple-darwin.tar.gz.asc) | | | Docker | [${{ env.OP_IMAGE_NAME }}](${{ env.DOCKER_OP_IMAGE_NAME_URL }}) | - | ENDBODY ) assets=() for asset in ./*reth-*.tar.gz*; do assets+=("$asset/$asset") done tag_name="${{ env.VERSION }}" echo "$body" | gh release create --draft $prerelease_flag -t "Reth $tag_name" -F "-" "$tag_name" "${assets[@]}" dry-run-summary: name: dry run summary runs-on: ubuntu-latest needs: [build, extract-version] if: ${{ github.event.inputs.dry_run == 'true' }} env: VERSION: ${{ needs.extract-version.outputs.VERSION }} steps: - name: Summarize dry run run: | echo "## 🧪 Release Dry Run Summary" echo "" echo "✅ Successfully completed dry run for commit ${{ github.sha }}" echo "" echo "### What would happen in a real release:" echo "- Binary artifacts would be uploaded to GitHub" echo "- Docker images would be pushed to registry" echo "- A draft release would be created" echo "" echo "### Next Steps" echo "To perform a real release, push a git tag."