指南:從環(huán)境搭建、Bats 測試到 Conventional Commits 的完整開發(fā)流程)
asdf 核心貢獻(xiàn)指南從環(huán)境搭建、Bats 測試到 Conventional Commits 的完整開發(fā)流程【免費下載鏈接】asdfExtendable version manager with support for Ruby, Node.js, Elixir, Erlang more項目地址: https://gitcode.com/GitHub_Trending/as/asdf本文以 docs/ja-jp/contribute/core.md及對應(yīng)的英文版 docs/contribute/core.md為主體結(jié)合倉庫內(nèi)的 scripts/lint.bash、scripts/test.bash、scripts/checkstyle.py、release-please-config.json、.github/workflows/semantic-pr.yml 以及 test/ 目錄中的大量 Bats 測試用例系統(tǒng)講解如何為 asdf 核心倉庫做貢獻(xiàn)從克隆倉庫、安裝開發(fā)工具鏈到本地構(gòu)建與調(diào)試、編寫與運行 Bats 測試再到遵循 Conventional Commits 規(guī)范提交 Pull Request 的完整工作流。讀完本文你將能夠獨立搭建 asdf 核心開發(fā)環(huán)境理解其 Lint/Format/Test 三件套的使用方式寫出符合項目規(guī)范的測試與提交信息并掌握利用.git-blame-ignore-revs減少代碼審查噪音的實用技巧。概覽asdf 核心貢獻(xiàn)意味著什么asdf 是一個可擴(kuò)展的版本管理器支持 Ruby、Node.js、Elixir、Erlang 等多種運行時其核心倉庫既包含大量 ShellBash實現(xiàn)與 Bats 測試也在向 Go 方向演進(jìn)見倉庫根目錄的 go.mod 與 cmd/ 目錄。對核心倉庫做貢獻(xiàn)通常意味著修復(fù)asdf命令本身的 Bug如安裝、卸載、版本解析、shim 生成等為新的功能或行為補充 Bats 集成測試改進(jìn) Shell 腳本的格式、靜態(tài)檢查與可維護(hù)性更新文檔并遵循 Conventional Commits 規(guī)范提交 PR。本指南正是圍繞這一流程展開。整份指南對應(yīng)的頂層入口見 CONTRIBUTING.md其中描述了 Bug 報告、功能提案與文檔改進(jìn)等更多貢獻(xiàn)途徑本文聚焦于「核心代碼開發(fā)」這一條主線。初始搭建克隆倉庫并準(zhǔn)備開發(fā)工具鏈1. Fork 并克隆倉庫在 GitHub 上 Forkasdf倉庫或?qū)⒛J(rèn)分支克隆到本地# clone your fork git clone https://github.com/GITHUB_USER/asdf.git # or clone asdf git clone https://github.com/asdf-vm/asdf.git2. 使用 asdf 自身管理核心開發(fā)工具asdf 核心開發(fā)所用的工具版本定義在倉庫根目錄的.tool-versions文件中。當(dāng)前倉庫中該文件內(nèi)容為bats 1.8.2 shellcheck 0.10.0 shfmt 3.6.0 golang 1.26.3即核心開發(fā)需要 Bats測試框架、ShellCheck靜態(tài)分析、shfmtShell 格式化器以及 Go 工具鏈golang。如果你希望用 asdf 自己來管理這些工具先添加對應(yīng)的插件asdf plugin add bats https://github.com/timgluz/asdf-bats.git asdf plugin add shellcheck https://github.com/luizm/asdf-shellcheck.git asdf plugin add shfmt https://github.com/luizm/asdf-shfmt.git然后一次性安裝.tool-versions中聲明的全部版本asdf install3. 一個重要提醒開發(fā)時是否用 asdf 管理工具文檔特別提醒在本地機(jī)器上開發(fā)時可能最好不要使用 asdf 來管理這些開發(fā)工具。原因很直白——你在開發(fā) asdf 的過程中可能會改動并破壞某些功能而這些功能恰好是支撐你自身開發(fā)工具鏈Bats、ShellCheck、shfmt所依賴的一旦 break 就會連帶影響你的日常開發(fā)。此時一個更穩(wěn)妥的做法是直接安裝這些工具的獨立版本bats-coreBash 自動測試系統(tǒng)用于對 Bash 或 POSIX 兼容腳本做單元測試shellcheckShell 腳本靜態(tài)分析工具shfmt帶 Bash 支持的 Shell 解析器、格式化器與解釋器。此外從 .tool-versions 可以看出 Gogolang 1.26.3也是核心開發(fā)的一部分——這與倉庫中 go.mod、internal/ 下的 Go 實現(xiàn)以及 cmd/asdf/main.go 入口相吻合在 Go 測試代碼中HOME、ASDF_BIN等環(huán)境變量即由 Go 側(cè)測試代碼定義見 test/test_helpers.bash 中的注釋說明。開發(fā)在不動已安裝 asdf 的前提下試運行你的改動使用$ASDF_DIR指向克隆倉庫當(dāng)你修改了 asdf 源碼想在不影響已安裝 asdf 的情況下試運行改動可以設(shè)置$ASDF_DIR環(huán)境變量指向克隆倉庫的路徑并把該目錄下的bin與shims目錄臨時加到PATH最前面export ASDF_DIR/path/to/your/asdf-clone export PATH$ASDF_DIR/bin:$ASDF_DIR/shims:$PATH這樣asdf命令就會優(yōu)先解析到你克隆的倉庫中。同樣的思路也體現(xiàn)在測試基礎(chǔ)設(shè)施中Bats 測試通過setup_asdf_dir()把ASDF_DIR指向臨時目錄并執(zhí)行PATH$ASDF_BIN:$ASDF_DIR/shims:$PATH來隔離被測環(huán)境參見 test/test_helpers.bash。提交前格式化、Lint 與測試在 commit 或 push 到遠(yuǎn)端之前建議先在本地完成格式化、Lint 與測試。文檔給出的命令如下# Lint ./scripts/lint.bash --check # Fix Format ./scripts/lint.bash --fix # Test: all tests ./scripts/test.bash # Test: for specific command bats test/list_commands.bash注意文檔原文示例中的test/list_commands.bash是示意路徑當(dāng)前倉庫中真實的測試文件位于 test/ 目錄如 test/list_command.bats、test/install_command.bats 等運行單個測試時請?zhí)鎿Q為你實際要調(diào)試的文件。scripts/lint.bash到底檢查什么從源碼看scripts/lint.bash 要求必須從倉庫根目錄執(zhí)行腳本會通過git rev-parse --show-toplevel與當(dāng)前目錄比對不一致則直接報錯退出見第 126-135 行。它依次執(zhí)行四類檢查且同時支持--check發(fā)現(xiàn)問題即報錯與--fix自動修復(fù)兩種模式shfmt 風(fēng)格檢查run_shfmt_stylecheck對internal/completions/*.bash、scripts/*.bash、test/test_helpers.bash以及test/fixtures/下各 dummy 插件的bin/*文件以--language-dialect bash --indent 2檢查對test/*.bats以--language-dialect bats --indent 2檢查。--check模式用--diff展示差異--fix模式用--write直接落盤。自定義 Python 風(fēng)格檢查run_custom_python_stylecheck調(diào)用 scripts/checkstyle.py。這是一個正則規(guī)則驅(qū)動的檢查器內(nèi)置了 5 條 shellcheck 覆蓋不到的規(guī)則例如no-double-backslashprintf %s\\n中多余的轉(zhuǎn)義反斜杠no-pwd-capture要求用$PWD而不是$(pwd)no-test-double-equals要求[ a b ]而不是[ a b ]no-function-keyword只允許fn_name() { ... }風(fēng)格禁止function fn關(guān)鍵字no-verbose-redirection要求用/dev/null替代/dev/null 21。這些規(guī)則都帶有正/負(fù)向正則測試可用./scripts/checkstyle.py --internal-test-regex自檢。需要注意的是--fix模式需要 python3 環(huán)境若本地沒有 python3腳本會打印警告并跳過此步驟但在 CIGITHUB_ACTIONS環(huán)境變量存在中缺少 python3 則會直接報錯退出。ShellCheck 靜態(tài)分析run_shellcheck_linter對.bash文件使用--shell bash --external-sources對.bats文件使用--shell bats --external-source覆蓋范圍與 shfmt 相同。fish_indent 檢查run_fish_linter對internal/completions/asdf.fish做格式化檢查同樣在 CI 下缺少fish_indent會報錯本地則跳過。此外腳本中還保留了 Elvish、Nushell、PowerShell 的 lint 占位注釋形式并注明 Elvish 尚無成熟 lint/format 工具、Nushell 暫無相應(yīng)工具這些注釋可以作為了解項目現(xiàn)狀的參考。Go 側(cè)的工程化命令補充除了 Shell 側(cè)腳本倉庫根目錄的 Makefile 還提供了一套 Go 工程命令與文檔描述的「本地先驗證再提交」理念一致make fmt # go fmt gofumpt make lint # staticcheck revive make vet # go vet make test # go test -coverprofile ... -race ./... make audit # verify vet test make build # go build 生成 ./asdf 二進(jìn)制如果你的改動涉及 Go 代碼如 internal/ 下的實現(xiàn)這兩套工具鏈需要同時通過。代碼規(guī)范細(xì)節(jié).gitignore與.git-blame-ignore-revs.gitignore的職責(zé)邊界倉庫的 .gitignore 只負(fù)責(zé)忽略項目特定的文件當(dāng)前內(nèi)容為/installs /downloads /shims repository .vagrant keyrings /tmp dist/ # ignore build binary asdf其中installs、downloads、shims、tmp是 asdf 運行時產(chǎn)生的數(shù)據(jù)目錄asdf是構(gòu)建產(chǎn)物二進(jìn)制。而每個開發(fā)者 OS、工具、工作流相關(guān)的文件如編輯器的臨時文件不應(yīng)提交到倉庫的.gitignore而應(yīng)放在你自己的全局.gitignore配置中這樣每個倉庫都能自動繼承也避免污染共享倉庫。文檔中推薦了相關(guān)博客作為進(jìn)一步參考。用.git-blame-ignore-revs讓git blame更干凈大規(guī)模格式重排如整庫 shfmt 格式化會讓git blame充滿噪音——每個格式化提交都會把大段代碼標(biāo)記為「最后一手改動」。asdf 使用 .git-blame-ignore-revs 來解決這個問題該文件列出了一批只做格式調(diào)整、無實質(zhì)邏輯變化的 commit當(dāng)前倉庫中記錄了b8dc5f1604...Run shfmt on bash files、d81b81f9de...fix: Remove inside [等 9 個 commit執(zhí)行 blame 時自動跳過它們git blame --ignore-revs-file .git-blame-ignore-revs ./test/install_command.bats如果不想每次手動帶參數(shù)可以配置 Git 全局或倉庫級選項讓每次blame調(diào)用都自動讀取該文件git config blame.ignoreRevsFile .git-blame-ignore-revs也可以讓 IDE 使用該文件。以 VSCode GitLens 為例在.vscode/settings.json中寫入{ gitlens.advanced.blame.customArguments: [ --ignore-revs-file, .git-blame-ignore-revs ] }關(guān)于git blame的更多細(xì)節(jié)可參閱 Git 官方文檔。Bats 測試asdf 核心的測試體系如何運行測試在本地執(zhí)行全部測試./scripts/test.bash從 scripts/test.bash 源碼看它同樣要求從倉庫根目錄執(zhí)行然后調(diào)用 bats 并攜帶--timing --print-output-on-failure參數(shù)如果檢測到parallel命令還會追加--jobs 2 --no-parallelize-within-files以并行加速CI 環(huán)境中若缺少 GNU parallel 會直接報錯。因此本地安裝 GNU parallel 可以顯著加快測試。寫測試前必讀的三樣?xùn)|西文檔要求在編寫測試之前務(wù)必先通讀test/ 目錄下已有的測試當(dāng)前倉庫包含install_command.bats、set_command.bats、shim_exec.bats、version_commands.bats等 20 余個.bats文件bats-core 的官方文檔scripts/test.bash 中使用的既有 Bats 配置。測試基礎(chǔ)設(shè)施速覽倉庫的測試通過 test/test_helpers.bash 提供輔助函數(shù)理解它們有助于寫出符合項目慣例的測試setup_asdf_dir()為每個測試建立隔離的$HOME、$ASDF_DIR、$ASDF_DATA_DIR并把被測的bin與shims目錄注入PATHinstall_mock_plugin/install_dummy_plugin系列把test/fixtures/dummy_plugin等夾具復(fù)制為插件并初始化 Git 倉庫test/fixtures/dummy_plugin 等夾具可在 test/fixtures/ 下找到install_mock_plugin_version/install_dummy_version在installs/plugin/version下創(chuàng)建假安裝目錄用于測試版本相關(guān)命令init_git_repo()以--initial-branchmaster初始化夾具倉庫并完成首次提交clean_asdf_dir()清理測試目錄并取消相關(guān)環(huán)境變量。這些輔助函數(shù)會被install_command.bats、uninstall_command.bats、set_command.bats等大量測試文件復(fù)用是理解 asdf 測試風(fēng)格的最佳入口。Bats 調(diào)試技巧用-t與3輸出到終端Bats 的調(diào)試有時比較棘手。默認(rèn)情況下測試中被執(zhí)行的命令的 stdout/stderr 會被 bats 吞掉除非失敗否則不展示。文檔推薦使用-t開啟 TAP 輸出配合特殊文件描述符3可以在測試執(zhí)行過程中即時打印內(nèi)容極大簡化調(diào)試# test/some_tests.bats printf %s\n Will not be printed during bats test/some_tests.bats printf %s\n Will be printed during bats -t test/some_tests.bats 3即普通printf在bats test/some_tests.bats運行時不會顯示而寫入3的輸出在bats -t test/some_tests.bats下會實時打印到終端。該機(jī)制在 bats-core 文檔的 Printing to the Terminal 一節(jié)有更詳細(xì)的說明。測試的必要性文檔以醒目提示強調(diào)請為你的改動編寫測試新功能必須有測試覆蓋這是硬性要求Bug 修復(fù)附上測試也能顯著加快 Review 速度。在提交 Pull Request 之前請確保新代碼路徑已有對應(yīng)的測試用例。提交與發(fā)布Pull Request、Conventional Commits 與 Release Please提交信息格式Conventional Commitsasdf 使用自動發(fā)布工具 Release Please其依據(jù)是自上次發(fā)布以來的提交歷史。因此提交信息必須遵循 Conventional Commits 規(guī)范——它在默認(rèn)分支上定義了提交消息格式也即 Pull Request 標(biāo)題的格式。該規(guī)范由 GitHub Actionamannn/action-semantic-pull-request強制校驗倉庫中的 .github/workflows/semantic-pr.yml 即該 Action 的實際配置并額外限制了允許的 scope 列表docs、website、plugin、completions、deps、golang-rewrite等。Conventional Commit 的格式如下type[optional scope][optional !]: description !-- examples -- fix: some fix feat: a new feature docs: some documentation update docs(website): some change for the website feat!: feature with breaking change可用的types完整列表為feat、fix、docs、style、refactor、perf、test、build、ci、chore、revert。type 與 SemVer 版本的對應(yīng)關(guān)系!表示這是一個破壞性變更breaking changefix觸發(fā) SemVerpatch版本提升feat觸發(fā) SemVerminor版本提升type!如feat!、fix!觸發(fā) SemVermajor版本提升。Pull Request 的標(biāo)題必須遵循該格式這是合并的前置條件。Release Please 與版本管理倉庫根目錄的 release-please-config.json 是發(fā)布配置的倉庫內(nèi)證據(jù)包類型為go開啟bump-minor-pre-major1.x 之前以 minor 遞增changelog-types將feat/fix/docs分別歸入 Features/Patches/Documentation 三個章節(jié)并指定SECURITY.md、多語言 getting-started 文檔含 docs/ja-jp/guide/getting-started.md以及 cmd/asdf/main.go 中的版本信息作為發(fā)布時需要同步更新的額外文件。發(fā)布的版本清單記錄在 .release-please-manifest.json當(dāng)前版本號為0.16.x階段可結(jié)合 version.txt 與 docs/ja-jp/guide/upgrading-to-v0-16.md 了解對應(yīng)升級說明。進(jìn)階把 asdf 打包進(jìn) Docker 鏡像asdf-alpine 和 asdf-ubuntu 是持續(xù)進(jìn)行的社區(qū)項目為部分 asdf 工具提供 Docker 化鏡像。這些鏡像既可以用作開發(fā)服務(wù)器的基礎(chǔ)鏡像也可以直接用于運行生產(chǎn)應(yīng)用——如果你需要把 asdf 管理的運行時部署到容器環(huán)境這兩個項目值得關(guān)注它們不屬于本倉庫請到對應(yīng)項目了解詳情。常見問題與檢查清單腳本必須在倉庫根目錄運行scripts/lint.bash與scripts/test.bash都會校驗當(dāng)前目錄是否為倉庫根目錄否則直接報錯。本地沒有 python3 / fish_indent / parallel 怎么辦本地環(huán)境下對應(yīng)檢查會被跳過并給出[WARNING]Go 工具鏈與 bats 不受影響但 CI 環(huán)境下缺少這些依賴會直接失敗。改動會不會影響我的開發(fā)環(huán)境文檔建議開發(fā) asdf 時謹(jǐn)慎使用 asdf 管理開發(fā)工具防止改壞自身依賴如需隔離使用$ASDF_DIR 臨時 PATH 的方式試運行。PR 標(biāo)題規(guī)范必須使用 Conventional Commit 格式否則會被 .github/workflows/semantic-pr.yml 攔截。提交前自查./scripts/lint.bash --check→./scripts/test.bash→ 為改動補充 Bats 測試 → 檢查git blame噪音用.git-blame-ignore-revs。按照上述流程你就可以在保持本地開發(fā)環(huán)境安全的前提下完成「克隆 → 裝工具 → 改代碼 → 試運行 → Lint/Format → 寫測試 → 跑測試 → 提交 PR」的完整 asdf 核心貢獻(xiàn)閉環(huán)?!久赓M下載鏈接】asdfExtendable version manager with support for Ruby, Node.js, Elixir, Erlang more項目地址: https://gitcode.com/GitHub_Trending/as/asdf創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考