發布流程

routerd 採用以日期為基礎的版本號。
執行檔版本號、發布標籤與發布封存檔名稱均使用 vYYYYMMDD.HHmm 格式。
日期與時間預設以 UTC 為基準計算。
Qualification 的觀測結果
區分實際觀測到的產品違規(product_failure)、證據不足或含糊造成的觀測不成立
(observation_inconclusive)以及執行環境故障(infra_failure)。
觀測不成立仍保留 status: fail,既不證明產品存在缺陷,也不代表 qualification 通過。
即使後續嘗試成功,也應保留每次失敗、傳送端實際開始和結束時間及結果。
管理 RPC 的時間本身不能證明刺激實際發生的時間。
先重播保存的失敗與相鄰正常範例,再驗證現有環境中的相關節點。 根據變更影響範圍,事先說明追加測試的對象和理由。重新採集觀測必須處於同一期限、 採集視窗和故障狀態內。不得改寫封存結果、在不同條件下沿用部分 PASS,或為了除錯測試 而重新部署全部雲端環境。參見 qualification 原則(英語)。
開始實機驗證之前
在經過評審的完整 checkout 中執行 make release-qa-preflight-test,
然後驗證即將凍結的最終 contract 原始檔:
python3 scripts/release_certification.py validate-contract \
--contract prospective-contract.json --environment "$environment" \
--topology "$topology" --providers "$providers" > contract-validation.json
必要的離線測試失敗、缺漏或被略過,複製的 phase 仍使用舊 run ID,證據發生變化, 以及保留媒體的 baseline 缺少管理 IP 等欄位時,檢查會在認證 driver 啟動前拒絕執行。 保存原始碼、fixture 的雜湊與 contract 的 SHA256;準備內容變更後重新執行, 並與凍結檔案核對。認證、qualification preflight 與付費測試的 precheck 也會自動執行此檢查。僅原始碼測試通過並不證明實環境或 private caller 正確。
保留失敗的 run,使用保存資料及負例重現擷取、判定或準備缺陷,修正並驗證後再凍結 新的 run。不要反覆建立雲端資源來除錯已知的測試程式缺陷。產品改善不能成為這些返工 的藉口。產品二進位檔不變時,僅 QA 的修正本身不要求重新進行四環境產品驗證。 參見 R1–R12 原因分類、前提、失敗範例及重試條件。 實際費用與浪費金額須核對帳單,不能僅憑經過時間推斷。
自動發布
確保工作目錄乾淨後,執行發布輔助指令:
make release
輔助程式會使用 UTC 的當前日期與起始時間,更新執行檔的版本號字串,將目前 Unreleased 的 changelog 項目升格至新的發布標籤,並保留一個新的空 Unreleased 標題。接著重新產生(render)儲存庫管理的 schema,提交變更,建立標籤,並同時將 main 與標籤推送至遠端。
例如,在 UTC 15:30 開始的發布會使用 .1530 後綴。
常用選項如下:
scripts/release.sh --dry-run
scripts/release.sh --date 20260510
scripts/release.sh --timezone UTC
scripts/release.sh --no-push
執行輔助程式前,工作目錄必須是乾淨狀態。
功能變更與 changelog 變更請先提交。輔助程式只建立發布提交。
changelog 中請以 ## Unreleased 作為最前面的發布區塊,且該區塊必須有項目才能建立發布。
推送發布標籤後,GitHub Actions 工作流程將會啟動。
Release 工作流程會建置下列目標:
linux-amd64linux-arm64freebsd-amd64freebsd-arm64routerd-ndpi-agent-libndpi-linux-amd64(選用的原生 nDPI 代理程式覆蓋封存檔)
每個目標的封存檔以兩個名稱發布:
- 指向特定發布的
routerd-<tag>-<os>-<arch>.tar.gz - 以固定 URL 下載最新版的
routerd-<os>-<arch>.tar.gz - 選用原生 nDPI 代理程式覆蓋用的
routerd-ndpi-agent-libndpi-<tag>-linux-amd64.tar.gz與routerd-ndpi-agent-libndpi-linux-amd64.tar.gz
Linux 封存檔以 CGO_ENABLED=0 建置,因此封存檔內的 routerd 二進位檔為靜態連結,不依賴目標主機的 glibc 版本。工作流程在封裝 Linux 封存檔前會執行 make check-linux-static。選用的原生 nDPI 代理程式封存檔刻意分離,因為它以 CGO_ENABLED=1 -tags libndpi 建置並連結至主機的 libndpi 執行期,不包含在一般靜態 Linux 封存檔中。
每個名稱均附有對應的 .sha256 檔案。
封存檔包含下列內容:
bin/:routerd、routerctl及受管理常駐程式的二進位檔install.sh:POSIX sh 安裝程式uninstall.sh:POSIX sh 解除安裝程式etc/routerd/router.yaml.sample:不含密鑰的設定範例systemd/或rc.d/:目標 OS 的服務範本share/doc/:README、VERSION、LICENSE、第三方授權清單
原生 nDPI 代理程式覆蓋用封存檔僅包含 bin/routerd-ndpi-agent 與最精簡的文件。希望以 libndpiLoaded=true 執行 routerd-ndpi-agent 的主機,應與一般 routerd 封存檔一同安裝:
sudo ./install.sh --with-ndpi \
--with-ndpi-archive ./routerd-ndpi-agent-libndpi-linux-amd64.tar.gz
安裝程式的下載動作保持明確。它不會自行取得功能封存檔。發布 runbook 中請在呼叫 install.sh 前先下載封存檔與對應的 .sha256 檔案。
工作流程會將版本化封存檔、固定名稱封存檔及各自的 .sha256 檔案上傳至 GitHub Release 頁面。
快速入門文件使用固定 URL 下載最新版:
https://github.com/imksoo/routerd/releases/latest/download/routerd-linux-amd64.tar.gz
只有在需要固定特定發布的 runbook 中才使用版本化 URL。
一般分支的推送與 pull request 使用另一個 CI 工作流程,該工作流程只執行開發期間的檢查,不發布發布成品。pre-commit hook 與 CI 的範圍請參閱開發時的檢查。
職責分工
安裝邏輯位於 install.sh。
Makefile 僅供開發作業使用,包含建置、測試、schema 檢查、範例驗證、網站建置及發布封存檔產生等。
發布封存檔不含 Makefile。
這樣可將面向終端使用者的安裝與升級行為集中在單一 script 中。
開發時的測試使用 Makefile 目標:
make test
make check-schema
make validate-example
make dist ROUTERD_OS=linux GOARCH=amd64 VERSION="$(git describe --tags --abbrev=0)"
make dist-ndpi-agent-libndpi ROUTERD_OS=linux GOARCH=amd64 VERSION="$(git describe --tags --abbrev=0)"
部署時的冒煙測試使用 install.sh。
安裝完成後,若 routerd 的唯讀 status socket 存在,install.sh 會呼叫 routerctl get status。
GitHub 發布工作流程也會展開每個封存檔,並在系統外的臨時 prefix 下執行 install.sh。
此冒煙測試確認封存檔可在不使用 Makefile 的情況下正常安裝與解除安裝。
由於安裝相依套件是目標路由器主機的職責,CI 冒煙測試會傳入 --no-install-deps。
在路由器主機上安裝發布封存檔:
tar -xzf routerd-linux-amd64.tar.gz
sudo ./install.sh
install.sh 會將二進位檔複製至 /usr/local/sbin、安裝服務範本,並寫出 router.yaml.sample。
執行開始時會偵測 OS 的套件管理器,並在未傳入 --no-install-deps 的情況下安裝已知的執行期套件。
不會覆蓋現有的 /usr/local/etc/routerd/router.yaml。
若發現現有的 /usr/local/sbin/routerd,安裝程式會自動切換至升級模式。
此時會顯示舊版與新版的 routerd --version 輸出,替換二進位檔與服務範本,保留設定與狀態,並在服務已在執行時重新啟動 routerd.service 或 FreeBSD 的 routerd rc.d 服務。
在 systemd 主機上,重新啟動後會等待 routerd.service 的 status socket,並僅重新啟動仍以已刪除的升級前二進位檔執行、或在輔助程序啟動後 unit 檔案已更新的作用中 routerd 輔助服務。
替換的檔案在替換前會複製為 *.backup.YYYYMMDDHHMMSS。
若只想替換檔案而不重新啟動服務,請傳入 --no-restart。
若要顯示預計的檔案與服務管理器變更而不實際執行,請傳入 --dry-run。
若要輸出 shell 追蹤,請傳入 --verbose。
若要保留 router.yaml.sample 不變,請傳入 --no-config-update。
若要略過 OS 套件安裝,請傳入 --no-install-deps。
若要在不變更主機的情況下列出套件與指令清單,請傳入 --list-deps。
若要在安裝套件後、複製 routerd 檔案前即結束,請傳入 --deps-only。
若要加入選用的 Tailscale 套件與指令檢查,請傳入 --with-tailscale。
若要在新安裝時呼叫主機的服務管理器,請傳入 --enable-service 或 --start-service。
安裝完成後,若 routerd 的唯讀 status socket 存在,script 會執行 routerctl get status。
安裝程式不會對下列執行期與狀態路徑做任何變更:
/usr/local/etc/routerd/router.yaml/var/lib/routerd/var/db/routerd/run/routerd/var/run/routerd/var/log/otelcol
授權清單
routerd 本體以 BSD 3-Clause License 發布。 發布封存檔與 Live ISO 包含採用其他授權的第三方軟體。 發布前請重新產生清單:
go mod download all
make third-party-licenses
產生的 THIRD_PARTY_LICENSES.md 記錄 Go 模組的授權檔案及基礎系統授權資訊的取得說明。Live ISO 是集合性發布物。
採用 GPL 授權的套件各自保留其授權與原始碼取得方式,不視為以 GPL 著作重新授權整個 ISO。
目前 Live ISO 透過 debootstrap 建置,以 Ubuntu 為基礎,預設 suite 為 noble。
產生的清單指向 Ubuntu archive 的基礎系統套件資訊,並不是逐套件原始碼清單。
重新散布映像前,請核對實際使用的 Ubuntu 版本的原始碼和授權資訊。
執行期相依套件
install.sh 將相依套件的安裝納入與二進位檔安裝相同的面向終端使用者的流程,以避免使用 Makefile 作為另一條安裝路徑。
Debian 與 Ubuntu 上,安裝程式使用 apt-get 安裝下列套件:
ca-certificates curl dnsmasq-base nftables wireguard-tools chrony bind9-dnsutils tcpdump cron jq ppp pppoe conntrack iproute2 iputils-ping iputils-tracepath net-tools kmod radvd strongswan-swanctl iptables keepalived
Fedora 系統上,安裝程式使用 dnf 安裝下列套件:
ca-certificates curl dnsmasq nftables wireguard-tools chrony bind-utils tcpdump cronie jq ppp rp-pppoe conntrack-tools iproute iputils traceroute kmod radvd strongswan iptables keepalived
Arch 系統上,安裝程式使用 pacman 安裝下列套件:
ca-certificates curl dnsmasq nftables wireguard-tools chrony bind tcpdump cronie jq ppp rp-pppoe conntrack-tools iproute2 iputils traceroute kmod radvd strongswan iptables keepalived
FreeBSD 上,安裝程式使用 pkg 安裝下列套件:
ca_root_nss curl dnsmasq wireguard-tools mpd5 bind-tools tcpdump jq chrony strongswan
FreeBSD 的 pf、ifconfig、route、service、sysrc、cron 均為基本系統工具,不以套件方式安裝,僅確認指令是否存在。
安裝相依套件後,script 會確認預期的指令是否存在。 由於套件名稱因發行版而異,若找不到指令,視為警告而非致命錯誤。 確認相依套件清單請使用:
./install.sh --list-deps
解除安裝
若要在不影響狀態的情況下移除已安裝的檔案,請使用 uninstall.sh:
sudo ./uninstall.sh --yes
預設的解除安裝會停止並停用服務,移除 routerd 二進位檔、服務範本與執行期檔案。
/usr/local/etc/routerd、/var/lib/routerd、/var/db/routerd、/var/log/otelcol 會保留。
完全移除的選項需明確指定:
sudo ./uninstall.sh --yes --purge-config
sudo ./uninstall.sh --yes --purge-state
sudo ./uninstall.sh --yes --all
若要在不變更主機的情況下預覽移除內容,請使用 --dry-run。
手動觸發
若標籤已存在,也可透過 GitHub Actions 的 workflow_dispatch 輸入啟動工作流程:
tag = vYYYYMMDD.HHmm
工作流程會在建置前 checkout 該標籤。
備援方案
若 GitHub Actions 無法使用,可在本機建置相同的封存檔:
tag=$(git describe --tags --abbrev=0)
make dist ROUTERD_OS=linux GOARCH=amd64 VERSION="$tag"
make dist ROUTERD_OS=freebsd GOARCH=amd64 VERSION="$tag"
make dist-ndpi-agent-libndpi ROUTERD_OS=linux GOARCH=amd64 VERSION="$tag"
再透過 GitHub CLI 建立發布:
tag=$(git describe --tags --abbrev=0)
gh release create "$tag" \
"dist/linux-amd64/routerd-${tag}-linux-amd64.tar.gz" \
"dist/linux-amd64/routerd-${tag}-linux-amd64.tar.gz.sha256" \
dist/linux-amd64/routerd-linux-amd64.tar.gz \
dist/linux-amd64/routerd-linux-amd64.tar.gz.sha256 \
"dist/freebsd-amd64/routerd-${tag}-freebsd-amd64.tar.gz" \
"dist/freebsd-amd64/routerd-${tag}-freebsd-amd64.tar.gz.sha256" \
dist/freebsd-amd64/routerd-freebsd-amd64.tar.gz \
dist/freebsd-amd64/routerd-freebsd-amd64.tar.gz.sha256 \
"dist/linux-amd64/routerd-ndpi-agent-libndpi-${tag}-linux-amd64.tar.gz" \
"dist/linux-amd64/routerd-ndpi-agent-libndpi-${tag}-linux-amd64.tar.gz.sha256" \
dist/linux-amd64/routerd-ndpi-agent-libndpi-linux-amd64.tar.gz \
dist/linux-amd64/routerd-ndpi-agent-libndpi-linux-amd64.tar.gz.sha256 \
--title "routerd ${tag}" \
--generate-notes \
--verify-tag