一篇讲透「后台一键云端编译」的原理、接入、排障的完整教程。跟着做约 20~30 分钟即可跑通。
一、背景:这套东西是什么
在运营 iOS 插件授权平台时,核心产物是一个已经注入授权验证代码的 dylib / deb 安装包。编译这类苹果生态的二进制,需要 macOS 环境——大多数站长手头只有一台 Linux 服务器(宝塔 + PHP),根本没法本地编译。
解决办法就是借用 GitHub Actions 的免费云端算力:平台后台把编译参数投递到你的 GitHub 仓库,由 GitHub 提供的 macOS 云机器完成编译,再把产物(deb / dylib)传回来供你下载分发。
整条链路涉及三个角色:
| 角色 | 承担什么 | 你需要准备什么 |
|---|---|---|
| 管理后台 | 发起构建、跟踪进度、提供下载 | 已部署的平台 |
| GitHub 仓库 | 存放编译工作流,执行云端编译 | 一个仓库 + 一个令牌 |
| GitHub Actions | 免费的 macOS 编译机器 | 无需额外准备,仓库自带 |
二、它是干什么用的:解决三个真实痛点
- 没有 Mac 也能编译 iOS 产物 —— 编译发生在 GitHub 的 macOS 服务器上,你只需要一个浏览器。
- 参数化批量出包 —— 后台改一下参数(弹窗文案、主题色、授权策略),一键重新出包,不用手动改代码重编译。
- 产物管理闭环 —— 构建历史、成功/失败状态、产物下载、下载留痕,全部在后台完成,不散落在聊天记录里。
三、配置完成后你会实现什么
配置打通后,日常工作流变成这样:
- 在后台「应用管理」新建应用 → 自动生成 app_key
- 在「自定义参数」里按表单填写插件参数
- 在「云端构建」点一下「创建构建」
- 几分钟后,构建状态变绿 → 点「下载」拿到编译好的 deb / dylib
- 把包发给客户,配合卡密 / UDID 授权即刻可用
一句话总结:改参数 → 点按钮 → 下载成品包。
四、整体流程与三个硬性约定
┌─ 你的后台 ──────────────┐ ┌─ GitHub 仓库 ─────────────┐ ┌─ 回到后台 ───────────┐
│ 1. 应用管理建应用(app_key)│ │ 4. Actions 收到 │ │ 6. 每8秒轮询"读时对账" │
│ 2. 自定义参数填参数 │ ───▶ │ repository_dispatch │ ───▶ │ 状态→成功/失败 │
│ 3. 云端构建→创建构建 │ │ 5. 编译→上传 artifact │ │ 7. 接口转发下载产物 │
└─────────────────────────┘ │ (命名: 前缀-runId) │ └─────────────────────┘
└───────────────────────────┘
后台与工作流之间靠三处严格对齐才能通信,配置前先记住:
| # | 硬性约定 | 不对齐的后果 |
|---|---|---|
| 1 | 工作流顶层 name: 必须等于后台投递的 buildRef | 任务永远停在「已投递」 |
| 2 | on.repository_dispatch.types 必须等于后台「Dispatch 事件类型」 | GitHub 返回 204 看似成功,实际不运行 |
| 3 | artifact 名必须 = {产物前缀}-{runId} | 后台提示找不到产物 |
五、具体怎么用:六步实操
步骤 1:创建构建仓库
操作入口:登录 GitHub 后,页面右上角你的头像左侧有一个 「+」号按钮,点开菜单选第一项 New repository;如果找不到,直接在浏览器地址栏输入 github.com/new 也能到达同一页面。
逐项填写:
| 项目 | 示例 | 说明 |
|---|---|---|
| Repository name | ios-dylib | 自定义;这个名字要填进后台「构建仓库名」 |
| 可见性 | Public(推荐) | 后台「拉取契约」按钮走的是匿名 raw 地址,Private 仓库会返回 404;仓库里只放 CI 流水线和 JSON 契约,不含任何密钥,公开无风险 |
| Add a README file | ✅ 勾上 | 保证仓库非空,有默认分支 |
创建完成后确认三件事(都在仓库首页完成):
- 浏览器地址栏此时应为
github.com/你的用户名/ios-dylib——这两段名字就是后台字段 1(账号名)和字段 2(仓库名)的来源; - 左上角分支下拉按钮显示的分支名(一般是
main)就是后台字段 3「触发分支」要填的内容; - 页面中能看到 README 文件,说明仓库非空、创建成功。
若你坚持用 Private:后台「拉取契约」按钮会一直报 HTTP 404,跳过它即可——程序自带
resources/params.schema.json,构建功能不受影响。
步骤 2:创建 build.yml 工作流
- 回到仓库首页 → 点右上方的 Add file 按钮 → 选 Create new file
- 文件名输入框逐字输入:
.github/workflows/build.yml——输入第一个/时 GitHub 会自动把前面的部分识别为目录,输入完应看到面包屑路径为用户名 / 仓库名 / .github / workflows /,末尾是高亮的build.yml - 在下方代码编辑区整段粘贴下面的模板
- 拉到页面最底部点绿色 Commit changes 按钮,弹出确认框后保持默认选项 Commit directly to the main branch(不要选 “Create a new branch”),再点一次 Commit changes 即提交成功
# 顶层 name 就是本次 run 的名称。
# 后台轮询进度时按 buildRef 精确匹配 run.name,这一行绝对不能改!
name: ${{ github.event.client_payload.buildRef }}
# 触发方式:repository_dispatch
# types 必须与后台「Dispatch 事件类型」字段完全一致(默认 build-plugin)
on:
repository_dispatch:
types: [build-plugin]
permissions:
contents: read
jobs:
build:
# 编译 iOS dylib 需要 macOS 环境
runs-on: macos-latest
steps:
- name: 拉取仓库代码
uses: actions/checkout@v4
- name: 校验构建参数
env:
PARAMS: ${{ toJson(github.event.client_payload.params) }}
run: |
# 后台投递的 params 必须是 JSON 对象
echo "$PARAMS" | jq -e 'type == "object"' >/dev/null \
|| { echo "::error::params 必须是 JSON 对象"; exit 1; }
echo "$PARAMS" > build_params.json
echo "参数校验通过:"
jq . build_params.json
- name: 编译插件
run: |
# ↓↓↓ 这里替换成你自己的编译/注入逻辑 ↓↓↓
# 示例:用注入脚本把 app_key 与参数烧进 dylib 模板
# python3 render.py build_params.json templates/AuthDylib_template.dylib
mkdir -p out
# cp build/*.dylib out/
echo "在此处放置你的编译命令,产物放入 out/ 目录"
- name: 上传产物
uses: actions/upload-artifact@v4
with:
# 命名必须 = {前缀}-{runId},后端按这个名字精确反查!
name: ${{ github.event.client_payload.artifactPrefix }}-${{ github.run_id }}
path: out/*
# 与后台产物保留时长(7天)保持一致
retention-days: 7
# 没产物时直接失败,避免"构建成功却下载不到包"的迷惑现象
if-no-files-found: error
模板关键点逐条解释:
| 代码片段 | 作用 | 为什么必须这样写 |
|---|---|---|
顶层 name: ${{ ...buildRef }} | 定义本次运行的名称 | 后台按 run.name === buildRef 精确反查进度,写死文字则永远查不到 |
types: [build-plugin] | 声明接受哪种 dispatch 事件 | 必须与后台字段一字不差,否则事件石沉大海 |
jq -e 'type == "object"' | 校验参数是 JSON 对象 | 拦截上游误传数组等脏数据,第一时间报清晰错误 |
runs-on: macos-latest | 指定 macOS 编译机 | 编译 iOS 二进制必须 macOS |
artifact name: 表达式 | 产物命名 | 后端按 {前缀}-{runId} 精确查找 |
if-no-files-found: error | 无产物即失败 | 避免”绿灯但没包”的迷惑现象 |
retention-days: 7 | 产物在 GitHub 保留 7 天 | 与平台侧产物清理周期对齐 |
注意:「编译插件」步骤是占位符,需要替换为你自己的编译/注入脚本(例如用平台提供的 dylib 模板 + 注入脚本生成成品)。在替换之前发起的构建会在「上传产物」一步失败,这是预期行为,正好用来验证前四步连通性。
步骤 2.5:上传参数契约文件
后台的「拉取契约」和「资源体检」都依赖仓库里的 build/params.schema.json,仓库缺这个文件时点「拉取契约」会报 HTTP 404。
- 仓库首页 → Add file → Create new file
- 文件名输入:
build/params.schema.json - 内容来源:服务器上的
/www/wwwroot/你的项目/resources/params.schema.json(随程序自带,约 41 个字段的 JSON) - 粘贴内容后拉到最底部 → Commit changes
该文件只声明「有哪些参数、类型与默认值是什么」,不含任何密钥,公开也无风险。 也可以不做这步——程序自带的契约副本已能正常工作,只是「拉取契约」按钮会报 404。
步骤 3:生成 Fine-grained Token
3.1 进入创建页并完成安全验证
GitHub → 右上角头像 → Settings → 左侧拉到底 → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token。
首次进入会弹出安全确认页(Confirm access,即 sudo 模式),这是 GitHub 在敏感操作前的本人校验,两种方式任选其一:
- 手机装了 GitHub App 并已登录 → 点绿色按钮 Use GitHub Mobile,然后到手机 App 里点确认
- 没装 App → 点下方 Having problems? 里的蓝色链接 Use your password,输入 GitHub 登录密码确认
验证通过后会自动回到创建 Token 的表单页。
3.2 填写 Token 表单
表单从上往下依次填写:
| 项目 | 填什么 | 说明 |
|---|---|---|
| Token name | yzplus-build | 随意备注 |
| Expiration | No expiration 或 90 days | No expiration 一劳永逸;90 days 更安全但要记得换。选 No expiration 时令牌保管好,泄露可在 GitHub 上随时 Delete 作废 |
3.3 限定仓库
继续往下拉到 Repository access 区块,三个单选项中选择第二个 Only select repositories(默认可能选中的是 “Public repositories” 或 “All repositories”,要改过来):
- 选中后下方出现 Select repositories 下拉框
- 点开下拉框 → 搜索并点选你的构建仓库(如
ios-dylib) - 不要选 All repositories——权限最小化,令牌泄露时损失可控
3.4 设置权限(最容易错的一步)
继续往下拉到 Permissions 大区块,点开其中的 Repository permissions 分组,在这个分组里逐项找到下表的权限项并设置下拉框:
| 权限项 | 下拉选 | 漏配的后果 |
|---|---|---|
| Actions | Read and write | 后台提示「可读不可写」,触发不了构建——最关键的一项 |
| Contents | Read-only | 读不到仓库内容;若希望用 API/脚本把 params.schema.json 推送到仓库,需改成 Read and write |
| Metadata | Read-only(自动) | GitHub 必选项,不用动 |
| 其余全部 | No access | 保持不动 |
补充一:修改权限不会改变令牌值。在令牌页面点 Edit 改权限再 Update token,后台已保存的令牌继续有效,不用重新粘贴;只有「重新生成」才产生新令牌。 补充二:Token 有效期到了会直接 401,构建全线失败,到期前记得换。
3.5 生成与保存
拉到底点 Generate token → 页面显示 github_pat_ 开头的令牌 → 立刻点复制。
⚠️ 令牌只完整显示这一次,离开页面就再也看不到;丢了只能重新生成。
步骤 4:后台填写「构建接入配置」
登录后台 → 插件管理 → 构建接入配置,把 8 个字段填完(详见第七、八节)→ 保存配置。
步骤 5:验证连通
依次点页面上的验证按钮:
- 测试连接 → 必须看到「连接正常,仓库可写」
- 拉取契约 → 从仓库拉取
build/params.schema.json到服务器(仓库为 Private 或缺少该文件时会报 404,不影响使用) - 资源体检 → 确认 dylib 模板等本地构建资源齐全
步骤 6:发起第一次构建
- 「应用管理」新建测试应用 → 「自定义参数」填参数(可先点「只校验」)
- 「云端构建」→ 创建构建 → 观察状态流转:
已投递 → 排队 → 运行中 → ✅ 成功 - 成功后点「下载」,得到
{前缀}-{runId}.zip
进度原理是「读时对账」:前端每 8 秒调一次状态接口,后端顺手去 GitHub 查 run 进度——CI 侧无需配置回调地址,服务器无需挂计划任务,超时 30 分钟自动判失败。
六、以后其他平台怎么接入
这套约定与具体平台无关——任何能调 GitHub API 的系统都可以复用同一套构建仓库。接入只需实现三步 API 调用:
① 触发构建(repository_dispatch):
curl -X POST \
-H "Authorization: Bearer github_pat_xxxx" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/OWNER/REPO/dispatches \
-d '{
"event_type": "build-plugin",
"client_payload": {
"buildRef": "b20260101xxxx",
"artifactPrefix": "gzhmod",
"params": { "app_key": "xxx", "popup_text": "授权弹窗文案" }
}
}'
返回 204 = 受理成功。
② 查询进度(按 run name 反查 buildRef):
curl -H "Authorization: Bearer github_pat_xxxx" \
"https://api.github.com/repos/OWNER/REPO/actions/runs?event=repository_dispatch&per_page=50"
在返回的 workflow_runs[] 里找 name === buildRef 的记录,读 status / conclusion。
③ 下载产物(按 {前缀}-{runId} 精确匹配 artifact):
curl -H "Authorization: Bearer github_pat_xxxx" \
"https://api.github.com/repos/OWNER/REPO/actions/runs/{run_id}/artifacts"
# 找到 name 匹配的 artifact 后:
curl -L -H "Authorization: Bearer github_pat_xxxx" \
-o artifact.zip \
"https://api.github.com/repos/OWNER/REPO/actions/artifacts/{artifact_id}/zip"
这就是为什么 build.yml 的三处约定不能改:它们是所有接入方共同遵守的「通信协议」。换后台系统、写小程序端、做自动化机器人,都走同一套契约。
七、配置所需字段一览
后台「构建接入配置」共 8 个字段:
| # | 字段 | 示例值 | 必填 |
|---|---|---|---|
| 1 | GitHub 账号 / 组织名 | your-username | ✅ |
| 2 | 构建仓库名 | ios-dylib | ✅ |
| 3 | 触发分支 | main | ✅ |
| 4 | Workflow 文件名 | build.yml | ✅ |
| 5 | Dispatch 事件类型 | build-plugin | ✅ |
| 6 | 产物名称前缀 | gzhmod | 可留默认 |
| 7 | GitHub Personal Access Token | github_pat_xxxx | ✅ |
| 8 | GitHub API 地址 | https://api.github.com | 可留默认 |
八、逐字段详细介绍
每个字段按「它是干什么的 → 在哪里找 → 怎么填 → 填错的典型表现」四段讲。
字段 1:GitHub 账号 / 组织名(owner)
- 干什么的:标识构建仓库的归属者,与字段 2 拼出完整仓库路径
github.com/{owner}/{repo}。后端所有 API 调用的 URL 都由它俩拼出来。 - 在哪里找:打开你的仓库页面,看浏览器地址栏
https://github.com/your-username/ios-dylib——斜杠前那段就是。也可以点自己头像看 Public profile 页显示的用户名。 - 怎么填:直接填用户名。如果是组织仓库,填组织名。
- 填错的表现:测试连接报 404 / 找不到仓库。注意大小写要与 GitHub 实际用户名一致。
字段 2:构建仓库名(repo)
- 干什么的:与 owner 一起定位仓库;这个仓库里必须已放好本项目(含
.github/workflows/build.yml)。 - 在哪里找:地址栏斜杠后那段。
- 怎么填:只填仓库名,如
ios-dylib。不要带https://、不带账号名、不带.git后缀。 - 填错的表现:测试连接 404;或连到了别人的同名仓库。
字段 3:触发分支(branch)
- 干什么的:告诉平台去哪个分支找 workflow 文件;查询构建进度时也按此分支过滤。
- 在哪里找:仓库首页左上角的分支下拉按钮(显示
main ▾或master ▾)。 - 怎么填:下拉显示什么就填什么,一般
main。 - 填错的表现:任务一直停在「已投递」——因为反查 run 时按分支过滤,永远查不到。这是新手最常见的卡点。
字段 4:Workflow 文件名(workflow)
- 干什么的:指定触发
.github/workflows/目录下的哪个工作流文件。 - 在哪里找:仓库里
.github/workflows/目录下的文件名。 - 怎么填:只填文件名含后缀,如
build.yml;不带目录路径。 - 填错的表现:不报错,但 dispatch 受理后没有任何工作流启动,任务永远「已投递」。改过文件名的(如
ios-build.yml)两边必须同步。
字段 5:Dispatch 事件类型(event_type)
- 干什么的:
repository_dispatch的事件名,相当于「暗号」——工作流只响应与自己types:匹配的事件。 - 在哪里找:build.yml 里的
on: repository_dispatch: types:。 - 怎么填:默认
build-plugin,与教程模板一致即可;改了必须两边同步。 - 填错的表现:最阴险的一个——GitHub 对 dispatch 返回 204(成功),后台显示「已投递」,但工作流根本不会启动。排查时先核对这个字段。
字段 6:产物名称前缀(artifact_prefix)
- 干什么的:CI 产物 artifact 的命名前缀,最终产物名 =
{前缀}-{runId}(如gzhmod-17310948213)。后端按这个名字精确反查产物供你下载。 - 在哪里找 / 怎么填:保持默认
gzhmod即可。前缀会由后台在投递时自动传给 workflow(client_payload.artifactPrefix),模板已按此动态拼接,两边天然一致。 - 填错的表现:后台提示找不到产物。只要 build.yml 用的是动态表达式(不是写死名字),改这里不需要动 workflow;但手动写死了 artifact 名就必须同步。
字段 7:GitHub Personal Access Token(token)
- 干什么的:后台代替你操作 GitHub 的”钥匙”——触发构建(写)、查进度、拉契约、下载产物(读)全靠它。
- 在哪里找:需要你手动生成:GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token。权限三件套:只勾构建仓库 + Actions Read and write + Contents Read-only。
- 怎么填:粘贴完整令牌(
github_pat_或ghp_开头)。留空保存 = 不修改已保存的令牌(改其他字段时不用重贴)。 - 填错的表现:401 Bad credentials(令牌错/过期/被删);「可读不可写」(Actions 权限只给了 Read)。注意 Fine-grained 令牌有有效期,到期前记得换。
字段 8:GitHub API 地址(api_base)
- 干什么的:所有 GitHub API 请求的基地址。
- 怎么填:公有 GitHub 留空/保持
https://api.github.com。两种情况才需要改:自建 GitHub Enterprise(填 https://你的域名/api/v3);国内访问 api.github.com 不稳定时换成反代地址。 - 填错的表现:全部请求超时或 404。
九、常见故障排查
| 现象 | 原因 | 解决 |
|---|---|---|
| 任务一直停在「已投递」 | Workflow 文件名 / 触发分支 / 事件类型 三者之一不对 | 逐个核对字段 3、4、5 与 build.yml |
| dispatch 成功但 Actions 页面没有 run | 事件类型不匹配或 Token 权限不足 | 核对字段 5;确认 Actions 为 Read and write |
| 「可读不可写」 | Token 的 Actions 权限只给了 Read | 重新生成或编辑 Token 权限 |
| 401 Bad credentials | Token 错误 / 过期 / 被删 | 重新生成并更新后台 |
| 构建失败 | 参数格式错误或仓库缺文件 | 先「只校验」参数;去仓库 Actions 页看红叉日志 |
| 构建成功但没有产物 | 编译步骤是占位符 / 产物没放进 out/ | 看「上传产物」步骤是否报 No files were found |
| 找不到产物 | artifact 命名不符合 {前缀}-{runId} | 检查 upload-artifact 的 name 表达式 |
| 拉取契约报 404 | 仓库为 Private,或缺少 build/params.schema.json | 改 Public 或手动上传该文件;不影响构建 |
万能排查入口:打开仓库 → Actions 标签页。有 run 就看日志(哪一步红叉点开看详情);没 run 说明 dispatch 没送达(查事件类型与 Token 权限)。
十、安全建议
- 仓库可见性:想用后台「拉取契约」按钮,仓库必须是 Public(后端为匿名拉取 raw 地址)。若坚持 Private,跳过拉取契约——程序自带契约,功能不受影响
- 令牌权限最小化:只勾一个仓库;Actions 读写 + Contents 只读(无需 API 推送文件时);其余 No access
- 令牌即钥匙:不贴群、不进代码、不进截图;泄露立即在 GitHub 上 Delete 并重新生成
- 定期检查:Fine-grained tokens 列表页可随时查看/作废;后台「操作日志」有全部构建与下载留痕
- 产物 7 天自动清理,重要成品及时下载归档
附:速查卡片
后台字段 ↔ build.yml
───────────────────────────────────────────────────────
Workflow 文件名 build.yml ↔ .github/workflows/build.yml
Dispatch 事件类型 build-plugin ↔ on.repository_dispatch.types
产物名称前缀 gzhmod ↔ name: ${{ ...artifactPrefix }}-${{ github.run_id }}
触发分支 main ↔ 工作流所在分支
(自动投递 buildRef) ↔ 顶层 name: ${{ github.event.client_payload.buildRef }}
三步验证口诀:保存配置 → 测试连接(看”连接正常,仓库可写”)→ 发起一次测试构建(看状态变绿)。
完成以上配置,你就拥有了一条「改参数 → 点按钮 → 下载成品包」的全自动云端编译流水线。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!













暂无评论内容