sign-sideinstaller #35
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: sign-sideinstaller | |
| # Re-signs the SideInstaller IPA with every certificate in the cert pool and | |
| # publishes a tap-to-install page. The IPA source is whatever URL you put in | |
| # ipa-url.txt (editable any time) — or a one-off override passed below. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| channel: | |
| description: "Build channel: stable -> index.html (public), beta -> beta.html (test)" | |
| required: true | |
| type: choice | |
| default: stable | |
| options: | |
| - stable | |
| - beta | |
| ipa_url: | |
| description: "Override unsigned IPA URL (leave blank to use ipa-url.txt)" | |
| required: false | |
| default: "" | |
| cert_zip_url: | |
| description: "Override certificate pool zip URL (leave blank to use cert-url.txt)" | |
| required: false | |
| default: "" | |
| push: | |
| paths: | |
| - "ipa-url.txt" # re-run automatically when you point at a new IPA | |
| schedule: | |
| - cron: "0 23 * * *" # daily refresh so the page tracks cert expiry | |
| concurrency: | |
| group: sign-sideinstaller | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write # commit generated files back to the repo | |
| pages: write # publish the install page to GitHub Pages | |
| id-token: write # required by actions/deploy-pages | |
| jobs: | |
| sign: | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Make scripts executable | |
| run: chmod +x scripts/sign_with_all_certs.sh scripts/generate_plist.sh scripts/generate_index.sh | |
| # Resolve the channel once and export the paths every later step + script | |
| # reads from env. Beta gets its own output dir and page so a test build is | |
| # never mixed into the public index.html / output/ artifacts. Automatic | |
| # triggers (push, schedule) have no channel input and fall back to stable. | |
| - name: Resolve release channel | |
| shell: bash | |
| env: | |
| CHANNEL_INPUT: ${{ github.event.inputs.channel }} | |
| run: | | |
| channel="${CHANNEL_INPUT:-stable}" | |
| base="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/${GITHUB_REF_NAME}" | |
| { | |
| echo "CHANNEL=$channel" | |
| if [[ "$channel" == "beta" ]]; then | |
| echo "OUTPUT_HTML=beta.html" | |
| echo "OUTPUT_DIR=output-beta" | |
| echo "OUTPUT_BASE_URL=$base/output-beta" | |
| echo "PAGE_TITLE=SideInstaller — Beta" | |
| echo "APP_TAGLINE=Beta test build — not the public release. Follow the three steps below to get set up." | |
| else | |
| echo "OUTPUT_HTML=index.html" | |
| echo "OUTPUT_DIR=output" | |
| echo "OUTPUT_BASE_URL=$base/output" | |
| fi | |
| } >> "$GITHUB_ENV" | |
| echo "Resolved channel: $channel" | |
| - name: Sign IPA with all certificates | |
| env: | |
| # Dispatch overrides win; otherwise the scripts fall back to the | |
| # ipa-url.txt / cert-url.txt files in the repo. | |
| UNSIGNED_IPA_URL: ${{ github.event.inputs.ipa_url }} | |
| CERT_ZIP_URL: ${{ github.event.inputs.cert_zip_url }} | |
| run: ./scripts/sign_with_all_certs.sh | |
| - name: Ensure signed IPAs exist | |
| shell: bash | |
| run: | | |
| shopt -s nullglob | |
| signed=("${OUTPUT_DIR}"/"${OUTPUT_PREFIX:-sideinstaller}"-*.ipa) | |
| shopt -u nullglob | |
| if [[ ${#signed[@]} -eq 0 ]]; then | |
| echo "No signed IPAs were produced in ${OUTPUT_DIR}/." >&2 | |
| exit 1 | |
| fi | |
| printf '%s\n' "${signed[@]}" | |
| - name: Generate OTA manifests | |
| run: ./scripts/generate_plist.sh | |
| - name: Generate install page | |
| run: ./scripts/generate_index.sh | |
| - name: Commit and push generated files | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add -A "$OUTPUT_DIR" "$OUTPUT_HTML" | |
| if git diff --cached --quiet; then | |
| echo "Nothing to commit" | |
| exit 0 | |
| fi | |
| git commit -m "sign-sideinstaller ($CHANNEL): refresh signed IPAs, manifests, and install page" | |
| for attempt in 1 2 3; do | |
| git pull --rebase origin "${GITHUB_REF_NAME}" || true | |
| if git push; then exit 0; fi | |
| echo "Push failed; retrying (attempt $attempt)" >&2 | |
| sleep 5 | |
| done | |
| echo "Failed to push after 3 attempts" >&2 | |
| exit 1 | |
| - name: Assemble Pages site | |
| run: | | |
| rm -rf _site | |
| mkdir -p _site | |
| # Publish whichever channel pages exist so a beta deploy never drops the | |
| # public index.html (and vice versa). Install links inside each page point | |
| # at committed raw-githubusercontent manifests, so the pages work | |
| # standalone; Pages just needs the HTML itself. | |
| if [[ -f index.html ]]; then cp index.html _site/index.html; fi | |
| if [[ -f beta.html ]]; then cp beta.html _site/beta.html; fi | |
| # DNS profile linked from the page's Setup step — must ship with the site. | |
| if [[ -f SideInstallerDNS.mobileconfig ]]; then cp SideInstallerDNS.mobileconfig _site/SideInstallerDNS.mobileconfig; fi | |
| - name: Upload Pages artifact | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: _site | |
| # Publishes the install page. Requires Settings -> Pages -> Source = "GitHub Actions" | |
| # (one-time). This job is what shows up in the Actions tab as the Pages deploy. | |
| deploy-pages: | |
| needs: sign | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 |