···11+# Fork Sync and Personal Release Workflow
22+33+## Goal
44+55+Keep `onevcat/supacode` close to `supabitapp/supacode` while preserving local customizations (keybindings and feature trims), and make personal releases easy to produce and download from the fork Release page.
66+77+## Current Release Build in This Repo
88+99+The repository already has two production-grade workflows:
1010+1111+- `.github/workflows/release.yml`
1212+ - Trigger: GitHub Release published.
1313+ - Build: `make archive` + `make export-archive` on `macos-26`.
1414+ - Packaging: app zip, dmg, Sparkle appcast, delta files.
1515+ - Signing/notarization: required (Apple cert + notary credentials).
1616+ - Publish target in workflow: hard-coded `supabitapp/supacode`.
1717+- `.github/workflows/release-tip.yml`
1818+ - Trigger: push to `main` (and manual dispatch).
1919+ - Produces/updates `tip` prerelease assets and appcast.
2020+ - Also requires signing/notarization secrets.
2121+2222+### Fork Impact
2323+2424+Out of the box, these workflows are not fork-friendly:
2525+2626+- They require many signing/secrets that forks usually do not have.
2727+- Stable release publish target is hard-coded to upstream repo (`supabitapp/supacode`).
2828+- Some appcast URLs are hard-coded to `supacode.sh`.
2929+3030+## Recommended Branch Strategy
3131+3232+- `upstream/main`: source of truth (read-only remote branch).
3333+- `main` (origin): your integration branch with custom patches.
3434+- `feat/onevcat-*`: optional short-lived branches per local customization.
3535+3636+## One-Time Setup
3737+3838+```bash
3939+git fetch origin upstream --prune
4040+git config rerere.enabled true
4141+git config rerere.autoupdate true
4242+```
4343+4444+`rerere` records your conflict resolutions so repeated upstream syncs become easier.
4545+4646+## Upstream Sync Runbook (Recommended: Merge)
4747+4848+```bash
4949+git switch main
5050+git fetch origin upstream --prune
5151+git pull --ff-only origin main
5252+git merge --no-ff upstream/main
5353+make build-app
5454+make test
5555+git push origin main
5656+```
5757+5858+If conflicts happen, resolve once, commit, and `rerere` will likely auto-apply next time.
5959+6060+## Personal Release Strategy (Fork Release Page)
6161+6262+For personal usage, the easiest path is:
6363+6464+1) Build unsigned Debug app locally (`make build-app`).
6565+2) Zip app bundle.
6666+3) Create a tag.
6767+4) Upload zip to your fork GitHub Release page.
6868+6969+This avoids Apple signing/notarization setup and keeps the workflow simple.
7070+7171+## Helper Scripts
7272+7373+- Sync helper: `doc-onevcat/scripts/sync-upstream-main.sh`
7474+- Release helper: `doc-onevcat/scripts/release-to-fork.sh`
7575+7676+### Example
7777+7878+```bash
7979+# Sync upstream into local main and verify build
8080+./doc-onevcat/scripts/sync-upstream-main.sh
8181+8282+# Create a personal release on fork release page
8383+./doc-onevcat/scripts/release-to-fork.sh
8484+8585+# Or specify tag explicitly
8686+./doc-onevcat/scripts/release-to-fork.sh onevcat-v2026.02.26-01
8787+```
8888+8989+## Optional: Full Signed Release on Fork
9090+9191+If you need notarized DMG and Sparkle feed in your fork:
9292+9393+- Copy/adjust release workflows to publish to `${{ github.repository }}`.
9494+- Replace hard-coded download URL and release-notes URL with fork values.
9595+- Configure all required secrets:
9696+ - `DEVELOPER_ID_CERT_P12`
9797+ - `DEVELOPER_ID_CERT_PASSWORD`
9898+ - `DEVELOPER_ID_IDENTITY`
9999+ - `KEYCHAIN_PASSWORD`
100100+ - `APPLE_TEAM_ID`
101101+ - `APPLE_NOTARIZATION_ISSUER`
102102+ - `APPLE_NOTARIZATION_KEY_ID`
103103+ - `APPLE_NOTARIZATION_KEY`
104104+ - `SPARKLE_PRIVATE_KEY`
105105+ - plus telemetry/sentry secrets used by workflow
106106+107107+For your current goal (personal periodic builds), the unsigned release helper is usually enough.