Skip to content

Commit 199c963

Browse files
authored
Enhance build-ipa workflow for signing IPAs
Refactor the build-ipa workflow to improve clarity and error handling when fetching certificates and signing IPAs.
1 parent d229f91 commit 199c963

File tree

1 file changed

+71
-30
lines changed

1 file changed

+71
-30
lines changed

.github/workflows/build-ipa.yml

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -335,33 +335,43 @@ jobs:
335335
exit 1
336336
fi
337337
338-
# Fetch README.md
339-
curl -s https://raw.githubusercontent.com/ProStore-iOS/certificates/refs/heads/main/README.md > readme.md
338+
# Fetch README.md containing the certificates table
339+
curl -s https://raw.githubusercontent.com/ProStore-iOS/certificates/refs/heads/main/README.md -o readme.md
340340
341341
echo "----- README excerpt -----"
342342
sed -n '1,200p' readme.md || true
343343
344-
echo "----- Matching lines -----"
345-
grep -nF '| **✅ Signed** |' readme.md || true
344+
echo "----- Matching lines (table rows) -----"
345+
# Print all data rows from the Markdown table:
346+
# lines that start with '|' but skip the alignment row and header row containing 'Company'
347+
awk -F'|' '/^\|/ && $2 !~ /Company/ && $2 !~ /^:/{ name=$2; gsub(/^[ \t]+|[ \t]+$/,"",name); print " " $0 }' readme.md || true
348+
349+
# Extract company/display names (field 2) from every table data row (skip header & alignment)
350+
# This produces one company/display name per line.
351+
awk -F'|' '/^\|/ && $2 !~ /Company/ && $2 !~ /^:/{ name=$2; gsub(/^[ \t]+|[ \t]+$/,"",name); print name }' readme.md > cert-names.txt || true
352+
353+
MATCH_COUNT=0
354+
if [ -f cert-names.txt ]; then
355+
MATCH_COUNT=$(wc -l < cert-names.txt | tr -d ' ')
356+
fi
357+
echo "Found $MATCH_COUNT certificate line(s) in README."
346358
347-
# Count matches
348-
MATCH_COUNT=$(grep -F '| **✅ Signed** |' readme.md | wc -l || true)
349-
echo "Found $MATCH_COUNT matching line(s)."
350359
if [ "$MATCH_COUNT" -eq 0 ]; then
351-
echo "No signed certs found. Exiting."
360+
echo "No certificate rows found. Exiting."
352361
exit 0
353362
fi
354363
355-
# Install dependencies
364+
# Install dependencies (no-op if already installed)
356365
brew install pkg-config openssl minizip
357366
358367
# Build zsign
368+
rm -rf zsign || true
359369
git clone https://github.com/zhlynn/zsign.git
360370
pushd zsign/build/macos >/dev/null
361371
make clean && make
362372
popd >/dev/null
363373
364-
# Locate the zsign binary
374+
# Locate the zsign binary (expected at zsign/bin/zsign)
365375
ZSIGN_PATH="$(pwd)/zsign/bin/zsign"
366376
if [ ! -x "$ZSIGN_PATH" ]; then
367377
echo "zsign not found at expected path $ZSIGN_PATH; searching..."
@@ -377,52 +387,83 @@ jobs:
377387
echo "Using zsign: $ZSIGN_PATH"
378388
ls -l "$ZSIGN_PATH" || true
379389
380-
# Output dir to upload later
390+
# Prepare output directory for signed IPAs
381391
SIGNED_DIR="signed-ipas"
382392
mkdir -p "$SIGNED_DIR"
383393
384-
# Extract all '✅ Signed' names using awk (no backslash line-continuations)
385-
awk -F'|' '/✅ Signed/ { gsub(/^[ \t]+|[ \t]+$/,"",$2); print $2 }' readme.md \
386-
| while IFS= read -r FULL_NAME; do
394+
# Iterate over every certificate name (one per line) and attempt to sign
395+
while IFS= read -r FULL_NAME || [ -n "$FULL_NAME" ]; do
396+
# skip empty lines
387397
if [ -z "${FULL_NAME// /}" ]; then
388-
echo "Skipping empty name"
398+
echo "Skipping empty certificate name"
389399
continue
390400
fi
391401
392402
echo "---- Processing: '$FULL_NAME' ----"
393403
394-
# sanitized short name for filenames/dirs
404+
# Create safe short name for filenames and dirs
395405
SHORT_NAME=$(echo "$FULL_NAME" | tr '[:upper:]' '[:lower:]' \
396406
| sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-+|-+$//g')
397407
398-
# url-encode the full display name for the GitHub path
399-
ENCODED=$(python3 -c "import sys,urllib.parse as u; print(u.quote(sys.stdin.read().strip()))" <<< "$FULL_NAME")
408+
# URL-encode the full display name for GitHub raw path
409+
ENCODED=$(python3 - <<PY
410+
import sys, urllib.parse
411+
s = sys.stdin.read().strip()
412+
print(urllib.parse.quote(s))
413+
PY
414+
<<< "$FULL_NAME")
400415

401416
CERT_DIR="certs/$SHORT_NAME"
402417
mkdir -p "$CERT_DIR"
403418
pushd "$CERT_DIR" >/dev/null
404419

405-
# download cert files; -f makes curl fail the step if missing
406-
curl -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.mobileprovision"
407-
curl -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.p12"
408-
curl -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/password.txt"
420+
# Try downloading the three required files. If any are missing, skip this cert.
421+
echo "Downloading assets for '$FULL_NAME' (encoded: $ENCODED)..."
422+
if ! curl -sS -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.mobileprovision"; then
423+
echo " -> Missing mobileprovision for '$FULL_NAME', skipping."
424+
popd >/dev/null
425+
continue
426+
fi
427+
if ! curl -sS -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.p12"; then
428+
echo " -> Missing .p12 for '$FULL_NAME', skipping."
429+
popd >/dev/null
430+
continue
431+
fi
432+
if ! curl -sS -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/password.txt"; then
433+
echo " -> Missing password.txt for '$FULL_NAME', skipping."
434+
popd >/dev/null
435+
continue
436+
fi
409437

410438
popd >/dev/null
411439

412440
SIGNED_IPA="${SIGNED_DIR}/com.prostoreios.prostore-signed-${SHORT_NAME}-ios.ipa"
413441

414-
# run zsign
415-
"$ZSIGN_PATH" -k "${CERT_DIR}/${ENCODED}.p12" \
416-
-p "$(cat "${CERT_DIR}/password.txt")" \
417-
-m "${CERT_DIR}/${ENCODED}.mobileprovision" \
418-
-o "$SIGNED_IPA" \
419-
"$UNSIGNED_IPA"
442+
# Run zsign; ensure p12 password is read safely
443+
P12_PASS="$(cat "${CERT_DIR}/password.txt" || echo "")"
444+
if [ -z "$P12_PASS" ]; then
445+
echo " -> Empty password for ${FULL_NAME}, skipping."
446+
continue
447+
fi
448+
449+
echo " -> Signing into $SIGNED_IPA ..."
450+
if "$ZSIGN_PATH" -k "${CERT_DIR}/${ENCODED}.p12" \
451+
-p "$P12_PASS" \
452+
-m "${CERT_DIR}/${ENCODED}.mobileprovision" \
453+
-o "$SIGNED_IPA" \
454+
"$UNSIGNED_IPA"; then
455+
echo " -> Signed OK: $SIGNED_IPA"
456+
else
457+
echo " -> zsign failed for $FULL_NAME; see zsign output above. Skipping."
458+
# don't exit whole job; continue with next cert
459+
continue
460+
fi
420461

421-
echo "Signed IPA created: $SIGNED_IPA"
422-
done
462+
done < cert-names.txt
423463

424464
echo "Signing complete. Signed files:"
425465
ls -la "$SIGNED_DIR" || true
466+
426467
- name: Upload signed IPAs
427468
uses: actions/upload-artifact@v4
428469
with:

0 commit comments

Comments
 (0)