-
-
Notifications
You must be signed in to change notification settings - Fork 218
Expand file tree
/
Copy pathbundle-axe.sh
More file actions
executable file
Β·270 lines (229 loc) Β· 9.87 KB
/
bundle-axe.sh
File metadata and controls
executable file
Β·270 lines (229 loc) Β· 9.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#!/bin/bash
# Build script for AXe artifacts
# This script downloads pre-built AXe artifacts from GitHub releases and bundles them
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
BUNDLED_DIR="$PROJECT_ROOT/bundled"
AXE_LOCAL_DIR="${AXE_LOCAL_DIR:-}"
AXE_TEMP_DIR="/tmp/axe-download-$$"
echo "π¨ Preparing AXe artifacts for bundling..."
# Single source of truth for AXe version (overridable)
# 1) Use $AXE_VERSION if provided in env
# 2) Else, use repo-level pin from .axe-version if present
# 3) Else, fall back to default below
DEFAULT_AXE_VERSION="1.1.1"
VERSION_FILE="$PROJECT_ROOT/.axe-version"
if [ -n "${AXE_VERSION}" ]; then
PINNED_AXE_VERSION="${AXE_VERSION}"
elif [ -f "$VERSION_FILE" ]; then
PINNED_AXE_VERSION="$(cat "$VERSION_FILE" | tr -d ' \n\r')"
else
PINNED_AXE_VERSION="$DEFAULT_AXE_VERSION"
fi
echo "π Using AXe version: $PINNED_AXE_VERSION"
# Clean up any existing bundled directory
if [ -d "$BUNDLED_DIR" ]; then
echo "π§Ή Cleaning existing bundled directory..."
rm -r "$BUNDLED_DIR"
fi
# Create bundled directory
mkdir -p "$BUNDLED_DIR"
USE_LOCAL_AXE=false
AXE_ARCHIVE_FLAVOR="local-signed"
if [ -z "${AXE_FORCE_REMOTE}" ] && [ "${AXE_USE_LOCAL:-0}" = "1" ]; then
USE_LOCAL_AXE=true
fi
# Use local AXe build only when explicitly requested, otherwise download from GitHub releases.
if [ "$USE_LOCAL_AXE" = true ] && [ -d "$AXE_LOCAL_DIR" ] && [ -f "$AXE_LOCAL_DIR/Package.swift" ]; then
echo "π Using local AXe source at $AXE_LOCAL_DIR"
cd "$AXE_LOCAL_DIR"
# Build AXe in release configuration
echo "π¨ Building AXe in release configuration..."
swift build --configuration release
# Check if build succeeded
if [ ! -f ".build/release/axe" ]; then
echo "β AXe build failed - binary not found"
exit 1
fi
echo "β
AXe build completed successfully"
# Copy binary to bundled directory
echo "π¦ Copying AXe binary..."
cp ".build/release/axe" "$BUNDLED_DIR/"
# Fix rpath to find frameworks in Frameworks/ subdirectory
echo "π§ Configuring AXe binary rpath for bundled frameworks..."
install_name_tool -add_rpath "@executable_path/Frameworks" "$BUNDLED_DIR/axe"
# Create Frameworks directory and copy frameworks
echo "π¦ Copying frameworks..."
mkdir -p "$BUNDLED_DIR/Frameworks"
# Copy frameworks with better error handling
for framework in .build/release/*.framework; do
if [ -d "$framework" ]; then
echo "π¦ Copying framework: $(basename "$framework")"
cp -r "$framework" "$BUNDLED_DIR/Frameworks/"
# Only copy nested frameworks if they exist
if [ -d "$framework/Frameworks" ]; then
echo "π¦ Found nested frameworks in $(basename "$framework")"
cp -r "$framework/Frameworks"/* "$BUNDLED_DIR/Frameworks/" 2>/dev/null || true
fi
fi
done
else
if [ "$USE_LOCAL_AXE" = true ]; then
echo "β AXE_USE_LOCAL=1 requires AXE_LOCAL_DIR to point to a valid AXe checkout"
echo " Received AXE_LOCAL_DIR: ${AXE_LOCAL_DIR:-<unset>}"
exit 1
fi
echo "π₯ Downloading latest AXe release from GitHub..."
# On macOS, prefer the Homebrew-specific archive (unsigned for relocation
# compatibility) and ad-hoc sign it later. On non-macOS (e.g. CI on Linux),
# codesign is unavailable so use the legacy pre-signed archive directly.
AXE_RELEASE_BASE_URL="https://github.com/cameroncooke/AXe/releases/download/v${PINNED_AXE_VERSION}"
AXE_HOMEBREW_URL="${AXE_RELEASE_BASE_URL}/AXe-macOS-homebrew-v${PINNED_AXE_VERSION}.tar.gz"
AXE_LEGACY_URL="${AXE_RELEASE_BASE_URL}/AXe-macOS-v${PINNED_AXE_VERSION}.tar.gz"
# Create temp directory
mkdir -p "$AXE_TEMP_DIR"
cd "$AXE_TEMP_DIR"
# Download and extract the release
if [ "$(uname -s)" != "Darwin" ]; then
echo "π₯ Non-macOS detected; downloading pre-signed legacy archive ($AXE_LEGACY_URL)..."
curl -fL -o "axe-release.tar.gz" "$AXE_LEGACY_URL"
AXE_ARCHIVE_FLAVOR="legacy-signed"
elif curl -fL -o "axe-release.tar.gz" "$AXE_HOMEBREW_URL"; then
AXE_ARCHIVE_FLAVOR="homebrew-unsigned"
echo "β
Downloaded AXe Homebrew archive"
else
echo "β οΈ AXe Homebrew archive unavailable, falling back to legacy archive"
curl -fL -o "axe-release.tar.gz" "$AXE_LEGACY_URL"
AXE_ARCHIVE_FLAVOR="legacy-signed"
fi
echo "π¦ Extracting AXe release archive..."
tar -xzf "axe-release.tar.gz"
# Find the extracted directory (might be named differently)
EXTRACTED_DIR=$(find . -type d \( -name "*AXe*" -o -name "*axe*" \) | head -1)
if [ -z "$EXTRACTED_DIR" ]; then
# If no AXe directory found, assume files are in current directory
EXTRACTED_DIR="."
fi
cd "$EXTRACTED_DIR"
# Copy binary
if [ -f "axe" ]; then
echo "π¦ Copying AXe binary..."
cp "axe" "$BUNDLED_DIR/"
chmod +x "$BUNDLED_DIR/axe"
elif [ -f "bin/axe" ]; then
echo "π¦ Copying AXe binary from bin/..."
cp "bin/axe" "$BUNDLED_DIR/"
chmod +x "$BUNDLED_DIR/axe"
else
echo "β AXe binary not found in release archive"
ls -la
exit 1
fi
# Copy frameworks if they exist
echo "π¦ Copying frameworks..."
mkdir -p "$BUNDLED_DIR/Frameworks"
if [ -d "Frameworks" ]; then
cp -r Frameworks/* "$BUNDLED_DIR/Frameworks/"
elif [ -d "lib" ]; then
# Look for frameworks in lib directory
find lib -name "*.framework" -exec cp -r {} "$BUNDLED_DIR/Frameworks/" \;
else
echo "β οΈ No frameworks directory found in release archive"
echo "π Contents of release archive:"
find . -type f -name "*.framework" -o -name "*.dylib" | head -10
fi
fi
# Verify frameworks were copied
FRAMEWORK_COUNT=$(find "$BUNDLED_DIR/Frameworks" -name "*.framework" | wc -l)
echo "π¦ Copied $FRAMEWORK_COUNT frameworks"
# List the frameworks for verification
echo "π Bundled frameworks:"
ls -la "$BUNDLED_DIR/Frameworks/"
ad_hoc_sign_bundled_axe_assets() {
echo "π Applying ad-hoc signatures to bundled AXe assets..."
while IFS= read -r framework_path; do
framework_name="$(basename "$framework_path" .framework)"
framework_binary="$framework_path/Versions/A/$framework_name"
if [ ! -f "$framework_binary" ]; then
framework_binary="$framework_path/Versions/Current/$framework_name"
fi
if [ ! -f "$framework_binary" ]; then
echo "β Framework binary not found: $framework_binary"
exit 1
fi
codesign --force --deep --sign - "$framework_binary"
done < <(find "$BUNDLED_DIR/Frameworks" -name "*.framework" -type d)
codesign --force --deep --sign - "$BUNDLED_DIR/axe"
}
# Verify binary can run with bundled frameworks (macOS only)
OS_NAME="$(uname -s)"
if [ "$OS_NAME" = "Darwin" ]; then
if ! codesign -dv "$BUNDLED_DIR/axe" >/dev/null 2>&1; then
ad_hoc_sign_bundled_axe_assets
fi
if [ "$AXE_ARCHIVE_FLAVOR" = "homebrew-unsigned" ]; then
echo "βΉοΈ Homebrew AXe archive detected; using ad-hoc signatures for local runtime compatibility"
else
echo "π Verifying AXe signatures..."
if ! codesign --verify --deep --strict "$BUNDLED_DIR/axe"; then
echo "β Signature verification failed for bundled AXe binary"
exit 1
fi
while IFS= read -r framework_path; do
framework_name="$(basename "$framework_path" .framework)"
framework_binary="$framework_path/Versions/A/$framework_name"
if [ ! -f "$framework_binary" ]; then
framework_binary="$framework_path/Versions/Current/$framework_name"
fi
if [ ! -f "$framework_binary" ]; then
echo "β Framework binary not found: $framework_binary"
exit 1
fi
if ! codesign --verify --deep --strict "$framework_binary"; then
echo "β Signature verification failed for framework binary: $framework_binary"
exit 1
fi
done < <(find "$BUNDLED_DIR/Frameworks" -name "*.framework" -type d)
fi
if [ "$AXE_ARCHIVE_FLAVOR" = "homebrew-unsigned" ]; then
echo "βΉοΈ Skipping Gatekeeper assessment for unsigned AXe Homebrew archive"
else
echo "π‘οΈ Assessing AXe with Gatekeeper..."
SPCTL_LOG="$(mktemp)"
if ! spctl --assess --type execute "$BUNDLED_DIR/axe" 2>"$SPCTL_LOG"; then
if grep -q "does not seem to be an app" "$SPCTL_LOG"; then
echo "β οΈ Gatekeeper execute assessment is inconclusive for CLI binaries; continuing"
else
cat "$SPCTL_LOG"
echo "β Gatekeeper assessment failed for bundled AXe binary"
rm "$SPCTL_LOG"
exit 1
fi
fi
rm "$SPCTL_LOG"
fi
echo "π§ͺ Testing bundled AXe binary..."
if DYLD_FRAMEWORK_PATH="$BUNDLED_DIR/Frameworks" "$BUNDLED_DIR/axe" --version > /dev/null 2>&1; then
echo "β
Bundled AXe binary test passed"
else
echo "β Bundled AXe binary test failed"
exit 1
fi
# Get AXe version for logging
AXE_VERSION=$(DYLD_FRAMEWORK_PATH="$BUNDLED_DIR/Frameworks" "$BUNDLED_DIR/axe" --version 2>/dev/null || echo "unknown")
else
echo "β οΈ Skipping AXe binary verification on non-macOS (detected $OS_NAME)"
AXE_VERSION="unknown (verification skipped)"
fi
echo "π AXe version: $AXE_VERSION"
# Clean up temp directory if it was used
if [ -d "$AXE_TEMP_DIR" ]; then
echo "π§Ή Cleaning up temporary files..."
rm -r "$AXE_TEMP_DIR"
fi
# Show final bundle size
BUNDLE_SIZE=$(du -sh "$BUNDLED_DIR" | cut -f1)
echo "π Final bundle size: $BUNDLE_SIZE"
echo "π AXe bundling completed successfully!"
echo "π Bundled artifacts location: $BUNDLED_DIR"