Skip to content

Commit e7e70a4

Browse files
cwclaude
andcommitted
fix: 使用 Xcode 构建脚本在构建时修复 App.framework
避免重新打包 IPA 导致签名失效的问题 在构建阶段直接修复 App.framework 的 MinimumOSVersion Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 3fb7f0b commit e7e70a4

4 files changed

Lines changed: 711 additions & 39 deletions

File tree

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
"Bash(openssl md5:*)",
6666
"Bash(openssl rsa:*)",
6767
"Bash(security cms:*)",
68-
"Bash(plutil:*)"
68+
"Bash(plutil:*)",
69+
"Bash(yamllint:*)"
6970
]
7071
}
7172
}

.github/workflows/ios-app-store.yml

Lines changed: 75 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -133,57 +133,94 @@ jobs:
133133
pod install --repo-update
134134
echo "✅ CocoaPods dependencies installed"
135135
136+
- name: Add Xcode Build Script to Fix App.framework
137+
working-directory: opencli_mobile/ios
138+
run: |
139+
# Add a build phase script to fix App.framework Info.plist
140+
cat > fix_app_framework.sh << 'EOF'
141+
#!/bin/bash
142+
set -e
143+
144+
APP_FRAMEWORK_PATH="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/App.framework/Info.plist"
145+
146+
if [ -f "$APP_FRAMEWORK_PATH" ]; then
147+
/usr/libexec/PlistBuddy -c "Add :MinimumOSVersion string ${IPHONEOS_DEPLOYMENT_TARGET}" "$APP_FRAMEWORK_PATH" 2>/dev/null || \
148+
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion ${IPHONEOS_DEPLOYMENT_TARGET}" "$APP_FRAMEWORK_PATH"
149+
echo "✅ Set MinimumOSVersion to ${IPHONEOS_DEPLOYMENT_TARGET} in App.framework"
150+
fi
151+
EOF
152+
153+
chmod +x fix_app_framework.sh
154+
136155
- name: Build IPA
137156
working-directory: opencli_mobile
138157
env:
139158
IPHONEOS_DEPLOYMENT_TARGET: '13.0'
140159
run: |
141160
echo "🔨 Building iOS IPA..."
142161
162+
# Add build phase script to Xcode project
163+
python3 << 'PYTHON_SCRIPT'
164+
import re
165+
166+
project_path = "ios/Runner.xcodeproj/project.pbxproj"
167+
168+
with open(project_path, 'r') as f:
169+
content = f.read()
170+
171+
# Check if script phase already exists
172+
if 'Fix App.framework Info.plist' not in content:
173+
# Find the PBXNativeTarget section for Runner
174+
pattern = r'(/\* Begin PBXNativeTarget section \*/.*?97C146ED1CF9000F007C117D /\* Runner \*/ = \{.*?buildPhases = \(\s*)(.*?)(\s*\);)'
175+
176+
def add_script_phase(match):
177+
phases = match.group(2)
178+
# Add our script phase UUID
179+
new_phase_uuid = "7884E86A2EC3CC0800000000"
180+
if new_phase_uuid not in phases:
181+
phases += f"\n\t\t\t\t{new_phase_uuid} /* Fix App.framework Info.plist */,"
182+
return match.group(1) + phases + match.group(3)
183+
184+
content = re.sub(pattern, add_script_phase, content, flags=re.DOTALL)
185+
186+
# Add the script phase definition
187+
script_phase = '''
188+
7884E86A2EC3CC0800000000 /* Fix App.framework Info.plist */ = {
189+
isa = PBXShellScriptBuildPhase;
190+
buildActionMask = 2147483647;
191+
files = (
192+
);
193+
inputPaths = (
194+
);
195+
name = "Fix App.framework Info.plist";
196+
outputPaths = (
197+
);
198+
runOnlyForDeploymentPostprocessing = 0;
199+
shellPath = /bin/sh;
200+
shellScript = "bash \\"${SRCROOT}/fix_app_framework.sh\\"\\n";
201+
};
202+
'''
203+
204+
# Add before the "End PBXShellScriptBuildPhase section" marker
205+
content = content.replace(
206+
'/* End PBXShellScriptBuildPhase section */',
207+
script_phase + '/* End PBXShellScriptBuildPhase section */'
208+
)
209+
210+
with open(project_path, 'w') as f:
211+
f.write(content)
212+
213+
print("✅ Added build script to Xcode project")
214+
else:
215+
print("ℹ️ Build script already exists")
216+
PYTHON_SCRIPT
217+
143218
flutter build ipa --release \
144219
--export-options-plist=ios/ExportOptions.plist
145220
146221
echo "✅ IPA built successfully"
147222
ls -lh build/ios/ipa/
148223
149-
- name: Fix App.framework MinimumOSVersion
150-
working-directory: opencli_mobile
151-
run: |
152-
echo "🔧 Fixing App.framework Info.plist..."
153-
154-
# Find the IPA file and get absolute path
155-
IPA_FILE=$(find build/ios/ipa -name "*.ipa" | head -n 1)
156-
ABS_IPA_FILE=$(cd $(dirname "$IPA_FILE") && pwd)/$(basename "$IPA_FILE")
157-
158-
# Create a temporary directory
159-
TEMP_DIR=$(mktemp -d)
160-
161-
# Unzip the IPA
162-
unzip -q "$ABS_IPA_FILE" -d "$TEMP_DIR"
163-
164-
# Fix App.framework Info.plist
165-
APP_PLIST="$TEMP_DIR/Payload/Runner.app/Frameworks/App.framework/Info.plist"
166-
if [ -f "$APP_PLIST" ]; then
167-
/usr/libexec/PlistBuddy -c "Add :MinimumOSVersion string 13.0" "$APP_PLIST" 2>/dev/null || \
168-
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion 13.0" "$APP_PLIST"
169-
echo "✅ Set MinimumOSVersion to 13.0 in App.framework"
170-
/usr/libexec/PlistBuddy -c "Print :MinimumOSVersion" "$APP_PLIST"
171-
fi
172-
173-
# Repackage the IPA
174-
cd "$TEMP_DIR"
175-
NEW_IPA="$TEMP_DIR/fixed.ipa"
176-
zip -qr "$NEW_IPA" Payload
177-
cd -
178-
179-
# Replace the original IPA
180-
mv "$NEW_IPA" "$ABS_IPA_FILE"
181-
182-
# Cleanup
183-
rm -rf "$TEMP_DIR"
184-
185-
echo "✅ IPA fixed and repackaged"
186-
187224
- name: Upload IPA Artifact
188225
uses: actions/upload-artifact@v4
189226
with:

opencli_mobile/ios/Podfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,15 @@ post_install do |installer|
4040
installer.pods_project.targets.each do |target|
4141
flutter_additional_ios_build_settings(target)
4242
end
43+
44+
# Fix App.framework Info.plist to include MinimumOSVersion
45+
# This is required for App Store submission
46+
installer.aggregate_targets.each do |aggregate_target|
47+
aggregate_target.user_project.native_targets.each do |native_target|
48+
native_target.build_configurations.each do |config|
49+
# Ensure deployment target is set
50+
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
51+
end
52+
end
53+
end
4354
end

0 commit comments

Comments
 (0)