GitLab to GitHub Migration
We are migrating all source code repositories from GitLab (publicala group) to GitHub (publicala org, Enterprise plan). This document covers motivation, scope, approach, and current state.
Why​
We think this is what we would like to be using in 6 months.
- GitHub is the standard for open-source collaboration and AI-assisted development tooling
- Better integration with our tooling like Laravel Cloud, Claude Code, Codex and others
- Accelerate adoption of agentic tooling
Scope​
- Code and history only. Migration uses
git clone --mirror/git push --mirrorto transfer all branches, tags, and commit history. GitLab remains read-only as an archive for historical merge request references. - Not migrated: GitLab issues, merge requests, wiki pages, snippets, or CI/CD variables (secrets are re-created manually in GitHub).
- Archived repos excluded. The 76 archived repositories on GitLab are not migrated. GitLab remains as the reference for those.
Current State​
| Metric | Count |
|---|---|
| Total GitLab repos | 110 |
| Already archived | 76 |
| Active repos | 34 |
| Active repos with CI | 18 |
| Active repos without CI | 16 |
| Already on GitHub | 3 |
Already on GitHub​
| Repo | GitHub Location |
|---|---|
| publicalanewwebsite | publicala/publicalanewwebsite |
| claude-md-guide | publicala/claude-md-guide |
| publicanow | publicala/publicanow |
GitHub Org​
- Organization:
publicala(Enterprise Cloud, via GitHub for Startups grant) - Seats: 6 active members, 13 pending invitations. Seats auto-expand on Enterprise Cloud (usage-based billing); no manual increase needed
- Existing repos: 11
- Team: See Team Members checklist for invitation status. Invite to the Organization, not the Enterprise; Enterprise seats follow automatically.
Access Management​
Add a new team member: invite to the org, then add to Core Team:
gh api /orgs/publicala/teams/core-team/memberships/USERNAME -X PUT -f role=member
Grant Core Team access to a new repo:
gh api /orgs/publicala/teams/core-team/repos/publicala/REPO_NAME -X PUT -f permission=push
How access works (base role, Core Team, outside collaborators)
GitHub does not have GitLab's group-level role assignment (where adding someone to a group automatically grants access to all projects). Instead, access is managed through org base permissions and GitHub Teams.
- Base role:
Read(all org members can clone/pull all internal repos) - Core Team: GitHub Team (
core-team) withWritepermission. All org members who need push access should be in this team. - Outside Collaborators: Third parties (contractors, partners) are added as Outside Collaborators on specific repos, not as org members. This prevents them from inheriting the base role on all repos.
GitHub requires explicitly adding teams to each repo. When migrating a repo, always add the Core Team as part of the post-migration checklist.
GitLab Group Structure​
GitLab uses nested subgroups. GitHub is flat (no nested orgs).
publicala/ # ~90 flat repos
publicala/fenice/dep/dependencies/ # 1 repo (volpe-bundle)
publicala/fenice/dep/env/ # 12 repos (env configs, fastlane certs)
publicala/fenice/dev/ # 10 repos (app variants, monorepo)
publicala/fenice-legacy-archived/ # 3 repos (all archived)
publicala_exercises/ # 1 repo (search-inside-a-book)
Namespace Flattening​
Most repos live directly under publicala/ and map 1:1 to GitHub. The nested fenice/ subgroup repos flatten with a fenice- prefix (e.g., fenice/dev/monorepo becomes fenice-monorepo). See the Repository Inventory for per-repo mappings.
The fenice/ subgroup contains ~23 repos across three levels of nesting. Migrating them 1:1 with a fenice- prefix produces ~23 flat repos in the GitHub org (12 of which are per-tenant env configs).
The situation: GitLab subgroups provided implicit grouping and scoped permissions. GitHub has neither; naming conventions and Teams are the only tools.
Options:
- Flatten as-is with
fenice-prefix (table above). Simple, no code changes, but noisy. - Consolidate env/config repos into a single
fenice-configrepo. Reduces 12+ repos to 1. - Fold everything into the monorepo. Env configs, fastlane certs, volpe-bundle, tenant variants. Maximum consolidation.
- Hybrid: consolidate configs (option 2) now, evaluate monorepo absorption later.
To be discussed with JP before Fenice migration (Tier 5/6).
Migration Approach​
Repos transfer via git clone --mirror / git push --mirror (see Migration Guide). CI/CD translates via gh actions-importer (see CI/CD Translation Reference). Secrets are re-created manually as GitHub org/repo secrets. All repos standardize on main as default branch.
Priority Tiers​
Migration proceeds in tiers, starting with low-risk repos to validate the process before tackling critical infrastructure.
Tier 1: Pilot (validate process)​
| Repo | Rationale |
|---|---|
| docs | Simple CI, already on main, Cloudflare Pages target |
| picchio | No CI, trivial |
| claude-md-guide | No CI. Done (transferred to org) |
Tier 2: Cloudflare Workers (simple CI)​
| Repo | Rationale |
|---|---|
| gitlab-to-slack-proxy | Simple Wrangler deploy |
| vito | Small Workers project |
| micelio | Workers with staging/production |
| publicalanewwebsite | Already on GitHub, needs CI migration |
Tier 3: Laravel Cloud + tools (moderate CI)​
| Repo | Rationale |
|---|---|
| farfalla-https-guard | Laravel Cloud deploy hooks |
| mentat | Laravel Cloud, complex CI |
| formica | Tests only, no deploy |
| delfino | npm registry migration (GitLab Packages to GitHub Packages) |
Tier 4: Core services (Vapor, complex CI, DinD)​
| Repo | Rationale |
|---|---|
| coniglio | Hybrid Cloud/Vapor |
| castoro | LFS, Vapor, custom Docker image |
| medusa | Vapor, Sentry notifications |
| farfalla-integrations | Vapor, DinD |
| farfalla | Core monolith, 18 CI jobs, Vapor DinD |
Tier 5: Complex/special​
| Repo | Rationale |
|---|---|
| volpe | LFS + Cloudflare Pages + npm publish + cross-repo validation |
| fenice | App Store/Play Store, macOS runners, Fastlane, 26 tags, subgroups |
| criceto | Playwright, GitLab Pages reports |
Tier 6: Remaining active repos​
zoo, botesito, all fenice subgroup repos, utility repos (epub2-upgrader, pdf-extractor, pdf-processing-benchmark-tool, etc.), playground, prototipi, and others with no CI.
Third-Party Runners​
GitHub-hosted runners are insufficient for two use cases: Docker-in-Docker (Vapor deploys) and macOS/iOS/Android builds (Fenice). We use Depot as a third-party runner provider.
Dashboard: https://depot.dev/orgs/20vvk4c75n/github-actions
What Depot Replaces​
| GitLab Runner Tag | Depot Equivalent | Projects |
|---|---|---|
saas-linux-medium-amd64 (DinD) | depot-ubuntu-24.04-4 | farfalla, medusa, coniglio, castoro, farfalla-integrations |
saas-linux-large-amd64 | depot-ubuntu-24.04-8 or larger | farfalla, medusa, coniglio, criceto |
saas-macos-medium-m1 | depot-macos-14 / depot-macos-15 | fenice |
Depot details (runner types, capabilities, constraints)
Why Depot:
- Full VM-based Linux runners (Docker runs natively, no DinD workarounds)
- macOS Apple Silicon runners (M2) for iOS/Android builds
- Per-second billing with no minimum (rate expressed per-minute)
- Up to 64 vCPU Linux runners
Runner Types:
| OS | Hardware | Sizes | Use Case |
|---|---|---|---|
| Linux x64 | AMD EPYC Genoa | 2-64 vCPU | Tests, Docker builds, Vapor deploys |
| Linux ARM64 | Graviton4 | 2-64 vCPU | ARM-specific builds |
| macOS | Apple M2 | 8 vCPU / 24 GB | Fenice iOS/Android builds, Detox E2E |
Constraints:
- Only native GitHub Actions functionality is used (no Depot CLI or proprietary actions)
- Workflows must remain portable; switching runner providers should only require changing
runs-onlabels - macOS runners do not support Docker (standard Apple Silicon limitation across all providers)
Post-Migration Checklist​
See Phase 3: Cross-Cutting Updates in the Migration Guide.
Tools​
| Tool | Version | Purpose |
|---|---|---|
gh | latest | GitHub CLI |
gh actions-importer | v1.3.6 | Translate .gitlab-ci.yml to GitHub Actions |
glab | latest | GitLab CLI (for archive operations) |
Related Docs​
- Repository Inventory - Catalog of all 34 active repos
- Migration Guide - Step-by-step per-repo checklist
- CI/CD Translation Reference - GitLab CI to GitHub Actions mapping
- GitLab CI Practices and Standards - Current CI patterns