JLBA202505130001_关于吉林银行新建AI智能培训系统的需求_完善代码规范
This commit is contained in:
+238
-232
@@ -1,248 +1,254 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
agent {label 'macos'}
|
agent {
|
||||||
tools {
|
label 'macos'
|
||||||
nodejs 'node22'
|
}
|
||||||
}
|
tools {
|
||||||
environment {
|
nodejs 'node22'
|
||||||
UNIAPP_APP_ID = '__UNI__EDE52' // uni-app 应用ID
|
}
|
||||||
APP_DIR = "Ios/HBuilder-Hello" // iOS 项目根目录
|
environment {
|
||||||
PROJECT_NAME = 'HBuilder-Hello' // 项目名称(xcodeproj 前缀)
|
UNIAPP_APP_ID = '__UNI__EDE52' // uni-app 应用ID
|
||||||
ASSETS_DIR = "${APP_DIR}/${PROJECT_NAME}/Pandora/apps/${UNIAPP_APP_ID}/www" // 静态资源目录
|
APP_DIR = "Ios/HBuilder-Hello" // iOS 项目根目录
|
||||||
SCHEME_NAME = 'HBuilder' // Xcode 编译 Scheme
|
PROJECT_NAME = 'HBuilder-Hello' // 项目名称(xcodeproj 前缀)
|
||||||
CONFIGURATION = 'Release' // 编译模式:Release/Debug
|
ASSETS_DIR = "${APP_DIR}/${PROJECT_NAME}/Pandora/apps/${UNIAPP_APP_ID}/www" // 静态资源目录
|
||||||
ARCHIVE_PATH = "${APP_DIR}/build/HBuilder.xcarchive" // 归档文件输出路径
|
SCHEME_NAME = 'HBuilder' // Xcode 编译 Scheme
|
||||||
SOURCE_SDK="${HOME}/Library/SDK" // IOS的SDK存放路径
|
CONFIGURATION = 'Release' // 编译模式:Release/Debug
|
||||||
TARGET_LINK="${APP_DIR}/../SDK"
|
ARCHIVE_PATH = "${APP_DIR}/build/HBuilder.xcarchive" // 归档文件输出路径
|
||||||
|
SOURCE_SDK = "${HOME}/Library/SDK" // IOS的SDK存放路径
|
||||||
|
TARGET_LINK = "${APP_DIR}/../SDK"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ====================== 证书配置 ======================
|
// ====================== 证书配置 ======================
|
||||||
CERT_DIR = 'certificate/ios' // 证书文件存放目录
|
CERT_DIR = 'certificate/ios' // 证书文件存放目录
|
||||||
P12_FILE = "${CERT_DIR}/生产证书.p12" // 开发证书 p12 路径
|
P12_FILE = "${CERT_DIR}/生产证书.p12" // 开发证书 p12 路径
|
||||||
P12_PASSWORD = "123456" // p12 证书导入密码
|
P12_PASSWORD = "123456" // p12 证书导入密码
|
||||||
PROFILE_FILE = "${CERT_DIR}/jiaixuepro.mobileprovision" // 描述文件路径
|
PROFILE_FILE = "${CERT_DIR}/jiaixuepro.mobileprovision" // 描述文件路径
|
||||||
MAC_LOGIN_PWD = "667788" // Mac 登录密码(解锁钥匙串)
|
MAC_LOGIN_PWD = "667788" // Mac 登录密码(解锁钥匙串)
|
||||||
EXPORT_OPTIONS_PLIST = "${CERT_DIR}/ExportOptions.plist" // 导出配置文件路径
|
EXPORT_OPTIONS_PLIST = "${CERT_DIR}/ExportOptions.plist" // 导出配置文件路径
|
||||||
|
|
||||||
// ====================== 手动签名必须的变量 ======================
|
// ====================== 手动签名必须的变量 ======================
|
||||||
DEVELOPMENT_TEAM = "2EP6SRRN43" // 苹果开发者团队ID
|
DEVELOPMENT_TEAM = "2EP6SRRN43" // 苹果开发者团队ID
|
||||||
CERTIFICATE_NAME = "Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43)" // 证书名称(钥匙串里看)
|
CERTIFICATE_NAME = "Apple Distribution: Bank of Jilin Co., Ltd. (2EP6SRRN43)" // 证书名称(钥匙串里看)
|
||||||
PROVISIONING_PROFILE_UUID = "e3487fe1-19dc-4fc7-90df-11caf27da0c6" // 描述文件UUID
|
PROVISIONING_PROFILE_UUID = "e3487fe1-19dc-4fc7-90df-11caf27da0c6" // 描述文件UUID
|
||||||
|
|
||||||
// ====================== TestFlight上传配置 ======================
|
// ====================== TestFlight上传配置 ======================
|
||||||
API_KEY = "ACRB9XFL9G" // App Store Connect API 密钥ID
|
API_KEY = "ACRB9XFL9G" // App Store Connect API 密钥ID
|
||||||
API_ISSUER = "69a6de7f-3378-47e3-e053-5b8c7c11a4d1" // API 密钥对应的Issuer ID
|
API_ISSUER = "69a6de7f-3378-47e3-e053-5b8c7c11a4d1" // API 密钥对应的Issuer ID
|
||||||
API_TYPE = "ios" // 应用类型(固定为ios)
|
API_TYPE = "ios" // 应用类型(固定为ios)
|
||||||
P8_FILE = "${CERT_DIR}/AuthKey_ACRB9XFL9G.p8" // .p8 密钥文件
|
P8_FILE = "${CERT_DIR}/AuthKey_ACRB9XFL9G.p8" // .p8 密钥文件
|
||||||
APP_NAME = "吉AI学"
|
APP_NAME = "吉AI学"
|
||||||
API_ENDPOINT = "https://api.appstoreconnect.apple.com/v1"
|
API_ENDPOINT = "https://api.appstoreconnect.apple.com/v1"
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('打印环境变量') {
|
stage('打印环境变量') {
|
||||||
steps {
|
steps {
|
||||||
echo "使用的 UNIAPP_APP_ID:${env.UNIAPP_APP_ID}"
|
echo "使用的 UNIAPP_APP_ID:${env.UNIAPP_APP_ID}"
|
||||||
echo "IOS资源目录:${env.ASSETS_DIR}"
|
echo "IOS资源目录:${env.ASSETS_DIR}"
|
||||||
sh "node -v" // 打印 NodeJS 版本
|
sh "node -v" // 打印 NodeJS 版本
|
||||||
sh "npm -v" // 打印 NPM
|
sh "npm -v" // 打印 NPM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('清理旧构建') {
|
stage('清理旧构建') {
|
||||||
steps {
|
steps {
|
||||||
sh "rm -rf dist/" // 清理 UniApp 打包生成的 dist 目录
|
sh "rm -rf dist/" // 清理 UniApp 打包生成的 dist 目录
|
||||||
sh "rm -rf ${env.ARCHIVE_PATH}" // 清理 上次的构建文件
|
sh "rm -rf ${env.ARCHIVE_PATH}" // 清理 上次的构建文件
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('安装依赖') {
|
stage('安装依赖') {
|
||||||
steps {
|
steps {
|
||||||
echo "✅ 安装 UniApp 依赖(忽略平台+开权限+强制)"
|
echo "✅ 安装 UniApp 依赖(忽略平台+开权限+强制)"
|
||||||
sh "npm install --force --unsafe-perm --ignore-platform"
|
sh "npm install --force --unsafe-perm --ignore-platform"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('读取 manifest 版本号 → 写入环境变量') {
|
stage('读取 manifest 版本号 → 写入环境变量') {
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
// 2. 读取并设置为 环境变量(全局可用)
|
// 2. 读取并设置为 环境变量(全局可用)
|
||||||
env.versionName = sh(
|
env.versionName = sh(
|
||||||
script: '''
|
script: '''
|
||||||
node -p "require('json5').parse(require('fs').readFileSync('./src/manifest.json','utf8')).versionName"
|
node -p "require('json5').parse(require('fs').readFileSync('./src/manifest.json','utf8')).versionName"
|
||||||
''',
|
''',
|
||||||
returnStdout: true
|
returnStdout: true
|
||||||
).trim()
|
).trim()
|
||||||
|
|
||||||
env.versionCode = sh(
|
env.versionCode = sh(
|
||||||
script: '''
|
script: '''
|
||||||
node -p "require('json5').parse(require('fs').readFileSync('./src/manifest.json','utf8')).versionCode"
|
node -p "require('json5').parse(require('fs').readFileSync('./src/manifest.json','utf8')).versionCode"
|
||||||
''',
|
''',
|
||||||
returnStdout: true
|
returnStdout: true
|
||||||
).trim()
|
).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试输出(你能看到成功了)
|
// 测试输出(你能看到成功了)
|
||||||
echo "✅ 版本名称:${env.versionName}"
|
echo "✅ 版本名称:${env.versionName}"
|
||||||
echo "✅ 版本号:${env.versionCode}"
|
echo "✅ 版本号:${env.versionCode}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//stage('安装证书 & 描述文件') {
|
stage('安装证书 & 描述文件') {
|
||||||
// steps {
|
steps {
|
||||||
// echo "# =============== 安装 p12 证书 ==============="
|
echo "# =============== 安装 p12 证书 ==============="
|
||||||
// sh '''
|
sh '''
|
||||||
// security unlock-keychain -p ${MAC_LOGIN_PWD} ~/Library/Keychains/login.keychain-db >/dev/null 2>&1
|
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 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
|
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 "# =============== 安装描述文件 ==============="
|
echo "# =============== 安装描述文件 ==============="
|
||||||
// sh '''
|
sh '''
|
||||||
// mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
|
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
|
||||||
// cp "${PROFILE_FILE}" "$HOME/Library/MobileDevice/Provisioning Profiles/"
|
cp "${PROFILE_FILE}" "$HOME/Library/MobileDevice/Provisioning Profiles/"
|
||||||
// '''
|
'''
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//stage('打包uniapp') {
|
stage('打包uniapp') {
|
||||||
// steps {
|
steps {
|
||||||
// sh "npm run build:app-plus:${env.BRANCH_NAME}"
|
sh "npm run build:app-plus:${env.BRANCH_NAME}"
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//stage('复制UniApp资源到目录') {
|
stage('复制UniApp资源到目录') {
|
||||||
// steps {
|
steps {
|
||||||
// echo "开始复制 dist 资源到 ${ASSETS_DIR}"
|
echo "开始复制 dist 资源到 ${ASSETS_DIR}"
|
||||||
// // 先创建目标目录(防止目录不存在报错)
|
// 先创建目标目录(防止目录不存在报错)
|
||||||
// sh "mkdir -p ${ASSETS_DIR}"
|
sh "mkdir -p ${ASSETS_DIR}"
|
||||||
// // 把 dist 里所有文件 复制 到安卓资源目录(推荐)
|
// 把 dist 里所有文件 复制 到安卓资源目录(推荐)
|
||||||
// sh "cp -rf dist/build/app/* ${ASSETS_DIR}/"
|
sh "cp -rf dist/build/app/* ${ASSETS_DIR}/"
|
||||||
// echo "✅ 资源复制完成"
|
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 {
|
|
||||||
// 一行式 node -e "代码" 必须写在同一行!
|
|
||||||
JWT_TOKEN = sh(
|
|
||||||
script: '''
|
|
||||||
node -e "const fs=require('fs');const jwt=require('jsonwebtoken');const privateKey=fs.readFileSync(process.env.P8_FILE,'utf8');const token=jwt.sign({iss:process.env.API_ISSUER,exp:Math.floor(Date.now()/1000)+1200,aud:'appstoreconnect-v1'},privateKey,{algorithm:'ES256',header:{kid:process.env.API_KEY}});console.log(token);"
|
|
||||||
''',
|
|
||||||
returnStdout: true
|
|
||||||
).trim()
|
|
||||||
|
|
||||||
echo "✅ JWT 生成成功:${JWT_TOKEN}"
|
stage('️清理旧构建内容') {
|
||||||
}
|
steps {
|
||||||
}
|
sh """
|
||||||
}
|
xcodebuild clean \\
|
||||||
|
-project ${APP_DIR}/${PROJECT_NAME}.xcodeproj \\
|
||||||
|
-scheme ${SCHEME_NAME} \\
|
||||||
|
-configuration ${CONFIGURATION}
|
||||||
|
"""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
stage('创建SDK软链接') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
# 删除旧的软链接/目录
|
||||||
|
rm -rf "${TARGET_LINK}"
|
||||||
|
|
||||||
post {
|
# 创建软链接(不进入任何目录)
|
||||||
always {
|
ln -s "${SOURCE_SDK}" "${TARGET_LINK}"
|
||||||
echo '流水线已结束'
|
|
||||||
}
|
# 验证链接是否生效
|
||||||
success {
|
ls -la "${TARGET_LINK}"
|
||||||
echo '🎉 项目部署成功!'
|
'''
|
||||||
}
|
}
|
||||||
failure {
|
}
|
||||||
echo '⚠️ 部署失败,请检查日志!'
|
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 {
|
||||||
|
// 一行式 node -e "代码" 必须写在同一行!
|
||||||
|
JWT_TOKEN = sh(
|
||||||
|
script: '''
|
||||||
|
node -e "const fs=require('fs');const jwt=require('jsonwebtoken');const privateKey=fs.readFileSync(process.env.P8_FILE,'utf8');const token=jwt.sign({iss:process.env.API_ISSUER,exp:Math.floor(Date.now()/1000)+1200,aud:'appstoreconnect-v1'},privateKey,{algorithm:'ES256',header:{kid:process.env.API_KEY}});console.log(token);"
|
||||||
|
''',
|
||||||
|
returnStdout: true
|
||||||
|
).trim()
|
||||||
|
echo "✅ JWT 生成成功:${JWT_TOKEN}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('🚀 发布到 TestFlight 测试组') {
|
||||||
|
steps {
|
||||||
|
echo "todo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
echo '流水线已结束'
|
||||||
|
}
|
||||||
|
success {
|
||||||
|
echo '🎉 项目部署成功!'
|
||||||
|
}
|
||||||
|
failure {
|
||||||
|
echo '⚠️ 部署失败,请检查日志!'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 输出 JWT(Jenkins 会捕获这个值)
|
|
||||||
console.log(token);
|
|
||||||
Reference in New Issue
Block a user