Skip to main content

GitLab to GitHub Migration Guide

Step-by-step checklist for migrating repositories from GitLab to GitHub. Each repo follows the same per-repo process; cross-cutting tasks are handled once after all repos are moved.

For full repo details, see the Repository Inventory. For CI translation patterns, see the CI/CD Translation Reference.

Naming Convention​

GitHub repos use flat namespace. For nested GitLab subgroup repos:

GitLab PatternGitHub Pattern
publicala/<name><name> (as-is)
publicala/fenice/dev/<name>fenice-<name>
publicala/fenice/dep/env/<name>fenice-<name>
publicala/fenice/dep/dependencies/<name>fenice-<name>
publicala/fenice-legacy-archived/<name><name> (already prefixed)
publicala_exercises/<name><name>

Phase 1: Setup (one-time)​

Tools​

  • Install GitHub CLI: brew install gh
  • Install Actions Importer: gh extension install github/gh-actions-importer
  • Verify: gh actions-importer version (expect v1.3.6+)
  • Authenticate: gh auth login with org admin access
  • Configure Actions Importer: gh actions-importer configure (set GitLab instance URL, tokens)

Organization Settings​

  • Review publicala org settings on GitHub
  • Configure default repository permissions (read for members)
  • Create branch protection rule template for main:
    • Require pull request reviews (1 approval)
    • Require status checks to pass
    • Require branches to be up to date
    • No force pushes
  • Set up org-level secrets for shared values:
    • SENTRY_AUTH_TOKEN
    • CLOUDFLARE_API_TOKEN
    • LARAVEL_CLOUD_* deploy hooks (per-repo)
    • NPM_TOKEN (for GitHub Packages, if needed)

Team Members​

Invite all team members to the publicala GitHub Organization (not the Enterprise account directly). Organization membership grants repo access via teams and roles; Enterprise seats are consumed automatically when a member joins an org under it.

  • Invite the following members via GitHub API (completed 2026-03-18). Enterprise Cloud licenses were manually increased from 7 to 20 before sending invitations:
NameEmail
Martín Alejandro Pazapaz@publica.la
Juan Pablo Locatellijplocatelli@publica.la
Valentina Rojasvrojas@publica.la
Gonzalo Parragparra@publica.la
Augusto Ruclearucle@publica.la
Kijam Lópezklopez@publica.la
Nicolás Parolanparola@publica.la
Cecilia Salemecsaleme@publica.la
Nicolás Cabal Cullenncabal@publica.la
Anabella Pippoapippo@publica.la
Agustín Acevedoaacevedo@publica.la
José Luis Tanicuchíjtanicuchi@publica.la
Lara Macarena Sastrelsastre@publica.la
Lucca Costa Leandrolcosta@publica.la
Francisco Laurinoflaurino@publica.la
  • Assign org role: Member for all (Owners: Franco, Nicolas F already set)
  • Created Core Team GitHub Team with Write access (2026-03-24). All org members added. See Access Management for usage.
  • Verify all members have accepted invitations
  • Clean up duplicate account: Ignacio Milano has both igmilano and imilano-pla

Tracking Invitation Acceptance​

# List pending invitations (decreases as members accept)
gh api /orgs/publicala/invitations --jq '.[] | {email: .email, role: .role}'

# Count remaining pending
gh api /orgs/publicala/invitations --jq 'length'

# List current org members
gh api /orgs/publicala/members --jq '.[].login'

Third-Party Runners (Depot)​

  • Sign up for Depot Startup plan
  • Connect GitHub org to Depot
  • Configure runner labels in workflows
  • Test with a pilot repo before Tier 4

Phase 2: Per-Repo Migration Checklist​

Repeat for each repository. Copy this checklist as a template.

2.1 Mirror the Repository​

Commands: clone, create, push
# Clone all refs from GitLab
git clone --mirror git@gitlab.com:publicala/<repo>.git
cd <repo>.git

# For LFS repos (castoro, volpe): fetch LFS objects
git lfs fetch --all

# Create the GitHub repo
gh repo create publicala/<github-name> --private --confirm

# Push everything to GitHub
git push --mirror git@github.com:publicala/<github-name>.git

# For LFS repos: push LFS objects
git lfs push --all git@github.com:publicala/<github-name>.git

2.2 Rename Default Branch to main​

Skip if already on main. For repos on master, production, or other branches.

Commands: rename branch
# On GitHub (after mirror push)
gh api repos/publicala/<github-name> -X PATCH -f default_branch=main

# Or via git
git clone git@github.com:publicala/<github-name>.git
cd <github-name>
git branch -m master main
git push -u origin main
git push origin --delete master

Update the default branch in GitHub repo settings.

2.3 Verify the Mirror​

  • Compare branch count: GitLab vs GitHub
  • Compare tag count: GitLab vs GitHub
  • Verify latest commit SHA matches on default branch
  • For LFS repos: verify LFS objects are accessible (git lfs ls-files)

2.4 Migrate CI/CD (repos with .gitlab-ci.yml)​

Commands: actions-importer dry-run
# Dry-run: preview the translation
gh actions-importer dry-run gitlab \
--output-dir output/<repo> \
--namespace publicala \
--project <repo>

# Review the generated workflow files in output/<repo>/.github/workflows/
# Manually adjust as needed (see CI/CD Translation Reference)

Common adjustments after dry-run:

  • Replace services: [docker:dind] with appropriate Docker setup
  • Replace GitLab-specific variables (CI_JOB_TOKEN, CI_REGISTRY, etc.)
  • Convert resource_group: to concurrency: groups
  • Replace when: manual with workflow_dispatch or environment protection rules
  • Update cache configuration (GitLab cache: to actions/cache)
  • Replace GitLab Pages deployment with Cloudflare Pages or GitHub Pages action
  • Update Sentry release/deploy notification commands

Commit the workflow files to .github/workflows/ in the repo.

2.5 Configure Secrets​

  • Copy CI/CD variables from GitLab to GitHub Secrets
  • Use org-level secrets where possible
  • Verify secret names match workflow references

2.6 Set Branch Protection​

  • Apply branch protection rules to main
  • Configure required status checks (match CI job names)
  • Enable auto-delete head branches (automatically deletes the PR source branch after merge)

2.7 Update Deploy Integrations​

warning

Laravel Cloud deploy hooks are async. The curl returns immediately; deployment happens in the background. Remove any post-deploy health check scripts that expect the deploy to be done.

Per-target deploy integration steps

Laravel Cloud:

  • Update Laravel Cloud environment to connect to GitHub repo
  • Regenerate deploy hook URLs if needed
  • Update LARAVEL_CLOUD_*_DEPLOY_HOOK secrets

Laravel Vapor:

  • Continue using deploy hooks from GitHub Actions (Vapor does not support GitHub as a source)

Cloudflare Workers/Pages:

  • Update Cloudflare Pages project to connect to GitHub repo (if using Cloudflare Git integration)
  • Or keep Wrangler CLI deploy from GitHub Actions

npm Registry (Delfino):

  • Configure GitHub Packages authentication in workflow
  • Update publishConfig in package.json to point to GitHub Packages
  • Update consumer repos to pull from new registry

2.8 Verify End-to-End​

  • Push a test commit to a feature branch
  • Verify CI runs successfully
  • Create and merge a PR
  • Verify deployment triggers correctly (if applicable)

2.9 Update Local Development​

  • Update remote URL: git remote set-url origin git@github.com:publicala/<github-name>.git
  • Verify git pull and git push work

2.10 Archive on GitLab​

  • Mark the GitLab repo as archived (read-only)
  • Add a note to the GitLab repo description: Migrated to GitHub: github.com/publicala/<github-name>

Phase 3: Cross-Cutting Updates​

After all repos (or a significant batch) are migrated:

Laravel Cloud
  • Reconnect all Laravel Cloud environments to GitHub repos
  • Verify deploy hooks trigger from GitHub Actions
  • Test staging and production deploys for each Cloud service
Sentry
  • Update Sentry project integrations to watch GitHub repos
  • Update deploy notification webhooks in GitHub Actions
  • Verify source map uploads reference correct repo
Local Development (zoo)
  • Update zoo/ docker-compose files to reference GitHub remotes
  • Update any git clone/pull scripts in zoo
  • Update developer onboarding documentation
  • Notify team to update local clones (see step 2.9)
npm Registry (Delfino)
  • Publish @publicala/delfino to GitHub Packages
  • Update all consumer repos (farfalla, volpe, etc.) to pull from GitHub Packages
  • Verify npm install / yarn install resolves correctly
  • Remove GitLab Packages publishing from old CI
Documentation Hosting
  • Reconnect Cloudflare Pages docs project to use GitHub as source (currently connected to GitLab)
  • Set up Cloudflare Pages project for criceto test reports
  • Remove GitLab Pages configuration
Notifications
  • Evaluate if gitlab-to-slack-proxy is still needed
  • Set up GitHub native Slack integration for the publicala org
  • Configure notification channels per repo/event type
Cleanup
  • Verify all 34 active repos are on GitHub and functional
  • Verify all GitLab repos are archived
  • Update CLAUDE.md files across all projects
  • Update this migration documentation with final status
  • Remove GitLab-specific tooling and scripts (glab, GitLab tokens in CI)
X

Graph View