Files
tra-app/Jenkinsfile-ios
T

281 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
pipeline {
agent {label 'macos'}
tools {
nodejs 'node22'
}
environment {
UNIAPP_APP_ID = '__UNI__EDE52' // uni-app 应用ID
APP_DIR = "Ios/HBuilder-Hello" // iOS 项目根目录
PROJECT_NAME = 'HBuilder-Hello' // 项目名称(xcodeproj 前缀)
ASSETS_DIR = "${APP_DIR}/${PROJECT_NAME}/Pandora/apps/${UNIAPP_APP_ID}/www" // 静态资源目录
SCHEME_NAME = 'HBuilder' // Xcode 编译 Scheme
CONFIGURATION = 'Release' // 编译模式:Release/Debug
ARCHIVE_PATH = "${APP_DIR}/build/HBuilder.xcarchive" // 归档文件输出路径
SOURCE_SDK="${HOME}/Library/SDK" // IOS的SDK存放路径
TARGET_LINK="${APP_DIR}/../SDK"
// ====================== 证书配置 ======================
CERT_DIR = 'certificate/ios' // 证书文件存放目录
P12_FILE = "${CERT_DIR}/生产证书.p12" // 开发证书 p12 路径
P12_PASSWORD = "123456" // p12 证书导入密码
PROFILE_FILE = "${CERT_DIR}/jiaixuepro.mobileprovision" // 描述文件路径
MAC_LOGIN_PWD = "667788" // Mac 登录密码(解锁钥匙串)
EXPORT_OPTIONS_PLIST = "${CERT_DIR}/ExportOptions.plist" // 导出配置文件路径
// ====================== 手动签名必须的变量 ======================
DEVELOPMENT_TEAM = "2EP6SRRN43" // 苹果开发者团队ID
CERTIFICATE_NAME = "Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43)" // 证书名称(钥匙串里看)
PROVISIONING_PROFILE_UUID = "e3487fe1-19dc-4fc7-90df-11caf27da0c6" // 描述文件UUID
// ====================== TestFlight上传配置 ======================
API_KEY = "ACRB9XFL9G" // App Store Connect API 密钥ID
API_ISSUER = "69a6de7f-3378-47e3-e053-5b8c7c11a4d1" // API 密钥对应的Issuer ID
API_TYPE = "ios" // 应用类型(固定为ios)
P8_FILE = "${CERT_DIR}/AuthKey_ACRB9XFL9G.p8" // .p8 密钥文件
APP_NAME = "吉AI学"
API_ENDPOINT = "https://api.appstoreconnect.apple.com/v1"
}
stages {
stage('打印环境变量') {
steps {
echo "使用的 UNIAPP_APP_ID${env.UNIAPP_APP_ID}"
echo "IOS资源目录:${env.ASSETS_DIR}"
sh "node -v" // 打印 NodeJS 版本
sh "npm -v" // 打印 NPM
}
}
stage('清理旧构建') {
steps {
sh "rm -rf dist/" // 清理 UniApp 打包生成的 dist 目录
sh "rm -rf ${env.ARCHIVE_PATH}" // 清理 上次的构建文件
}
}
stage('安装依赖') {
steps {
echo "✅ 安装 UniApp 依赖(忽略平台+开权限+强制)"
sh "npm install --force --unsafe-perm --ignore-platform"
}
}
stage('读取 manifest 版本号 → 写入环境变量') {
steps {
script {
// 2. 读取并设置为 环境变量(全局可用)
env.versionName = sh(
script: '''
node -p "require('json5').parse(require('fs').readFileSync('./src/manifest.json','utf8')).versionName"
''',
returnStdout: true
).trim()
env.versionCode = sh(
script: '''
node -p "require('json5').parse(require('fs').readFileSync('./src/manifest.json','utf8')).versionCode"
''',
returnStdout: true
).trim()
}
// 测试输出(你能看到成功了)
echo "✅ 版本名称:${env.versionName}"
echo "✅ 版本号:${env.versionCode}"
}
}
//stage('安装证书 & 描述文件') {
// steps {
// echo "# =============== 安装 p12 证书 ==============="
// sh '''
// security unlock-keychain -p ${MAC_LOGIN_PWD} ~/Library/Keychains/login.keychain-db >/dev/null 2>&1
// security import ${P12_FILE} -k ~/Library/Keychains/login.keychain-db -P ${P12_PASSWORD} -A >/dev/null 2>&1
// security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k ${MAC_LOGIN_PWD} ~/Library/Keychains/login.keychain-db >/dev/null 2>&1
// '''
// echo "# =============== 安装描述文件 ==============="
// sh '''
// mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
// cp "${PROFILE_FILE}" "$HOME/Library/MobileDevice/Provisioning Profiles/"
// '''
// }
//}
//stage('打包uniapp') {
// steps {
// sh "npm run build:app-plus:${env.BRANCH_NAME}"
// }
//}
//stage('复制UniApp资源到目录') {
// steps {
// echo "开始复制 dist 资源到 ${ASSETS_DIR}"
// // 先创建目标目录(防止目录不存在报错)
// sh "mkdir -p ${ASSETS_DIR}"
// // 把 dist 里所有文件 复制 到安卓资源目录(推荐)
// sh "cp -rf dist/build/app/* ${ASSETS_DIR}/"
// echo "✅ 资源复制完成"
// }
//}
//
//stage('️清理旧构建内容') {
// steps {
// sh """
// xcodebuild clean \\
// -project ${APP_DIR}/${PROJECT_NAME}.xcodeproj \\
// -scheme ${SCHEME_NAME} \\
// -configuration ${CONFIGURATION}
// """
//
// }
//}
//stage('创建SDK软链接') {
// steps {
// sh '''
// # 删除旧的软链接/目录
// rm -rf "${TARGET_LINK}"
//
// # 创建软链接(不进入任何目录)
// ln -s "${SOURCE_SDK}" "${TARGET_LINK}"
//
// # 验证链接是否生效
// ls -la "${TARGET_LINK}"
// '''
// }
//}
//stage('✅ 开始归档(静默模式)') {
// steps {
// script {
// // Groovy 里拼接命令,随便写注释,不会影响 shell
// def xcodeCommand = [
// 'xcodebuild archive',
// // 项目路径
// "-project ${APP_DIR}/${PROJECT_NAME}.xcodeproj",
// // Scheme 配置
// "-scheme ${SCHEME_NAME}",
// // 编译模式 Release/Debug
// "-configuration ${CONFIGURATION}",
// // 归档输出路径
// "-archivePath ${ARCHIVE_PATH}",
// // 平台通用 iOS
// "-destination generic/platform=iOS",
// // 版本号
// "MARKETING_VERSION=${versionName}",
// "CURRENT_PROJECT_VERSION=${versionCode}",
//
// // 手动签名
// "CODE_SIGN_STYLE=Manual",
// "CODE_SIGN_IDENTITY='${CERTIFICATE_NAME}'",
// "PROVISIONING_PROFILE_SPECIFIER='${PROVISIONING_PROFILE_UUID}'",
// "PROVISIONING_PROFILE='${PROVISIONING_PROFILE_UUID}'",
// "DEVELOPMENT_TEAM='${DEVELOPMENT_TEAM}'",
//
// // 钥匙串
// "OTHER_CODE_SIGN_FLAGS='--keychain ~/Library/Keychains/login.keychain-db'",
//
// // 编译所有架构
// "ONLY_ACTIVE_ARCH=NO",
//
// // 清空编译参数
// "OTHER_CFLAGS=''",
// "OTHER_CPLUSPLUS_FLAGS=''",
// "OTHER_SWIFT_FLAGS=''",
// "> /dev/null 2>&1"
// ].join(' ') // 拼接成一行完整命令
// // 打印最终命令
// echo "执行命令:${xcodeCommand}"
// // 执行!
// sh(xcodeCommand)
// }
// }
//}
//stage('✅ 开始导出 IPA安装包') {
// steps {
// sh '''
// xcodebuild -exportArchive \\
// -archivePath ${ARCHIVE_PATH} \\
// -exportPath ${APP_DIR}/build \\
// -exportOptionsPlist ${EXPORT_OPTIONS_PLIST} \\
// -allowProvisioningUpdates
// '''
// }
//}
//stage('🚀 验证并上传 TestFlight') {
// steps {
// echo "✅ 开始验证 IPA 有效性"
// sh '''
// mkdir -p $HOME/private_keys
// cp -f "${P8_FILE}" $HOME/private_keys/
// '''
// // 1. 先验证 IPA(必须这一步,提前拦截错误)
// sh """
// xcrun altool --validate-app \\
// --file ${APP_DIR}/build/${SCHEME_NAME}.ipa \\
// --type ${API_TYPE} \\
// --apiKey ${API_KEY} \\
// --apiIssuer ${API_ISSUER}
// """
//
// echo "✅ IPA 验证成功!开始上传到 TestFlight"
//
// echo "🎉 全部完成!请到 App Store Connect TestFlight 查看构建"
// }
//}
stage('🔐 生成 JWT') {
steps {
script {
//JWT_TOKEN = sh(
// script: "node ${CERT_DIR}/generate-jwt.js",
// returnStdout: true
//).trim()
JWT_TOKEN = sh(
script: '''
node -e
const fs = require('fs');
const jwt = require('jsonwebtoken');
// 从 Jenkins 环境变量获取
const API_KEY = process.env.API_KEY;
const API_ISSUER = process.env.API_ISSUER;
const P8_FILE = process.env.P8_FILE;
// 读取 p8 私钥
const privateKey = fs.readFileSync(P8_FILE, 'utf8');
// 生成 JWT(苹果标准格式)
const token = jwt.sign(
{
iss: API_ISSUER,
exp: Math.floor(Date.now() / 1000) + 1200, // 20分钟
aud: 'appstoreconnect-v1'
},
privateKey,
{
algorithm: 'ES256',
header: {
kid: API_KEY,
alg: 'ES256'
}
}
);
// 输出 JWTJenkins 会捕获这个值)
console.log(token);
''',
returnStdout: true
).trim()
}
echo "✅ JWT 生成成功${JWT_TOKEN}"
}
}
}
post {
always {
echo '流水线已结束'
}
success {
echo '🎉 项目部署成功!'
}
failure {
echo '⚠️ 部署失败,请检查日志!'
}
}
}