天津品牌网站建设,网站建设企业所得税,央企网站群建设,网站建设推广语言你要是做过 Unity、iOS、Android、或者任何需要“打包交付”的活#xff0c;大概率都经历过这种人生惨剧#xff1a; 早上 10 点#xff1a;产品说“给测试一个包看看”中午 12 点#xff1a;测试说“再来一个修复版”下午 3 点#xff1a;运营说“渠道包要十个#xff0…你要是做过 Unity、iOS、Android、或者任何需要“打包交付”的活大概率都经历过这种人生惨剧早上 10 点产品说“给测试一个包看看”中午 12 点测试说“再来一个修复版”下午 3 点运营说“渠道包要十个今晚投放”晚上 8 点老板说“iOS 也要顺便上传 TestFlight”晚上 11 点你电脑风扇像直升机证书突然掉了Gradle 还报红然后你发现你一天没写几行业务代码全在“打包、签名、传包、发群、解释为什么失败”。这时候你终于明白打包这件事不该靠人。人应该做创造性的事情打包这种重复劳动应该交给机器。这台机器就叫CIContinuous Integration持续集成。用一句大白话概括本文CI 就是你的“自动打包小弟”你把流程写成脚本它负责跑、负责签名、负责归档、负责把结果送到你面前。下面我们就用大白话把 CI 讲透它到底负责啥、Jenkins/GitLab CI/GitHub Actions 三个怎么选、怎么搭一套“跑脚本 签名 归档”的流水线、以及最关键的坑签名资产怎么管、归档怎么做才可追溯、失败怎么定位。1. 先把 CI 说成人话从“手工厨房”变成“中央厨房”没有 CI 的打包交付像什么像一家小饭馆每次有订单你就跑去厨房现做盐多盐少全凭手感锅糊了就重来做完还要你自己打包、自己送外卖。有 CI 之后像什么像中央厨房菜谱写清楚脚本做菜流程固定流水线谁来下单都按同一套标准出餐做完自动封装、贴标签、入库顺手发短信告诉你“外卖到了”。大白话总结脚本菜谱Runner/Agent厨师 厨房Pipeline出餐流程切菜→炒菜→装盒→贴单→入库Artifact装盒后的成品APK/IPA/Zip/日志Signing盖章这包是“官方出品”不是野包Archive/归档入库 可追溯想找哪次出餐都能找回2. CI 负责的“三件大事”跑脚本、签名、归档题目已经把核心写出来了CI 在打包交付里通常就干这三件事。2.1 跑脚本把“点点点”变成“跑跑跑”你手工打包要点切平台改版本号选 Development/ReleaseBuild导出 Xcode/Gradle再去 Xcode/Gradle 编译再上传CI 的思路是把这堆动作写成命令行脚本然后在固定环境里自动执行。Unity 常见是Unity -batchmode -executeMethodAndroid 常见是./gradlew assembleRelease / bundleReleaseiOS 常见是xcodebuild archivexcodebuild -exportArchive再加上 fastlanefastlane pilot上传 TestFlightfastlane supply上传 Google Play2.2 签名让包“合法”并且“能升级”签名这件事是打包里最容易翻车的环节Androidkeystore、alias、密码iOS证书、私钥、Provisioning Profile、Team、Bundle IDCI 必须做两件事安全地拿到签名材料不能明文放仓库稳定地完成签名不靠某个人电脑2.3 归档让每一次构建都可追溯、可回滚、可复现归档不是“把包扔群里”。归档应该包含安装包APK/AAB/IPA符号文件Android mapping.txt、iOS dSYM构建日志Unity.log、Gradle log、xcodebuild log构建元信息commit hash、分支、构建号、渠道、环境、版本号依赖/配置快照ExportOptions.plist、gradle.properties 的脱敏版本等大白话归档就是“把这次做饭用的菜谱、食材批次、做菜录像、成品照片都存起来”。下次出问题你才能追责、复盘、重做、回滚。3. Jenkins / GitLab CI / GitHub Actions三兄弟怎么选它们都能干活但气质不一样。3.1 Jenkins老牌“自建工厂”自由度最高也最需要运维优点插件多、生态成熟自由度很高想怎么玩都行适合复杂流水线、大公司多项目统一管理可以接各种自建机器macOS 构建机、Windows 构建机缺点需要你自己维护 Jenkins 服务插件多也意味着“插件地狱”安全、权限、升级都得有人管适用你们公司有运维/DevOps需要自建 macOS 节点iOS 打包有复杂的内部流程审批、签名机、制品库3.2 GitLab CI自带“流水线基因”适合代码在 GitLab 的团队优点和 GitLab 仓库深度绑定.gitlab-ci.yml配起来统一Runner 机制成熟自建机器也方便权限、变量、制品、环境管理都比较顺缺点依赖 GitLab 的平台某些高级玩法仍需要自己折腾 Runner 与缓存适用代码在 GitLab想要“仓库即流水线”的体验团队规模中等到大想把 CI 当基础设施3.3 GitHub Actions云端“拎包入住”开源项目和轻量团队很爽优点仓库里放个 workflow 就能跑Marketplace action 多对开源项目、跨平台构建很方便生态和 GitHub 强绑定PR、Release、Tag缺点私有仓库、大型构建可能会受限于额度/并发iOS 构建需要 macOS runner费用/资源一些公司对代码出云有合规顾虑适用代码在 GitHub想要快速上手团队不想自己维护 CI 服务大白话选型口诀想“自己开厂”→ Jenkins用 GitLab、想“内网一体化”→ GitLab CI用 GitHub、想“省事上云”→ GitHub Actions4. 一条能落地的流水线长什么样通用模板我们先给一个“跑脚本 签名 归档”的通用流程你不管用谁都差不多Stage 0准备Prepare拉代码checkout拉 LFS如果有初始化子模块读取构建参数分支、环境、渠道、版本号策略Stage 1跑 Unity 构建脚本Build UnityUnity batchmode 执行-executeMethod导出 Android Gradle 工程 / iOS Xcode 工程生成 build_info.json保存 Unity Editor.log非常关键Stage 2平台编译Build PlatformAndroid./gradlew assembleRelease或bundleReleaseiOSpod install如需→xcodebuild archive→xcodebuild exportStage 3签名SignAndroidGradle signingConfigs / apksigneriOScodesign profile一般由 Xcode/fastlane 接管Stage 4归档与发布Archive Distribute归档产物APK/AAB/IPA、dSYM、mapping.txt、日志、build_info上传制品库Nexus/Artifactory/S3/OSS上传分发平台蒲公英、Firebase App Distribution、TestFlight发通知飞书/钉钉/Slack/邮件带下载链接和构建信息Stage 5清理Cleanup清缓存可选清 keychain 临时证书iOS清临时文件5. CI 里最难的其实是“签名”怎么做到安全又稳定签名材料有一个共同点它们都不能随便放但又必须让 CI 机器拿到。5.1 Android 签名keystore 的正确保管姿势错误做法keystore 放仓库密码写在脚本里keystore 发群里正确做法keystore 放在 CI 的“秘密变量/文件变量”里或放在私有制品库CI 运行时拉取密码走 CI SecretJenkins Credentials/GitLab CI Variables/GitHub Secrets常用套路keystore 以 base64 字符串存在 secret 里CI 运行时写回文件release.keystore大白话keystore 是公章你可以放保险柜里但不能贴在办公室门上。5.2 iOS 签名证书私钥Profile三件套缺一不可iOS 签名更麻烦因为它是“三件套”证书.cer私钥.p12或者 Keychain 里的私钥Provisioning Profile.mobileprovisionCI 要做的事把 p12 导入到构建机的 keychain建议临时 keychain安装 provisioning profile 到~/Library/MobileDevice/Provisioning Profiles/确保 Xcodebuild 能找到匹配的 team/bundle id/profile更高级的做法是 fastlane match证书和 profile 存在加密仓库CI 用密钥解密拉取保证团队所有机器签名一致大白话iOS 签名像“三把钥匙开一扇门”少一把都进不去。match 就是“把钥匙统一放一个加密钥匙柜”谁需要谁去拿。6. 归档到底怎么做才算“专业”别只存一个安装包很多团队的归档是“打出来的包扔到群里/网盘里名字叫 final_final_3.apk。”出了线上崩溃你就会傻眼没有符号文件没法还原堆栈不知道是哪次提交不知道是哪套宏回滚也找不到旧包。6.1 归档清单建议固定模板每次构建至少归档这些安装包Androidapp-release.apk/app-release.aabiOSApp.ipa符号文件AndroidIL2CPPsymbols.zip或 Unity 生成的符号AndroidProguard/R8mapping.txtiOSdSYM.zip构建日志UnityEditor.logGradle logxcodebuild log构建信息build_info.jsoncommit、branch、pipeline id、version、channel、env导出参数快照iOS ExportOptions.plist脱敏Android 的 gradle 配置脱敏6.2 归档命名规范别小看它救命推荐命名{project}_{platform}_{env}_{channel}_v{version}_{buildNumber}_{commitShort}例子MyGame_android_prod_huawei_v1.8.0_10234_a1b2c3d.apkMyGame_ios_staging_appstore_v1.8.0_567_a1b2c3d.ipa大白话包名写清楚等于你给每个包贴了身份证。没身份证迟早“找不到人”。7. 三个平台的落地示例不贴大段 YAML/Jenkinsfile但把思路讲清7.1 Jenkins 怎么干核心点用 PipelineJenkinsfile节点agent分平台Android 可以 Linux/Windows/macOSiOS 必须 macOSCredentials 管理Android keystore 文件iOS p12 密码App Store Connect API Key用于上传建议iOS 构建机尽量固定一台或几台专用 Mac mini构建前创建临时 keychain构建后删掉7.2 GitLab CI 怎么干核心点.gitlab-ci.yml写 stagesGitLab Runner 自建安卓 runner 可以 docker 化iOS runner 需要 shell executor macOS 机器CI/CD Variables 存 secretartifacts cacheartifacts 存产物cache 存 Unity Library/Gradle 缓存提升速度7.3 GitHub Actions 怎么干核心点.github/workflows/build.ymlrunner 选windows-latest / ubuntu-latest / macos-latestsecrets 存 keystore/p12artifacts 上传产物release 或 tag 触发发布注意macos runner 成本较高建议只在需要 iOS 时触发Unity License 激活需要处理用 Unity 官方 action 或自建8. 提升效率的“隐藏大招”缓存、并行、分层CI 之所以让人又爱又恨是因为它可能很慢。想快主要靠三招8.1 缓存 Unity Library但要小心Library 缓存能大幅减少导入时间但要注意Unity 版本变更要刷新缓存平台切换会导致缓存失效缓存键要包含 Unity 版本 平台 分支8.2 缓存 Gradle / CocoaPods~/.gradle~/.cocoapodsPods/视情况8.3 并行构建Android 与 iOS 可以并行前提是资源与脚本能并行多渠道包可以 matrix 并行但注意签名与配置隔离大白话缓存像“预制菜”并行像“开两个灶”。你不想快都难。9. 失败怎么定位CI 不是黑盒关键看日志和分段很多人觉得 CI 难是因为失败时只看到一屏红字。解决方法是“分段 关键日志抓取”。建议每个 stage 都把日志独立保存并在失败时输出最后 200 行关键日志上传完整日志作为 artifact对常见错误做关键词提示可选例如iOS codesign 失败就提示检查 bundleId、profile、teamIdGradle 依赖冲突提示检查 duplicate class10. 一套“能上生产”的 CI 最终长什么样目标态当你把 CI 真正跑顺它会变成这样开发合并到develop→ 自动打测试包→ 上传分发平台 → 群里发链接打 tag例如v1.8.0→ 自动打正式包Android AAB 上传 Google Play或生成渠道 APKiOS IPA 上传 TestFlight/App Store自动生成 Release Note从 commit/PR 里提取自动归档符号与日志到制品库出问题随时回滚找到某次构建产物 → 一键重发/重签/重传大白话你从“打包工”升级成“按按钮发车的人”。车怎么造、怎么检修、怎么开都在流水线里。11. 结尾CI 不是工具是“把团队从重复劳动里解放出来”的生产力CI 最值钱的点从来不是“省一次打包时间”而是打包变得稳定交付变得可追溯新人上手不靠口口相传出问题能快速定位多渠道、多环境不再恐怖你们团队的效率很大一部分就藏在这条流水线里。