文档导航
文档 / 阿里云 OSS 发布镜像

阿里云 OSS 发布镜像

OpenSquilla 会把已发布的 GitHub Release 资源镜像到阿里云 OSS,以加快中国大陆的下载。

镜像 workflow 位于 .github/workflows/mirror-release-to-oss.yml。它在 GitHub Release 发布时运行,也可以带上一个 tag 手动运行。该 workflow 会从 GitHub 下载发布资源, 校验 SHA256SUMS,然后上传带版本号的资源、可移动的安装包别名,以及供更新客户端使用的 严格 JSON channel manifest。

仓库配置

配置以下 GitHub 仓库 secret:

  • ALIYUN_OSS_ACCESS_KEY_ID
  • ALIYUN_OSS_ACCESS_KEY_SECRET

配置以下 GitHub 仓库变量:

  • ALIYUN_OSS_BUCKET:OSS bucket 名称,例如 opensquilla-downloads
  • ALIYUN_OSS_REGION:OSS region ID,例如 cn-hangzhou
  • ALIYUN_OSS_PREFIX:可选的对象前缀。默认为 releases
  • ALIYUN_OSS_ENDPOINT:可选的自定义 endpoint 或 CNAME endpoint。当 bucket 或账号 需要一个自定义的 OSS 数据 API endpoint 时使用它。
  • ALIYUN_OSS_ADDRESSING_STYLE:可选的 ossutil 寻址风格。支持的取值为 virtualpathcname。对于常规 OSS endpoint,请不要设置它。当 ALIYUN_OSS_ENDPOINT 是一个绑定的自定义上传域名时,把它设为 cname;当 endpoint 主机名不以 aliyuncs.com 结尾时,workflow 也会自动选择 cname

请使用一个专用的、作用域限定在发布镜像 bucket/前缀上的 RAM 用户或角色。它需要 oss:ListObjectsoss:GetObjectoss:PutObjectoss:DeleteObject,以及 bucket 级的 oss:GetBucketVersioning 权限:该 workflow 会校验 bucket 状态、列出别名、 把已有别名复制到一个短期备份、上传带版本号的资源、别名与 channel manifest,并移除 备份和遗留的 latest.html。不要使用完全访问权限的账号密钥。

请让该镜像的 OSS bucket 版本控制保持关闭。在上传之前,workflow 会通过标准的区域 OSS endpoint 查询版本控制状态,除非 bucket 未启用版本控制,否则会 fail closed。 带版本号的上传随后会使用 OSS 的 x-oss-forbid-overwrite 条件,这样并发写入者就无法 在 workflow 的存在性检查与上传之间替换某个对象;当 bucket 版本控制处于启用或暂停 状态时,OSS 会忽略该条件。移动 latest/channels/ 对象保留其显式的备份与回滚 行为。

目标布局

对于 tag v0.5.0rc4 和默认前缀,workflow 会写入带版本号的资源:

oss://<bucket>/releases/v0.5.0rc4/OpenSquilla-0.5.0-rc4-win-x64.exe
oss://<bucket>/releases/v0.5.0rc4/OpenSquilla-0.5.0-rc4-mac-arm64.dmg
oss://<bucket>/releases/v0.5.0rc4/opensquilla-0.5.0rc4-py3-none-any.whl
oss://<bucket>/releases/v0.5.0rc4/SHA256SUMS

在这些经过校验的资源上传后,它还会替换以下两个可移动的安装包别名:

oss://<bucket>/releases/latest/OpenSquilla-win-x64.exe
oss://<bucket>/releases/latest/OpenSquilla-mac-arm64.dmg

当某个下载必须固定在某个发版 tag 上时,请使用带版本号的路径。仅在面向用户的 “下载最新桌面应用”链接中使用 latest 别名。只有当被镜像的 release 是符合条件的 最高已发布 release 时,别名才会前进;更早的手动回填无法替换它们。

更新客户端不使用这些可移动的安装包别名或 latest.json。稳定版客户端读取 stable.json;预览版客户端读取其发版线的 manifest。manifest 提供一个经过验证的 tag 以及带版本号的资源文件名,从而让发现与下载都停留在同一个 release 上:

oss://<bucket>/releases/channels/latest.json
oss://<bucket>/releases/channels/stable.json
oss://<bucket>/releases/channels/preview/0.5.0.json

stable.json 只由正式版推进。某个预览线的 manifest 会由同一基础版本的更高 RC 或正式版 推进,因此 0.5.0rc4 可以移动到 0.5.0rc50.5.0,但绝不会移动到 0.6.0rc1latest.json 记录跨发版线的既有固定链接行为,且仅用于提交并回滚这些别名。 Channel JSON 需要缓存重新验证。带版本号的 OSS 对象是一次写入的,并使用不可变的缓存 策略:重新运行时会下载每个已有对象,验证其 SHA-256 与 GitHub Release 资源匹配,且仅在 字节完全相同时才跳过上传。新对象会以 OSS 服务端的 forbid-overwrite 条件创建,并在上传后 再次验证。对已镜像 tag 下发生变更的资源会被拒绝;请改为在一个新的 tag 下发布修正后的 发布字节。

未签名的 Windows 客户端不会直接执行某个 OSS 对象。它们会获取对应 GitHub Release 的 权威 SHA256SUMS,把确切的带版本号 EXE 从所选的 GitHub 或 OSS 源流式传输到一个由 应用拥有的目录中,验证其 SHA-256,然后才让该文件显现出来以供显式手动安装。如果 GitHub 的校验和不可用或摘要不一致,客户端会 fail closed 并删除部分或不匹配的下载。

使用默认公开 endpoint 时,使用以下直接下载 URL:

https://<bucket>.oss-<region>.aliyuncs.com/releases/latest/OpenSquilla-win-x64.exe
https://<bucket>.oss-<region>.aliyuncs.com/releases/latest/OpenSquilla-mac-arm64.dmg

OSS 默认域名会强制这些文件在浏览器中下载。对于安装包链接来说这是预期行为,无需自定义 域名。该 workflow 不会发布 HTML 的最新发布着陆页,因为 OSS 默认域名的安全策略同样会 强制 HTML 以下载方式打开。

手动回填

要镜像一个已经发布的 release,请手动运行 workflow 并输入 release tag,例如 v0.5.0rc4。手动回填会上传缺失的带版本号对象,并逐字节验证已有对象。它们绝不会在 同一 tag 下用不同字节替换某个已有对象。在更改任何可移动对象之前,workflow 会把候选与 一份经过认证的已发布 GitHub Release 清单以及任何已有的 OSS manifest 进行比较。候选 必须是该 channel 的最高 release,且不得比 OSS 状态更旧。这也保护了引入 channel manifest 之后的首次运行:回填 v0.5.0rc3 不能仅仅因为 latest.json 尚未创建,就替换已经上线 的 rc4 别名。无法推进 latest.json 的回填也会让别名与已退役的 latest.html 对象保持 不变。

失败模型

在以下情况下镜像 workflow 会失败:所需的 OSS 配置缺失、GitHub Release 没有可下载的 资源、SHA256SUMS 缺失、某个发布资源未列在 SHA256SUMS 中、校验和验证失败、找不到 恰好一个 macOS DMG 与 Windows EXE 安装包,或某个已有的 channel manifest 格式错误, 或某个已有的带版本号对象与经过验证的 GitHub 资源不一致。Channel manifest 与别名会作为 一个提升组一并备份和回滚;当遗留的 latest.html 对象在同一次提升中被移除时,它也会被 包含在内。每次 workflow 尝试都使用一个不同的备份前缀,因此重新运行失败的 workflow 无法 覆盖为手动恢复而保留的快照。在这些情况下,GitHub 仍是唯一可信来源,且可移动对象不会 被留在部分更新的状态。在一次成功且经过验证的提升之后,若未能移除临时备份,会作为 workflow 警告报告,而不会错误地把已提交的发布镜像标记为失败。

在 GitHub 上编辑此页(英文原稿) OpenSquilla 文档 · 中文社区翻译