Documentation
¶
Overview ¶
Package release 负责「把某个版本的 handoff 二进制正确落到某个路径」。
职责:
- 查 GitHub 的 latest release,解出 tag 与本平台资产的下载 URL
- 下载、校 sha256、解包、自检、原子替换,并把旧二进制留成 .prev
边界:
- **不决定何时替换**:那是 internal/selfupdate 的事。本包是一个执行器, 调用方说装就装
- 不知道 agentd、不知道任务、不读 handoff 的配置
- 不做自动回滚(D10):留下 .prev 供人工 handoff upgrade --rollback
install.go —— 下载、校验、自检、原子替换。
边界:
- 临时文件**必须**落在目标二进制的同目录:os.Rename 的原子性只在同一 文件系统内成立,从 /tmp rename 到 /usr/local/bin 会因跨设备直接失败
- 任何一步失败都清干净临时文件:留一份坏二进制在二进制目录里, 下一轮可能被误当成已就绪的 pending
- 不做自动回滚(D10):只把旧二进制留成 .prev,回退是人工命令
- 下载与安装是两件事,前者可跨平台、后者必须在目标平台执行
Index ¶
- Constants
- func Activate(newPath, target string) (string, error)
- func AssetName(tag, goos, goarch string) string
- func CurrentPlatform() (string, string)
- func PrevPath(target string) string
- func Rollback(target string) error
- func TempName(tag string) string
- type Asset
- type Client
- type Installer
- func (i *Installer) Fetch(ctx context.Context, rel Release, destDir string) (string, error)
- func (i *Installer) FetchArchive(ctx context.Context, rel Release, goos, goarch string) ([]byte, string, error)
- func (i *Installer) InstallArchive(tgz []byte, wantSum, wantTag, destDir string) (string, error)
- type Release
Constants ¶
const ChecksumsName = "checksums.txt"
ChecksumsName 是校验和文件名,与 .github/workflows/release.yml 产出一致。
const DefaultAPIBase = "https://api.github.com"
DefaultAPIBase 是 GitHub REST API 的根。
D11:自动更新链路一律打 GitHub 原生 URL,不走自有域名——域名过期、DNS 故障、 重定向规则改错,任何一样都会让所有机器的自动更新一起哑掉。
const DefaultRepo = "Xsxdot/handoff"
DefaultRepo 是 Release 所在的 GitHub 仓库。
注意 go.mod 的 module path(github.com/Xsxdot/handoff)已与 GitHub owner 一致:`go install github.com/Xsxdot/handoff@latest` 与下载链指向同一个仓库。
Variables ¶
This section is empty.
Functions ¶
func Activate ¶
Activate 把新二进制换到目标路径,旧的留成 <target>.prev。
参数:
- newPath: Fetch 返回的临时文件路径(必须与 target 同目录)
- target: 目标二进制路径(应已 EvalSymlinks 解析过)
返回:
- 留存的旧二进制路径
- 错误:目录不可写、rename 失败
注意:
- 两次 rename 都是同目录内操作,因而是原子的。中途失败最坏的结果是 「旧的已挪到 .prev、新的还没就位」——此时目标路径暂时缺失, 所以第二次 rename 失败时会把 .prev 挪回来
- **两次 rename 的顺序在 Windows 上是承重的**:Windows 允许 rename 一个 正在运行的 exe,但不允许覆盖或删除它。所以「先把旧的挪走、再把新的挪进来」 恰好就是 Windows 自更新的标准手法。**不要**把它「优化」成先删后写—— 那在 unix 上照样绿,在 Windows 上当场炸
func AssetName ¶
AssetName 拼装某平台的资产名。
参数:
- tag: 版本号,形如 v0.1.0
- goos / goarch: 目标平台
返回:
- 资产文件名
注意:
- 格式必须与 .github/workflows/release.yml 里的产出**逐字一致**。 不一致的症状是查得到版本但下不到东西,且每轮重试
- 扩展名按平台分(见 archiveExt),install.sh / install.ps1 两边也依赖这条
func CurrentPlatform ¶
CurrentPlatform 返回当前进程的 goos/goarch,便于调用方少写两个 runtime 引用。
Types ¶
type Client ¶
Client 查 GitHub release。
type Installer ¶
Installer 执行下载与安装。
func NewInstaller ¶
NewInstaller 构造默认 installer(10 分钟超时,覆盖慢网下的 20MB 下载)。
func (*Installer) Fetch ¶
Fetch 下载本平台资产、校验、解包、自检,返回可供 Activate 的临时文件路径。
参数:
- ctx: 上下文
- rel: 目标发布
- destDir: 临时文件落点,**必须**与目标二进制同目录
返回:
- 临时二进制的完整路径(已 chmod 0755 并通过自检)
- 错误:缺资产、下载失败、校验不过、解包失败、自检不过
注意:
- 任何一步失败都会把临时文件删掉,不留残件
- 本函数是 FetchArchive + InstallArchive 的本机组合,行为与拆分前一致
func (*Installer) FetchArchive ¶
func (i *Installer) FetchArchive(ctx context.Context, rel Release, goos, goarch string) ([]byte, string, error)
FetchArchive 按指定平台下载资产并校验完整性,返回字节与期望哈希。
参数:
- ctx: 上下文
- rel: 目标发布
- goos / goarch: **目标机器**的平台,不是本机——跨平台推送时远端可能 是 linux/amd64 而本机是 darwin/arm64,必须知道该下哪份资产
返回:
- tgz: 资产原文(tar.gz 字节,**未经解包**)
- 期望的 sha256(十六进制小写),**来自 checksums.txt 的声明**—— 这是信任链的第一道校验,消费方把它原样传给 InstallArchive 让两端 比同一个来自 release 的声明,不互相背书
- 错误:缺资产、下载失败、校验不过
注意:
- **不解包、不自检**。自检要 exec 执行新二进制,而本机执行别的平台的 二进制必然失败——自检必须在目标平台上做(agentd 收到推送后)
- 不重试:完整性失败重试只会重下同一份坏数据(spec §4.7)
func (*Installer) InstallArchive ¶
InstallArchive 校验、解包、自检一份已下载的资产,返回可供 Activate 的临时文件路径。
参数:
- tgz: FetchArchive 返回的资产原文
- wantSum: 期望的 sha256(十六进制小写),agentd 侧来自 CLI 推来的 query 参数,是信任链的第二道校验(传输完整性)
- wantTag: 目标版本,自检时拿新二进制 version 首行与它比对
- destDir: 临时文件落点,**必须**与目标二进制同目录
返回:
- 临时二进制的完整路径(已 chmod 0755 并通过自检)
- 错误:校验不过、解包失败、置位失败、自检不过
注意:
- 任何一步失败都会把临时文件删掉,不留残件