← All posts
January 15, 2026·6 min read

Planning a GitHub Enterprise to EMU Migration: The Pre-Flight Inventory That Prevents Day-One Incidents

GitHub Enterprise Managed Users migration is a one-way door. Once you move to EMU, every identity in your org is controlled by your IdP. Personal GitHub accounts are replaced with managed accounts. There's no hybrid state, no rollback, and no "we'll figure out the edge cases after we migrate."

The planning work happens before you start, or you find out about the gaps when an engineer loses access to a production repo at 2pm on a Wednesday.

We migrated 600 users and 2,300 repositories to EMU. I'm reasonably proud of how it went. The incidents we had were in categories I knew were risks but underestimated the remediation effort for. The pre-flight toolkit is what I built afterward to surface those same issues before the migration starts rather than during it.

What EMU Actually Changes

Most guides spend the first half explaining the EMU value proposition. If you're reading this, you've already decided to migrate. Here's what actually changes that most guides gloss over.

GitHub usernames become IdP-provisioned. Every user in the org gets a new managed account with a new username. Their personal GitHub account still exists, but it no longer has any relationship to your org. Any authentication tied to the personal account stops working at migration: SSH keys generated for the personal account, personal access tokens, OAuth app authorizations.

The consequence that causes the most pain: any CI/CD pipeline authenticating via a personal PAT — or using a personal account as a service account — breaks immediately after migration. The personal account is no longer a member of the org. The PAT is now invalid for org operations. If you didn't find and rotate those credentials before migration day, you're doing it under pressure with production pipelines down.

The second consequence that surprises people: GitHub Apps and OAuth apps authorized by personal accounts need to be re-authorized after migration by the managed account. Third-party integrations that relied on personal authorization need to be identified and migrated explicitly.

The Pre-Flight Inventory

The toolkit runs 4 inventory passes against your GitHub org before you touch anything.

The first pass is the repo inventory. For every repository in the org, it pulls visibility (public, private, or internal), whether the repo uses GitHub Actions, whether it has webhooks configured, and archive status. Public repos get a RED flag because EMU changes how org-level permissions interact with public repositories in ways that aren't always intuitive. Repos with Actions get an AMBER flag because those are the ones most likely to have credentials that need rotation.

The second pass is team mapping. Every team, every member count, every repo count. High-access warnings surface for anyone with org owner role — those accounts need special handling in the IdP mapping phase.

The third pass is risk flags. The CLI outputs a risk_flags.txt with specific flags: how many public repos were found, how many repos have webhooks, how many repos use Actions, and how many outside collaborators the org has.

Outside collaborators are the issue most migration guides bury in a footnote. In a standard GitHub org, outside collaborators are non-members who have been granted repo-level access. In an EMU org, the model changes. Outside collaborators lose their existing access model at migration and need to be explicitly re-invited under the EMU access framework. For a large org, that's a significant coordination effort that needs to happen before migration day, not after.

The fourth pass is Actions-specific: repos that have .github/workflows present are flagged for credential audit. That's where the PAT rotation list comes from.

The 9-Phase Runbook

The toolkit generates a sequenced migration runbook automatically based on your inventory results. The 9 phases are:

Phase 1 is pre-flight — the risk flags output from the inventory, surfaced as the first section so nothing is buried.

Phase 2 is EMU org setup: create the EMU organization, configure SAML SSO and SCIM provisioning, run pilot users through the authentication flow before touching anyone else.

Phase 3 is repo migration for low-risk repos first. Low-risk means no Actions, no webhooks, not archived. These are the repos you migrate first to validate the process before touching the complex ones.

Phase 4 is team migration. Every team in the org, with member counts from the inventory so you know the scope before starting.

Phase 5 is webhook remediation. Repos with webhooks need webhook configurations updated or recreated post-migration because webhook secrets change at migration.

Phase 6 is Actions secrets. Every repo using GitHub Actions needs its secrets audited. Secrets tied to personal accounts need to be rotated to org-level or repo-level secrets.

Phase 7 is outside collaborator resolution. Review the outside collaborator list from the pre-flight inventory, decide who gets re-invited under the new access model, and execute before cutover.

Phase 8 is cutover and validation. Verify all access, confirm CI/CD pipelines are running, test SSO authentication end-to-end.

Phase 9 is source org decommission: archive repositories, notify teams, cancel the plan after a 30-day window.

What We Missed

The incidents we had during the 600-user migration map directly to things the toolkit would have surfaced.

The first: several legacy bot accounts that weren't in Okta. They had been created as personal GitHub accounts years earlier, granted org membership, and used for CI/CD authentication. They weren't in any IdP mapping. The toolkit's team mapping pass and outside collaborator check surfaces exactly this kind of account.

The second: multiple CI/CD pipelines that broke post-migration because they were authenticating via personal PATs. The Actions inventory pass flags every repo using GitHub Actions. We knew about most of these in first-party pipelines. The harder-to-find cases were PATs embedded in third-party integrations that weren't visible without a dedicated pre-migration audit pass. The toolkit's webhook and Actions flags are the starting point for that audit.

The third: engineers who hadn't logged into GitHub recently who didn't see the migration notification and showed up post-cutover not knowing anything had changed. The team mapping output gives you the full membership list, which is the starting point for a targeted communication plan that goes beyond a single all-hands email.


The toolkit has both a Streamlit UI for teams who want a visual interface and a Python CLI for teams who want to script the inventory pass into their migration workflow. The CLI produces inventory.csv, team_map.csv, risk_flags.txt, and migration_runbook.md in a single run.

Code and setup instructions are on GitHub. You'll need a classic PAT with repo, admin:org, and read:org scopes.