多Target iOS应用通过Github Actions传App Store遇-21017错误求助
错误详情
*** Error: Error uploading 'build/Products/IPA/myapp.ipa'.
*** Error: Could not determine the package’s bundle ID. The package is missing an Info.plist or the CFBundlePackageType is not ‘APPL’ or ‘FMWK’. Unable to validate your application. (-21017)
{
NSLocalizedDescription = "Could not determine the package’s bundle ID. The package is missing an Info.plist or the CFBundlePackageType is not ‘APPL’ or ‘FMWK’.",
NSLocalizedFailureReason = "Unable to validate your application."
}
已尝试操作:
- 在对应Target的Info.plist中设置
CFBundlePackageType为APPL,也尝试过改为FMWK,问题依旧
相关文件内容
对应Target的Info.plist内容
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleDisplayName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>$(MARKETING_VERSION)</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>com.myapp.internal</string> <key>CFBundleURLSchemes</key> <array> <string>com.myapp.internal</string> </array> </dict> </array> <key>CFBundleVersion</key> <string>$(CURRENT_PROJECT_VERSION)</string> <key>LSRequiresIPhoneOS</key> <true/> <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> <key>NSExceptionDomains</key> <dict> <key>localhost</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> </dict> <key>NSAppleMusicUsageDescription</key> <string>$(PRODUCT_NAME) would like to use Apple Music</string> <key>NSCameraUsageDescription</key> <string>$(PRODUCT_NAME) would like to use your camera for modifying your avatar picture.</string> <key>NSFaceIDUsageDescription</key> <string>Allow $(PRODUCT_NAME) to use FaceID</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>$(PRODUCT_NAME) would like to use location</string> <key>NSLocationAlwaysUsageDescription</key> <string>$(PRODUCT_NAME) would like to use location</string> <key>NSLocationWhenInUseUsageDescription</key> <string>$(PRODUCT_NAME) would like to use location</string> <key>NSMicrophoneUsageDescription</key> <string>$(PRODUCT_NAME) would like to use your microphone</string> <key>NSPhotoLibraryAddUsageDescription</key> <string>$(PRODUCT_NAME) would like to save photos to your photo gallery</string> <key>NSPhotoLibraryUsageDescription</key> <string>$(PRODUCT_NAME) would like access to your photo gallery for uploading your avatar picture.</string> <key>UIBackgroundModes</key> <array> <string>fetch</string> <string>location</string> </array> <key>UILaunchStoryboardName</key> <string>SplashScreen</string> <key>UIRequiredDeviceCapabilities</key> <array> <string>armv7</string> </array> <key>UIStatusBarStyle</key> <string>UIStatusBarStyleDefault</string> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> </array> <key>UIViewControllerBasedStatusBarAppearance</key> <false/> </dict> </plist>
生成安装包的命令
cd ios BUILD_NUMBER=$(date +%Y%m%d%H%M) xcrun agvtool new-version -all ${BUILD_NUMBER} # creates an .xarchive file xcodebuild -workspace myapp.xcworkspace \ -scheme myappinternal clean archive -configuration Internal \ -archivePath ./build/Products/myapp.xcarchive \ # converts the .xarchive file to .ipa by including the provisioning profile xcodebuild -exportArchive \ -archivePath ./build/Products/myapp.xcarchive \ -exportPath ./build/Products/IPA/myapp.ipa \ -exportOptionsPlist exportOptionsInternal.plist # upload the .ipa to Apple Connect xcrun altool --upload-app --type ios --file ./build/Products/IPA/myapp.ipa \ --username "$IOS_APP_STORE_CONNECT_USERNAME" --password "$IOS_APP_STORE_CONNECT_PASSWORD"
exportOptionsInternal.plist内容
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>method</key> <string>app-store</string> <key>provisioningProfiles</key> <dict> <key>com.myapp.internal</key> <string>Github_Actions_Myapp_Internal</string> </dict> </dict> </plist>
排查与解决方案
1. 修正IPA打包路径参数
xcodebuild -exportArchive的-exportPath需要指定文件夹路径,而非直接指定IPA文件名。当前命令会导致打包出的IPA结构异常,Info.plist无法被正确识别。
修改后的exportArchive命令:
xcodebuild -exportArchive \ -archivePath ./build/Products/myapp.xcarchive \ -exportPath ./build/Products/IPA \ -exportOptionsPlist exportOptionsInternal.plist
IPA会自动生成在./build/Products/IPA/myapp.ipa,上传命令路径保持不变即可。
2. 验证Archive中Info.plist变量替换
打开本地生成的myapp.xcarchive/Products/Applications/myapp.app/Info.plist,确认:
CFBundleIdentifier实际值为com.myapp.internalCFBundlePackageType实际值为APPL
如果变量未替换,检查Target的Build Settings:
- 确认
PRODUCT_BUNDLE_IDENTIFIER在Internal配置下设置为com.myapp.internal - 确认
Info.plist File路径指向当前Target的Info.plist文件
3. 完善exportOptions.plist字段
添加teamID字段,避免权限验证问题:
<key>teamID</key> <string>你的Team ID</string>
4. 确认环境与权限
- 在Github Actions中指定Xcode版本(例如
xcode-select -s /Applications/Xcode_15.0.app),避免旧版本工具的兼容性问题 - 使用App Store Connect专用密码而非Apple ID密码进行上传
- 确认账号拥有该应用的App Store上传权限
内容的提问来源于stack exchange,提问作者gfrancoa

