🏢 GitHub-организация: выгоды и момент миграции
Статус: анализ для решения · 2026-08-17. Все утверждения о планах (Free/Team/Enterprise) и механике переноса проверены по официальной документации GitHub и Cloudflare в этот день; там, где дока противоречит сама себе, это отмечено явно. Организация
fortemateсоздана (Free), репозитории пока подrabestro. Решение по фазе D (brand-fortemate §8): переносить строго после фазы C, или не переносить вовсе — эта заметка даёт критерии.
1. Что реально даёт организация (и работает на Free)
CI и раннеры — главный практический выигрыш
- Один self-hosted runner на все репозитории. Раннер регистрируется на уровне организации и обслуживает задания всех её репо. На личном аккаунте уровня «организация» не существует в принципе — раннер привязывается только к одному репозиторию (ровно та стена, в которую упирались с homelab-раннером: 30 репо = 30 регистраций). Org-уровень доступен на Free; управление доступом — через единственную default-группу с политикой «All / Selected repositories». ⚠️ Дополнительные runner groups — противоречие в самой доке GitHub (врезка «Who can use this feature?» говорит Free, абзац ниже — только Team); для одного homelab-раннера default-группы достаточно.
- Практический эффект для нас: sbt-сборки движка/play-api на homelab-раннере с тёплыми кешами (coursier, sbt, JMH-бейзлайны) вместо холодных GitHub-hosted машин — быстрее и не тратит минуты.
- Org-secrets/variables: один
INGEST_TOKEN/CLOUDFLARE_API_TOKENна организацию вместо копий в каждом репо, одна точка ротации. Лимиты щедрые (1000 секретов, 48 KB). ⚠️ На Free org-секреты видны только публичным репо — приватным нужен Team. - Reusable/starter workflows между репо работают на Free — но это НЕ аргумент за миграцию: публичные reusable workflows работают и между репозиториями личного аккаунта.
Люди и bus factor
- Роли: в организации на каждом репо доступны Read / Triage / Write / Maintain / Admin + орг-роли (Owner, Member, Billing manager, Security manager, Moderator). На личном репо ролей две: владелец и collaborator, причём collaborator — это всегда write, в приватном личном репо нельзя дать даже read-only. Для второго участника (супруга) это разница между «полный push-доступ или ничего» и, например, triage-ролью (разбирать issues без права трогать код).
- Teams +
CODEOWNERSс@fortemate/team— автоназначение ревьюеров. - 🔑 Bus factor — самый недооценённый пункт. У личного аккаунта один владелец, и наследование доступа — юридически мутная процедура через поддержку GitHub. У организации может быть два owner’а: супруга как второй owner означает, что проект переживает потерю доступа к личному аккаунту (или его владельцу). Для проекта с прод-сервисами и пользователями это страховка, которую нельзя получить никак иначе.
Бренд и доверие
github.com/fortemate— витрина open-core-проекта: профиль организации, README, pinned repos. Для AGPL-стратегии «серьёзная платформа, а не хобби одного человека» — это часть позиционирования.- Верификация домена fortemate.com → бейдж Verified на профиле организации — доступно на Free (подтверждено докой).
- GitHub Sponsors на организацию — отдельный от личного спонсор-профиль (регистрация по waitlist). Слой 0 монетизации может собирать спонсорство на бренд, а не на частное лицо — чище и для доверия, и для будущей бухгалтерии.
Политики и безопасность
- Audit log организации: 180 дней на Free (ограничения «без стриминга, Git-события 7 дней» касаются всех не-Enterprise).
- Централизованный контроль fine-grained PAT: организация может требовать одобрения токенов, запрашивающих доступ к её репо, — на Free.
- GitHub Apps (CodeRabbit, Cloudflare Pages, …): один инсталл на организацию с «All repositories», включая будущие репо, — вместо поштучной установки.
2. Чего организация НЕ даёт на Free (границы и мифы)
| Хотелось бы | Реальность |
|---|---|
| Org-rulesets (центральная защита веток на все репо) | Team (доки противоречат: Team vs Enterprise; специализированная страница говорит Team) |
| Org-секреты для приватных репо | Team |
| Branch protection / rulesets в приватных репо | Недоступны на Free вообще — и в организации, и на личном аккаунте. Миграция здесь ничего не меняет |
| Дополнительные runner groups | Вероятно Team (противоречие в доке) |
| Кастомные роли репо | Enterprise |
🔑 Лайфхак с минутами Actions: пул 2000 бесплатных минут/мес для приватных репо у Free-организации — отдельный от такого же пула личного аккаунта. Если приватные репо (hunter, house-bots, lab) остаются под rabestro, а публичные едут в fortemate — получается два независимых бесплатных пула, и приватные ничего не теряют (org-фич для приватных на Free всё равно нет). Это аргумент за частичную миграцию: публичное — в org, приватное — на личном.
3. Цена переноса: что ломается (проверено по докам)
Переезжают автоматически: issues, PR, stars, watchers, wiki, releases, webhooks, deploy keys, репо-секреты; git- и веб-ссылки редиректятся (редирект живёт, пока на старом месте не создан репо с тем же именем).
Ломается и требует рук:
- Cloudflare Pages git-интеграция не переживает transfer (официальная позиция Cloudflare: пересоздать проект под новым владельцем) — затрагивает play и docs. Это самый болезненный пункт.
- GitHub Apps не переезжают — installation привязан к владельцу; CodeRabbit/CF Pages ставить на организацию и выдавать доступ заново.
- Fine-grained PAT с resource owner = rabestro теряют доступ к перенесённым репо — перевыпуск с resource owner = fortemate (и включить поддержку fine-grained PAT в настройках организации).
- GitHub Pages не редиректится (в отличие от git-ссылок): project-сайты переезжают на
fortemate.github.io/<repo>; user-сайтrabestro.github.io(contributor-docs на jc.id.lv) в организацию не переносится в принципе — у org может быть только свойfortemate.github.io. - GitHub Packages: Maven/Docker-пакеты переезжают вместе с репо, но URL реестра меняется (
maven.pkg.github.com/rabestro/…→…/fortemate/…) без редиректа — все потребители ломаются разом. Поэтому фаза D — строго после фазы C (движок уже на Central, GH Packages пуст). npm/RubyGems/NuGet-пакеты: связка «пакет↔репо» рвётся. - Приватный репо, перенесённый в Free-организацию, лишается Pages (если был опубликован).
- SonarCloud-проекты не переносятся между SonarCloud-организациями (привязка 1:1 к GitHub-аккаунту): пересоздание с нуля, история обнуляется, новые project key +
SONAR_TOKENв CI — детали в oss-services. Затрагивает 4 Scala-репо.
4. Когда мигрировать: триггеры
Предусловие всегда одно: фаза C выполнена (пакеты ушли с GitHub Packages на Central) — иначе п. 5 выше ломает всех потребителей движка.
Дальше миграция оправдана, когда наступают хотя бы два из четырёх:
- Общий homelab-раннер реально нужен — CI-минуты или скорость sbt-сборок стали болью (это может случиться и раньше остальных: раннер — самая осязаемая выгода).
- Второй человек работает регулярно — нужны роли/teams, а не «collaborator с полным write»; и/или пора оформить второго owner’а как bus-factor-страховку.
- Бренд публичен (фаза B сделана) — github.com/fortemate становится витриной open-core, спонсорство направляется на организацию.
- Слой 0 монетизации запущен и хочется собирать Sponsors на организацию, а не на частное лицо.
Рекомендуемый порядок самой миграции (когда время придёт): пилот на некритичном публичном репо без интеграций → волна простых публичных репо → play/docs с Cloudflare Pages последними (по чеклисту: снять конфиг → перенести → переустановить Apps → пересоздать Pages-проект → перевыпустить PAT) → приватные не переносить вовсе до апгрейда на Team (лайфхак минут + отсутствие выгод).
Отдельно: второй owner можно оформить хоть завтра — организация уже существует, и добавление супруги owner’ом не требует переноса ни одного репозитория. Bus-factor-страховка доступна без миграции.
5. Пилот выполнен: dicechess-bot-java (2026-08-17)
Первый репозиторий перенесён в организацию и проверен снаружи end-to-end. Результаты — эталон для остальных волн:
| Проверка | Результат |
|---|---|
| Transfer | ✅ issues/PR/секреты/история ранов переехали; github.com/rabestro/dicechess-bot-java отдаёт 301 на новый адрес |
| CI: доступ к GH Packages чужого владельца | ✅ главный неизвестный вопрос решён положительно: воркфлоу под GITHUB_TOKEN организации fortemate успешно тянет dicechess-engine-scala_3 из maven.pkg.github.com/rabestro/... (публичный пакет, кросс-владельческая аутентификация работает). Org-секрет с PAT не понадобился |
| CD: Docker-образ | ✅ пуш-цель сама переехала на ghcr.io/fortemate/dicechess-bot-java (имя из github.repository); старые образы остались под rabestro |
| Docs/Pages | ✅ публикуется на fortemate.github.io/dicechess-bot-java (200); ⚠️ старый URL jc.id.lv/dicechess-bot-java — 404 без редиректа (как и предсказывалось: Pages не редиректится) |
| Release workflow | ✅ ручной dispatch прошёл под новым владельцем |
| Локальная копия | ✅ remote обновлён на git@github.com:fortemate/... (SSH-схема сохранена) |
Хвосты после пилота (ручные, не блокируют):
- Перенастроить потребителя образа (хостинг, где бот запущен) с
ghcr.io/rabestro/...наghcr.io/fortemate/.... - Обновить ссылки на докс-сайт бота (
jc.id.lv/dicechess-bot-java→fortemate.github.io/dicechess-bot-java) в bots.jc.id.lv и README соседних репо. - Убедиться, что CodeRabbit и прочие Apps имеют доступ к репо в организации (инсталлы не переезжают).
- Не создавать под
rabestroрепозиторий с именемdicechess-bot-java— это убьёт редиректы.
Вывод для следующих волн: перенос простого публичного репо занимает минуты, все три «типовые грабли» (пакетная auth, ghcr-namespace, Pages-URL) ведут себя ровно как задокументировано выше. Порядок остальных волн — без изменений (§4): простые публичные → play/docs с Cloudflare Pages последними → приватные не переносить до Team.
🔗 Связанное
- brand-fortemate §8 — фазовый план миграции (эта заметка раскрывает фазу D).
- 🏷️ Раздел Fortemate.