Skip to content

perf(ensv2): dedupe addr.reverse label-heal + perf testing infra (#1989) #706

perf(ensv2): dedupe addr.reverse label-heal + perf testing infra (#1989)

perf(ensv2): dedupe addr.reverse label-heal + perf testing infra (#1989) #706

Workflow file for this run

# Full Release Workflow (@latest)
#
# This workflow creates stable releases of ENSNode packages and Docker images.
# It is triggered automatically when the Changesets Release PR is merged to main.
#
# How it works:
# 1. When PRs with changesets are merged to main, the Changesets bot creates/updates a Release PR
# 2. When the Release PR is merged, this workflow:
# - Publishes NPM packages with @latest tag
# - Builds and publishes Docker images to GitHub Container Registry with @latest tag
# - Creates a GitHub release with version tags and release notes
# - Sends Slack notification
#
# Published artifacts:
# - NPM packages: @ensnode/* packages published to npm registry with @latest tag
# - Docker images: ensindexer, ensadmin, ensapi, ensrainbow published to ghcr.io with @latest tag
# - GitHub Release: Created with version tag (e.g., v1.2.3) and autogenerated release notes
#
# Version management:
# - All ENSNode packages use "fixed" versioning - they all advance to the same version
# - The version is determined by the changesets included in the Release PR
# - Version bump type (major/minor/patch) is based on the changeset severity levels
#
# Important notes:
# - Only Full Releases are considered stable for production use
# - Only NameHash Labs ensnode team members can merge the Release PR
# - This workflow does NOT run on regular commits to main (see release_snapshot.yml for that)
# - GitHub releases and tags are only created for Full Releases
#
# Documentation: https://ensnode.io/docs/contributing/releases#full-release
name: Release
permissions:
contents: write
pull-requests: write
packages: write
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
changesets:
name: Changesets
if: github.repository == 'namehash/ensnode'
runs-on: blacksmith-4vcpu-ubuntu-2204
outputs:
published: ${{ steps.changesets.outputs.published }}
publishedApps: ${{ steps.publishedApps.outputs.output }}
publishedPackages: ${{ steps.publishedPackages.outputs.output }}
publishedLambdas: ${{ steps.publishedLambdas.outputs.output }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: ./.github/actions/setup_node_environment
- name: Create Release Pull Request or Publish to npm
uses: changesets/action@v1.7.0
id: changesets
with:
commit: "chore(release): version apps"
title: "Release New Version"
version: pnpm changeset:version
publish: pnpm changeset-publish
createGithubReleases: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# https://github.com/changesets/action/issues/98#issuecomment-2519457411
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Filter Published Packages For Apps
uses: cloudposse/github-action-jq@main
id: publishedApps
with:
compact: true
input: ${{ steps.changesets.outputs.publishedPackages }}
# filter publishedPackages for apps (projects whose artifact is a docker image)
script: |-
map(select(
.name == "ensindexer"
or .name == "ensadmin"
or .name == "ensapi"
or .name == "ensrainbow"
))
- name: Filter Published Packages For NPM Packages
uses: cloudposse/github-action-jq@main
id: publishedPackages
with:
compact: true
input: ${{ steps.changesets.outputs.publishedPackages }}
# filter publishedPackages for packages (projects whose artifact is an NPM package)
script: |-
map(select(
.name == "@ensnode/datasources"
or .name == "@ensnode/ens-referrals"
or .name == "@ensnode/ensnode-react"
or .name == "@ensnode/ensdb-sdk"
or .name == "@ensnode/ensnode-sdk"
or .name == "@ensnode/ensrainbow-sdk"
or .name == "@ensnode/namehash-ui"
or .name == "@ensnode/ponder-sdk"
or .name == "@ensnode/ponder-subgraph"
or .name == "enssdk"
or .name == "enskit"
or .name == "enscli"
or .name == "ensskills"
))
- name: Filter Published Packages For Lambdas
uses: cloudposse/github-action-jq@main
id: publishedLambdas
with:
compact: true
input: ${{ steps.changesets.outputs.publishedPackages }}
# filter publishedPackages for lambdas (projects whose artifact is a dist/lambda.zip)
script: |-
map(select(
.name == "fallback-ensapi"
))
build-and-push-ensnode:
name: ${{ matrix.apps.name }} ${{ matrix.apps.version }}
# if changesets published our npm packages, also build docker images
needs: changesets
if: needs.changesets.outputs.published == 'true' && needs.changesets.outputs.publishedApps != '[]'
runs-on: blacksmith-4vcpu-ubuntu-2204
strategy:
fail-fast: false
matrix:
apps: ${{ fromJson(needs.changesets.outputs.publishedApps) }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Build & Push
uses: ./.github/actions/build_docker_image
with:
image: ghcr.io/${{ github.repository }}/${{ matrix.apps.name }}
dockerfile: apps/${{ matrix.apps.name }}/Dockerfile
registry_user: ${{ github.actor }}
registry_token: ${{ secrets.GITHUB_TOKEN }}
# construct docker tag using the changesets-reported version
tags: |
type=semver,pattern={{version}},value=${{ matrix.apps.version }}
type=ref,event=branch
type=sha
build-lambdas:
name: ${{ matrix.lambdas.name }} ${{ matrix.lambdas.version }}
needs: changesets
if: needs.changesets.outputs.published == 'true' && needs.changesets.outputs.publishedLambdas != '[]'
runs-on: blacksmith-4vcpu-ubuntu-2204
strategy:
fail-fast: false
matrix:
lambdas: ${{ fromJson(needs.changesets.outputs.publishedLambdas) }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Build and Publish Lambda
uses: ./.github/actions/build_and_publish_lambda
with:
name: ${{ matrix.lambdas.name }}
version: ${{ matrix.lambdas.version }}
create-github-release:
name: Create GitHub Release
runs-on: blacksmith-4vcpu-ubuntu-2204
# run only if (1) changesets published our npm packages AND
if: needs.changesets.outputs.published == 'true'
# (2) we built and pushed the docker images
needs: [changesets, build-and-push-ensnode]
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get PR information
id: get-pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get the PR number from the commit message
# Note: it must be a release PR with a title "Release New Version"
PR_NUMBER=$(git log -1 --pretty=%B | grep -o 'Release New Version (#[0-9]\+)' | grep -o '[0-9]\+')
if [ -z "$PR_NUMBER" ]; then
echo "Could not find PR number in commit message"
exit 1
fi
# Get PR body using GitHub CLI
PR_BODY=$(gh pr view $PR_NUMBER --json body -q .body)
if [ -z "$PR_BODY" ]; then
echo "Could not fetch PR body"
exit 1
fi
# Extract version from PR body
VERSION=$(echo "$PR_BODY" | grep -o '@[^@]*@[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 | awk -F@ '{print $3}')
if [ -z "$VERSION" ]; then
echo "Could not extract version from PR body"
exit 1
fi
# Extract release notes (everything below # Releases)
RELEASE_NOTES=$(echo "$PR_BODY" | awk '/^# Releases/{p=1;next}p')
# Strip out @ensnode/shared-configs section (thank you claude-san)
RELEASE_NOTES=$(echo "$RELEASE_NOTES" | awk '
/^## @ensnode\/shared-configs@.*/ { skip=1; next } # Set skip flag and skip further processing for this line
/^## / { skip=0 } # On subsequent lines, clear skip flag if H2 is found
!skip # Print line only if skip flag is not set
')
# Add NPM package links
RELEASE_NOTES+=$'\n\n## :package: NPM packages\n'
RELEASE_NOTES+=$(echo '${{ needs.changesets.outputs.publishedPackages }}' | jq -r '.[] | "- [\(.name)@\(.version)](https://www.npmjs.com/package/\(.name)/v/\(.version))"')
# Add Docker image links
RELEASE_NOTES+=$'\n\n## :whale: Docker images\n'
RELEASE_NOTES+=$(echo '${{ needs.changesets.outputs.publishedApps }}' | jq -r '.[] | "- [\(.name):\(.version)](https://ghcr.io/namehash/ensnode/\(.name):\(.version))"')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "pr_body<<EOF" >> $GITHUB_OUTPUT
echo "$RELEASE_NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.get-pr.outputs.version }}
name: v${{ steps.get-pr.outputs.version }}
body: ${{ steps.get-pr.outputs.pr_body }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: ./.github/actions/send_slack_notification
with:
slack_webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
slack_title: "ENSNode new version released: v${{ steps.get-pr.outputs.version }}"
slack_message: "✅ Release ENSNode completed"