name: Stable SideStore build on: push: tags: - '[0-9]+.[0-9]+.[0-9]+' # example: 1.0.0 workflow_dispatch: jobs: build: name: Build SideStore - stable (on tag push) strategy: fail-fast: false matrix: include: - os: 'macos-15' version: '16.2' runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v4 with: submodules: recursive - name: Echo Build.xcconfig run: | echo "cat Build.xcconfig" cat Build.xcconfig shell: bash # - name: Change MARKETING_VERSION to the pushed tag that triggered this build # run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig - name: Echo Updated Build.xcconfig run: | cat Build.xcconfig shell: bash - name: Extract MARKETING_VERSION from Build.xcconfig id: version run: | version=$(grep MARKETING_VERSION Build.xcconfig | sed -e 's/MARKETING_VERSION = //g') echo "version=$version" >> $GITHUB_OUTPUT echo "version=$version" echo "MARKETING_VERSION=$version" >> $GITHUB_ENV echo "MARKETING_VERSION=$version" >> $GITHUB_OUTPUT echo "MARKETING_VERSION=$version" shell: bash - name: Fail the build if pushed tag and embedded MARKETING_VERSION in Build.xcconfig are mismatching run: | if [ "$MARKETING_VERSION" != "${{ github.ref_name }}" ]; then echo 'Version mismatch: $tag != $marketing_version ... ' echo " expected-tag : $MARKETING_VERSION" echo " pushed-tag : ${{ github.ref_name }}" exit 1 fi echo 'Version matches: $tag == $marketing_version ... ' echo " expected-tag : $MARKETING_VERSION" echo " pushed-tag : ${{ github.ref_name }}" shell: bash - name: Install dependencies - ldid & xcbeautify run: | brew install ldid xcbeautify - name: Setup Xcode uses: maxim-lobanov/setup-xcode@v1.6.0 with: xcode-version: ${{ matrix.version }} - name: (Build) Restore Xcode & SwiftPM Cache (Exact match) id: xcode-cache-restore uses: actions/cache/restore@v3 with: path: | ~/Library/Developer/Xcode/DerivedData ~/Library/Caches/org.swift.swiftpm key: xcode-cache-build-stable-${{ github.sha }} - name: (Build) Restore Xcode & SwiftPM Cache (Last Available) id: xcode-cache-restore-recent uses: actions/cache/restore@v3 with: path: | ~/Library/Developer/Xcode/DerivedData ~/Library/Caches/org.swift.swiftpm key: xcode-cache-build-stable- - name: (Build) Restore Pods from Cache (Exact match) id: pods-restore uses: actions/cache/restore@v3 with: path: | ./Podfile.lock ./Pods/ ./AltStore.xcworkspace/ key: pods-cache-build-stable-${{ hashFiles('Podfile') }} - name: (Build) Restore Pods from Cache (Last Available) if: ${{ steps.pods-restore.outputs.cache-hit != 'true' }} id: pods-restore-recent uses: actions/cache/restore@v3 with: path: | ./Podfile.lock ./Pods/ ./AltStore.xcworkspace/ key: pods-cache-build-stable- - name: (Build) Install CocoaPods run: pod install shell: bash - name: (Build) Save Pods to Cache id: save-pods if: ${{ steps.pods-restore.outputs.cache-hit != 'true' }} uses: actions/cache/save@v3 with: path: | ./Podfile.lock ./Pods/ ./AltStore.xcworkspace/ key: pods-cache-build-stable-${{ hashFiles('Podfile') }} - name: (Build) Clean previous build artifacts run: | make clean mkdir -p build/logs shell: bash - name: (Build) List Files and derived data if: always() shell: bash run: | echo ">>>>>>>>> Workdir <<<<<<<<<<" ls -la . echo "" echo ">>>>>>>>> Pods <<<<<<<<<<" find Pods -maxdepth 2 -exec ls -ld {} + || true # List contents if directory exists echo "" echo ">>>>>>>>> SideStore <<<<<<<<<<" find SideStore -maxdepth 2 -exec ls -ld {} + || true # List contents if directory exists echo "" echo ">>>>>>>>> Dependencies <<<<<<<<<<" find Dependencies -maxdepth 2 -exec ls -ld {} + || true # List contents if directory exists echo "" echo ">>>>>>>>> Xcode-Derived-Data <<<<<<<<<<" ls -la ~/Library/Developer/Xcode/DerivedData || true # List contents if directory exists echo "" - name: Build SideStore.xcarchive # using 'tee' to intercept stdout and log for detailed build-log run: | NSUnbufferedIO=YES make -B build 2>&1 | tee -a build/logs/build.log | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]} shell: bash - name: Fakesign app run: make fakesign | tee -a build/logs/build.log shell: bash - name: Convert to IPA run: make ipa | tee -a build/logs/build.log shell: bash - name: (Build) Save Xcode & SwiftPM Cache id: cache-save if: ${{ steps.xcode-cache-restore.outputs.cache-hit != 'true' }} uses: actions/cache/save@v3 with: path: | ~/Library/Developer/Xcode/DerivedData ~/Library/Caches/org.swift.swiftpm key: xcode-cache-build-stable-${{ github.sha }} - name: (Build) List Files and Build artifacts run: | echo ">>>>>>>>> Workdir <<<<<<<<<<" ls -la . echo "" echo ">>>>>>>>> Build <<<<<<<<<<" find build -maxdepth 3 -exec ls -ld {} + || true # List contents if directory exists echo "" echo ">>>>>>>>> SideStore <<<<<<<<<<" find SideStore -maxdepth 3 -exec ls -ld {} + || true # List contents if directory exists echo "" echo ">>>>>>>>> SideStore.xcarchive <<<<<<<<<<" find SideStore.xcarchive -maxdepth 3 -exec ls -ld {} + || true # List contents if directory exists echo "" echo ">>>>>>>>> Xcode-Derived-Data <<<<<<<<<<" ls -la ~/Library/Developer/Xcode/DerivedData || true # List contents if directory exists echo "" shell: bash - name: Encrypt build-logs for upload id: encrypt-build-log run: | DEFAULT_BUILD_LOG_PASSWORD=12345 BUILD_LOG_ZIP_PASSWORD=${{ secrets.BUILD_LOG_ZIP_PASSWORD }} BUILD_LOG_ZIP_PASSWORD=${BUILD_LOG_ZIP_PASSWORD:-$DEFAULT_BUILD_LOG_PASSWORD} if [ "$BUILD_LOG_ZIP_PASSWORD" == "$DEFAULT_BUILD_LOG_PASSWORD" ]; then echo "Warning: BUILD_LOG_ZIP_PASSWORD is not set. Defaulting to '${DEFAULT_BUILD_LOG_PASSWORD}'." fi pushd build/logs && zip -e -P "$BUILD_LOG_ZIP_PASSWORD" ../../encrypted-build-logs.zip * || popd echo "::set-output name=encrypted::true" shell: bash - name: Upload encrypted-build-logs.zip id: attach-encrypted-build-log if: ${{ always() && steps.encrypt-build-log.outputs.encrypted == 'true' }} uses: actions/upload-artifact@v4 with: name: encrypted-build-logs-${{ steps.version.outputs.version }}.zip path: encrypted-build-logs.zip - name: Upload SideStore.ipa Artifact uses: actions/upload-artifact@v4 with: name: SideStore-${{ steps.version.outputs.version }}.ipa path: SideStore.ipa - name: Zip dSYMs run: zip -r -9 ./SideStore.dSYMs.zip ./SideStore.xcarchive/dSYMs shell: bash - name: Upload *.dSYM Artifact uses: actions/upload-artifact@v4 with: name: SideStore-${{ steps.version.outputs.version }}-dSYMs.zip path: SideStore.dSYMs.zip - name: Get current date id: date run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT shell: bash - name: Get current date in AltStore date form id: date_altstore run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT shell: bash - name: Upload to releases uses: IsaacShelton/update-existing-release@v1.3.1 with: token: ${{ secrets.GITHUB_TOKEN }} draft: true release: ${{ github.ref_name }} # name tag: ${{ github.ref_name }} # stick with what the user pushed, do not use latest commit or anything, # ex: if we want to go back to previous release due to hot issue, dev can create a new tag pointing to that older working tag/commit so as to keep it as an update (to revert major issue) # in this case we do not want the tag to be auto-updated to latest updateTag: false prerelease: false files: > SideStore.ipa SideStore.dSYMs.zip encrypted-build-logs.zip body: | ## Changelog - TODO ## Build Info Built at (UTC): `${{ steps.date.outputs.date }}` Built at (UTC date): `${{ steps.date_altstore.outputs.date }}` Commit SHA: `${{ github.sha }}` Version: `${{ steps.version.outputs.version }}`