diff --git a/.github/workflows/bump-chainlink-protos.yml b/.github/workflows/bump-chainlink-protos.yml new file mode 100644 index 00000000..1421282f --- /dev/null +++ b/.github/workflows/bump-chainlink-protos.yml @@ -0,0 +1,171 @@ +# ============================================================================= +# Bump chainlink-protos Version Workflow +# ============================================================================= +# +# This workflow updates the chainlink-protos/cre/go dependency in the EVM +# capability module, regenerates code, and creates a PR with version tags. +# +# TRIGGERS: +# - workflow_dispatch: Manual trigger via GitHub UI or gh CLI +# - repository_dispatch: Triggered by external workflows (e.g., chainlink-protos repo) +# +# PARAMETERS: +# version (required): +# The new chainlink-protos/cre/go version to bump to. +# Format: v0.0.0-YYYYMMDDHHMMSS- (e.g., v0.0.0-20251202154221-30236deecda8) +# +# evm_cap_version (optional): +# Explicit version tag for EVM capability (e.g., v1.0.0-beta.2). +# If empty, auto-increments from the latest capabilities/blockchain/evm/* tag. +# +# sdk_version (optional): +# Explicit version tag for SDK (e.g., v1.1.2). +# If empty, auto-increments from the latest v*.*.* tag. +# +# skip_tagging (optional, default: false): +# If true, skips version calculation and tagging entirely. +# +# CROSS-REPO TRIGGER EXAMPLE: +# uses: peter-evans/repository-dispatch@v3 +# with: +# token: ${{ secrets.PAT_TOKEN }} +# repository: smartcontractkit/cre-sdk-go +# event-type: bump-chainlink-protos +# client-payload: '{"version": "v0.0.0-20251202154221-30236deecda8"}' +# +# ============================================================================= + +name: Bump chainlink-protos version + +on: + # Manual trigger via GitHub UI or CLI + workflow_dispatch: + inputs: + version: + description: 'New version for github.com/smartcontractkit/chainlink-protos/cre/go (e.g., v0.0.0-20251202154221-30236deecda8)' + required: true + type: string + evm_cap_version: + description: 'EVM capability tag (e.g., v1.0.0-beta.2). Leave empty to auto-increment.' + required: false + type: string + sdk_version: + description: 'SDK version tag (e.g., v1.1.2). Leave empty to auto-increment.' + required: false + type: string + skip_tagging: + description: 'Skip version tagging entirely' + required: false + type: boolean + default: false + + # External trigger from other workflows (e.g., chainlink-protos repo) + repository_dispatch: + types: [bump-chainlink-protos] + +jobs: + bump-version: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # Clone repo with full history to access git tags for version calculation + - name: Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up Go + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version-file: "go.mod" + + # Update the chainlink-protos dependency in the EVM capability module + - name: Bump chainlink-protos version + working-directory: capabilities/blockchain/evm + run: | + go get github.com/smartcontractkit/chainlink-protos/cre/go@${{ inputs.version || github.event.client_payload.version }} + go mod tidy + + # Regenerate all protobuf and SDK code to reflect the updated protos + - name: Run make clean-generate + run: make clean-generate + + # Determine next version tags (uses explicit input or auto-increments from latest git tags) + - name: Calculate next versions + if: ${{ !inputs.skip_tagging && !github.event.client_payload.skip_tagging }} + id: calc-versions + run: | + ./script/calculate-next-versions.sh \ + "${{ inputs.evm_cap_version || github.event.client_payload.evm_cap_version || '' }}" \ + "${{ inputs.sdk_version || github.event.client_payload.sdk_version || '' }}" + + # Construct PR labels including version info for post-merge tagging workflows + - name: Build labels list + id: labels + run: | + LABELS="bump-chainlink-protos" + if [ -n "${{ steps.calc-versions.outputs.evm_version }}" ]; then + LABELS="${LABELS},evm:${{ steps.calc-versions.outputs.evm_version }}" + fi + if [ -n "${{ steps.calc-versions.outputs.sdk_version }}" ]; then + LABELS="${LABELS},sdk:${{ steps.calc-versions.outputs.sdk_version }}" + fi + echo "labels=${LABELS}" >> $GITHUB_OUTPUT + echo "Labels: ${LABELS}" + + # Create or update the PR with all changes + - name: Create Pull Request + id: create-pr + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + env: + VERSION: ${{ inputs.version || github.event.client_payload.version }} + EVM_VERSION: ${{ steps.calc-versions.outputs.evm_version || '' }} + SDK_VERSION: ${{ steps.calc-versions.outputs.sdk_version || '' }} + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore: bump chainlink-protos/cre/go to ${{ env.VERSION }}" + branch: chore/bump-chainlink-protos-${{ env.VERSION }} + delete-branch: true + title: "chore: bump chainlink-protos/cre/go to ${{ env.VERSION }}" + body: | + This PR bumps `github.com/smartcontractkit/chainlink-protos/cre/go` to version `${{ env.VERSION }}`. + + Changes: + - Updated dependency in `capabilities/blockchain/evm/go.mod` + - Ran `make clean-generate` to regenerate code + + **Tags to be created after merge:** + - EVM capability: `capabilities/blockchain/evm/${{ env.EVM_VERSION || 'skipped' }}` + - SDK: `${{ env.SDK_VERSION || 'skipped' }}` + + --- + *This PR was automatically created by the bump-chainlink-protos workflow.* + labels: ${{ steps.labels.outputs.labels }} + + # Write a summary to the GitHub Actions UI for visibility + - name: Output summary + env: + VERSION: ${{ inputs.version || github.event.client_payload.version }} + EVM_VERSION: ${{ steps.calc-versions.outputs.evm_version || 'skipped' }} + SDK_VERSION: ${{ steps.calc-versions.outputs.sdk_version || 'skipped' }} + run: | + echo "## Bump chainlink-protos Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Version Update" >> $GITHUB_STEP_SUMMARY + echo "- **chainlink-protos/cre/go:** \`${{ env.VERSION }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Pull Request" >> $GITHUB_STEP_SUMMARY + if [ "${{ steps.create-pr.outputs.pull-request-number }}" != "" ]; then + echo "- **PR Number:** #${{ steps.create-pr.outputs.pull-request-number }}" >> $GITHUB_STEP_SUMMARY + echo "- **PR URL:** ${{ steps.create-pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY + echo "- **PR Operation:** ${{ steps.create-pr.outputs.pull-request-operation }}" >> $GITHUB_STEP_SUMMARY + else + echo "- No PR was created (no changes detected)" >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Tags to be created after merge" >> $GITHUB_STEP_SUMMARY + echo "- **EVM capability:** \`capabilities/blockchain/evm/${{ env.EVM_VERSION }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **SDK:** \`${{ env.SDK_VERSION }}\`" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/create-release-tags.yml b/.github/workflows/create-release-tags.yml new file mode 100644 index 00000000..3b097ccf --- /dev/null +++ b/.github/workflows/create-release-tags.yml @@ -0,0 +1,190 @@ +# ============================================================================= +# Create Release Tags Workflow +# ============================================================================= +# +# This workflow creates git tags and GitHub Releases for the EVM capability +# module and the SDK. It runs automatically when bump-chainlink-protos PRs +# are merged, or can be triggered manually. +# +# TRIGGERS: +# - pull_request (closed): Runs when a PR with 'bump-chainlink-protos' label is merged +# - workflow_dispatch: Manual trigger via GitHub UI or gh CLI +# - repository_dispatch: Triggered by external workflows +# +# PARAMETERS: +# evm_cap_version (optional): +# Version tag for EVM capability (e.g., v1.0.0-beta.2). +# Creates tag and release: capabilities/blockchain/evm/ +# If empty, EVM tagging is skipped. +# +# sdk_version (optional): +# Version tag for SDK (e.g., v1.1.2). +# Creates tag and release: (e.g., v1.1.2) +# If empty, SDK tagging is skipped. +# +# VERSION SOURCES (in priority order): +# 1. Manual inputs (workflow_dispatch) or client_payload (repository_dispatch) +# 2. PR labels: 'evm:' and 'sdk:' (set by bump-chainlink-protos workflow) +# +# ============================================================================= + +name: Create Release Tags + +on: + # Triggered when PRs are merged (filtered to bump-chainlink-protos label in job condition) + pull_request: + types: [closed] + + # Manual trigger via GitHub UI or CLI + workflow_dispatch: + inputs: + evm_cap_version: + description: 'EVM capability tag (e.g., v1.0.0-beta.2). Leave empty to skip.' + required: false + type: string + sdk_version: + description: 'SDK version tag (e.g., v1.1.2). Leave empty to skip.' + required: false + type: string + + # External trigger from other workflows + repository_dispatch: + types: [create-release-tags] + +jobs: + create-tags: + runs-on: ubuntu-latest + # Only run if: manual trigger OR (PR was merged AND has the bump-chainlink-protos label) + if: | + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' || + (github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'bump-chainlink-protos')) + permissions: + contents: write + steps: + # Clone repo with full history to create and push tags + - name: Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + fetch-depth: 0 + fetch-tags: true + + # Parse version info from inputs, dispatch payload, or PR labels + - name: Extract versions from labels or inputs + id: versions + env: + LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }} + run: | + # Start with manual inputs / dispatch payload (highest priority) + EVM_VERSION="${{ inputs.evm_cap_version || github.event.client_payload.evm_cap_version || '' }}" + SDK_VERSION="${{ inputs.sdk_version || github.event.client_payload.sdk_version || '' }}" + + # If triggered by PR merge, extract versions from labels + if [ "${{ github.event_name }}" == "pull_request" ]; then + echo "Extracting versions from PR labels..." + echo "Labels: $LABELS" + + # Extract evm:vX.X.X label + if [ -z "$EVM_VERSION" ]; then + EVM_VERSION=$(echo "$LABELS" | jq -r '.[] | select(startswith("evm:")) | sub("evm:"; "")' | head -n1) + fi + + # Extract sdk:vX.X.X label + if [ -z "$SDK_VERSION" ]; then + SDK_VERSION=$(echo "$LABELS" | jq -r '.[] | select(startswith("sdk:")) | sub("sdk:"; "")' | head -n1) + fi + fi + + echo "evm_cap_version=${EVM_VERSION}" >> $GITHUB_OUTPUT + echo "sdk_version=${SDK_VERSION}" >> $GITHUB_OUTPUT + + echo "EVM version: ${EVM_VERSION:-'(empty)'}" + echo "SDK version: ${SDK_VERSION:-'(empty)'}" + + # Set up git identity for creating annotated tags + - name: Configure Git + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + # Create and push EVM capability tag if it doesn't already exist + - name: Create EVM capability tag + if: steps.versions.outputs.evm_cap_version != '' + env: + EVM_VERSION: ${{ steps.versions.outputs.evm_cap_version }} + run: | + TAG="capabilities/blockchain/evm/${EVM_VERSION}" + if git rev-parse "${TAG}" >/dev/null 2>&1; then + echo "Tag ${TAG} already exists, skipping tag creation" + else + echo "Creating tag: ${TAG}" + git tag -a "${TAG}" -m "Release ${TAG}" + git push origin "${TAG}" + fi + + # Create GitHub Release for EVM capability (creates release even if tag existed) + - name: Create EVM capability release + if: steps.versions.outputs.evm_cap_version != '' + uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 + with: + tag_name: capabilities/blockchain/evm/${{ steps.versions.outputs.evm_cap_version }} + name: EVM Capability ${{ steps.versions.outputs.evm_cap_version }} + body: | + Release of the EVM blockchain capability module. + + **Tag:** `capabilities/blockchain/evm/${{ steps.versions.outputs.evm_cap_version }}` + + To use this version: + ``` + go get github.com/smartcontractkit/cre-sdk-go/capabilities/blockchain/evm@${{ steps.versions.outputs.evm_cap_version }} + ``` + prerelease: ${{ contains(steps.versions.outputs.evm_cap_version, 'beta') || contains(steps.versions.outputs.evm_cap_version, 'alpha') }} + + # Create and push SDK tag if it doesn't already exist + - name: Create SDK tag + if: steps.versions.outputs.sdk_version != '' + env: + SDK_VERSION: ${{ steps.versions.outputs.sdk_version }} + run: | + TAG="${SDK_VERSION}" + if git rev-parse "${TAG}" >/dev/null 2>&1; then + echo "Tag ${TAG} already exists, skipping tag creation" + else + echo "Creating tag: ${TAG}" + git tag -a "${TAG}" -m "Release ${TAG}" + git push origin "${TAG}" + fi + + # Create GitHub Release for SDK (creates release even if tag existed) + - name: Create SDK release + if: steps.versions.outputs.sdk_version != '' + uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 + with: + tag_name: ${{ steps.versions.outputs.sdk_version }} + name: SDK ${{ steps.versions.outputs.sdk_version }} + body: | + Release of the CRE SDK for Go. + + **Tag:** `${{ steps.versions.outputs.sdk_version }}` + + To use this version: + ``` + go get github.com/smartcontractkit/cre-sdk-go@${{ steps.versions.outputs.sdk_version }} + ``` + prerelease: ${{ contains(steps.versions.outputs.sdk_version, 'beta') || contains(steps.versions.outputs.sdk_version, 'alpha') }} + + # Write a summary to the GitHub Actions UI for visibility + - name: Summary + run: | + echo "## Releases Created" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ -n "${{ steps.versions.outputs.evm_cap_version }}" ]; then + echo "- **EVM Capability:** \`capabilities/blockchain/evm/${{ steps.versions.outputs.evm_cap_version }}\`" >> $GITHUB_STEP_SUMMARY + else + echo "- EVM capability: skipped (not specified)" >> $GITHUB_STEP_SUMMARY + fi + if [ -n "${{ steps.versions.outputs.sdk_version }}" ]; then + echo "- **SDK:** \`${{ steps.versions.outputs.sdk_version }}\`" >> $GITHUB_STEP_SUMMARY + else + echo "- SDK: skipped (not specified)" >> $GITHUB_STEP_SUMMARY + fi diff --git a/script/calculate-next-versions.sh b/script/calculate-next-versions.sh new file mode 100755 index 00000000..8e0cd220 --- /dev/null +++ b/script/calculate-next-versions.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Calculate next versions based on existing git tags +# Usage: ./calculate-next-versions.sh [evm_override] [sdk_override] +# +# Outputs (to stdout): +# evm_version=v1.0.0-beta.X +# sdk_version=v1.1.X +# +# If running in GitHub Actions, also writes to $GITHUB_OUTPUT + +EVM_OVERRIDE="${1:-}" +SDK_OVERRIDE="${2:-}" + +# Get latest EVM capability tag +LATEST_EVM_TAG=$(git tag -l "capabilities/blockchain/evm/v*" --sort=-v:refname | head -n1 || echo "") +echo "Latest EVM tag: ${LATEST_EVM_TAG}" >&2 + +if [ -n "$EVM_OVERRIDE" ]; then + EVM_VERSION="$EVM_OVERRIDE" +elif [ -n "$LATEST_EVM_TAG" ]; then + # Auto-increment: extract version and increment beta number + # Format: capabilities/blockchain/evm/v1.0.0-beta.1 -> v1.0.0-beta.2 + LATEST_EVM_VERSION=${LATEST_EVM_TAG#capabilities/blockchain/evm/} + + if [[ "$LATEST_EVM_VERSION" =~ ^(v[0-9]+\.[0-9]+\.[0-9]+-beta\.)([0-9]+)$ ]]; then + PREFIX="${BASH_REMATCH[1]}" + BETA_NUM="${BASH_REMATCH[2]}" + NEXT_BETA=$((BETA_NUM + 1)) + EVM_VERSION="${PREFIX}${NEXT_BETA}" + else + # Non-beta format, increment patch: v1.0.0 -> v1.0.1 + if [[ "$LATEST_EVM_VERSION" =~ ^(v[0-9]+\.[0-9]+\.)([0-9]+)$ ]]; then + PREFIX="${BASH_REMATCH[1]}" + PATCH="${BASH_REMATCH[2]}" + NEXT_PATCH=$((PATCH + 1)) + EVM_VERSION="${PREFIX}${NEXT_PATCH}" + else + EVM_VERSION="" + echo "Could not parse EVM version format: ${LATEST_EVM_VERSION}" >&2 + fi + fi +else + # No existing tag, start at v1.0.0-beta.1 + EVM_VERSION="v1.0.0-beta.1" +fi + +echo "Next EVM version: ${EVM_VERSION}" >&2 + +# Get latest SDK tag (format: v1.1.1) +LATEST_SDK_TAG=$(git tag -l "v[0-9]*.[0-9]*.[0-9]*" --sort=-v:refname | grep -E "^v[0-9]+\.[0-9]+\.[0-9]+$" | head -n1 || echo "") +echo "Latest SDK tag: ${LATEST_SDK_TAG}" >&2 + +if [ -n "$SDK_OVERRIDE" ]; then + SDK_VERSION="$SDK_OVERRIDE" +elif [ -n "$LATEST_SDK_TAG" ]; then + # Auto-increment patch: v1.1.1 -> v1.1.2 + if [[ "$LATEST_SDK_TAG" =~ ^(v[0-9]+\.[0-9]+\.)([0-9]+)$ ]]; then + PREFIX="${BASH_REMATCH[1]}" + PATCH="${BASH_REMATCH[2]}" + NEXT_PATCH=$((PATCH + 1)) + SDK_VERSION="${PREFIX}${NEXT_PATCH}" + else + SDK_VERSION="" + echo "Could not parse SDK version format: ${LATEST_SDK_TAG}" >&2 + fi +else + # No existing tag, start at v1.0.0 + SDK_VERSION="v1.0.0" +fi + +echo "Next SDK version: ${SDK_VERSION}" >&2 + +# Output for consumption +echo "evm_version=${EVM_VERSION}" +echo "sdk_version=${SDK_VERSION}" + +# If in GitHub Actions, write to GITHUB_OUTPUT +if [ -n "${GITHUB_OUTPUT:-}" ]; then + echo "evm_version=${EVM_VERSION}" >> "$GITHUB_OUTPUT" + echo "sdk_version=${SDK_VERSION}" >> "$GITHUB_OUTPUT" +fi +