A GitHub gh CLI extension to create a report containing repository
rulesets for a single repository, list of repositories, and/or organization, as well as create
repository rulesets from a file.
Note
The authenticated user must be an organization owner and a GitHub Personal Access Token needs the
admin:read scope at the organization level to use this CLI extension to it's fullest.
-
Install the
ghCLI - see the installation instructions. -
Install the extension:
gh extension install katiem0/gh-migrate-rulesets
For more information: gh extension install.
The gh-migrate-rulesets extension supports GitHub.com and GitHub Enterprise Server,
through the use of --hostname and the following commands:
$ gh migrate-rulesets -h
List and create repository/organization level rulesets for repositories in an organization.
Usage:
migrate-rules [command]
Available Commands:
create Create repository rulesets
list Generate a report of rulesets for repositories and/or organization.
Flags:
-h, --help help for migrate-rules
Use "migrate-rules [command] --help" for more information about a command.The gh migrate-rulesets list command will create a csv report of repository rulesets for the specified
<organization> and/or [repo ..] list, with the ability to specify the --host-name and
--token associated to a Server instance. If only <organization> is provided, all
repositories will be used.
To specify the type of ruleset to list, setting the --ruleType flag will either list:
all: Organization level, and repository level rulesetsrepoOnly: Repository level rulesets for list of repos or all repos under<organization>orgOnly: Organization level rulesets only
$ gh migrate-rulesets list -h
Generate a report of rulesets for a list of repositories and/or organization.
Usage:
migrate-rules list [flags] <organization> [repo ...]
Flags:
-d, --debug To debug logging
-h, --help help for list
--hostname string GitHub Enterprise Server hostname (default "github.com")
-o, --output-file string Name of file to write CSV list to (default "ruleset-20240819094546.csv")
-r, --ruleType string List rulesets for a specific application or all: {all|repoOnly|orgOnly} (default "all")
-t, --token string GitHub Personal Access Token (default "gh auth token")The output csv file contains the following information:
Click to Expand output csv file contents
| Field Name | Description |
|---|---|
RulesetLevel | Indicates whether the ruleset is at the organization or repository level. |
SourceRepositoryName | If repository level ruleset, the name of the repository where the data is extracted from. For Organization rulesets, this is N/A. |
TargetRepositoryName | The destination repository name used when creating rulesets with --from-file. Defaults to the same value as SourceRepositoryName on export; edit this column to rename the destination repository during a --from-file migration. For Organization rulesets, this is N/A. |
RuleID | Unique identifier for the rule. |
RulesetName | Name of the ruleset. |
Target | Indicates the type of ruleset, can be branch, tag, or push. |
Enforcement | Enforcement level of the ruleset (e.g., active, evaluate, or disabled). |
BypassActors | Actors who can bypass the ruleset, specified in the format ID;Role;Name;Condition. |
ConditionsRefNameInclude | Array of ref names to include in the ruleset conditions. |
ConditionsRefNameExclude | Array of ref names to exclude from the ruleset conditions. |
ConditionsRepoNameInclude | Array of repository names to include in the ruleset conditions. |
ConditionsRepoNameExclude | Array of repository names to exclude from the ruleset conditions. |
ConditionsRepoNameProtected | Indicates whether renaming of target repositories is prevented. |
ConditionRepoPropertyInclude | Array of repository properties values to include in the ruleset conditions. |
ConditionRepoPropertyExclude | Array of repository properties values to exclude from the ruleset conditions. |
RulesCreation | Only allow users with bypass permission to create matching refs. |
RulesUpdate | Only allow users with bypass permissions to delete matching refs. |
RulesDeletion | Prevent merge commits from being pushed to matching refs. |
RulesRequiredLinearHistory | Prevent merge commits from being pushed to matching refs. |
RulesMergeQueue | Merges must be performed via a merge queue. In the format check_response_timeout_minutes|grouping_strategy|max_entries_to_build|max_entries_to_merge|merge_method|min_entries_to_merge|min_entries_to_merge_wait_minutes |
RulesRequiredDeployments | Choose which environments must be successfully deployed to before refs can be pushed into a ref that matches this rule. Includes required_deployment_environments array. |
RulesRequiredSignatures | Commits pushed to matching refs must have verified signatures. |
RulesPullRequest | Require all commits be made to a non-target branch and submitted via a pull request before they can be merged. In the format DismissStaleReviewsOnPush:<bool>|RequireCodeOwnerReview:<bool>|RequireLastPushApproval:<bool>|RequiredApprovingReviewCount:<int>|RequiredReviewThreadResolution:<bool>. Optionally includes AllowedMergeMethods:[merge squash rebase] (allowed merge methods), DismissalRestriction:{Enabled=<bool>\|ActorID=<int>\|ActorType=<User\|Team\|IntegrationInstallation\|RepositoryRole>};... (restrict who can dismiss reviews), and RequiredReviewers:{FilePatterns=<space-separated globs>\|MinimumApprovals=<int>\|ReviewerID=<int>\|ReviewerType=Team};... (require review from specific teams). Note: actor and team IDs in DismissalRestriction/RequiredReviewers are exported and imported as-is; when migrating across organizations they are not remapped, so update them manually in the target org. |
RulesRequiredStatusChecks | Choose which status checks must pass before the ref is updated. An array of required status check rules, in the format do_not_enforce_on_create|required_status_checks:{context|integration}|strict_required_status_checks_policy |
RulesNonFastForward | Prevent users with push access from force pushing to refs. |
RulesCommitMessagePattern | Indicates commit message patterns and matching. In the format Name|Negate|Operator|Pattern |
RulesCommitAuthorEmailPattern | Indicates commit author email patterns and matching. In the format Name|Negate|Operator|Pattern |
RulesCommitterEmailPattern | Indicates committer email patterns and matching. In the format Name|Negate|Operator|Pattern |
RulesBranchNamePattern | Indicates branch name patterns and matching. In the format Name|Negate|Operator|Pattern |
RulesTagNamePattern | Indicates tag name patterns and matching. In the format Name|Negate|Operator|Pattern |
RulesFilePathRestriction | Prevent commits that include changes in specified file paths from being pushed to the commit graph. |
RulesFilePathLength | Prevent commits that include file paths that exceed a specified character limit from being pushed to the commit graph. |
RulesFileExtensionRestriction | Restrictions on file extensions for the ruleset. |
RulesMaxFileSize | Maximum file size allowed to be pushed to the commit. |
RulesWorkflows | Require all changes made to a targeted branch to pass the specified workflows before they can be merged. An array of workflow rules, in the format do_not_enforce_on_create|workflows:{Path|ref|repository_id|sha} |
RulesCodeScanning | Choose which tools must provide code scanning results before the reference is updated. An array of code scanning rules in the format {Tool|SecurityAlertsThreshold|AlertsThreshold} |
RulesCodeQuality | Require code quality checks to pass before the ref is updated. In the format Severity:<level>, where level is one of errors, warnings_and_higher, notes_and_higher, or all. |
RulesCopilotCodeReview | Request an automatic review from Copilot on matching pull requests. In the format ReviewDraftPullRequests:<bool>|ReviewOnPush:<bool>. |
RulesLicenseComplianceScanning | Require license compliance scanning results before the ref is updated. |
RulesCodeCoverage | Require a minimum code coverage threshold before the ref is updated. In the format MinimumCoverage:<int>|MaxCoverageDrop:<int>. |
CreatedAt | Timestamp of when the ruleset was created. |
UpdatedAt | Timestamp of when the ruleset was last updated. |
Note
Fields within multi-value columns (e.g. RulesBranchNamePattern, RulesCommitMessagePattern)
are written in a stable, alphabetically-sorted order. This keeps exports deterministic so
re-running list produces byte-identical output for unchanged rulesets, making before/after
diffs reliable.
Repository Rulesets can be created from a csv file using --from-file following the format outlined
in gh-migrate-rulesets list, or specifying the --source-org and/or
--repos to retrieve rulesets from.
Warning
If your rulesets include the following rules, ensure that the csv has been updated to point to
the updated information under your organization:
- Bypass Actors: Update Actor ID for Teams, Roles, and Integrations
- Status Checks: Ensure Context name exists and update Integration ID
- Code Scanning: Ensure Tool name exists
- Workflows: Update Repository ID to point to the correct repo/workflow
- Required Deployments: Ensure deployment names exist for the repository
$ gh migrate-rulesets create -h
Create repository rulesets at the repo and/or org level from a file or list.
Usage:
migrate-rules create [flags] <organization>
Flags:
--actor-mapping string Path and Name of CSV file mapping source bypass actor IDs to target IDs (for predefined repository roles and renamed actors)
-d, --debug To debug logging
--dry-run Preview ruleset creates without writing changes
-f, --from-file string Path and Name of CSV file to create rulesets from
-h, --help help for create
--hostname string GitHub Enterprise Server hostname (default "github.com")
-R, --repos strings List of repositories names to recreate rulesets for separated by commas (i.e. repo1,repo2,repo3)
-r, --ruleType string List rulesets for a specific application or all: {all|repoOnly|orgOnly} (default "all")
--source-hostname string GitHub Enterprise Server hostname where rulesets are copied from (default "github.com")
-s, --source-org string Name of the Source Organization to copy rulesets from
-p, --source-pat string GitHub personal access token for Source Organization (default "gh auth token")
-T, --target-repo string Rename the destination repository when migrating a single repository's rulesets
-t, --token string GitHub personal access token for organization to write to (default "gh auth token")When migrating a single repository with --source-org, use --target-repo to create the
rulesets under a different repository name (a repository rename). This is useful when the
destination repository has been renamed relative to the source. --target-repo requires exactly
one repository via --repos and cannot be combined with --from-file (a file already contains the
destination repository name).
# Rename during a single-repo migration from a source organization
$ gh migrate-rulesets create target-org --source-org source-org --repos old-repo --target-repo new-repoWhen creating rulesets with --from-file, repository renames are driven by the CSV itself. Each
repository-level row carries both a SourceRepositoryName and a TargetRepositoryName column. On
export these values are identical; edit TargetRepositoryName to create the ruleset under a
different destination repository. If TargetRepositoryName is empty, the destination defaults to
SourceRepositoryName. Files exported by earlier versions that only contain a RepositoryName
column remain supported and are treated as the source (and target) repository name.
If specifying --source-org and/or --repos, the CLI extension performs a live read from the source
organization and attempts to map each object based on name to the new ID under the target organization:
- Bypass Actors
- Teams
- Custom Repository Roles
- Integrations
- Status Checks
- Context
- Required Workflow
- Repository
This automatic name-based translation applies to the live --source-org (and optional --repos)
path and resolves the IDs called out in the warning above for teams, integrations, custom roles,
required workflow repositories, and status check integrations. The --from-file path is assumed to
already contain the correct target IDs; edit the exported csv directly before importing it.
create supports GitHub.com, GitHub Enterprise Server, and GitHub Enterprise Cloud with data
residency through --hostname and --source-hostname. Both hostname flags default to github.com;
use the target hostname with --hostname and the source hostname with --source-hostname.
Use --dry-run to log the org and repository rulesets that would be created without writing any
changes to the target:
gh migrate-rulesets create <target-org> --source-org <source-org> --dry-runWhen moving rulesets between organizations or instances, bypass actor IDs for teams, custom
repository roles, and apps often differ on the target. Use --actor-mapping to supply a csv that
maps source bypass actor IDs to their target IDs — this is required for predefined repository
roles (e.g. Write, Maintain, Admin), which cannot be resolved automatically by name. The
mapping applies only to the live --source-org path and cannot be combined with --from-file (for
file imports, set the target IDs directly in the exported csv's bypass actor column).
See docs/predefined-repository-roles.md for the mapping csv
format, a fillable template, per-platform role ID reference, and override behavior.
Note
If a bypass actor ID is not mapped and cannot be resolved automatically, the ruleset is skipped and
written to the error csv file for manual follow-up.
When the command finishes it logs a summary of how many rulesets were created successfully and how many failed, for example:
Summary: 12 ruleset(s) created successfully, 2 failed
Note
Any ruleset that fails to be created is captured and written to a csv file in the current
directory with the name format <org>-ruleset-errors-<date>.csv, containing the Source,
RulesetName, and Error. Source is where creation was attempted: for repository-level
rulesets it is in org/repo format (reflecting any --target-repo or TargetRepositoryName
rename), and for organization-level rulesets it is the organization name. This includes
per-ruleset creation failures as well as failures to fetch organization or repository rulesets
from the source (recorded with a RulesetName of N/A), so all issues are available for easy
review.