Skip to content

Commit 1ce6d82

Browse files
JoeMattclaude
andcommitted
feat(CI): alpha build pipeline with separate bundle ID and sideload feed
- Alpha builds (develop pushes) now use bundle ID `com.provenance-emu.provenance.alpha` and display name "Provenance Alpha" so they can be installed side-by-side with stable - Sideload feed (AltStore/SideStore JSON) now has two separate app entries: "Provenance" (stable) and "Provenance Alpha" (alpha) - Alpha feed limited to latest 3 versions to avoid clutter - Alpha versions use date+SHA format: `3.3.1-alpha.20260315.abc1234` - Alpha release notes now include commit log since last alpha, merged PRs list, and link to CI run - Issue #3163 auto-updates with latest alpha build status on each successful develop push Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7583492 commit 1ce6d82

2 files changed

Lines changed: 337 additions & 81 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 218 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,24 @@ jobs:
114114
echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $GITHUB_ENV
115115
echo "MARKETING_VERSION=$(grep 'MARKETING_VERSION' Build.xcconfig | cut -d'=' -f2 | xargs)" >> $GITHUB_ENV
116116
117+
- name: Set Alpha Build Overrides
118+
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
119+
run: |
120+
SHORT_SHA="${GITHUB_SHA:0:7}"
121+
ALPHA_DATE=$(date -u +"%Y%m%d")
122+
echo "IS_ALPHA=true" >> $GITHUB_ENV
123+
echo "ALPHA_BUNDLE_SUFFIX=.alpha" >> $GITHUB_ENV
124+
echo "ALPHA_DISPLAY_NAME_SUFFIX= Alpha" >> $GITHUB_ENV
125+
echo "ALPHA_VERSION_SUFFIX=-alpha.${ALPHA_DATE}.${SHORT_SHA}" >> $GITHUB_ENV
126+
127+
- name: Set Stable Build Overrides
128+
if: github.event_name != 'push' || github.ref != 'refs/heads/develop'
129+
run: |
130+
echo "IS_ALPHA=false" >> $GITHUB_ENV
131+
echo "ALPHA_BUNDLE_SUFFIX=" >> $GITHUB_ENV
132+
echo "ALPHA_DISPLAY_NAME_SUFFIX=" >> $GITHUB_ENV
133+
echo "ALPHA_VERSION_SUFFIX=" >> $GITHUB_ENV
134+
117135
- uses: actions/cache@v3
118136
with:
119137
path: |
@@ -134,12 +152,32 @@ jobs:
134152
rm -rf ./build
135153
mkdir -p ./build
136154
155+
- name: Patch Info.plist for Alpha (bundle ID + display name)
156+
if: env.IS_ALPHA == 'true'
157+
run: |
158+
echo "Patching for alpha build: bundle suffix='${ALPHA_BUNDLE_SUFFIX}', display name suffix='${ALPHA_DISPLAY_NAME_SUFFIX}'"
159+
# Patch all Info.plist files to add alpha display name
160+
for plist in Provenance/Info.plist ProvenanceTV/Info.plist; do
161+
if [ -f "$plist" ]; then
162+
# Add CFBundleDisplayName if not present, or it will come from build settings
163+
/usr/libexec/PlistBuddy -c "Add :CFBundleDisplayName string 'Provenance Alpha'" "$plist" 2>/dev/null || \
164+
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName 'Provenance Alpha'" "$plist" 2>/dev/null || true
165+
fi
166+
done
167+
137168
- name: Build Provenance
138169
id: build
139170
env:
140171
MARKETING_VERSION: ${{ env.MARKETING_VERSION }}
141172
BUILD_NUMBER: ${{ env.BUILD_NUMBER }}
142173
run: |
174+
# For alpha builds, override bundle identifier to allow side-by-side install
175+
EXTRA_BUILD_SETTINGS=""
176+
if [ "$IS_ALPHA" = "true" ]; then
177+
EXTRA_BUILD_SETTINGS="PRODUCT_BUNDLE_IDENTIFIER=org.provenance-emu.provenance${ALPHA_BUNDLE_SUFFIX}"
178+
echo "Alpha build: overriding bundle ID to org.provenance-emu.provenance${ALPHA_BUNDLE_SUFFIX}"
179+
fi
180+
143181
start_time=$(date +%s)
144182
xcodebuild -configuration Release \
145183
-workspace Provenance.xcworkspace \
@@ -157,6 +195,7 @@ jobs:
157195
SWIFT_PACKAGE_ALLOW_WRITING_TO_DIRECTORY=${{ env.SWIFT_PACKAGE_ALLOW_WRITING_TO_DIRECTORY }} \
158196
DEVELOPMENT_TEAM=S32Z3HMYVQ \
159197
ORG_IDENTIFIER=org.provenance-emu \
198+
$EXTRA_BUILD_SETTINGS \
160199
| xcbeautify
161200
end_time=$(date +%s)
162201
echo "duration=$((end_time - start_time))" >> $GITHUB_OUTPUT
@@ -253,12 +292,93 @@ jobs:
253292
runs-on: ubuntu-latest
254293
permissions:
255294
contents: write
295+
issues: write
256296
steps:
297+
- name: Checkout repository
298+
uses: actions/checkout@v4
299+
with:
300+
fetch-depth: 0
301+
257302
- name: Download all artifacts
258303
uses: actions/download-artifact@v4
259304
with:
260305
path: artifacts
261306

307+
- name: Build Release Notes
308+
id: release_notes
309+
env:
310+
GH_TOKEN: ${{ github.token }}
311+
REPO: ${{ github.repository }}
312+
run: |
313+
SHA="${{ github.sha }}"
314+
SHORT_SHA="${SHA:0:7}"
315+
DATE=$(date -u +"%Y-%m-%d %H:%M UTC")
316+
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
317+
318+
# Get the previous alpha tag SHA (if it exists)
319+
PREV_SHA=$(gh api "repos/${REPO}/git/refs/tags/alpha" --jq '.object.sha' 2>/dev/null || echo "")
320+
321+
# Build commit log since last alpha
322+
COMMIT_LOG=""
323+
if [ -n "$PREV_SHA" ] && [ "$PREV_SHA" != "$SHA" ]; then
324+
COMMIT_LOG=$(git log --oneline --no-merges "${PREV_SHA}..${SHA}" 2>/dev/null | head -30 || echo "")
325+
fi
326+
if [ -z "$COMMIT_LOG" ]; then
327+
COMMIT_LOG=$(git log --oneline --no-merges -10 2>/dev/null || echo "No commit history available")
328+
fi
329+
330+
# Get merged PRs since last alpha
331+
MERGED_PRS=""
332+
if [ -n "$PREV_SHA" ]; then
333+
# Extract PR numbers from merge commits
334+
PR_NUMBERS=$(git log --oneline "${PREV_SHA}..${SHA}" 2>/dev/null | grep -oP '#\d+' | sort -u | head -15 || echo "")
335+
for pr in $PR_NUMBERS; do
336+
PR_NUM="${pr#\#}"
337+
PR_TITLE=$(gh pr view "$PR_NUM" --repo "$REPO" --json title --jq '.title' 2>/dev/null || echo "")
338+
if [ -n "$PR_TITLE" ]; then
339+
MERGED_PRS="${MERGED_PRS}- ${pr}: ${PR_TITLE}"$'\n'
340+
fi
341+
done
342+
fi
343+
344+
# Write release notes to file (avoids quoting issues)
345+
cat > /tmp/release_notes.md << NOTESEOF
346+
## Alpha Build \`${SHORT_SHA}\`
347+
348+
**Automated alpha build from \`develop\` branch**
349+
350+
| | |
351+
|---|---|
352+
| **Commit** | [\`${SHORT_SHA}\`](https://github.com/${REPO}/commit/${SHA}) |
353+
| **Built** | ${DATE} |
354+
| **CI Run** | [View build log](${RUN_URL}) |
355+
| **Bundle ID** | \`com.provenance-emu.provenance.alpha\` |
356+
357+
> **Note:** This alpha build uses a separate bundle ID so it can be installed alongside the stable release.
358+
359+
### Commits since last alpha
360+
\`\`\`
361+
${COMMIT_LOG}
362+
\`\`\`
363+
NOTESEOF
364+
365+
if [ -n "$MERGED_PRS" ]; then
366+
cat >> /tmp/release_notes.md << PREOF
367+
368+
### Merged PRs
369+
${MERGED_PRS}
370+
PREOF
371+
fi
372+
373+
cat >> /tmp/release_notes.md << FOOTEREOF
374+
375+
---
376+
These builds are unsigned and intended for sideloading via AltStore/SideStore.
377+
Install the **Provenance Alpha** app (separate from stable) using the [sideload feed](https://provenance-emu.github.io/Provenance/altstore-source.json).
378+
379+
> This release is automatically updated on every successful develop push.
380+
FOOTEREOF
381+
262382
- name: Update alpha release
263383
env:
264384
GH_TOKEN: ${{ github.token }}
@@ -267,7 +387,6 @@ jobs:
267387
REPO="${{ github.repository }}"
268388
SHA="${{ github.sha }}"
269389
SHORT_SHA="${SHA:0:7}"
270-
DATE=$(date -u +"%Y-%m-%d %H:%M UTC")
271390
272391
# Create or update the alpha tag
273392
gh api repos/$REPO/git/refs/tags/$TAG \
@@ -284,20 +403,107 @@ jobs:
284403
# Create new pre-release with IPAs
285404
gh release create $TAG \
286405
--repo $REPO \
287-
--title "Alpha Build ($SHORT_SHA)" \
288-
--notes "$(cat <<EOF
289-
**Automated alpha build from \`develop\` branch**
290-
291-
- Commit: $SHA
292-
- Built: $DATE
293-
- These builds are unsigned and intended for sideloading via AltStore/SideStore
294-
295-
> This release is automatically updated on every successful develop push.
296-
EOF
297-
)" \
406+
--title "Provenance Alpha ($SHORT_SHA)" \
407+
--notes-file /tmp/release_notes.md \
298408
--prerelease \
299409
*.ipa 2>/dev/null || echo "::warning::No IPA files to attach"
300410
411+
- name: Update Build Status Issue
412+
env:
413+
GH_TOKEN: ${{ github.token }}
414+
REPO: ${{ github.repository }}
415+
run: |
416+
SHORT_SHA="${{ github.sha }}"
417+
SHORT_SHA="${SHORT_SHA:0:7}"
418+
DATE=$(date -u +"%Y-%m-%d %H:%M UTC")
419+
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
420+
421+
# Update issue #3163 with latest build status
422+
ISSUE_BODY=$(cat << 'ISSUEEOF'
423+
# Alpha & Beta Builds -- Download & Install Guide
424+
425+
## Latest Alpha Build
426+
427+
| | |
428+
|---|---|
429+
ISSUEEOF
430+
)
431+
432+
ISSUE_BODY="${ISSUE_BODY}
433+
| **Status** | :white_check_mark: Build Passing |
434+
| **Commit** | [\`${SHORT_SHA}\`](https://github.com/${REPO}/commit/${{ github.sha }}) |
435+
| **Built** | ${DATE} |
436+
| **CI Run** | [View build log](${RUN_URL}) |
437+
| **Download** | [GitHub Release](https://github.com/${REPO}/releases/tag/alpha) |
438+
| **Bundle ID** | \`com.provenance-emu.provenance.alpha\` |"
439+
440+
ISSUE_BODY="${ISSUE_BODY}
441+
442+
---
443+
444+
## Install via AltStore
445+
446+
1. Open AltStore on your device
447+
2. Go to **Sources** (or **Browse** > **Sources**)
448+
3. Tap **Add Source** and enter:
449+
\`\`\`
450+
https://provenance-emu.github.io/Provenance/altstore-source.json
451+
\`\`\`
452+
4. You will see **two** apps: **Provenance** (stable) and **Provenance Alpha** (latest dev builds)
453+
5. Install either or both -- they use separate bundle IDs so both can be installed simultaneously
454+
455+
## Install via SideStore
456+
457+
1. Open SideStore on your device
458+
2. Go to **Sources**
459+
3. Add the following source URL:
460+
\`\`\`
461+
https://provenance-emu.github.io/Provenance/sidestore-source.json
462+
\`\`\`
463+
4. Browse the source and install **Provenance** or **Provenance Alpha**
464+
465+
## Direct IPA Download from GitHub Releases
466+
467+
- **Latest stable release:** [Releases page](https://github.com/${REPO}/releases/latest)
468+
- **Latest alpha build:** [Alpha release](https://github.com/${REPO}/releases/tag/alpha)
469+
470+
---
471+
472+
## FAQ
473+
474+
### What is the difference between stable and alpha builds?
475+
476+
| | Stable | Alpha |
477+
|---|---|---|
478+
| **Source** | Tagged releases on \`master\` | Automatic builds from \`develop\` branch |
479+
| **Bundle ID** | \`com.provenance-emu.provenance\` | \`com.provenance-emu.provenance.alpha\` |
480+
| **App Name** | Provenance | Provenance Alpha |
481+
| **Side-by-side** | N/A | Yes -- install both at once |
482+
| **Reliability** | Tested and ready for daily use | May contain bugs or incomplete features |
483+
| **Updates** | Released periodically | Built on every successful \`develop\` CI run |
484+
485+
### Can I install both stable and alpha at the same time?
486+
487+
**Yes!** Alpha builds use a different bundle ID (\`com.provenance-emu.provenance.alpha\`) so they install as a separate app called **Provenance Alpha**. Your stable install is not affected.
488+
489+
### Are alpha builds safe to use?
490+
491+
Alpha builds pass all CI checks before being published, but they have not gone through the full QA process of a stable release. **Back up your save data** before switching to an alpha build.
492+
493+
### How do I report bugs in alpha builds?
494+
495+
Please [open an issue](https://github.com/${REPO}/issues/new) and include:
496+
- The build version (visible in Settings > About)
497+
- Steps to reproduce
498+
- Device model and iOS/tvOS version
499+
500+
---
501+
502+
> **Note:** This issue is auto-updated by CI on every successful alpha build. Do not edit manually."
503+
504+
gh issue edit 3163 --repo "$REPO" --body "$ISSUE_BODY" 2>/dev/null || \
505+
echo "::warning::Could not update issue #3163"
506+
301507
# Post artifact download links to PR for workflow_dispatch builds (label / /build triggered)
302508
post-to-pr:
303509
name: Post IPA links to PR

0 commit comments

Comments
 (0)