Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit 3bd5aab

Browse files
authored
Refactor IPA signing process in workflow
1 parent c43f9ef commit 3bd5aab

1 file changed

Lines changed: 79 additions & 67 deletions

File tree

.github/workflows/build-ipa.yml

Lines changed: 79 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -325,75 +325,87 @@ jobs:
325325
with:
326326
name: com.prostoreios.prostore-unsigned-ios.ipa
327327
path: build
328-
- name: Fetch Certificates List and Sign
329-
run: |
330-
set -e
331-
UNSIGNED_IPA="build/com.prostoreios.prostore-unsigned-ios.ipa"
332-
if [ ! -f "$UNSIGNED_IPA" ]; then
333-
echo "ERROR: Unsigned IPA not found"
328+
- name: Fetch Certificates List and Sign
329+
run: |
330+
set -euo pipefail
331+
332+
UNSIGNED_IPA="build/com.prostoreios.prostore-unsigned-ios.ipa"
333+
if [ ! -f "$UNSIGNED_IPA" ]; then
334+
echo "ERROR: Unsigned IPA not found: $UNSIGNED_IPA"
335+
exit 1
336+
fi
337+
338+
# Fetch README.md that lists signed certs
339+
curl -s https://raw.githubusercontent.com/ProStore-iOS/certificates/refs/heads/main/README.md > readme.md
340+
341+
# Extract signed certificate full names (line format in your README)
342+
FULL_NAMES=$(grep -F '| **✅ Signed** |' readme.md | awk -F'|' '{gsub(/^\s+|\s+$/,"",$2); print $2}')
343+
344+
if [ -z "$FULL_NAMES" ]; then
345+
echo "No signed certificates found. Skipping signing."
346+
exit 0
347+
fi
348+
349+
# Install zsign dependencies
350+
brew install pkg-config openssl minizip
351+
352+
# Build zsign
353+
git clone https://github.com/zhlynn/zsign.git
354+
cd zsign/build/macos
355+
make clean && make
356+
357+
# Find the built zsign binary (most zsign builds place it in zsign/bin/zsign)
358+
cd ../../..
359+
ZSIGN_PATH="$(pwd)/zsign/bin/zsign"
360+
361+
# As a fallback, try to locate if not found
362+
if [ ! -x "$ZSIGN_PATH" ]; then
363+
echo "Expected binary not found at $ZSIGN_PATH, searching..."
364+
FOUND=$(find "$(pwd)/zsign" -type f -name zsign -perm -111 -print -quit || true)
365+
if [ -n "$FOUND" ]; then
366+
ZSIGN_PATH="$FOUND"
367+
else
368+
echo "zsign binary not found. Listing zsign tree:"
369+
ls -la zsign || true
334370
exit 1
335371
fi
336-
337-
# Fetch README.md
338-
curl -s https://raw.githubusercontent.com/ProStore-iOS/certificates/refs/heads/main/README.md > readme.md
339-
340-
# Extract signed certificate full names
341-
FULL_NAMES=$(grep -F '| **✅ Signed** |' readme.md | awk -F'|' '{gsub(/^\s+|\s+$/,"",$2); print $2}')
342-
343-
if [ -z "$FULL_NAMES" ]; then
344-
echo "No signed certificates found. Skipping signing."
345-
exit 0
346-
fi
347-
348-
# Install zsign dependencies
349-
brew install pkg-config openssl minizip
350-
351-
# Build zsign
352-
git clone https://github.com/zhlynn/zsign.git
353-
cd zsign/build/macos
354-
make clean && make
355-
ZSIGN_PATH="$(pwd)/zsign"
356-
cd ../../..
357-
358-
# Process each cert
359-
echo "$FULL_NAMES" | while read -r FULL_NAME; do
360-
if [ -z "$FULL_NAME" ]; then continue; fi
361-
362-
SHORT_NAME=$(echo "$FULL_NAME" | awk '{print tolower($1)}')
363-
ENCODED=$(echo "$FULL_NAME" | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))')
364-
365-
CERT_DIR="certs/$SHORT_NAME"
366-
mkdir -p "$CERT_DIR"
367-
cd "$CERT_DIR"
368-
369-
curl -LO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.mobileprovision"
370-
curl -LO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.p12"
371-
curl -LO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/password.txt"
372-
373-
cd ../..
374-
375-
SIGNED_IPA="build/com.prostoreios.prostore-signed-${SHORT_NAME}-ios.ipa"
376-
377-
"$ZSIGN_PATH" -k "${CERT_DIR}/${ENCODED}.p12" \
378-
-p "$(cat "${CERT_DIR}/password.txt")" \
379-
-m "${CERT_DIR}/${ENCODED}.mobileprovision" \
380-
-o "$SIGNED_IPA" \
381-
"$UNSIGNED_IPA"
382-
383-
echo "Signed IPA created: $SIGNED_IPA"
384-
done
385-
- name: Upload Signed IPAs
386-
if: always()
387-
continue-on-error: true
388-
run: |
389-
for ipa in build/com.prostoreios.prostore-signed-*-ios.ipa; do
390-
if [ -f "$ipa" ]; then
391-
SHORT_NAME=$(basename "$ipa" | sed -E 's/com\.prostoreios\.prostore-signed-(.*)-ios\.ipa/\1/')
392-
echo "Uploading $ipa as artifact com.prostoreios.prostore-signed-${SHORT_NAME}-ios.ipa"
393-
mkdir -p "artifact_dir/${SHORT_NAME}"
394-
cp "$ipa" "artifact_dir/${SHORT_NAME}/"
395-
fi
396-
done
372+
fi
373+
374+
echo "Using zsign at: $ZSIGN_PATH"
375+
ls -l "$ZSIGN_PATH" || true
376+
377+
# Process each cert
378+
echo "$FULL_NAMES" | while IFS= read -r FULL_NAME; do
379+
if [ -z "$FULL_NAME" ]; then continue; fi
380+
381+
# short name used for filenames: sanitize to lowercase alnum and dashes
382+
SHORT_NAME=$(echo "$FULL_NAME" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-+|-+$//g')
383+
384+
# URL-encode the full display name for the GitHub path
385+
ENCODED=$(python3 -c "import sys,urllib.parse as u; print(u.quote(sys.stdin.read().strip()))" <<< "$FULL_NAME")
386+
387+
CERT_DIR="certs/$SHORT_NAME"
388+
mkdir -p "$CERT_DIR"
389+
pushd "$CERT_DIR" >/dev/null
390+
391+
# download files; if any are missing this will fail, which is likely what you want
392+
curl -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.mobileprovision"
393+
curl -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/${ENCODED}.p12"
394+
curl -fLO "https://github.com/ProStore-iOS/certificates/raw/refs/heads/main/${ENCODED}/password.txt"
395+
396+
popd >/dev/null
397+
398+
SIGNED_IPA="build/com.prostoreios.prostore-signed-${SHORT_NAME}-ios.ipa"
399+
400+
# run zsign
401+
"$ZSIGN_PATH" -k "${CERT_DIR}/${ENCODED}.p12" \
402+
-p "$(cat "${CERT_DIR}/password.txt")" \
403+
-m "${CERT_DIR}/${ENCODED}.mobileprovision" \
404+
-o "$SIGNED_IPA" \
405+
"$UNSIGNED_IPA"
406+
407+
echo "Signed IPA created: $SIGNED_IPA"
408+
done
397409
- name: Upload Artifacts
398410
if: always()
399411
continue-on-error: true

0 commit comments

Comments
 (0)