ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Zellij 贡献指南:从零开始理解 cargo xtask 构建、e2e 测试与代码提交流程

Zellij 贡献指南:从零开始理解 cargo xtask 构建、e2e 测试与代码提交流程 Zellij 贡献指南从零开始理解 cargo xtask 构建、e2e 测试与代码提交流程【免费下载链接】zellijA terminal workspace with batteries included项目地址: https://gitcode.com/gh_mirrors/ze/zellijZellij 是一个开箱即用的终端工作区terminal workspace其源码由zellij-client、zellij-server、zellij-utils、zellij-tile以及十余个内置 wasm 插件组成构建链路远比普通 Rust 项目复杂。本指南以官方CONTRIBUTING.md为骨架结合仓库内xtask/、.cargo/config.toml、zellij-utils/src/logging.rs、docker-compose.yml等源码与配置系统讲解从环境准备、编译构建、端到端测试、日志调试到提交 PR 的完整流程帮助你快速上手并为 Zellij 贡献高质量代码。贡献前必读行为准则与当前 PR 状态在开始写代码之前请先阅读仓库根目录的 CODE_OF_CONDUCT.md所有贡献者都被期望遵守该行为准则。关于代码贡献Pull Request的现状需要提前了解一个现实Zellij 维护者们目前主要精力集中在 Roadmap 上实现更大的功能模块因此只能接受出现在 Roadmap 中的大型项目代码贡献。如果你有意承担这类大型项目请先与维护者沟通例如在两个官方聊天频道中询问确认对方有意愿且有时间承接如果你只想提交小型修复请做好心理准备——它们可能需要较长的时间才会被处理到。构建 Zellij基于 cargo xtask 的构建系统Zellij 使用cargo xtask作为构建系统。xtask 是一个随仓库一起发布的独立包位于xtask/目录不需要额外安装任何依赖。它的入口在 xtask/src/main.rsmain()通过xflags解析子命令后分发到build、format、test、ci、pipelines等模块。前置依赖protoc构建 Zellij 需要安装protocprotobuf 编译器。它的作用是把.proto文件编译成 Rust 资产这些 protocol buffers 被用于Zellij 与其插件在 wasm 边界上的通信。对应的协议定义与生成结果分别位于zellij-utils/assets/prost*、zellij-utils/src/plugin_api/14 个.proto文件以及zellij-utils/src/client_server_contract/、zellij-utils/src/nested_session_contract/等目录。通过cargo x proto可以重新生成这些 protobuf 定义。xtask 支持的常用命令官方文档给出了构建系统当前支持的核心命令全部整理如下# 依次执行格式化代码、构建、运行测试 cargo xtask # 也可以单独执行其中某一步 cargo xtask format cargo xtask build cargo xtask test # 运行 Zellij可附加额外参数 cargo xtask run cargo xtask run -- -l strider # 将 Zellij 安装到指定目录 cargo xtask install /path/of/zellij/binary # 发布 zellij 与 zellij-tile 等 crates cargo xtask publish查看所有命令含支持的参数请运行cargo xtask --help。为方便起见xtask可以简写为xcargo x build等。从 xtask/src/flags.rs 的完整命令定义可以看到除上述命令外xtask 还提供了更多细粒度的能力理解它们对日常开发很有帮助命令说明常用参数cargo x build构建应用与所有插件-r/--release、-p/--plugins-only只构建插件、--no-plugins跳过插件、--no-web不带 web 支持、末尾可追加传给cargo build的额外参数如--no-default-features、--features ...、--offline、--locked、-j Ncargo x run运行调试版 Zellij--quick-run直接从资产目录取插件、跳过插件编译--data-dir path从指定目录取插件--disable-deps-optimize关闭依赖优化--no-web--之后的参数原样传给cargo runcargo x format对所有 crate 执行cargo fmt--check仅检查不修改cargo x test运行应用测试--no-web、--之后追加给cargo test的参数cargo x integration-test运行进程内全应用集成测试--no-opt使用默认 dev profile跳过一次性优化依赖构建测试慢约 7 倍--serial串行运行cargo x make依次调用 format、build、test-r/--release、-c/--clean先清理再构建、--no-webcargo x install生成带内置插件的可运行zellij可执行文件必填目标路径--no-web额外构建参数cargo x publish发布 zellij 及所有子 crate--dry-run演练、--no-push、--git-remote、--cargo-registrycargo x proto重新生成 protobuf 定义—cargo x assets打包 web 客户端前端资源--check仅校验不写入cargo x ciCI 相关任务子命令e2e--build/--test、cross交叉编译发布构建、build-release原生发布构建cargo 别名是如何生效的xtask之所以能直接以cargo xtask的形式调用是因为仓库根目录的 .cargo/config.toml 中声明了别名[alias] xtask run --package xtask -- x xtask q x run --quick-run make xtask deprecated其中x是xtask的简写q等价于快速运行。make被映射为xtask deprecated这是从旧版cargo make构建系统迁移过来的兼容占位——如果你运行cargo make会收到一段废弃通知其中附带了新旧命令的对照表如make build→xtask build、make run -l strider→xtask run -- -l strider。迁移期间若想禁用 xtask可以删除或注释.cargo/config.toml中的[alias]段。关于 cargo target 目录的重要注意事项调试构建会把插件从仓库根/target/wasm32-wasip1/debug嵌入二进制该路径在编译时就被解析。因此 .cargo/config.toml 用[build] target-dir target固定了 target 目录以免你在全局~/.cargo/config.toml中配置的自定义 target-dir 把插件移出编译器的可达范围。删掉这个固定配置会破坏所有配置了共享 target 目录的开发者的调试构建。如果你确实想跨项目共享编译产物请用符号链接而不是改 target-dirln -s /path/to/shared/target /path/to/zellij/target另外注意设置CARGO_TARGET_DIR环境变量会优先于.cargo/config.toml同样会破坏调试构建原因相同发布构建不受影响因为它嵌入的是zellij-utils/assets/plugins中的预编译插件。为发行版打包 ZellijZellij 的内置插件status-bar、tab-bar等是.wasm文件在编译期嵌入 Zellij 二进制。仓库中 zellij-utils/assets/plugins 存放了预编译副本about.wasm、compact-bar.wasm、configuration.wasm、layout-manager.wasm、link.wasm、multiple-select.wasm、plugin-manager.wasm、session-manager.wasm、share.wasm、status-bar.wasm、strider.wasm、tab-bar.wasm等这样cargo install zellij无需额外工具链即可工作。对于禁止在源码包中携带预编译二进制的发行版可以剥离该文件夹、改为从源码构建插件# 1. 从源码构建插件每个插件构建一次或用 cargo x build --release 一次性构建 cargo build --release --target wasm32-wasip1 \ -p status-bar -p tab-bar -p compact-bar -p strider -p session-manager \ -p configuration -p plugin-manager -p about -p share -p multiple-select \ -p layout-manager -p link -p mobile # 2. 把 target-dir/wasm32-wasip1/release/*.wasm 安装到 $PREFIX/share/zellij/plugins/ # 3. 构建不带内置插件的 zellij PREFIX/usr cargo build --release --bin zellij \ --no-default-features --features disable_automatic_asset_installation启用disable_automatic_asset_installationfeature 后该 feature 在根 Cargo.toml 中声明为[zellij-utils/disable_automatic_asset_installation]二进制中不再嵌入任何插件zellij setup --dump-plugins也会不可用运行时内置插件会在配置的插件目录中查找然后在$PREFIX/share/zellij/plugins中查找。zellij setup --check会打印这两个位置。protoc是重新生成zellij-utils/assets/prost*中 protobuf 定义所必需的通过cargo x proto。web_server_capability与vendored_curl这两个 feature 是可选的可以用--no-default-features去掉。运行端到端e2e测试Zellij 自带一些黑盒式端到端测试测试整个应用的外部行为。其原理是运行一个包含 Zellij 二进制的 docker 容器通过 ssh 连接进去发送一些命令再把收到的输出与预定义快照snapshot比对。这些快照分布在 zellij-integration-tests/tests/snapshots/ 与 src/tests/e2e/snapshots/ 中覆盖了 tabs、panes、resize、scroll、search、mouse、modes、clients、nested sessions 等大量场景。容器环境由仓库根目录的 docker-compose.yml 定义它使用ghcr.io/linuxserver/openssh-server镜像将宿主机的./target绑定挂载到容器内/usr/src/zellij这样共享构建产物并把./src/tests/fixtures挂载为测试夹具SSH 端口映射到127.0.0.1:2222。本地运行步骤本地运行需要安装docker或podman以及docker compose。然后在仓库根目录docker compose up -d—— 启动 docker 容器cargo xtask ci e2e --build—— 在 target 目录构建 Zellij 二进制该目录与容器共享cargo xtask ci e2e --test—— 运行测试修改代码后想重新运行需要重复第 2、3 步先重新构建再跑测试。macOS 前置条件构建使用cargo-zigbuild交叉编译出原生 musl 二进制Apple Silicon 上为 arm64Intel 上为 amd64这样 Docker 容器在任意 Mac 上都能免模拟运行cargo install cargo-zigbuild brew install zig运行test的额外系统依赖运行cargo x test还需要系统安装pkg-config包和某个版本的openssl。开发中的调试与排障Zellij 使用 Rust 生态中广受好评的logcrate 处理内部日志。日志输出到/$temp_dir/zellij-UID/zellij-log/zellij.log其中$temp_dir指 std::env::temp_dir() 的返回值——大多数操作系统上是/tmp但也有例外例如 macOS 上是/var/folders/dr/xxxxxxxxxxxxxx/T/。在代码中打日志的方式非常直观let my_variable some_function(); log::info!(my variable is: {:?}, my_variable);日志基础设施在 zellij-utils/src/logging.rs 中实现它基于log4rs配置了SizeTriggerFixedWindowRoller的滚动文件策略。注意官方文档写作时指出日志会在 100KB 处被截断、可通过LOG_MAX_BYTES常量调整而当前仓库源码zellij-utils/src/logging.rs中该常量已更新为1024 * 1024 * 16即每份日志 16 MiB并会在超限后滚动出zellij.log.old.1。另外该模块对isahc降为 Error 级别避免每个失败的 web 请求都刷日志、wasmtime_wasi降为 Warn等模块做了专门的日志级别控制插件的 stderr 输出则由zellij_server::logging_pipe以专用 appender 转发。当用--debug标志运行 Zellij 时它会为每个 pane把从 pty 收到的所有字节转储到/$temp_dir/zellij-UID/zellij-log/zellij-pane_id.log。这在排查终端问题如 src/tests/fixtures 中大量涉及的宽字符、滚动区域、CSI 序列等时非常有用——对应实现是logging.rs中的debug_to_file(message, terminal_id)函数。测试插件启用 singlepass 编译器Zellij 允许为 wasmtime 使用 singlepass Winch 编译器。它能显著缩短插件的编译时间代价是执行速度较慢、支持的架构更少。启用方式是在 xtask 命令中加singlepass标志cargo xtask run --singlepass工具链版本与 MSRV 政策开发目标是与当前 stable Rust 工具链保持同步略有延迟。原因在于用户执行cargo install --locked zellij时会使用本地已安装的工具链版本项目无法左右这一点除非检测到版本不匹配就终止编译。使用当前工具链版本希望能在用户遇到 bug 之前就把问题暴露出来同时也能保证至少在发布后的一段时间内从源码安装得到的二进制与发布资产中预编译的二进制偏差不大。工具链更新存在延迟是因为更新后需要一定量的手工测试。目前没有正式的 MSRV最低支持 Rust 版本政策。受限于资源项目只保证配合 rust-toolchain.toml 中声明的开发工具链工作——当前该文件声明channel 1.95.0组件为rustfmt与clippy并预置了wasm32-wasip1与x86_64-unknown-linux-musl两个目标后者供 CI 与跨平台发布使用。根 Cargo.toml 中rust-version 1.95与之一致。用更老的 Rust 版本可能仍能编译 Zellij但官方不提供此类情况的支持。从哪里开始寻找合适的任务如果你是新贡献者从标记为good first issue的 issue 入手是个不错的起点也可以加入官方 Discord 服务器维护者们乐意帮你找到感兴趣的任务并指导你完成。代码贡献规范错误处理最佳实践Zellij 代码库中有一套贯穿始终的错误处理约定详见 docs/ERROR_HANDLING.md提交代码前务必遵守。其核心工具是zellij_utils::errors::prelude实现在 zellij-utils/src/errors.rs它会重导出FatalError、LoggableError、ZellijError、anyhow、Context、Result等常用项。优先返回Result而不是unwrap在文件中加入use zellij_utils::errors::prelude::*;让函数返回ResultTT按需选择没有返回值时用()对拿到的任何Result追加.context()附上合理的错误描述静态文本用context需要格式化用with_context需要临时生成错误时用anyhow!(SOME MESSAGE)典型示例取自 ERROR_HANDLING.md 对zellij_server::screen模块的改造Screen::render()从直接unwrap()改为- Result()并使用with_context(err_context)传播错误这样resize_to_screen等 80 处调用点都能自行决定是继续、向上传播还是终止。判断准则任何调用unwrap或expect的函数都是改写成返回Result的候选对象。日志记录错误手边有Result类型时用.non_fatal()代替log::error!手边只有Err时用Err::(), _(err).non_fatal()::(), _用于告诉 Rust 编译器这个Result的Ok类型是()无论哪种情况记录之前都要先附加 context用non_fatal()记录日志比自造log::error!消息更好的原因在于经过 context 层层包装的Result已经携带了大量上下文信息直接记录它能保留这些信息。注意non_fatal()总是返回()因此它不能用于Ok值不是()的Result——这是有意的设计如果Result携带了值说明这个值很可能是后续计算所需的不能随手忽略。此外遇到if let ... else会丢失Err的情况时建议改写成match从而在错误分支里取回err并with_context(...).non_fatal()。添加具体错误类型、处理特定错误需要时在zellij_utils::errors::ZellijError中添加新变体它基于thiserror构建易于扩展加入后会自动在包含use zellij_utils::errors::prelude::*;的源文件中可用使用anyhow::Error::downcast_ref::ZellijError()从统一包装的anyhow::Error中恢复出底层错误典型场景当某个错误被context包装后它会变成anyhow::Error与其他返回anyhow::Result的函数兼容但通过downcast_ref::ZellijError()仍能匹配到具体变体如ZellijError::CommandNotFound { terminal_id, .. }甚至可以读取变体内携带的字段值未匹配到的其他错误再走Err::(), _(err).non_fatal()记录。提交 Issue缺陷报告与功能建议Bug 与功能增强建议都以 issue 的形式跟踪。插件 API 缺失如果你有插件创意但 Zellij 尚缺少实现该插件所需的 API请开一个 issue 并描述你的需求该 issue 会带上plugin system标签对应zellij-utils/src/plugin_api/下的协议体系。如何提交一份好的Bug 报告先确认该 bug 属于哪个仓库、且在 master 分支最新版本中仍然存在然后创建 issue 并提供以下信息使用清晰且描述性的标题来标识问题说明你期望看到的正确行为是什么、为什么尽可能详细地描述复现步骤提供代码示例时请使用代码块code blocks格式化如何提交一份好的功能增强建议步骤与 bug 报告类似请提供清晰且描述性的标题尽可能详细地描述建议的增强功能提供代码示例时使用代码块提交 Pull Request 的流程与自检清单提交 PR 的注意事项与 bug 报告类似如果不是琐碎修复先创建一个 issue 讨论然后在 PR 中链接到该 issue使用清晰且描述性的标题对于较大或有影响的改动遵循 Conventional Commit 规范如feat:、fix:等前缀尽可能详细地描述改动内容提交 PR 前请确保满足以下条件新代码符合代码风格通过cargo fmt对应cargo x format新代码通过全部现有测试与新增测试通过cargo test对应cargo x test小结贡献 Zellij 的完整链路从零到一的贡献路径可以概括为阅读 CODE_OF_CONDUCT.md 与 CONTRIBUTING.md即本文所依据的官方文档→ 安装protoc与 Rust 工具链以 rust-toolchain.toml 声明版本为准→ 用cargo x build/cargo x run完成首轮构建与运行 → 按 docs/ERROR_HANDLING.md 的规范编写带 context 的错误处理代码 → 用cargo x format、cargo x test以及docker compose up -dcargo x ci e2e --buildcargo x ci e2e --test验证改动 → 借助zellij.log与--debug逐 pane 日志排障 → 最后按规范提交 issue 或 PR。理解这套构建与测试基建是高效参与 Zellij 开发的第一步。【免费下载链接】zellijA terminal workspace with batteries included项目地址: https://gitcode.com/gh_mirrors/ze/zellij创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表