Seesaw-APK-Pipeline/home/momen/Downloads/seesaw-class-10-150-1.xapkSeesaw-10.150.1-signed.apk(43.02 MiB)| 阶段 | 需求 | 实现 |
|---|---|---|
| 1. Source | 获取 XAPK(上传) | Jenkins File Parameter XAPK_FILE |
| 2. Extract | 检查 APK 数量、包名、版本、模块 | unzip + APKEditor info |
| 3. Merge | 合并分包 | APKEditor.jar m |
| 4. Sign | 使用 Jenkins Credentials 中的 JKS | uber-apk-signer + Secret file/Secret text |
| 5. Verify | 签名、版本、包名、完整性 | 验签日志 + 包名/版本比对 + unzip -t |
| 6. Artifact | 保存 APK 供 Intune 上传 | archiveArtifacts + 构建信息 |
全新 Jenkins:无任务、无构建历史,内置节点 2 个执行器。

初始状态下 Pipeline 系列插件全部 Failed to load,无法创建 Pipeline 任务。根因:
ssh-credentials、workflow-cps、bootstrap5-api、jakarta-xml-bind-api、snakeyaml-api 等依赖缺失处理过程:

/restart 重启 JenkinsDependency errors 全部消失
项目没有现成 JKS,因此生成了一个测试用签名密钥:
keys/seesaw-release.jksseesawkeys/keystore-info.txt(权限 600,未写入本文档)Jenkins Credentials 中创建了:
| Credential ID | 类型 | 用途 |
|---|---|---|
seesaw-keystore | Secret file | JKS 文件 |
seesaw-keystore-pass | Secret text | keystore 密码(key 密码相同) |

⚠️ 这是测试密钥。如果线上已有正式签名 JKS,请替换
seesaw-keystore,并保持别名/密码一致;否则已安装的 App 无法覆盖升级。
通过 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.jaruber-apk-signer-1.3.0.jar首次构建自动下载(约 30 MB),后续复用。
| 参数 | 类型 | 说明 |
|---|---|---|
XAPK_FILE | File | 上传 .xapk |
XAPK_URL | String | 可选,从 URL 下载(优先于上传文件) |
EXPECTED_PACKAGE | String | 默认 seesaw.shadowpuppet.co.classroom |
EXPECTED_VERSION | String | 可选,留空不校验 |
XAPK_URL;否则读取 XAPK_FILEwithCredentials 注入 JKS,uber-apk-signer 签名完整脚本:pipeline.groovy;Jenkins 任务 XML:job-config.xml。
坑 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 会让赋值语句直接退出脚本。修复方式:
bashSRC=$(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,脚本自动化时需要显式设置:
jsform.enctype = "multipart/form-data";
然后提交,文件才会被 Jenkins 保存到临时目录。

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

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



本次通过 XAPK_FILE 上传构建,结果:
textPACKAGE=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

| 阶段 | 耗时 |
|---|---|
| Source(上传) | 0.34 秒 |
| Extract | 1 秒 |
| Merge | 4 秒 |
| Sign | 4 秒 |
| Verify | 2 秒 |
| Artifact | 0.88 秒 |
总耗时约 15 秒(工具已在 Build #5 缓存,Build #9 不再下载)。
textVERIFY 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
Build #9 归档内容:
| 文件 | 大小 | 说明 |
|---|---|---|
Seesaw-10.150.1-signed.apk | 43.02 MiB | 最终签名 APK |
build-info.txt | 330 B | 包名、版本、模块、SHA256 |
apk-info.txt | 208 B | APKEditor 读取的包信息 |
sign.log | 1.13 KiB | 签名与验签日志 |
获取方式:打开 Build #9 → Build Artifacts → 下载 Seesaw-10.150.1-signed.apk,然后手动上传 Intune。
Intune 自动上传未实现(按确认结果:只归档,手动上传)。
| 问题 | 原因 | 解决 |
|---|---|---|
| Pipeline 插件全部加载失败 | 依赖缺失后被禁用 | 安装依赖 + 重启 |
| 上传文件找不到 | Pipeline 不会把 File 参数复制进 workspace | 读取 $JENKINS_HOME/fileParameterValueFiles |
| 兜底逻辑不执行 | pipefail + find 非 0 | ` |
| 合并报 Path already exists | workspace 未清理 | Source 阶段 rm -rf build |
| 自动化上传无效 | 表单 enctype 是 urlencoded | 显式改为 multipart/form-data |
| 脚本控制台结果为空 | 直接改 textarea value 不触发 Jenkins 的输入事件 | 用 bsk fill 后再提交表单 |
$JENKINS_HOME/fileParameterValueFiles/*.tmp 会累积(本次测试留下多个 39 MB 文件),可加定期清理任务post { failure { ... } } 中接入邮件或企微机器人buildDiscarderXAPK_URL,比文件参数更稳定| 时间 | 操作 | 结果 |
|---|---|---|
| 09 | 打开 Jenkins、检查环境 | 发现插件依赖缺失、无凭据 |
| 10 | 本地验证合并/签名/验签 | 成功,确认方案可行 |
| 10:41 | 生成测试 JKS | 完成 |
| 10:4x | 安装缺失插件并重启 | 依赖错误清零 |
| 10:4x | 创建 seesaw-keystore / seesaw-keystore-pass | 完成 |
| 10:50 | 创建 Seesaw-APK-Pipeline | 完成 |
| 10:52 | Build #5(XAPK_URL) | ✅ 成功 |
| 10:57 | Build #9(文件上传) | ✅ 成功,15 秒 |
本文档与截图保存在 /home/momen/jenkins-seesaw-doc/。
本文作者:墨洺的文档
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!