编辑
2026-11-09
小白笔记
0

目录

Seesaw APK 自动构建流水线 — 配置复盘
1. 需求与实现
2. 环境勘查与问题修复
2.1 初始环境
2.2 插件依赖损坏(已修复)
2.3 凭据为空(已补充)
2.4 构建节点工具链
3. 流水线实现
3.1 任务参数
3.2 六个阶段
3.3 实现中的关键坑
4. 构建验证
4.1 任务创建
4.2 构建过程
4.3 上传文件构建(最终验收)
4.4 阶段耗时
4.5 签名验证
5. 构建产物与 Intune
6. 复盘:做对了什么 / 下次怎么更快
做对了
踩过的坑
后续建议
7. 操作时间线

Seesaw APK 自动构建流水线 — 配置复盘

  • Jenkins:http://10.71.1.86:7080/(2.580.2,Linux 容器,Java 21)
  • 任务名:Seesaw-APK-Pipeline
  • 测试输入:/home/momen/Downloads/seesaw-class-10-150-1.xapk
  • 最终产物:Seesaw-10.150.1-signed.apk(43.02 MiB)
  • 验证结果:✅ 上传文件构建成功(Build #9,耗时 15 秒)
  • 状态:已完成并通过一次真实上传构建

1. 需求与实现

阶段需求实现
1. Source获取 XAPK(上传)Jenkins File Parameter XAPK_FILE
2. Extract检查 APK 数量、包名、版本、模块unzip + APKEditor info
3. Merge合并分包APKEditor.jar m
4. Sign使用 Jenkins Credentials 中的 JKSuber-apk-signer + Secret file/Secret text
5. Verify签名、版本、包名、完整性验签日志 + 包名/版本比对 + unzip -t
6. Artifact保存 APK 供 Intune 上传archiveArtifacts + 构建信息

2. 环境勘查与问题修复

2.1 初始环境

01-jenkins-dashboard.png 全新 Jenkins:无任务、无构建历史,内置节点 2 个执行器。

2.2 插件依赖损坏(已修复)

02-script-console-env.png

初始状态下 Pipeline 系列插件全部 Failed to load,无法创建 Pipeline 任务。根因:

  • ssh-credentials、workflow-cps、bootstrap5-api、jakarta-xml-bind-api、snakeyaml-api 等依赖缺失
  • 插件加载失败被禁用后,Jenkins 不会自动重试

处理过程:

03-manage-plugins-error.png

  1. 在 Update Center 选择并安装缺失依赖
  2. 等待所有插件下载完成
  3. 通过 /restart 重启 Jenkins
  4. 重启后 Dependency errors 全部消失

2.3 凭据为空(已补充)

04-credentials-empty.png 项目没有现成 JKS,因此生成了一个测试用签名密钥:

  • 文件:keys/seesaw-release.jks
  • 别名:seesaw
  • 类型:JKS,RSA 4096,有效期 10000 天
  • 密码:单独保存在 keys/keystore-info.txt(权限 600,未写入本文档)

Jenkins Credentials 中创建了:

Credential ID类型用途
seesaw-keystoreSecret fileJKS 文件
seesaw-keystore-passSecret textkeystore 密码(key 密码相同)

创建 JKS 凭据

⚠️ 这是测试密钥。如果线上已有正式签名 JKS,请替换 seesaw-keystore,并保持别名/密码一致;否则已安装的 App 无法覆盖升级。

2.4 构建节点工具链

通过 Script Console 只读检查容器环境:

Script Console 环境检查

工具结果
unzip / curl / git✅ 已有
java / keytool⚠️ 在 /opt/java/openjdk/bin/,PATH 中没有
Android SDK / aapt2 / apksigner❌ 未安装
apkeditor❌ 未安装

方案:不安装完整 Android SDK,改用两个纯 Java 工具,缓存在 $JENKINS_HOME/tools:

  • APKEditor-1.4.9.jar
  • uber-apk-signer-1.3.0.jar

首次构建自动下载(约 30 MB),后续复用。


3. 流水线实现

3.1 任务参数

参数类型说明
XAPK_FILEFile上传 .xapk
XAPK_URLString可选,从 URL 下载(优先于上传文件)
EXPECTED_PACKAGEString默认 seesaw.shadowpuppet.co.classroom
EXPECTED_VERSIONString可选,留空不校验

3.2 六个阶段

  1. Source:优先使用 XAPK_URL;否则读取 XAPK_FILE
  2. Extract:统计 APK 数量、解包、APKEditor 读取包名/版本/模块
  3. Merge:APKEditor 合并为单体 APK
  4. Sign:withCredentials 注入 JKS,uber-apk-signer 签名
  5. Verify:验签、包名/版本比对、ZIP 完整性检查
  6. Artifact:归档 APK、构建信息、签名日志

完整脚本:pipeline.groovy;Jenkins 任务 XML:job-config.xml。

3.3 实现中的关键坑

坑 1:Pipeline 的 File 参数不会自动进入 workspace

Jenkins 的 FileParameterValue 只有 Freestyle 的 BuildWrapper 会把它复制到 workspace。Pipeline 构建中文件实际保存在:

text
$JENKINS_HOME/fileParameterValueFiles/jenkins*.tmp

并且 XAPK_FILE 环境变量只是原始文件名,不是路径。因此在 Source 阶段增加了兜底逻辑:如果 workspace 找不到,就取该目录下最新的 .tmp 文件。

坑 2:set -euo pipefail 导致兜底逻辑被跳过

find 查找不存在的目录时返回非 0,配合 pipefail 会让赋值语句直接退出脚本。修复方式:

bash
SRC=$(find ... | head -1) || SRC=""

坑 3:workspace 残留导致合并失败

APKEditor 拒绝覆盖已存在的 build/seesaw-merged.apk。修复:Source 阶段先 rm -rf build。

坑 4:Jenkins 2.580 的文件参数表单

新 UI 的 <form> 默认是 application/x-www-form-urlencoded,脚本自动化时需要显式设置:

js
form.enctype = "multipart/form-data";

然后提交,文件才会被 Jenkins 保存到临时目录。


4. 构建验证

4.1 任务创建

Pipeline 任务创建

4.2 构建过程

首次构建(Build #1)用于验证参数传递,因文件参数未进入 workspace 而失败:

Build #1 运行中

随后通过 XAPK_URL 方式验证了完整流程(Build #5):

Build #5 成功

Build #5 阶段

4.3 上传文件构建(最终验收)

Build #9 成功

本次通过 XAPK_FILE 上传构建,结果:

text
PACKAGE=seesaw.shadowpuppet.co.classroom VERSION=10.150.1 VERSION_CODE=1988154 APK_COUNT=30 MODULES=ar,arm64_v8a,armeabi_v7a,de,en,es,et,fr,hdpi,hi,in,it,ja,km,ko,ms,my,nl,pt,ru,th,tr,tvdpi,uk,vi,xhdpi,xxhdpi,xxxhdpi,zh SIGNED_APK=Seesaw-10.150.1-signed.apk SHA256=7a9a49f285609162fcbf86c0699f405407f33c3fdfcdb22cb943caed6f99b99a

4.4 阶段耗时

Build #9 阶段

阶段耗时
Source(上传)0.34 秒
Extract1 秒
Merge4 秒
Sign4 秒
Verify2 秒
Artifact0.88 秒

总耗时约 15 秒(工具已在 Build #5 缓存,Build #9 不再下载)。

4.5 签名验证

text
VERIFY file: .../seesaw-merged-aligned-signed.apk (43.02 MiB) - zipalign verified - signature verified [v3] Subject: CN=Seesaw Internal, OU=Mobile, O=DEXA, L=Shanghai, ST=Shanghai, C=CN SHA256: 627a802032312e8266bb5a1d154575e59b73af6688ae2c63a7e36111fa5e9853 Expires: Fri Mar 27 02:41:01 UTC 2054 Successfully processed 1 APKs and 0 errors

5. 构建产物与 Intune

Build #9 归档内容:

文件大小说明
Seesaw-10.150.1-signed.apk43.02 MiB最终签名 APK
build-info.txt330 B包名、版本、模块、SHA256
apk-info.txt208 BAPKEditor 读取的包信息
sign.log1.13 KiB签名与验签日志

获取方式:打开 Build #9 → Build Artifacts → 下载 Seesaw-10.150.1-signed.apk,然后手动上传 Intune。

Intune 自动上传未实现(按确认结果:只归档,手动上传)。


6. 复盘:做对了什么 / 下次怎么更快

做对了

  1. 先在本地跑通合并/签名/验签,确认工具链可行,再动 Jenkins
  2. 用纯 Java 工具替代 Android SDK,减少 1 GB 级依赖
  3. 登录态掉线时使用 request-help 让用户接管,而不是猜测密码
  4. 每一步都保留截图和构建日志,最终有完整证据链

踩过的坑

问题原因解决
Pipeline 插件全部加载失败依赖缺失后被禁用安装依赖 + 重启
上传文件找不到Pipeline 不会把 File 参数复制进 workspace读取 $JENKINS_HOME/fileParameterValueFiles
兜底逻辑不执行pipefail + find 非 0`
合并报 Path already existsworkspace 未清理Source 阶段 rm -rf build
自动化上传无效表单 enctype 是 urlencoded显式改为 multipart/form-data
脚本控制台结果为空直接改 textarea value 不触发 Jenkins 的输入事件用 bsk fill 后再提交表单

后续建议

  1. 替换正式 JKS:当前为测试密钥,正式发布前务必换成组织现有签名密钥
  2. 清理临时文件:$JENKINS_HOME/fileParameterValueFiles/*.tmp 会累积(本次测试留下多个 39 MB 文件),可加定期清理任务
  3. 补充失败通知:可在 post { failure { ... } } 中接入邮件或企微机器人
  4. 产物保留策略:按 Intune 发布节奏设置 buildDiscarder
  5. 正式化 Source:如果后续从制品库获取 XAPK,可直接使用 XAPK_URL,比文件参数更稳定

7. 操作时间线

时间操作结果
09
打开 Jenkins、检查环境发现插件依赖缺失、无凭据
10
本地验证合并/签名/验签成功,确认方案可行
10:41生成测试 JKS完成
10:4x安装缺失插件并重启依赖错误清零
10:4x创建 seesaw-keystore / seesaw-keystore-pass完成
10:50创建 Seesaw-APK-Pipeline完成
10:52Build #5(XAPK_URL)✅ 成功
10:57Build #9(文件上传)✅ 成功,15 秒

本文档与截图保存在 /home/momen/jenkins-seesaw-doc/。

本文作者:墨洺的文档

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!