@@ -8,4 +8,114 @@ MultiGram is Forkgram (https://github.com/forkgram/TelegramAndroid) plus a small
88| `multigram` | The app: the latest `forkgram` snapshot plus the MultiGram commits on top. Build this branch. |
99| `main` | This README, the automation that keeps `multigram` in step with Forkgram, and helper scripts. |
1010
11−Setup is in progress.
11+The sync also uses `multigram-next` (the next `multigram`, while it is being checked) and tags
12+the `multigram` it replaces as `multigram-before-<version>`.
13+
14+## Build
15+
16+**Actions > Build MultiGram > Run workflow**, ref `multigram`. It compiles the Java and Kotlin
17+code (a few minutes). Tick **APK** to also build a release APK; it compiles the native code
18+too, so it takes much longer, and the APK is attached to the run as `multigram-apk`.
19+
20+## Secrets
21+
22+Set these in **Settings > Secrets and variables > Actions**:
23+
24+- `MULTIGRAM_APP_ID` and `MULTIGRAM_APP_HASH`: your own API id and hash from
25+ https://my.telegram.org (API development tools). Without them the APK cannot log in.
26+- Signing: the APK job signs with `TMessagesProj/config/release.keystore` from the tree, whose
27+ passwords are public, so anyone could sign an "update" for it. That is fine for testing. For
28+ an APK you give to people, sign with your own key and keep it out of the repository (see
29+ "Signing and updates" in `multigram/rebrand/README.md`); the workflow has no keystore secret yet.
30+
31+## How the sync works
32+
33+The **Sync with Forkgram** workflow runs every 6 hours (and by hand):
34+
35+1. If Forkgram's `dev` has a new tip (Forkgram rebases `dev` onto every Telegram release, so each
36+ new tip is a release candidate), it adds a snapshot commit to `forkgram`: that tree without
37+ `.github`, with `Forkgram-Commit`, `Forkgram-Version` and `Telegram-Base` lines in the message.
38+2. It replays the MultiGram commits (`forkgram..multigram`) onto the snapshot as `multigram-next`
39+ (`git rebase --onto`).
40+3. It compiles `multigram-next` with the Build MultiGram workflow.
41+4. If that passes, it tags the old `multigram` as `multigram-before-<version>`, moves `multigram`
42+ to `multigram-next`, deletes `multigram-next` and closes the sync issue.
43+5. On a conflict or a failed compile it opens an issue labelled `forkgram-sync` (or comments on the
44+ open one) with the details; `multigram` stays as it was.
45+
46+It never replaces a `multigram-next` that has commits it did not make (your fix, say): it then
47+changes nothing, not even `forkgram`, and says so on the issue until you run **use_next** or
48+delete `multigram-next`. It records the `multigram-next` it built last in the ref
49+`refs/multigram-sync/next`. Keep `multigram` linear (rebase, do not merge): the replay flattens
50+merges, so a merge commit with changes of its own stops the sync.
51+
52+Run it by hand with **force** to rebuild `multigram-next` without a new release (to test the
53+pipeline, or to retry), or with **use_next** to compile and promote a `multigram-next` you fixed
54+yourself. **use_next** checks that `multigram-next` still has every commit on `multigram` (a
55+commit pushed to `multigram` after you started the fix would otherwise be lost); tick
56+**allow_drop** as well if it leaves some out on purpose.
57+
58+The work is done by `scripts/sync-forkgram.sh` (see `--help`). It also runs locally without
59+pushing anything: from a checkout of `main`, `bash scripts/sync-forkgram.sh --remote origin`
60+leaves the results in your local `forkgram` and `multigram-next` branches.
61+`bash scripts/selftest-sync.sh` tests it against fake repositories.
62+
63+rerere (git's memory of conflict fixes) only knows the fixes recorded in the clone it runs in.
64+It helps when you redo a rebase or run the script in your own clone; the scheduled sync starts
65+from a fresh clone every time, so it reports a conflict again until `multigram` carries the fix.
66+
67+## When the sync issue opens
68+
69+The issue has the exact commands; in short:
70+
71+**Conflict.** Replay the stack yourself, fix the files, push the result to `multigram-next`:
72+
73+```sh
74+git fetch origin
75+git switch -C multigram-next origin/multigram
76+git config rerere.enabled true # reuses your fixes if you redo this rebase here
77+git rebase origin/forkgram
78+# fix the files git names, then: git add <files> && git rebase --continue (repeat)
79+git push --force origin multigram-next
80+```
81+
82+**Compile failure.** Fix the build on top of `multigram-next` and fold the fix into the commit it
83+belongs to:
84+
85+```sh
86+git fetch origin
87+git switch -C multigram-next origin/multigram-next
88+# edit, then:
89+git commit -a --fixup=<the MultiGram commit it belongs to>
90+GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash origin/forkgram
91+git push --force origin multigram-next
92+```
93+
94+Then **Actions > Sync with Forkgram > Run workflow** with **use_next** ticked: it compiles
95+`multigram-next` and, if that passes, moves `multigram` to it and closes the issue. If the
96+compile failed because of a runner or network hiccup, **Re-run failed jobs** on the run page
97+is enough. Until then the sync leaves your `multigram-next` alone; if you give up on it, delete
98+it (`git push origin --delete multigram-next`) and the next sync starts over from `multigram`.
99+
100+## Patches
101+
102+`bash scripts/export-patches.sh --base origin/forkgram --head origin/multigram` writes the stack
103+as numbered patches to `multigram-patches/`, with `APPLY.txt` saying how to apply them onto a
104+plain Forkgram checkout (`git am -3`).
105+
106+## What is on the multigram branch
107+
108+- `multigram/rebrand/`: the rebrand toolkit that gives a build its own name, applicationId,
109+ launcher icon and signing key (instructions in its `README.md`).
110+- `multigram/`: the other MultiGram tools and notes, such as the per-install random style and
111+ its palette check; the app code is in
112+ `TMessagesProj/src/main/java/org/telegram/messenger/multigram/`.
113+
114+## Repository settings
115+
116+- `main` must be the default branch: scheduled workflows only run from it.
117+- The workflows ask for the token permissions they need, so the default workflow permissions
118+ can stay read-only.
119+- Issues must be enabled: the sync reports on an issue labelled `forkgram-sync`.
120+- If you protect `forkgram`, `multigram`, `multigram-next` or `multigram-before-*` tags with
121+ branch protection or rulesets, let GitHub Actions push and force-push them.