Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
254 changes: 254 additions & 0 deletions .github/workflows/add-new-evm-chain.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
name: Add New EVM Chain

on:
workflow_dispatch:
inputs:
chain-selector:
description: 'The chain selector value (uint64)'
required: true
type: string
dry-run:
description: 'Dry run mode - show what would be done without making changes'
required: false
default: false
type: boolean
workflow_call:
inputs:
chain-selector:
description: 'The chain selector value (uint64)'
required: true
type: string
dry-run:
description: 'Dry run mode - show what would be done without making changes'
required: false
default: false
type: boolean

permissions:
id-token: write
contents: write
pull-requests: write

concurrency:
group: ${{ github.workflow }}-${{ inputs.chain-selector }}
cancel-in-progress: true

jobs:
add-new-evm-chain:
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
chain-name: ${{ steps.run-tool.outputs.chain_name }}
action: ${{ steps.run-tool.outputs.action }}
pr-url: ${{ steps.create-pr.outputs.pr_url }}
steps:
- name: Validate inputs
run: |
set -euo pipefail

CHAIN_SELECTOR="${{ inputs.chain-selector }}"

# Validate chain-selector is a positive integer (uint64)
if ! [[ "$CHAIN_SELECTOR" =~ ^[0-9]+$ ]]; then
echo "::error::chain-selector must be a positive integer, got: $CHAIN_SELECTOR"
exit 1
fi

# Validate it's within uint64 range (max: 18446744073709551615)
if [[ ${#CHAIN_SELECTOR} -gt 20 ]]; then
echo "::error::chain-selector exceeds uint64 maximum value"
exit 1
fi

echo "::notice::Input validation passed: chain-selector=$CHAIN_SELECTOR"

- name: Assume AWS GATI role
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN_GATI }}
role-duration-seconds: 900
aws-region: ${{ secrets.AWS_REGION }}
mask-aws-account-id: true

- name: Get GitHub token from GATI
id: get-gh-token
uses: smartcontractkit/chainlink-github-actions/github-app-token-issuer@main

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Add New EVM Chain' step
Uses Step: get-gh-token
uses 'smartcontractkit/chainlink-github-actions/github-app-token-issuer' with ref 'main', not a pinned commit hash
with:
url: ${{ secrets.AWS_LAMBDA_URL_GATI }}

- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
token: ${{ steps.get-gh-token.outputs.access-token }}
fetch-depth: 0

- name: Set tool versions to env vars
id: tool-versions
uses: smartcontractkit/tool-versions-to-env-action@aabd5efbaf28005284e846c5cf3a02f2cba2f4c2 # v1.0.8

- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.0.0
with:
go-version: ${{ steps.tool-versions.outputs.golang_version }}

- name: Build add-new-evm-chain tool
run: |
set -euo pipefail
cd cre/go
go build -o add-new-evm-chain ./tools/add-new-evm-chain

- name: Run add-new-evm-chain tool
id: run-tool
env:
INPUT_CHAIN_SELECTOR: ${{ inputs.chain-selector }}
INPUT_DRY_RUN: ${{ inputs.dry-run }}
run: |
set -euo pipefail
cd cre/go

# Build command arguments
ARGS="-chain-selector $INPUT_CHAIN_SELECTOR -proto-file ../capabilities/blockchain/evm/v1alpha/client.proto"
if [[ "$INPUT_DRY_RUN" == "true" ]]; then
ARGS="$ARGS -dry-run"
fi

# Run tool and capture output
echo "::group::Tool output"
if ! OUTPUT=$(./add-new-evm-chain $ARGS 2>&1); then
echo "$OUTPUT"
echo "::endgroup::"

# Try to parse ACTION even on failure
ACTION=$(echo "$OUTPUT" | grep "^ACTION=" | cut -d'=' -f2 || echo "error")
echo "action=$ACTION" >> $GITHUB_OUTPUT

echo "::error::Tool execution failed"
exit 1
fi
echo "$OUTPUT"
echo "::endgroup::"

# Parse structured output
CHAIN_NAME=$(echo "$OUTPUT" | grep "^CHAIN_NAME=" | cut -d'=' -f2)
CHAIN_SELECTOR=$(echo "$OUTPUT" | grep "^CHAIN_SELECTOR=" | cut -d'=' -f2)
ACTION=$(echo "$OUTPUT" | grep "^ACTION=" | cut -d'=' -f2)

# Validate outputs
if [[ -z "$CHAIN_NAME" || -z "$ACTION" ]]; then
echo "::error::Failed to parse tool output - missing CHAIN_NAME or ACTION"
exit 1
fi

echo "chain_name=$CHAIN_NAME" >> $GITHUB_OUTPUT
echo "chain_selector=$CHAIN_SELECTOR" >> $GITHUB_OUTPUT
echo "action=$ACTION" >> $GITHUB_OUTPUT

echo "::notice::Chain: $CHAIN_NAME, Selector: $CHAIN_SELECTOR, Action: $ACTION"

- name: Sanitize chain name for branch
id: sanitize
if: ${{ !inputs.dry-run && steps.run-tool.outputs.action == 'added' }}
env:
CHAIN_NAME: ${{ steps.run-tool.outputs.chain_name }}
run: |
set -euo pipefail

# Sanitize chain name for use in git branch names
# Only allow alphanumeric, hyphens, and underscores
SAFE_CHAIN_NAME=$(echo "$CHAIN_NAME" | tr -cd '[:alnum:]-_' | tr '[:upper:]' '[:lower:]')

if [[ -z "$SAFE_CHAIN_NAME" ]]; then
echo "::error::Chain name sanitization resulted in empty string"
exit 1
fi

echo "safe_chain_name=$SAFE_CHAIN_NAME" >> $GITHUB_OUTPUT
echo "::notice::Sanitized chain name: $SAFE_CHAIN_NAME"

- name: Create branch for PR
if: ${{ !inputs.dry-run && steps.run-tool.outputs.action == 'added' }}
id: create-branch
env:
SAFE_CHAIN_NAME: ${{ steps.sanitize.outputs.safe_chain_name }}
run: |
set -euo pipefail

BRANCH_NAME="add-evm-chain/${SAFE_CHAIN_NAME}-$(date +%Y%m%d-%H%M%S)"
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT

git checkout -b "$BRANCH_NAME"
echo "::notice::Created branch: $BRANCH_NAME"

- name: Commit changes using ghcommit
if: ${{ !inputs.dry-run && steps.run-tool.outputs.action == 'added' }}
uses: planetscale/[email protected]

Check failure on line 184 in .github/workflows/add-new-evm-chain.yml

View workflow job for this annotation

GitHub Actions / Validate Workflow Changes

1. v0.1.45 is not a valid SHA reference (sha-ref / error) 2. No version comment found (version-comment / warning)

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Add New EVM Chain' step
Uses Step
uses 'planetscale/ghcommit-action' with ref 'v0.1.45', not a pinned commit hash
with:
commit_message: "feat(cre): add EVM chain ${{ steps.run-tool.outputs.chain_name }}"
repo: ${{ github.repository }}
branch: ${{ steps.create-branch.outputs.branch_name }}
file_pattern: "cre/capabilities/blockchain/evm/v1alpha/client.proto"
env:
GITHUB_TOKEN: ${{ steps.get-gh-token.outputs.access-token }}

- name: Create Pull Request
if: ${{ !inputs.dry-run && steps.run-tool.outputs.action == 'added' }}
id: create-pr
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
CHAIN_NAME: ${{ steps.run-tool.outputs.chain_name }}
CHAIN_SELECTOR: ${{ steps.run-tool.outputs.chain_selector }}
BRANCH_NAME: ${{ steps.create-branch.outputs.branch_name }}
with:
github-token: ${{ steps.get-gh-token.outputs.access-token }}
script: |
const chainName = process.env.CHAIN_NAME;
const chainSelector = process.env.CHAIN_SELECTOR;
const branchName = process.env.BRANCH_NAME;

const { data: pr } = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `feat(cre): add EVM chain ${chainName}`,
head: branchName,
base: 'main',
body: `## Summary

This PR adds the EVM chain **${chainName}** to the CRE client.proto file.

### Chain Details
- **Chain Name**: ${chainName}
- **Selector**: ${chainSelector}

### Changes
- Added entry to \`cre/capabilities/blockchain/evm/v1alpha/client.proto\`

---
*This PR was automatically generated by the add-new-evm-chain workflow.*
`,
maintainer_can_modify: true
});

core.setOutput('pr_url', pr.html_url);
core.notice(`Created PR: ${pr.html_url}`);

- name: Summary
env:
CHAIN_NAME: ${{ steps.run-tool.outputs.chain_name }}
CHAIN_SELECTOR: ${{ steps.run-tool.outputs.chain_selector }}
ACTION: ${{ steps.run-tool.outputs.action }}
DRY_RUN: ${{ inputs.dry-run }}
PR_URL: ${{ steps.create-pr.outputs.pr_url }}
run: |
set -euo pipefail

echo "## Add New EVM Chain Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Chain Name | $CHAIN_NAME |" >> $GITHUB_STEP_SUMMARY
echo "| Chain Selector | $CHAIN_SELECTOR |" >> $GITHUB_STEP_SUMMARY
echo "| Action | $ACTION |" >> $GITHUB_STEP_SUMMARY
echo "| Dry Run | $DRY_RUN |" >> $GITHUB_STEP_SUMMARY
if [[ -n "$PR_URL" ]]; then
echo "| PR URL | $PR_URL |" >> $GITHUB_STEP_SUMMARY
fi
2 changes: 2 additions & 0 deletions cre/go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ go 1.24.5
require (
github.com/go-viper/mapstructure/v2 v2.4.0
github.com/shopspring/decimal v1.4.0
github.com/smartcontractkit/chain-selectors v1.0.85
github.com/stretchr/testify v1.10.0
google.golang.org/protobuf v1.36.7
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 4 additions & 0 deletions cre/go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/smartcontractkit/chain-selectors v1.0.85 h1:A7eyN7KIACxmngn1MJJ0giVtfELK9vh/eYyNU/Q/sFo=
github.com/smartcontractkit/chain-selectors v1.0.85/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
Expand Down
Loading
Loading