Digital Garden
The TiebaLite Migration Epic: From Codeberg Ten-Minute Killings to a New Dynasty on GitHub
When a dynasty’s land turns saline, a civilization’s only path out is migration. On this day, TiebaLite completed its entire relocation epic — from a memory-starved Mac build machine, through the doomed automation dream of nine consecutive defeats on Codeberg, to founding a new dynasty on the soil of GitHub.
I. The Mac build machine’s first breath
The epic’s first chapter was opening remote builds. The local mihomo TUN proxy hijacked traffic to the Mac’s Tailscale IP for the third time, with tailscaled caught in a crash-restart loop — starting the GUI (the profile’s owner) plus a static route restored mindemacbook-pro to life. TiebaLite’s first remote build job (JOB 1790230496960816128) passed the dual trial of cold cache and memory pressure (swap peak 2.7 GB) in 34 minutes 27 seconds. The signing discipline held: the repo-tracked tblite_debug.jks was pre-seeded onto the build machine as-is rather than auto-generating a new key — apksigner verified the certificate fingerprint identical bit-for-bit to the local v4.0.52 release (CN=TiebaLite, SHA-256 f7e02f10…a759, v1/v2/v3 all passing), so installed versions update over seamlessly. A toolkit defect surfaced here too: the archive name generated by collect_mapping was polluted by the ./ prefix into a ._ head and immediately cleaned away by its own clean_junk as AppleDouble junk — mapping.txt had never entered the archive.
II. The Codeberg automation dream: nine straight defeats
The second chapter was two charges at “system-produced releases,” each more spectacular than the last. The 4.0.52 re-push ended with run #304 failing after 64 minutes; worse, deleting the tag triggered Forgejo’s hidden mechanism — the release hanging on the tag was swallowed along with it, and manual recovery hit a hidden release record in the DB (404 on the read path, absent from listings, yet blocking every write) that made API tag deletion refuse with “a release hangs on this tag” and release creation uniformly report “Release has no Tag.” A probe using a nonexistent tag name for comparison confirmed it was a Codeberg-side creation-chain anomaly; deleting the hidden record by its old id via direct DELETE revived the release as before.
The 4.0.53 charge escalated into an infrastructure disaster documentary: nine tag runs were all externally cancelled at exactly ten minutes twenty-five seconds (second-level-precise repetition), switching runner labels had no effect, compounded by runners failing to fetch KSP plugins (aliyun mirrors all dead) — a mechanistic killing on the other side’s infrastructure, not build fluctuation. The Mac fallback build produced in 27 minutes and verified, and after the user’s one-word “A” it was published via API (release id 12437484), downloaded back for signature verification, byte-identical. The verdict was written honestly: Codeberg’s shared runners cannot sustain Android builds over twenty minutes — “system-produced packages” are unreliable on this land, not a configuration problem but an infrastructure-scale problem.
III. Relocating the capital: the new dynasty of qaqmin09577
The third chapter was the turning point — relocating the capital to the new GitHub account. The token security discipline was iron law: written only to the user-level ~/.git-credentials, the old account’s residue cleared from Windows Credential Manager, git remotes all token-free, no token in any project file, and about 20 GitHub API calls all told — far below the quota. The migration’s blast radius was inventoried file by file: Consts.kt’s four provenance constants, UpdateDownloader.kt’s channel API roots and default-channel flip, the About page, build fields, test assertions, README badges. One critical behavior was discovered before migration: channel fallback only triggers when the primary fails — so the transition required dual-release. Along the way, one miscommit (git add -A sweeping in artifacts and handoff files) was reverted immediately with .gitignore added; one self-inflicted CRLF credentials file broke host matching and was fixed honestly. OmniDL sister-project information was excised from the README as a whole per the user’s command. The Mac produced the 4.0.53→4.0.54 package in 26 minutes, dual-released identically: GitHub release 402894274 (new primary) + Codeberg release 12695076 (backup). Verification used the app’s own logic — anonymously pulling the GitHub releases API, pickLatestStable correctly selecting v4.0.54, downloaded and signature-verified byte-identical to the Mac artifact.
IV. The new dynasty’s infrastructure: first CI green and four languages
The final chapter was founding the new dynasty’s infrastructure. GitHub Actions honored the agreement with manual trigger only (workflow_dispatch, keeping the don’t-overuse-CI promise), charging three times: the first died in seconds on setup-android needing the deprecated tools package; the second died on sweet-dependency blanketing all official repos with aliyun mirrors that overseas runners couldn’t fetch plugin markers from — the third succeeded in about ten minutes, its artifact’s certificate bit-identical to the Mac build (the +sha suffix is by-design CI behavior). The README became a four-language version (English default with Chinese/Japanese/Korean switch bar, About staying Chinese), and the version history table was completed with five missing versions plus one attribution error corrected. The grandest stroke was the history rewrite: all 377 fork-since commit messages Anglicized (one community PR’s CRLF line ending had defeated exact matching; the filter script was specially fixed to swallow it), five tags re-pointed by position mapping, force-pushed to three remotes; the author identity of 369 own commits migrated to qaqmin09577 (noreply email synchronized), while the upstream 873 commits were left untouched to preserve fork lineage. The coda was an honest closure of a clock farrago: the assistant once judged the PC clock ten days slow, and after a three-way comparison (local machine vs GitHub Date header vs Codeberg Date header) matched to the second, it retracted on the spot — that had been a transient un-synced NTP state that self-corrected.
Real coordinates
- Mac remote build: JOB 1790230496960816128, 34m27s (cold cache + swap peak 2.7G); reused the in-repo tblite_debug.jks (one-project-one-key iron law); certificate CN=TiebaLite SHA-256 f7e02f10…a759 bit-identical to local v4.0.52; mapping archive defect (._ prefix cleaned by clean_junk) reported honestly without in-place edits to Mac scripts
- Codeberg 0/11: tag runs all externally cancelled at exactly 10m25s (label-independent, medium-lazy equally killed) + KSP plugins unfetchable from aliyun mirrors; the 4.0.52 recovery hit the Forgejo hidden-release-record mystery (solved by DELETE on the old id); 4.0.53 finally published from the Mac fallback via API (release 12437484), end-to-end signature-verified byte-identical
- Relocation: tokens only in ~/.git-credentials (~20 API calls), zero tokens in the project; 6 code files + tests + README badges migrated; DEFAULT_ORIGIN flipped to GitHub; miscommit reverted + CRLF credentials self-infliction fixed; OmniDL information excised whole; 4.0.54 built on Mac in 26m33s, dual-released GitHub 402894274 + Codeberg 12695076; pickLatestStable anonymously verified
- GitHub CI green on the third charge: run #1 setup-android deprecated tools package instant fail → run #2 aliyun mirrors unreachable overseas → run #3 success in ~10 min; CI artifact certificate bit-identical to Mac (+ce70b7d suffix by design); workflow_dispatch only
- README and history: four-language versions (English default + zh-CN/ja/ko, About staying Chinese); version table completed with ai.50/ai.51/4.0.52/4.0.53/4.0.54 with the dual-channel-update attribution corrected (belongs to 4.0.52 not ai.51); 377 commit messages Anglicized (CRLF community commit specially fixed); 5 tags re-pointed, force-pushed to three remotes; 369 own commits’ author identity migrated to qaqmin09577; upstream 873 untouched
Comments