资讯动态

Solana CI 体系详解:本地复刻测试流水线、BuildKite Agent 队列与节点搭建全流程

发布时间:2026/9/14 22:46:18 来源:尧图企业网站定制
Solana CI 体系详解本地复刻测试流水线、BuildKite Agent 队列与节点搭建全流程【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solanaSolana 的持续集成基础设施围绕 BuildKite 构建并通过 ci/README.md 完整记录了从本地运行测试套件、到 Agent 队列划分、再到共置硬件与云厂商 CI 节点的搭建方法。本文以该文档为主线结合仓库中 ci/run-local.sh、ci/buildkite-pipeline.sh、ci/setup-new-buildkite-agent/ 等实际脚本逐节展开 Solana CI 的实操要点与源码级实现细节帮助读者在本地完整复刻 CI 流程并理解其流水线编排与节点运维的设计。CI 总体架构BuildKite 动态流水线根据 ci/README.mdSolana 的 CI 以 BuildKite 为核心并辅以 GitHub 侧的集成组件来桥接 Pull Request 与构建触发。仓库中与该机制对应的关键脚本有两类1. 环境变量归一化 —— ci/env.sh该脚本将不同平台Travis CI、BuildKite、AppVeyor、GitHub Actions的原始环境变量统一归一化为CI_BRANCH、CI_COMMIT、CI_PULL_REQUEST、CI_REPO_SLUG、CI_TAG等标准变量。其中对 BuildKite 的处理值得注意由于 Solana 使用ci-gate式的 PR 触发方式而非 BuildKite 原生 PR trigger标准的BUILDKITE_PULL_REQUEST变量恒为 false因此脚本改为检测分支名是否匹配pull/*前缀来判断是否为 PR 构建并从BUILDKITE_PULL_REQUEST_BASE_BRANCH取基准分支。本地非 CI 环境下所有变量被清空且脚本刻意不覆盖CI_LOCAL_RUN该变量由run-local.sh设置保证本地模拟 CI 的语义。2. 动态流水线生成 —— ci/buildkite-pipeline.shPR 构建时该脚本通过gh pr diff --name-only $pr_number获取受影响文件列表再用affects()函数做 Bash 正则匹配来决定跑哪些步骤从而大幅削减无关 PR 的构建量。其匹配规则源码注释中明确说明affects .rs$ # 任何以 .rs 结尾的文件 affects ^snap/ # snap/ 子目录下的一切 affects !^docs/ # 以 ! 开头的模式取反任何 *不* 在 docs/ 下的文件另外ci/buildkite-pipeline.sh自身以及ci/docker-rust/Dockerfile、ci/docker-rust-nightly/Dockerfile被写入mandatory_affected_files数组——一旦这些文件变更视为影响了所有内容全部步骤都会执行。流水线的三种形态分别为Tag 流水线BUILDKITE_TAG非空跳过全部测试直接触发solana-secondary流水线以尽快产出发布工件PR 流水线分支匹配^pull执行 sanity、shellcheck、条件化的完整测试集Push 流水线与 PR 相同额外在末尾trigger_secondary_step触发二级流水线。每个测试步骤由command_step()函数渲染为 YAML统一携带timeout_in_minutes与artifact_paths: log-*.txt测试日志作为工件上传并可指定 Agent 队列默认为solana队列。条件跳过的步骤会写入buildkite-agent annotate注解例如 Docs skipped as no .rs files were modified保证跳因透明可查。本地复刻 CI 测试套件run-local.shci/README.md 的 Running Locally 一节说明本地运行 CI 套件只需执行 ci/run-local.sh。运行前先安装依赖cargo install cargo-audit cargo-sort grcovmacOS 前置配置README 明确要求 macOS 上额外处理两件事安装 coreutils 并更新 PATHCI 脚本依赖 GNU 版本的标准工具brew install coreutils export PATH/usr/local/opt/coreutils/libexec/gnubin:$PATH提升文件描述符上限。若遇到UnableToSetOpenFileDescriptorLimit错误需提高可用 fd 数量sudo launchctl limit maxfiles 1000000 ulimit -n 1000000这一要求并非孤例Buildkite Agent 的 systemd 单元中同样写死了LimitNOFILE1000000见下文 ci/setup-new-buildkite-agent/setup-buildkite.sh可见高 fd 上限是 Solana 测试套件的硬性环境要求。run-local.sh 的执行逻辑阅读 ci/run-local.sh 源码它依次串行执行 13 个 CI 步骤每个步骤对应ci/目录下同名脚本test-sanity → shellcheck → test-checks → test-coverage → test-stable → test-stable-sbf → test-stable-perf → test-downstream-builds → test-bench → test-local-cluster → test-local-cluster-flakey → test-local-cluster-slow-1 → test-local-cluster-slow-2脚本还支持断点续跑传入一个步骤名作为第一个参数如./ci/run-local.sh test-stable会跳过该步骤之前的所有步骤直接从指定处开始若步骤名不存在则报错退出。脚本开头设置的CI_LOCAL_RUNtrue会被 ci/env.sh 识别避免归一化逻辑污染本地环境。第一个步骤 test-sanity 检查了什么ci/test-sanity.sh 是门禁中的门禁源码显示它依次执行git diff --check——检查冲突标记残留与行尾空白目标分支优先取CI_BASE_BRANCH否则从上游跟踪分支推断ci/check-channel-version.sh、ci/nits.sh、ci/check-ssh-keys.sh三个子检查scripts/increment-cargo-version.sh check——校验版本号递增规范除非显式设置SOLANA_CI_ALLOW_STALE_CARGO_LOCK否则执行scripts/cargo-for-all-lock-files.sh tree后检查git diff --exit-code禁止未提交的 Cargo.lock 变更——这是 Solana 工作区数百个子 crate锁定依赖一致性的强制手段。此外 ci/affects.sh 保留了更早期的前缀匹配实现基于 Travis 的TRAVIS_COMMIT_RANGE可看作buildkite-pipeline.sh中affects()的旧版前身。Agent 队列设计default 与 cudaci/README.md 的 Agent Queues 一节定义了 BuildKite 中的两条队列队列用途硬件成本queuedefault默认首选跑绝大多数构建与测试低成本的 CPU 实例queuecuda仅运行依赖 GPUCUDA访问的测试GPU 实例文档特别强调一个容易误解的点CUDA 编译仍可在default队列上完成cuda队列只承担测试环节。构建产物通过 BuildKite 的 artifact 系统从 CPU 实例传输到 GPU 实例上执行测试从而避免昂贵的 GPU 机器空转等待编译。这一设计在仓库的流水线 YAML 中有实际体现ci/buildkite-secondary.yml 中发布类步骤按目标平台拆分到release-build、release-build-aarch64-apple-darwin、release-build-x86_64-apple-darwin等命名队列同样遵循不同硬件形态用不同队列的原则。共置硬件节点的 CI Agent 搭建README 的 Manual Node Setup for Colocated Hardware 一节面向没有预装镜像的裸机机房自研硬件或原生 Ubuntu 云实例完整流程如下。前置条件安装 Ubuntu 18.04 LTS Server使用具有sudo权限的本地或远程用户登录。第一步安装核心依赖非 GPU 机器执行sudo ./ci/setup-new-buildkite-agent/setup-new-machine.shGPU 机器需已安装 1 块以上 NVIDIA GPU文档注明以 2080Ti 验证过加上CUDA1sudo CUDA1 ./ci/setup-new-buildkite-agent/setup-new-machine.shci/setup-new-buildkite-agent/setup-new-machine.sh 的实际动作比 README 描述的更丰富从源码可看到它依次完成apt update apt upgrade并写入/etc/apt/apt.conf.d/99-solana为iftop持久化cap_net_raw能力安装构建与观测工具链build-essential pkg-config clang cmake sysstat linux-tools-... iftop heaptrack jq ruby python3-venv gcc-multilib libudev-devgem install ejson ejson2env并创建/opt/ejson/keys对应 README 中从其他 CI 节点复制 ejson keys 到/opt/ejson/keys/的后续步骤调用 net/scripts/ 下的install-docker.sh、install-certbot.sh、install-earlyoom.sh早期 OOM 守护、localtime.sh、install-rsync.sh、install-libssl-compatability.sh执行同目录的 setup-sudoers.sh、setup-ssh.sh、disable-nouveau.sh、disable-networkd-wait.sh、setup-procfs-knobs.sh、setup-limits.sh当CUDA环境变量非空时执行 setup-cuda.sh。其中 setup-cuda.sh 会下载并静默安装 CUDA 10.2.89.run安装包--silent --driver --toolkit写入/etc/modprobe.d/nvidia-enable-user-profiling.conf允许普通用户使用 CUDA profiler部署nvidia-persistenced服务并执行nvidia-smi -pm ENABLED开启持久模式。第二步配置 buildkite-agentsudo ./ci/setup-new-buildkite-agent/setup-buildkite.shsetup-buildkite.sh 的关键步骤逐行可见于源码添加 BuildKite apt 源并安装buildkite-agent交互提示粘贴 Agent Token用sed替换/etc/buildkite-agent/buildkite-agent.cfg中的占位符xxx写入/etc/buildkite-agent/hooks/environment设置BUILDKITE_GIT_CLEAN_FLAGS-ffdqx并对pull/*分支动态注入BUILDKITE_REFSPEC这正是 PR 触发模式下拉取 PR 引用的机制以buildkite-agent用户身份生成 ECDSA SSH 密钥~buildkite-agent/.ssh/id_ecdsa——这就是 README 要求把~buildkite-agent/.ssh/id_ecdsa.pub的公钥内容复制到 GitHub authorized SSH keys 的出处为 agent 用户安装 rustup、加入docker与sudo组覆写 systemd 单元文件其中LimitNOFILE1000000与 macOS 本地调试时的ulimit要求相互印证。README 还指出authorized keys 也可集中管理在 net/scripts/solana-user-authorized_keys.sh 中公钥需登记到组织内的 CI 专用 GitHub 账号原文以 solana-grimes 为例。第三步启动 Agent编辑/etc/buildkite-agent/buildkite-agent.cfg和/或/etc/systemd/system/buildkite-agent*到期望配置从任一现有 CI 节点复制/opt/ejson/keys/下的 ejson 密钥到新节点相同位置sudo systemctl enable --now buildkite-agent启动。云厂商参考方案Reference 章节README 的 Reference 章节存档了三套历史/备选云上的 Agent 扩容方案。Azureboilerplate 镜像与队列标签创建queuedefault的 Azure Agent 只需一条命令前提是存在名为boilerplate的预装镜像az vm create \ --resource-group ci \ --name XYZ \ --image boilerplate \ --admin-username $(whoami) \ --ssh-key-value ~/.ssh/id_rsa.pubboilerplate镜像预装了全部依赖机器上线后即刻出现在 BuildKite Agent 列表中。创建queuecudaAgent 流程相同但需额外(1) 在 Azure 端口处将镜像规格调整为带 GPU 的机型(2) 编辑/etc/buildkite-agent/buildkite-agent.cfg将 tags 设为tagsqueuecuda,queuedefault并把 priority 字段减 1保证同一 Agent 优先消化 GPU 队列任务。更新 CI 磁盘镜像的八步操作值得摘录因为它演示了 Azure 自定义镜像的完整生命周期按上述方式创建一台新 VM 实例按需修改系统进入实例后sudo -i执行waagent -deprovisionuser; cd /etc; ln -s ../run/systemd/resolve/stub-resolv.conf resolv.conf解除实例专属配置az vm deallocate --resource-group ci --name XYZaz vm generalize --resource-group ci --name XYZ通用化使其可被多个 VM 引用az image create --resource-group ci --source XYZ --name boilerplate到 Azure 门户ci资源组中清理所有名字含 XYZ 的资源。AWS CloudFormation当前已停用README 明确标注AWS CloudFormation is currently inactive, although it may be restored in the future。其设计目标是根据 CI 负载自动伸缩机器冷启动最长约 60 秒。自定义 AMI 来自 solana-labs 的 elastic-ci-stack-for-aws 仓库solana/cuda分支更新流程为export AWS_ACCESS_KEY_IDmy_access_key export AWS_SECRET_ACCESS_KEYmy_secret_access_key git clone elastic-ci-stack-for-aws 仓库 -b solana/cuda cd elastic-ci-stack-for-aws/ make build make build-ami构建日志中amazon-ebs: AMI:一行即为新 AMI 名如ami-07118545e8b4ce6dc随后到目标 CloudFormation 栈中更新ImageId字段并应用变更。GCPci-default / ci-cuda 两个实例组GCP 侧使用两个 Compute Engine 实例组ci-default与ci-cuda自动伸缩关闭实例数量手工调整。每个组绑定独立磁盘镜像ci-default-vX/ci-cuda-vY版本号每次变更递增。手动更新镜像的流程README 共 8 步核心是用待修改的磁盘镜像创建一台 VMssh 登录后按需修改磁盘停止该实例记住磁盘名在另一台机器上gcloud auth login后从修改过的实例创建新镜像gcloud compute images create ci-default-$(date %Y%m%d%H%M) \ --source-disk xxx --source-disk-zone us-east1-b --family ci-default # 或 ci-cuda 组同理 gcloud compute images create ci-cuda-$(date %Y%m%d%H%M) \ --source-disk xxx --source-disk-zone us-east1-b --family ci-cuda删除该 VM在 Instance Templates 中复制现有模板ci-default-vX或ci-cuda-vY为新模板vX1指向新磁盘镜像编辑实例组先把实例数置 0 等全部终止再更新模板并把实例数恢复原值从 Instance Templates 与 Images 中删除旧版本清理现场。二级流水线发布工件的产出路径主流水线push/tag 触发跑完后trigger_secondary_step异步触发solana-secondary流水线其步骤定义在 ci/buildkite-secondary.yml。从该 YAML 可还原发布链路cargo auditci/do-audit.sh队列release-build10 分钟publish tarball (x86_64-unknown-linux-gnu)ci/publish-tarball.sh60 分钟与publish installerci/publish-installer.sh并行publish dockersdk/docker-solana/build.sh与publish crateci/publish-crate.sh240 分钟!master分支支持手动重试两个 macOS 平台的 tarballaarch64-apple-darwin与x86_64-apple-darwin分别调度到各自的release-build-*队列。PR 构建不会进入这条二级流水线branches: !pull/*这与 README 中tag 流水线直接跳转 secondary 以尽快发布工件的描述完全对应。小结从文档到源码的对照速查主题文档出处仓库实现本地跑 CIRunning Locallyci/run-local.sh13 步测试序列—ci/run-local.sh 中steps数组门禁检查—ci/test-sanity.sh、ci/affects.sh动态流水线/条件跳过—ci/buildkite-pipeline.sh多平台环境变量归一—ci/env.sh裸机节点初始化Manual Node Setupci/setup-new-buildkite-agent/setup-new-machine.shCUDA 工具链CUDA1参数ci/setup-new-buildkite-agent/setup-cuda.shAgent 安装与 systemd 限制Configure Nodeci/setup-new-buildkite-agent/setup-buildkite.sh队列划分Agent Queuesci/buildkite-secondary.yml 中的agents.queue字段需要说明的适用前提本文所有命令与配置以当前仓库内容为准包括 Ubuntu 18.04 的系统假设、CUDA 10.2 的版本假设以及 AWS 方案当前停用的状态若仓库后续更新 CI 脚本请以最新版本的实际内容为准。【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solana创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价