Skip to content

Commit 00d9740

Browse files
authored
chore(ci): Validate XCFramework structure (#6048)
* chore(ci): Validate XCFramework structure * Add script * Update environment variable for XCFramework validation * Check structure when building locally
1 parent 3279d4e commit 00d9740

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed

.github/workflows/assemble-xcframework-variant.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ jobs:
172172
mv "${{env.SCHEME}}${{env.SUFFIX}}.xcframework" "${{env.OVERRIDE_NAME}}.xcframework"
173173
shell: bash
174174

175+
- name: Validate XCFramework structure
176+
# only validate if the xcframework was not cached
177+
if: steps.cache-xcframework.outputs.cache-hit != 'true'
178+
run: ./scripts/validate-xcframework-format.sh "${{env.XCFRAMEWORK_NAME}}.xcframework"
179+
shell: bash
180+
env:
181+
XCFRAMEWORK_NAME: ${{ env.XCFRAMEWORK_NAME }}
182+
175183
- name: Zip XCFramework
176184
if: steps.cache-xcframework.outputs.cache-hit != 'true'
177185
env:

scripts/build-xcframework-local.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,42 @@ mkdir Carthage
1111

1212
if [ "$variants" = "DynamicOnly" ] || [ "$variants" = "AllVariants" ]; then
1313
./scripts/build-xcframework-variant.sh "Sentry" "-Dynamic" "mh_dylib" "" "$sdks" "arm64e"
14+
./scripts/validate-xcframework-format.sh "Sentry-Dynamic.xcframework"
1415
./scripts/compress-xcframework.sh "$signed" Sentry-Dynamic
1516
mv Sentry-Dynamic.xcframework.zip Carthage/Sentry-Dynamic.xcframework.zip
1617
fi
1718

1819
if [ "$variants" = "DynamicWithARM64eOnly" ] || [ "$variants" = "AllVariants" ]; then
1920
./scripts/build-xcframework-variant.sh "Sentry" "-Dynamic-WithARM64e" "mh_dylib" "" "$sdks" ""
21+
./scripts/validate-xcframework-format.sh "Sentry-Dynamic-WithARM64e.xcframework"
2022
./scripts/compress-xcframework.sh "$signed" Sentry-Dynamic-WithARM64e
2123
mv Sentry-Dynamic-WithARM64e.xcframework.zip Carthage/Sentry-Dynamic-WithARM64e.xcframework.zip
2224
fi
2325

2426
if [ "$variants" = "StaticOnly" ] || [ "$variants" = "AllVariants" ]; then
2527
./scripts/build-xcframework-variant.sh "Sentry" "" "staticlib" "" "$sdks" ""
28+
./scripts/validate-xcframework-format.sh "Sentry.xcframework"
2629
./scripts/compress-xcframework.sh "$signed" Sentry
2730
mv Sentry.xcframework.zip Carthage/Sentry.xcframework.zip
2831
fi
2932

3033
if [ "$variants" = "SwiftUIOnly" ] || [ "$variants" = "AllVariants" ]; then
3134
./scripts/build-xcframework-variant.sh "SentrySwiftUI" "" "mh_dylib" "" "$sdks" ""
35+
./scripts/validate-xcframework-format.sh "SentrySwiftUI.xcframework"
3236
./scripts/compress-xcframework.sh "$signed" SentrySwiftUI
3337
mv SentrySwiftUI.xcframework.zip Carthage/SentrySwiftUI.xcframework.zip
3438
fi
3539

3640
if [ "$variants" = "WithoutUIKitOnly" ] || [ "$variants" = "AllVariants" ]; then
3741
./scripts/build-xcframework-variant.sh "Sentry" "-WithoutUIKitOrAppKit" "mh_dylib" "WithoutUIKit" "$sdks" "arm64e"
42+
./scripts/validate-xcframework-format.sh "Sentry-WithoutUIKitOrAppKit.xcframework"
3843
./scripts/compress-xcframework.sh "$signed" Sentry-WithoutUIKitOrAppKit
3944
mv Sentry-WithoutUIKitOrAppKit.xcframework.zip Carthage/Sentry-WithoutUIKitOrAppKit.xcframework.zip
4045
fi
4146

4247
if [ "$variants" = "WithoutUIKitWithARM64eOnly" ] || [ "$variants" = "AllVariants" ]; then
4348
./scripts/build-xcframework-variant.sh "Sentry" "-WithoutUIKitOrAppKit-WithARM64e" "mh_dylib" "WithoutUIKit" "$sdks" ""
49+
./scripts/validate-xcframework-format.sh "Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework"
4450
./scripts/compress-xcframework.sh "$signed" Sentry-WithoutUIKitOrAppKit-WithARM64e
4551
mv Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip Carthage/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip
4652
fi
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/bin/bash
2+
3+
# Script to validate the format of XCFramework bundles
4+
# Usage: ./scripts/validate-xcframework-format.sh <xcframework_path>
5+
# Example: ./scripts/validate-xcframework-format.sh Sentry.xcframework
6+
7+
set -e
8+
9+
# Check if required arguments are provided
10+
if [ $# -ne 1 ]; then
11+
echo "Usage: $0 <xcframework_path>"
12+
echo "Example: $0 Sentry.xcframework"
13+
exit 1
14+
fi
15+
16+
XCFRAMEWORK_PATH="$1"
17+
18+
# Validate that the xcframework path exists
19+
if [ ! -d "$XCFRAMEWORK_PATH" ]; then
20+
echo "Error: XCFramework path does not exist: $XCFRAMEWORK_PATH"
21+
exit 1
22+
fi
23+
24+
# Check if it's actually an xcframework
25+
if [ ! -f "$XCFRAMEWORK_PATH/Info.plist" ]; then
26+
echo "Error: $XCFRAMEWORK_PATH is not a valid XCFramework (missing Info.plist)"
27+
exit 1
28+
fi
29+
30+
echo "Validating XCFramework format: $XCFRAMEWORK_PATH"
31+
32+
# Track validation results
33+
validation_errors=0
34+
35+
# Function to check if a path is a symlink
36+
is_symlink() {
37+
[ -L "$1" ]
38+
}
39+
40+
# Function to check if a symlink is valid (points to existing target)
41+
is_valid_symlink() {
42+
if is_symlink "$1"; then
43+
target=$(readlink "$1")
44+
[ -e "$(dirname "$1")/$target" ]
45+
else
46+
false
47+
fi
48+
}
49+
50+
# Function to validate framework structure
51+
validate_framework() {
52+
local framework_path="$1"
53+
local framework_name
54+
framework_name=$(basename "$framework_path" .framework)
55+
local binary_path="$framework_path/$framework_name"
56+
57+
echo " Validating framework: $framework_name"
58+
59+
# Check if framework has a Versions directory
60+
if [ -d "$framework_path/Versions" ]; then
61+
echo " Framework is versioned"
62+
63+
# Check if the main binary is a symlink
64+
if is_symlink "$binary_path"; then
65+
echo " ✅ Main binary is a symlink"
66+
67+
# Check if the symlink is valid
68+
if is_valid_symlink "$binary_path"; then
69+
echo " ✅ Symlink is valid"
70+
71+
# Get the target of the symlink
72+
symlink_target=$(readlink "$binary_path")
73+
echo " ✅ Symlink points to: $symlink_target"
74+
75+
# Verify the target exists in Versions
76+
if [ -f "$framework_path/$symlink_target" ]; then
77+
echo " ✅ Symlink target exists"
78+
else
79+
echo " ❌ Symlink target does not exist: $framework_path/$symlink_target"
80+
((validation_errors++))
81+
fi
82+
else
83+
echo " ❌ Symlink is broken (target does not exist)"
84+
((validation_errors++))
85+
fi
86+
else
87+
echo " ❌ Main binary should be a symlink when Versions directory exists"
88+
((validation_errors++))
89+
fi
90+
91+
# Check Versions directory structure
92+
if [ -d "$framework_path/Versions/Current" ]; then
93+
echo " Found Versions/Current directory"
94+
95+
# Check if Current is a symlink
96+
if is_symlink "$framework_path/Versions/Current"; then
97+
echo " ✅ Versions/Current is a symlink"
98+
99+
if is_valid_symlink "$framework_path/Versions/Current"; then
100+
echo " ✅ Versions/Current symlink is valid"
101+
else
102+
echo " ❌ Versions/Current symlink is broken"
103+
((validation_errors++))
104+
fi
105+
else
106+
echo " ❌ Versions/Current should be a symlink"
107+
((validation_errors++))
108+
fi
109+
else
110+
echo " ❌ Versions/Current directory not found"
111+
((validation_errors++))
112+
fi
113+
else
114+
echo " No Versions directory found (standard framework structure)"
115+
116+
# For frameworks without Versions, the binary should be a regular file
117+
if [ -f "$binary_path" ] && ! is_symlink "$binary_path"; then
118+
echo " ✅ Main binary is not a symlink"
119+
else
120+
echo " ❌ Main binary is a symlink or does not exist: $binary_path"
121+
((validation_errors++))
122+
fi
123+
fi
124+
}
125+
126+
# Find all platform-specific directories in the xcframework
127+
platform_dirs=$(find "$XCFRAMEWORK_PATH" -maxdepth 1 -type d -not -name "*.xcframework" -not -name "." | grep -v "Info.plist" | sort)
128+
129+
if [ -z "$platform_dirs" ]; then
130+
echo "Error: No platform directories found in XCFramework"
131+
exit 1
132+
fi
133+
134+
echo "Found platform directories:"
135+
echo "${platform_dirs//^/ }"
136+
137+
echo ""
138+
echo "Validating framework structures..."
139+
140+
# Validate each platform directory
141+
while IFS= read -r platform_dir; do
142+
if [ -n "$platform_dir" ]; then
143+
echo ""
144+
echo "Platform: $(basename "$platform_dir")"
145+
146+
# Find all .framework directories in this platform
147+
frameworks=$(find "$platform_dir" -name "*.framework" -type d)
148+
149+
if [ -z "$frameworks" ]; then
150+
echo " ⚠️ No .framework directories found"
151+
else
152+
while IFS= read -r framework; do
153+
if [ -n "$framework" ]; then
154+
validate_framework "$framework"
155+
fi
156+
done <<< "$frameworks"
157+
fi
158+
fi
159+
done <<< "$platform_dirs"
160+
161+
echo ""
162+
echo "=========================================="
163+
echo "Validation Summary:"
164+
165+
if [ $validation_errors -eq 0 ]; then
166+
echo "✅ All validations passed! XCFramework format is correct."
167+
exit 0
168+
else
169+
echo "❌ Validation failed with $validation_errors error(s)."
170+
echo "Please fix the errors before using this XCFramework."
171+
exit 1
172+
fi

0 commit comments

Comments
 (0)