Fix cert parsing fallback & OSStatus cast #40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ProStore iOS Build and Release | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [ main ] | |
| paths-ignore: | |
| - 'README.md' | |
| - 'app-repo.json' | |
| - 'gallery/**' | |
| - 'website/**' | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-unsigned-ipa: | |
| runs-on: macos-15 | |
| timeout-minutes: 60 | |
| outputs: | |
| version: ${{ steps.get_version.outputs.version }} | |
| release_exists: ${{ steps.check_release.outputs.exists }} | |
| changelog: ${{ steps.generate_changelog.outputs.CHANGELOG }} | |
| steps: | |
| - name: Checkout repo (full history) | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: true | |
| - name: Show Xcode version (debug) | |
| run: | | |
| echo "=== xcodebuild -version ===" | |
| xcodebuild -version || true | |
| echo "=== sw_vers ===" | |
| sw_vers || true | |
| - name: Ensure jq, yq & gh exist (best-effort — tries brew, then gh installer) | |
| run: | | |
| # jq | |
| if ! command -v jq >/dev/null 2>&1; then | |
| echo "jq not found — attempting to install via brew" | |
| if command -v brew >/dev/null 2>&1; then | |
| brew install jq || true | |
| fi | |
| fi | |
| # yq | |
| if ! command -v yq >/dev/null 2>&1; then | |
| echo "yq not found — attempting to install via brew" | |
| if command -v brew >/dev/null 2>&1; then | |
| brew install yq || true | |
| fi | |
| fi | |
| # gh (GitHub CLI) | |
| if ! command -v gh >/dev/null 2>&1; then | |
| echo "gh not found — attempting to install via brew" | |
| if command -v brew >/dev/null 2>&1; then | |
| brew install gh || true | |
| fi | |
| fi | |
| # Fallback: official gh installer script (works across platforms) | |
| if ! command -v gh >/dev/null 2>&1; then | |
| echo "gh still not found — attempting official installer script" | |
| curl -fsSL https://cli.github.com/install.sh | sh || true | |
| fi | |
| echo "Tool versions (if installed):" | |
| echo "jq: $(jq --version 2>/dev/null || echo 'not installed')" | |
| echo "yq: $(yq --version 2>/dev/null || echo 'not installed')" | |
| echo "gh: $(gh --version 2>/dev/null || echo 'not installed')" | |
| shell: bash | |
| - name: Ensure project.yml and sources exist (debug) | |
| run: | | |
| echo "Workspace files:" | |
| ls -la || true | |
| echo "project.yml (first 200 lines):" | |
| sed -n '1,200p' project.yml || true | |
| - name: Build xcodegen from source (install to $HOME/.local/bin) | |
| run: | | |
| set -e | |
| git clone --depth 1 https://github.com/yonaskolb/XcodeGen.git /tmp/XcodeGen | |
| cd /tmp/XcodeGen | |
| swift build -c release | |
| mkdir -p $HOME/.local/bin | |
| cp .build/release/xcodegen $HOME/.local/bin/xcodegen | |
| echo "Installed xcodegen to $HOME/.local/bin" | |
| - name: Generate Xcode project with xcodegen | |
| run: | | |
| set -e | |
| $HOME/.local/bin/xcodegen generate --spec project.yml | |
| echo "Generated project at: $(pwd)/prostore.xcodeproj" | |
| echo "project.pbxproj header (first 60 lines):" | |
| sed -n '1,60p' prostore.xcodeproj/project.pbxproj || true | |
| - name: Resolve Swift Package dependencies | |
| run: | | |
| set -e | |
| echo "Resolving Swift package dependencies for prostore..." | |
| xcodebuild -resolvePackageDependencies -project prostore.xcodeproj -scheme prostore -configuration Release | |
| - name: Try building archive, auto-fix objectVersion on future-format error | |
| run: | | |
| set -e | |
| ARCHIVE_PATH="$PWD/build/prostore.xcarchive" | |
| mkdir -p build | |
| candidates=(77 70 63 60 56 55) | |
| build_ok=0 | |
| for v in "${candidates[@]}"; do | |
| echo "----- Attempting build with objectVersion = $v -----" | |
| /usr/bin/perl -0777 -pe "s/objectVersion = \\d+;/objectVersion = $v;/" -i.bak prostore.xcodeproj/project.pbxproj || true | |
| echo "Applied objectVersion $v. Header preview:" | |
| sed -n '1,20p' prostore.xcodeproj/project.pbxproj || true | |
| echo "Running xcodebuild archive..." | |
| set +e | |
| xcodebuild clean archive \ | |
| -project prostore.xcodeproj \ | |
| -scheme prostore \ | |
| -archivePath "$ARCHIVE_PATH" \ | |
| -sdk iphoneos \ | |
| -configuration Release \ | |
| CODE_SIGN_IDENTITY="" CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO | |
| rc=$? | |
| set -e | |
| if [ $rc -eq 0 ]; then | |
| echo "xcodebuild succeeded with objectVersion = $v" | |
| build_ok=1 | |
| break | |
| else | |
| echo "xcodebuild failed (exit $rc). Logging last 200 lines from DiagnosticReports (if present):" | |
| tail -n 200 /Users/runner/Library/Logs/DiagnosticReports/* 2>/dev/null || true | |
| echo "Trying next objectVersion..." | |
| fi | |
| done | |
| if [ "$build_ok" -ne 1 ]; then | |
| echo "ERROR: All objectVersion attempts failed. Dumping debug info:" | |
| echo "===== project.pbxproj header =====" | |
| sed -n '1,200p' prostore.xcodeproj/project.pbxproj || true | |
| echo "===== build directory listing =====" | |
| ls -la build || true | |
| exit 74 | |
| fi | |
| - name: Create unsigned .ipa by packaging device .app (iphoneos) | |
| run: | | |
| set -e | |
| ARCHIVE_PATH="$PWD/build/prostore.xcarchive" | |
| APP_PATH="$ARCHIVE_PATH/Products/Applications/prostore.app" | |
| OUTPUT_IPA="build/com.prostoreios.prostore-unsigned-ios.ipa" | |
| echo "Device app path: $APP_PATH" | |
| if [ ! -d "$APP_PATH" ]; then | |
| echo "ERROR: App not found at expected path. Listing archive contents:" | |
| ls -la "$ARCHIVE_PATH" || true | |
| exit 1 | |
| fi | |
| mkdir -p build/Payload | |
| rm -rf build/Payload/* || true | |
| cp -R "$APP_PATH" build/Payload/ | |
| (cd build && zip -r "$(basename "$OUTPUT_IPA")" Payload) || exit 1 | |
| echo "Created device ipa: $OUTPUT_IPA" | |
| ls -la "$OUTPUT_IPA" || true | |
| - name: Build simulator (iphonesimulator) and package simulator .ipa (if possible) | |
| run: | | |
| set -e | |
| echo "Starting simulator build (won't fail the entire job if it fails)." | |
| SIM_DERIVED="$PWD/build/sim_derived" | |
| rm -rf "$SIM_DERIVED" | |
| set +e | |
| xcodebuild clean build \ | |
| -project prostore.xcodeproj \ | |
| -scheme prostore \ | |
| -configuration Release \ | |
| -sdk iphonesimulator \ | |
| -derivedDataPath "$SIM_DERIVED" \ | |
| CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY="" | |
| rc=$? | |
| set -e | |
| if [ $rc -ne 0 ]; then | |
| echo "Warning: simulator build failed (exit $rc). Will attempt to recover packaging if a simulator .app exists." | |
| fi | |
| POSSIBLE_APPS=( | |
| "$SIM_DERIVED/Build/Products/Release-iphonesimulator/prostore.app" | |
| "$SIM_DERIVED/Build/Products/Debug-iphonesimulator/prostore.app" | |
| "$PWD/build/Build/Products/Release-iphonesimulator/prostore.app" | |
| "$PWD/build/Release-iphonesimulator/prostore.app" | |
| ) | |
| FOUND_APP="" | |
| for p in "${POSSIBLE_APPS[@]}"; do | |
| if [ -d "$p" ]; then | |
| FOUND_APP="$p" | |
| break | |
| fi | |
| done | |
| if [ -z "$FOUND_APP" ]; then | |
| echo "Simulator .app not found in expected locations. Listing $SIM_DERIVED contents for debug:" | |
| ls -la "$SIM_DERIVED" || true | |
| echo "Skipping simulator .ipa packaging." | |
| exit 0 | |
| fi | |
| echo "Found simulator .app at: $FOUND_APP" | |
| SIM_IPA="build/com.prostoreios.prostore-unsigned-iossimulator.ipa" | |
| mkdir -p build/Payload-sim | |
| rm -rf build/Payload-sim/* || true | |
| cp -R "$FOUND_APP" build/Payload-sim/ | |
| (cd build && zip -r "$(basename "$SIM_IPA")" Payload-sim) || exit 1 | |
| echo "Created simulator ipa: $SIM_IPA" | |
| ls -la "$SIM_IPA" || true | |
| - name: Upload device unsigned IPA artifact (named as .ipa) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: com.prostoreios.prostore-unsigned-ios.ipa | |
| path: build/com.prostoreios.prostore-unsigned-ios.ipa | |
| - name: Upload simulator unsigned IPA artifact (named as .ipa) (ignore if not found) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: com.prostoreios.prostore-unsigned-iossimulator.ipa | |
| path: build/com.prostoreios.prostore-unsigned-iossimulator.ipa | |
| if-no-files-found: ignore | |
| - name: Extract version from project.yml | |
| id: get_version | |
| run: | | |
| VERSION=$(yq '.targets.prostore.info.properties.CFBundleShortVersionString' project.yml) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Detected version: $VERSION" | |
| - name: Check if release already exists | |
| id: check_release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.get_version.outputs.version }}" | |
| TAG="v$VERSION" | |
| echo "Checking if release $TAG exists..." | |
| if command -v gh >/dev/null 2>&1 && gh release view "$TAG" >/dev/null 2>&1; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Generate changelog | |
| id: generate_changelog | |
| if: steps.check_release.outputs.exists == 'false' | |
| run: | | |
| set -e | |
| VERSION="${{ steps.get_version.outputs.version }}" | |
| CURRENT_VERSION="$VERSION" | |
| SINCE_COMMIT="" | |
| # Walk commits that touched project.yml from newest -> oldest | |
| for c in $(git rev-list HEAD -- project.yml); do | |
| file=$(git show "$c:project.yml" 2>/dev/null || true) | |
| if [ -z "$file" ]; then | |
| continue | |
| fi | |
| v=$(printf "%s" "$file" | yq '.targets.prostore.info.properties.CFBundleShortVersionString' 2>/dev/null || true) | |
| if [ -z "$v" ]; then | |
| continue | |
| fi | |
| if [ "$v" != "$CURRENT_VERSION" ]; then | |
| SINCE_COMMIT="$c" | |
| break | |
| fi | |
| done | |
| # Always capture HEAD message | |
| HEAD_MSG=$(git log -1 --pretty=format:%s HEAD || echo "") | |
| # Derive SINCE_DATE (ISO 8601) from SINCE_COMMIT | |
| if [ -n "$SINCE_COMMIT" ]; then | |
| SINCE_DATE=$(git show -s --format=%cI "$SINCE_COMMIT" 2>/dev/null || true) | |
| else | |
| SINCE_DATE="" | |
| fi | |
| # Determine repo owner/repo | |
| ORIGIN_URL=$(git remote get-url origin 2>/dev/null || true) | |
| OWNER_REPO=$(printf "%s" "$ORIGIN_URL" | sed -E 's#.*github.com[:/]+([^/]+/[^/]+)(\.git)?#\1#') | |
| # Fetch workflow runs | |
| RUNS_JSON="" | |
| if [ -n "$OWNER_REPO" ] && command -v gh >/dev/null 2>&1; then | |
| echo "Fetching recent workflow runs for ${OWNER_REPO}..." | |
| RUNS_JSON=$(gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/"$OWNER_REPO"/actions/runs \ | |
| -f per_page=100 -f event=push 2>/dev/null || true) | |
| if [ -z "$RUNS_JSON" ] || [ "$(printf "%s" "$RUNS_JSON" | jq '.workflow_runs | length')" -eq 0 ]; then | |
| RUNS_JSON=$(gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/"$OWNER_REPO"/actions/runs \ | |
| -f per_page=100 -f event=workflow_dispatch 2>/dev/null || true) | |
| fi | |
| fi | |
| WORKFLOW_LINES="" | |
| if [ -n "$RUNS_JSON" ] && printf "%s" "$RUNS_JSON" | jq -e '.workflow_runs | length > 0' >/dev/null 2>&1; then | |
| if [ -n "$SINCE_DATE" ]; then | |
| SINCE_DATE_UTC=$(date -u -j -f "%Y-%m-%dT%H:%M:%S%z" "$SINCE_DATE" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "$SINCE_DATE") | |
| WORKFLOW_LINES=$(printf "%s" "$RUNS_JSON" | jq -r --arg SINCE "$SINCE_DATE_UTC" ' | |
| [.workflow_runs[] | select(.created_at >= $SINCE)] | | |
| sort_by(.created_at)[] | | |
| ( "- " + (.head_commit.message // .name // .workflow_name) + | |
| " (#" + (.run_number|tostring) + ") — " + | |
| ((.conclusion // "in_progress") | tostring) + | |
| " — " + (.created_at // "") + | |
| " — branch: " + (.head_branch // "") )' || true) | |
| else | |
| WORKFLOW_LINES=$(printf "%s" "$RUNS_JSON" | jq -r ' | |
| [.workflow_runs[]] | sort_by(.created_at)[] | | |
| ( " - " + | |
| (if (.head_commit.message | length) > 0 then .head_commit.message | |
| else (if (.name|length) > 0 then .name else .workflow_name end) end) + | |
| " (#" + (.run_number|tostring) + ") — " + | |
| ((.conclusion // "in_progress") | tostring) + | |
| " — " + (.created_at // "") + | |
| " — branch: " + (.head_branch // "") )' || true) | |
| fi | |
| if [ -n "$WORKFLOW_LINES" ]; then | |
| WORKFLOW_LINES=$(printf "%s\n" "$WORKFLOW_LINES" | awk 'NF && !seen[$0]++ { print $0 }' || true) | |
| fi | |
| fi | |
| # Fallback to commit messages | |
| if [ -z "$WORKFLOW_LINES" ]; then | |
| if [ -n "$SINCE_COMMIT" ]; then | |
| COMMITS_RAW=$(git log --pretty=format:%s "${SINCE_COMMIT}..HEAD" --reverse 2>/dev/null || true) | |
| COMMITS_RAW=$(echo "$COMMITS_RAW" | grep -v "Update ProStore app repo to v" || true) | |
| else | |
| COMMITS_RAW="" | |
| fi | |
| fi | |
| # Build description | |
| printf -v DESC "What's new in Version %s?\n" "$VERSION" | |
| if [ -n "$HEAD_MSG" ]; then | |
| DESC+=$'- '"$HEAD_MSG"$'\n' | |
| fi | |
| if [ -n "$WORKFLOW_LINES" ]; then | |
| DESC+="${WORKFLOW_LINES}"$'\n' | |
| elif [ -n "$COMMITS_RAW" ]; then | |
| OTHER_LINES=$(printf "%s\n" "$COMMITS_RAW" | awk -v head="$HEAD_MSG" 'NF && $0!=head { print "- "$0 }' || true) | |
| if [ -n "$OTHER_LINES" ]; then | |
| DESC+="${OTHER_LINES}"$'\n' | |
| fi | |
| fi | |
| DESC="${DESC%$'\n'}" | |
| echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT | |
| printf '%s\n' "$DESC" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| shell: bash | |
| create-github-release: | |
| needs: build-unsigned-ipa | |
| if: needs.build-unsigned-ipa.outputs.release_exists == 'false' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Ensure gh exists (best-effort) | |
| run: | | |
| # gh (GitHub CLI) | |
| if ! command -v gh >/dev/null 2>&1; then | |
| echo "gh not found — attempting official installer script" | |
| curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg | |
| echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null | |
| sudo apt update | |
| sudo apt install gh -y || true | |
| fi | |
| echo "gh: $(gh --version 2>/dev/null || echo 'not installed')" | |
| - name: Download device IPA artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: com.prostoreios.prostore-unsigned-ios.ipa | |
| path: build | |
| - name: Download simulator IPA artifact (optional) | |
| uses: actions/download-artifact@v4 | |
| continue-on-error: true | |
| with: | |
| name: com.prostoreios.prostore-unsigned-iossimulator.ipa | |
| path: build | |
| - name: Create GitHub Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ needs.build-unsigned-ipa.outputs.version }} | |
| CHANGELOG: ${{ needs.build-unsigned-ipa.outputs.changelog }} | |
| run: | | |
| TAG="v$VERSION" | |
| echo "Creating release $TAG with notes:" | |
| printf '%s\n' "$CHANGELOG" | |
| DEVICE_IPA="build/com.prostoreios.prostore-unsigned-ios.ipa" | |
| SIM_IPA="build/com.prostoreios.prostore-unsigned-iossimulator.ipa" | |
| SIM_ARG="" | |
| if [ -f "$SIM_IPA" ]; then | |
| SIM_ARG="$SIM_IPA" | |
| fi | |
| gh release create "$TAG" \ | |
| "$DEVICE_IPA" $SIM_ARG \ | |
| --title "ProStore v$VERSION" \ | |
| --notes "$CHANGELOG" \ | |
| --repo "$GITHUB_REPOSITORY" | |
| shell: bash | |
| create-app-source-json: | |
| needs: build-unsigned-ipa | |
| if: needs.build-unsigned-ipa.outputs.release_exists == 'false' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repo (full history) | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: true | |
| - name: Ensure jq exists (best-effort) | |
| run: | | |
| # jq | |
| if ! command -v jq >/dev/null 2>&1; then | |
| echo "jq not found — attempting to install" | |
| sudo apt update | |
| sudo apt install jq -y || true | |
| fi | |
| echo "jq: $(jq --version 2>/dev/null || echo 'not installed')" | |
| - name: Download device IPA artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: com.prostoreios.prostore-unsigned-ios.ipa | |
| path: build | |
| - name: Update app-repo.json with latest ProStore version | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ needs.build-unsigned-ipa.outputs.version }} | |
| CHANGELOG: ${{ needs.build-unsigned-ipa.outputs.changelog }} | |
| run: | | |
| set -e | |
| IPA_PATH="$PWD/build/com.prostoreios.prostore-unsigned-ios.ipa" | |
| DOWNLOAD_URL="https://github.com/ProStore-iOS/ProStore/releases/download/v$VERSION/com.prostoreios.prostore-unsigned-ios.ipa" | |
| REPO_FILE="app-repo.json" | |
| if [ -f "$IPA_PATH" ]; then | |
| IPA_SIZE=$(stat -c%s "$IPA_PATH") | |
| SHA256=$(sha256sum "$IPA_PATH" | awk '{print $1}') | |
| else | |
| IPA_SIZE=0 | |
| SHA256="" | |
| fi | |
| VERSION_DATE_ISO=$(date -u +"%Y-%m-%dT%H:%M:%S%z") | |
| MIN_OS="15.0" | |
| FULL_DATE=$(date +%Y%m%d%H%M%S) | |
| ICON_URL="https://raw.githubusercontent.com/ProStore-iOS/ProStore/refs/heads/main/Sources/prostore/Assets.xcassets/AppIcon.appiconset/Icon-1024.png" | |
| BUNDLE="com.prostoreios.prostore" | |
| META_DESC="The BEST alternative app store for iOS!" | |
| DEVNAME="ProStore iOS" | |
| SCREENSHOTS='[ | |
| "https://raw.githubusercontent.com/ProStore-iOS/ProStore/refs/heads/main/gallery/Screenshot1.png", | |
| "https://raw.githubusercontent.com/ProStore-iOS/ProStore/refs/heads/main/gallery/Screenshot2.png", | |
| "https://raw.githubusercontent.com/ProStore-iOS/ProStore/refs/heads/main/gallery/Screenshot3.png", | |
| "https://raw.githubusercontent.com/ProStore-iOS/ProStore/refs/heads/main/gallery/Screenshot4.png", | |
| "https://raw.githubusercontent.com/ProStore-iOS/ProStore/refs/heads/main/gallery/Screenshot5.png" | |
| ]' | |
| # Ensure base repo JSON exists | |
| if [ ! -f "$REPO_FILE" ]; then | |
| echo '{ | |
| "name": "Official ProStore Repo", | |
| "identifier": "com.prostoreios.prostore.repo", | |
| "sourceURL": "https://ProStore-iOS.github.io/apps.json", | |
| "iconURL": "'"$ICON_URL"'", | |
| "website": "https://ProStore-iOS.github.io", | |
| "ipawebsite": "https://github.com/ProStore-iOS/ProStore/releases", | |
| "subtitle": "The BEST alternative app store for iOS!", | |
| "META": { | |
| "repoName": "Official ProStore Repo", | |
| "repoIcon": "'"$ICON_URL"'" | |
| }, | |
| "apps": [] | |
| }' > "$REPO_FILE" | |
| fi | |
| TMP=$(mktemp) | |
| # Build the JSON representation of the new version | |
| NEW_VERSION=$(jq -c -n \ | |
| --arg version "$VERSION" \ | |
| --arg date "$VERSION_DATE_ISO" \ | |
| --arg desc "$CHANGELOG" \ | |
| --arg url "$DOWNLOAD_URL" \ | |
| --arg sha "$SHA256" \ | |
| --arg minos "$MIN_OS" \ | |
| --argjson size "$IPA_SIZE" \ | |
| --arg fulldate "$FULL_DATE" \ | |
| '{version: $version, date: $date, localizedDescription: $desc, downloadURL: $url, size: $size, sha256: $sha, minOSVersion: $minos, fullDate: $fulldate}') | |
| # Update or create the app entry | |
| jq --argjson newVer "$NEW_VERSION" \ | |
| --arg name "ProStore" \ | |
| --arg bundle "$BUNDLE" \ | |
| --arg dev "$DEVNAME" \ | |
| --arg desc "$META_DESC" \ | |
| --arg icon "$ICON_URL" \ | |
| --argjson screenshots "$SCREENSHOTS" \ | |
| 'if ( .apps | map(.bundleIdentifier // .bundleID) | index($bundle) ) then | |
| .apps |= map( | |
| if ((.bundleIdentifier // .bundleID) == $bundle) then | |
| ( { "name": $name, | |
| "bundleIdentifier": $bundle, | |
| "developerName": $dev, | |
| "localizedDescription": $desc, | |
| "iconURL": $icon, | |
| "screenshotURLs": $screenshots | |
| } + { "versions": ( [ $newVer ] + ( .versions // [] ) ) } ) | |
| else . end | |
| ) | |
| else | |
| .apps += [ | |
| { | |
| "name": $name, | |
| "bundleIdentifier": $bundle, | |
| "developerName": $dev, | |
| "localizedDescription": $desc, | |
| "iconURL": $icon, | |
| "screenshotURLs": $screenshots, | |
| "versions": [ $newVer ] | |
| } | |
| ] | |
| end' "$REPO_FILE" > "$TMP" && mv "$TMP" "$REPO_FILE" | |
| # Safe commit & push | |
| git config user.name "github-actions" | |
| git config user.email "github-actions@github.com" | |
| git add "$REPO_FILE" | |
| git commit -m "Update ProStore app repo to v$VERSION" || echo "No changes to commit" | |
| git fetch origin main --quiet | |
| if git rev-parse --verify origin/main >/dev/null 2>&1; then | |
| if git rebase origin/main; then | |
| echo "Rebase succeeded, pushing changes..." | |
| git push origin HEAD:main | |
| else | |
| echo "Rebase failed — aborting rebase and skipping push." | |
| git rebase --abort || true | |
| fi | |
| else | |
| git push origin HEAD:main | |
| fi | |
| shell: bash | |
| - name: Push apps.json to Pages repo (ProStore-iOS.github.io) using PAT | |
| env: | |
| PAGES_PAT: ${{ secrets.PAGES_PAT }} | |
| run: | | |
| set -e | |
| VERSION="${{ needs.build-unsigned-ipa.outputs.version }}" | |
| PAGES_REPO="ProStore-iOS/ProStore-iOS.github.io" | |
| PAGES_DIR=$(mktemp -d) | |
| echo "Cloning pages repo (masked token)..." | |
| git clone --depth 1 "https://x-access-token:${PAGES_PAT}@github.com/${PAGES_REPO}.git" "$PAGES_DIR" | |
| echo "Copying app-repo.json -> apps.json in pages repo" | |
| cp app-repo.json "$PAGES_DIR/apps.json" | |
| cd "$PAGES_DIR" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # Only commit if there's a change | |
| git add apps.json | |
| if git diff --quiet --cached; then | |
| echo "No changes to apps.json — nothing to commit/push." | |
| exit 0 | |
| fi | |
| git commit -m "Update apps.json from ProStore v${VERSION}" | |
| echo "Pushing apps.json to ${PAGES_REPO}:main" | |
| git push "https://x-access-token:${PAGES_PAT}@github.com/${PAGES_REPO}.git" HEAD:main | |
| shell: bash |