Skip to content

sign-sideinstaller

sign-sideinstaller #35

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