跳转到主要内容
学习如何配置一个 GitHub Action,在 Tenderly Virtual Environments 上使用 Foundry 建立持续集成和持续部署流水线(CI/CD)。 使用 Tenderly Virtual Environment Setup action 启用自动化构建来测试和暂存您的合约。此方法支持:
  • CI/CD 集成:针对 fork 的网络运行测试,并搭建 staging 环境
  • 多网络测试:一步完成多个网络的配置
  • 自动化部署:部署和验证合约,并附有完整的部署日志
  • 构件收集:使用结构化日志跨网络跟踪部署
在本指南中,您需要完成两个阶段:
  1. 本地设置:设置 Foundry 以创建和测试工作流文件
  2. GitHub 设置:设置 GitHub Action,配置 GitHub secrets 和变量,并测试构建
作为参考,请使用此示例项目:

Foundry CI/CD setup

Continuous integration (CI) and continous deployment (CD) with Virtual Environments

阶段 1:本地设置

首先,使用必要的设置创建一个工作流文件。
1
创建工作流文件
2
在您的 foundry 项目中,创建一个新的 workflows 目录和 ci-cd.yaml
3
mkdir -p .github/workflows
touch .github/workflows/ci-cd.yaml
4
接下来,将以下配置粘贴到 ci-cd.yaml 中,该配置设置了两个作业:
5
  • test 作业用于运行 Foundry 测试
  • deploy 作业用于将合约部署到 staging Virtual Environment
  • 6
    此示例工作流文件:
    7
  • 使用 tenderly/vnet-github-action 根据给定的 network_id(Mainnet 和 Base)配置 Virtual Environments,并使用自定义的 chain_id
  • 使用 update_foundry_config_and_build 修改 foundry.toml 中正确的链 ID(如果您使用自定义 chain_id 尤其重要),并传递验证信息。
  • 使用 set_wallet_balanceDEPLOYER_WALLET_ADDRESS EOA 注资 100 ETH
  • 在 Virtual Environment 上部署合约
  • 分别使用 foundry 的 --json 选项将部署信息收集到 $BUILD_OUTPUT_FILE_1$BUILD_OUTPUT_FILE_8453
  • 将捕获的部署信息推送到仓库
  • 8
    Tenderly/vnet-github-actionmode 参数取值为 CICD
    • CD 模式使 Virtual Environment 保持活动状态,您可以使用已部署的合约。
    • CI 模式在步骤完成后暂停 Virtual Environment。您将能够检查交易,但无法发送更多的 RPC 请求。
    9
    name: Foundry CI/CD
    
    on:
      push:
      pull_request:
    
    env:
      TENDERLY_ACCESS_KEY: ${{ secrets.TENDERLY_ACCESS_KEY }}
      DEPLOYER_WALLET_ADDRESS: ${{ vars.DEPLOYER_WALLET_ADDRESS }}
      DEBUG: tenderly/vnet-github-action@v1.0.14
    jobs:
      deploy:
        runs-on: ubuntu-latest
        defaults:
          run:
            working-directory: ./examples/foundry
        permissions:
          contents: write
        steps:
          - uses: actions/checkout@v4
            with:
              submodules: recursive
    
          - name: Setup Virtual Environment
            uses: tenderly/vnet-github-action@v1.0.14
            with:
              mode: CD
              access_key: ${{ secrets.TENDERLY_ACCESS_KEY }}
              project_name: ${{ vars.TENDERLY_PROJECT_NAME }}
              account_name: ${{ vars.TENDERLY_ACCOUNT_NAME }}
              testnet_name: "Staging"
              network_id: |
                1
                8453
              chain_id_prefix: 7357
              public_explorer: true
              verification_visibility: 'src'
              push_on_complete: true
    
          - name: Install Foundry
            uses: foundry-rs/foundry-toolchain@v1
    
          - name: Fund Deployer Account on Mainnet
            run: |
              source ../../fixtures/load-fixtures.sh
              update_foundry_config_and_build $TENDERLY_ACCESS_KEY $TENDERLY_FOUNDRY_VERIFICATION_URL_1  $TENDERLY_CHAIN_ID_1
              set_wallet_balance $TENDERLY_ADMIN_RPC_URL_1 ${{ vars.DEPLOYER_WALLET_ADDRESS }} $HUNDRED_ETH
    
          - name: Deploy Contracts Mainnet
            run: |
              forge build --sizes
              forge script script/Counter.s.sol \
                --private-key ${{ secrets.DEPLOYER_PRIVATE_KEY }} \
                --rpc-url ${{ env.TENDERLY_PUBLIC_RPC_URL_1 }} \
                --verifier-url ${{ env.TENDERLY_FOUNDRY_VERIFICATION_URL_1 }} \
                --etherscan-api-key $TENDERLY_ACCESS_KEY \
                --slow \
                --broadcast \
                --verify \
                --json > $BUILD_OUTPUT_FILE_1
    
          - name: Fund Deployer Account on Base
            run: |
              source ../../fixtures/load-fixtures.sh
              update_foundry_config_and_build $TENDERLY_ACCESS_KEY $TENDERLY_FOUNDRY_VERIFICATION_URL_8453  $TENDERLY_CHAIN_ID_8453
              set_wallet_balance $TENDERLY_ADMIN_RPC_URL_8453 ${{ vars.DEPLOYER_WALLET_ADDRESS }} $HUNDRED_ETH
    
          - name: Deploy Contracts Base
            working-directory: ./examples/foundry
            run: |
              forge script script/Counter.s.sol \
                --private-key ${{ secrets.DEPLOYER_PRIVATE_KEY }} \
                --rpc-url ${{ env.TENDERLY_PUBLIC_RPC_URL_8453 }} \
                --verifier-url ${{ env.TENDERLY_FOUNDRY_VERIFICATION_URL_8453 }} \
                --etherscan-api-key $TENDERLY_ACCESS_KEY \
                --slow \
                --broadcast \
                --verify \
                --json > $BUILD_OUTPUT_FILE_8453
    
    10
    配置 Foundry
    11
    创建或更新您的 foundry.toml 配置文件。要使用自动合约验证,您必须有一个 unknown_chain 条目,其中包含 keychainurl
    12
    从本地机器使用 Virtual Environments 时,请将 `chain = 0` 替换为您所连接的 Virtual Environment 的链 ID。
    13
    [profile.default]
    src = "src"
    out = "out"
    libs = ["lib"]
    cbor_metadata = true
    # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
    
    [etherscan]
    
    ## placeholders must be replaced with key ("string"), chain_id (number, non-quoted), and tenderly_foundry_verification_url ("string")
    unknown_chain = { key = "$TENDERLY_ACCESS_KEY", chain = 0, url = "$TENDERLY_FOUNDRY_VERIFICATION_URL" }
    
    14
    准备环境变量
    15
    对于本地测试,使用以下变量设置一个 .env 文件:
    16
    # Access parameters
    TENDERLY_ACCESS_KEY=...
    TENDERLY_PROJECT_NAME=...
    TENDERLY_ACCOUNT_NAME=...
    
    # Deployment parameters
    DEPLOYER_PRIVATE_KEY=...
    DEPLOYER_WALLET_ADDRESS=...
    
    17
    必需的变量:
    18
  • TENDERLY_ACCESS_KEY:您的 Tenderly access key
  • TENDERLY_ACCOUNT_NAMETENDERLY_PROJECT_NAME:您的账户和项目名称
  • DEPLOYER_PRIVATE_KEY:部署钱包的私钥
  • DEPLOYER_WALLET_ADDRESS:与私钥对应的地址
  • 19
    添加 fixtures 脚本
    20
    将以下 fixtures.sh 添加到您的仓库中,以便轻松地为账户注资并调整 foundry.toml
    21
    此文件暴露:
    22
  • set_wallet_balance 函数用于给余额充值 (RPC_URL WALLET_ADDRESS BALANCE_HEX)
  • update_foundry_config_and_build 函数用于替换 foundry.toml 中的占位符
  • HUNDRED_ETH 对应 100 ETH 的 wei 值
  • 23
    #!/bin/bash
    
    set_wallet_balance() {
        if [ "$#" -ne 3 ]; then
            echo "Usage: set_wallet_balance RPC_URL WALLET_ADDRESS BALANCE_HEX"
            return 1
        fi
    
        local rpc_url="$1"
        local wallet_address="$2"
        local balance_hex="$3"
    
        curl --location "$rpc_url" \
            --header 'Content-Type: application/json' \
            --data "{
                \"jsonrpc\": \"2.0\",
                \"method\": \"tenderly_setBalance\",
                \"params\": [\"$wallet_address\", \"$balance_hex\"],
                \"id\": \"1\"
            }"
    }
    
    update_foundry_config_and_build() {
        if [ "$#" -ne 3 ]; then
            echo "Usage: update_foundry_config_and_build ACCESS_KEY VERIFICATION_URL CHAIN_ID"
            return 1
        fi
    
        local access_key="$1"
        local verification_url="$2"
        local chain_id="$3"
    
        # Create temporary file and update foundry.toml
        sed -e "s|\${TENDERLY_ACCESS_KEY}|$access_key|g" \
            -e "s|\${TENDERLY_FOUNDRY_VERIFICATION_URL}|$verification_url|g" \
            -e "s/\(unknown_chain[[:space:]]*=[[:space:]]*{[^}]*chain[[:space:]]*=[[:space:]]*\)[0-9][0-9]*/\1$chain_id/g" \
            foundry.toml > foundry.toml.tmp && mv foundry.toml.tmp foundry.toml
    }
    
    # Export constant
    HUNDRED_ETH="0xDE0B6B3A7640000"
    export HUNDRED_ETH
    
    24
    该 github action 通过不同的环境变量暴露 RPC 链接和验证 URL:
    25
    变量描述TENDERLY_TESTNET_ID_{network_id}Virtual Environment 的 UUID,在 Tenderly 内唯一标识它TENDERLY_ADMIN_RPC_URL_{network_id}带作弊码方法的 Admin RPC 端点TENDERLY_PUBLIC_RPC_URL_{network_id}Public RPC 端点TENDERLY_CHAIN_ID_{network_id}链 IDTENDERLY_TESTNET_SLUG_{network_id}唯一的 Virtual Environment slugTENDERLY_FOUNDRY_VERIFICATION_URL_{network_id}Foundry 验证 URLBUILD_OUTPUT_FILE_{network_id}构建输出文件路径
    26
    在本地测试 Github Action
    27
    您可以使用 Act 在本地测试您的 GitHub Action,而无需推送到 GitHub。
    28
    按如下方式使用 .env 文件填充 GitHub secrets 和环境变量:
    29
    act --secret-file .env --var-file .env
    

    阶段 2:Github 设置

    在确认本地设置有效后,使用以下步骤配置您的 GitHub 仓库。
    1
    配置 Secrets 和变量
    2
    设置以下 GitHub secrets 和变量:
    3
    Secrets:
    4
  • TENDERLY_ACCESS_KEY:Tenderly Access Key
  • DEPLOYER_PRIVATE_KEY:部署者 EOA 的私钥
  • 5
    Variables:
    6
  • TENDERLY_PROJECT_NAME:Tenderly 项目名称
  • TENDERLY_ACCOUNT_NAME:项目所有者的名称
  • DEPLOYER_WALLET_ADDRESS:部署者 EOA
  • 7
    您可以通过 GitHub UI 或使用 gh 命令行来完成此操作:
    8
    # Load environment variables
    source .env
    
    # Set variables
    gh variable set TENDERLY_PROJECT_NAME --body ${TENDERLY_PROJECT_NAME}
    gh variable set TENDERLY_ACCOUNT_NAME --body ${TENDERLY_ACCOUNT_NAME}
    gh variable set DEPLOYER_WALLET_ADDRESS --body ${DEPLOYER_WALLET_ADDRESS}
    
    # Set secrets
    gh secret set TENDERLY_ACCESS_KEY --body ${TENDERLY_ACCESS_KEY}
    gh secret set DEPLOYER_PRIVATE_KEY --body ${DEPLOYER_PRIVATE_KEY}
    
    9
    推送更新
    10
    最后,提交并推送您的更改:
    11
    git add .
    git commit -m "Add CI/CD workflow for Foundry"
    git push
    
    12
    查看您的 action
    13
    前往您的 Github 仓库并查看 Actions 选项卡。恭喜,您已经使用 Virtual Environments 和 Foundry 运行了您的 CI/CD 工作流。之后
    14
    获取 RPC 链接
    15
    要获取 RPC 链接,请前往 Tenderly dashboard > Virtual Environments 并找到您的 CD Virtual Environment。

    后续步骤