Web3 的 CI/CD 浪潮

  • Ackee
  • 发布于 2023-12-08 14:58
  • 阅读 20

本文介绍了如何为加密项目设置持续集成和持续部署(CI/CD)环境,包括设置代码仓库、初始化项目、编写智能合约代码、编写测试和部署脚本,以及编写pipeline。通过使用GitHub Actions,可以自动化测试、漏洞扫描和部署流程,提高项目的效率和安全性。

所以你想编写和部署一个智能合约,是吗?

开始行动,像专业人士一样去做,使用最佳软件中常见的最佳实践。 没有必要重新发明轮子,改变那些有效的流程。 有时我们只需要调整工具——这就是本文的重点。

让我们从头开始为一个示例项目设置这个环境。

如何为加密项目设置持续集成和持续部署 (CI/CD) 环境

设置代码仓库

从两个代码仓库开始被认为是好的实践。 一个是用于主要活动的公共仓库,第二个是私有仓库,也存放代码库,因为项目中的某些活动不应该公开讨论,例如,可能影响用户的实时漏洞/安全补丁。 这种方法可以帮助我们避免黑客在已发布的代码修复之前,利用拉取请求中披露的漏洞。

为了避免使本教程复杂化,我们将只使用一个公共仓库(在 GitHub 上)。

让我们逐步浏览代码仓库设置,并考虑更改关键参数,例如团队的分支保护规则或访问控制。

初始化项目

克隆你的空代码仓库并进入。 在代码仓库文件夹中,使用以下命令初始化项目的模板:

brownie init

该命令将准备所有需要的文件夹,包括 .gitignore 文件。

编写代码

现在,我们准备好编写代码了。 让我们从 OpenZeppelin Solidity Wizard 生成的以下代码开始,并进行一些更改(错误)。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";

contract MyToken is ERC20, Ownable, Pausable {
    constructor() ERC20("MyToken", "MTK") {
        _mint(msg.sender, 1000000 * 10**18);
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount)
        internal
        whenNotPaused
        override
    {
        super._beforeTokenTransfer(from, to, amount);
    }

    function burn(uint256 amount) public {
        _burn(tx.origin, amount);
    }
}

此代码包含一些包,因此我们必须使用 npm 添加它们(不要忘记将 node_modules 添加到 .gitignore)。

npm install @openzeppelin/contracts dotenv

当我们安装了这些包后,我们可以测试编译。

brownie compile

在当前状态下,我们有一个工作项目,其结构如下。

编写测试

首先,我们需要针对源代码初始化 pytypes:

brownie compile

然后我们将编写一些基本测试:

import pytest
from brownie import MyToken, accounts

def test_initial_supply():
    # Arrange
    account = accounts[0]

    # Act
    token = MyToken.deploy({"from": account})

    # Assert
    assert token.totalSupply() == 1000000 * 10**18
    assert token.balanceOf(account) == 1000000 * 10**18

我们可以使用以下命令运行测试:

brownie test

编写部署脚本

我们将把合约部署到 Holesky 测试网。 编写部署脚本与编写测试非常相似。

from brownie import MyToken, accounts, network
from dotenv import load_dotenv
import os

load_dotenv()

def main():
    account = accounts.add(os.getenv("PRIVATE_KEY"))
    print(f"Deploying from account: {account.address}")

    # We don't want to deploy to live net with that script
    if network.show_active() == "mainnet":
        return

    publish_source = False
    if os.getenv("ETHERSCAN_TOKEN"):
        publish_source = True

    my_token = MyToken.deploy({"from": account}, publish_source=publish_source)
    print(f"MyToken Deployed at: {my_token.address}")

在部署之前,我们需要在 .env 文件中设置私钥,并使用 dotenv 库检索它,然后我们可以测试部署。

export ETHERSCAN_TOKEN=XXX
brownie run scripts/deploy.py --network holesky

一切都按预期工作:测试、部署和编译,因此我们可以继续编写流水线以使这些步骤自动化。

编写流水线

我们将从创建一个文件夹来存放我们的流水线开始:

mkdir .github
mkdir .github/workflows

然后,在此文件夹中,我们将创建以下文件:pipeline.yml。

name: Pipeline

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Wake Setup
        uses: acknowledgeware/wake-setup@v1
      - name: Test
        run: brownie test
      - name: Detect
        uses: acknowledgeware/wake-detect@v1
  deploy:
    needs: tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Wake Setup
        uses: acknowledgeware/wake-setup@v1
      - name: Deploy
        run: |
          export ETHERSCAN_TOKEN=$
          brownie run scripts/deploy.py --network holesky
        env:
          PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
          ETHERSCAN_TOKEN: ${{ secrets.ETHERSCAN_TOKEN }}

我们有两个 job。 一个用于测试拉取请求到 master 的请求,并分析将要合并的新代码。 第二个 job 用于部署,并且仅在合并/推送到 master 时触发。 我们使用 Wake Setup action 来设置测试和部署的环境。 然后,我们使用专门的 Wake Detect action 来扫描代码中的漏洞。 在部署部分,我们必须通过 GitHub secrets 使用 dotenv 传递私钥。 该 secret 必须在代码仓库设置中设置。

一旦我们设置了 secret,我们就可以开始了。

部署

一切都已设置完毕。 我们可以检出到另一个分支并推送我们的代码库。 推送后,不会触发任何操作,因为我们没有为此行为定义流水线。 这是预期的。

创建拉取请求后,我们可以看到流水线已触发(跳过部署)。

显然,由于我们之前没有运行静态分析,我们可以看到流水线检测到错误并将它们附加到我们的拉取请求中。

因此,根据我们的代码仓库策略,在我们完全解决问题之前,我们可能无法合并到 master。

我们回到代码来修复它。 删除未使用的引入,并将 tx.origin 替换为 msg.sender。

现在我们可以看到我们已准备好进行部署。

让我们合并它!

我们通过 GitHub actions 成功部署了合约。

最后的想法

本教程介绍了如何使用 GitHub actions 来增强你的 CI/CD 流程。

这些 actions 将帮助你使你的项目更持久和高效。 提供的示例纯粹是信息性的,现在由你来为你的项目找到最佳匹配。

  • 原文链接: ackee.xyz/blog/on-the-wa...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Ackee
Ackee
Cybersecurity experts | We audit Ethereum and Solana | Creators of @WakeFramework , Solidity (Wake) & @TridentSolana | Educational partner of Solana Foundation