This repository includes eleven operational GitHub Actions workflows:
02 - Config-Label-SyncConfig-Reset05 - Distribute-Label-Workflow03 - Inventory-LabelsRefresh Label Test After ReviewLabel TestValidate-ConfigsReverse-Config-Label-Sync01 - Org-Label-Sync04 - Remove-Labels06 - Transfer-Labels
Label Test, Refresh Label Test After Review, and 05 - Distribute-Label-Workflow are covered in Label Test. Validate-Configs is covered in Configuration.
Use this flow when the source repository labels are the source of truth.
- Edit labels directly on the configured source repository.
- Run
Config-Label-Sync, or runOrg-Label-Syncand let it callConfig-Label-Syncfirst. - Review the generated changes to
config/labels.jsoncandconfig/deleted-labels.jsonc. - Run
Org-Label-Syncto apply the managed label set to the selected repositories.
Config-Label-Sync reads the current labels on the source repository, rewrites config/labels.jsonc, moves removed managed labels into config/deleted-labels.jsonc, validates the default-label config, and commits the config update when something changed.
Use this flow when you want to edit the managed label config directly.
- Edit
config/labels.jsonc. - Push the change to the default branch.
- Let
Validate-Configsverify the config. - Let
Reverse-Config-Label-Syncupdate the source repository labels from the config.
Reverse-Config-Label-Sync ignores bot commits so automated config updates do not trigger a reverse sync loop.
Run Org-Label-Sync manually when you want to apply the managed label set across selected repositories.
Inputs:
dry_run: preview changes without applying themdelete_missing: delete labels that are not managed byconfig/labels.jsoncdelete_github_default_labels: delete exact GitHub default labels listed inconfig/github-default-labels.jsoncrepositories: comma-separated override for the target repository listlabel_replacements: comma-separated rename map inold=new, old2=new2format
label_replacements is meant for label renames. The new label must exist in config/labels.jsonc. The old label must exist in config/deleted-labels.jsonc, or it may exist in config/github-default-labels.jsonc when delete_github_default_labels is enabled.
The workflow also checks for automatic runs every day at midnight UTC. Configure scheduled behavior in the automaticSync object in config/repository-filter.jsonc:
Set enabled to true to allow the daily run. labelReplacements uses the same old=new, old2=new2 format as the manual input. The schedule itself must be changed in .github/workflows/01-org-label-sync.yml because GitHub evaluates workflow schedules before loading repository config.
Automatic runs perform the normal full organization sync after applying the configured whitelist or blacklist. Repositories that already match remain unchanged, new repositories receive the managed labels, and label drift in existing repositories is corrected.
When changes are made, the workflow writes the changelog Markdown directly to the GitHub Actions workflow run summary. Dry runs use the same summary format and are marked as test-mode output. If the run fails after processing some repositories, the workflow still writes the accumulated changelog before failing. Workflow summaries are retained according to GitHub Actions run retention settings.
Run Remove-Labels manually when you want to remove one exact label from issues and pull requests across selected repositories.
Inputs:
dry_run: preview removals without applying themrun_on_issues: remove the label from matching issuestarget_only_closed_issues: only target closed issuesrun_on_pull_requests: remove the label from matching pull requeststarget_only_closed_pull_requests: only target closed pull requestslabel_name: exact label name to removerepositories: comma-separated override for the target repository list
Like Org-Label-Sync, changelog Markdown is written directly to the GitHub Actions workflow run summary. Dry runs use the same summary format and are marked as test-mode output. If the run fails after processing some repositories, the workflow still writes the accumulated changelog before failing.
Run Inventory-Labels manually when you want an inventory of labels currently present on selected repositories.
Inputs:
exclude_configured_labels: exclude labels whose name, color, and description exactly match a label inconfig/labels.jsonclist_similarities: append a shared-label count and a section listing exact label specs shared by two or more selected repositories, with each matching repository listed under the labelrepositories: comma-separated override for the target repository list
Inventory skips archived repositories, but keeps non-archived read-only repositories because inventory does not write to them. If the run fails after inventorying some repositories, the workflow still writes the accumulated inventory summary before failing.
Run 06 - Transfer-Labels manually to copy all label names, colors, and descriptions directly from one repository to another.
Inputs, in workflow form order:
dry_run: the first checkbox, off by default; previews the transfer in the workflow summary without modifying either repositoryoverride_existing: off by default; makes the receiving repository's labels match the source exactly, including updating matching labels and deleting any labels absent from the sourcesource_repository: starting repository, asrepo-nameorowner/repo-nametarget_repository: receiving repository, asrepo-nameorowner/repo-name
Short names use the organization in config/properties.jsonc. Full names may reference other owners when the configured token can access both repositories. The workflow uses the existing PAT or GitHub App authentication settings and needs label write access to the receiving repository.
With override unchecked, the workflow only creates labels whose names are missing from the receiving repository. Existing labels keep their current names, colors, and descriptions, including when the source has a matching name with different capitalization. With override checked, matching labels are updated in place to preserve their issue and pull request assignments. Labels absent from the source are deleted after all additions and updates succeed; deleting those labels also removes their existing assignments. An empty source deletes all receiving labels only when override is checked.
Both inputs select repositories directly, independently of the configured sync source and repository filters. The source is only read, and selecting the same repository for both inputs is rejected. Archived receiving repositories are skipped; read-only receiving repositories are skipped for live transfers but can be previewed in test mode.
Override mode stops before any changes if the receiving repository has a label named . or .., because those names cannot be safely addressed through the label API's URL path.
Transfers pause at least one second between label writes to reduce GitHub secondary rate limits. When GitHub rejects a request due to rate limiting, the workflow logs the wait and retries up to five times, honoring Retry-After and exhausted primary-limit reset headers. Retry waits start at one minute and grow exponentially; GitHub's headers can require a longer pause. A transfer creating 233 labels takes roughly four minutes plus API response time and any rate-limit waits. Permission, validation, and ambiguous network/server errors still stop the run. Rerun a partially completed transfer with the same inputs to finish the remaining changes.
The workflow uses the Org-Label-Sync changelog layout in the GitHub Actions run summary, showing the source and receiving repositories, test and override settings, starting label counts, and created, updated, deleted, and retained counts. Retained labels are existing receiving labels left unchanged. Preview changelogs are marked as test-mode output. If the transfer fails partway through, the summary records completed changes and the failure; rerunning continues from the current label state.
Run Config-Reset manually when you want to restore selected config files to their default unconfigured versions.
Inputs:
reset_deleted_labels: resetconfig/deleted-labels.jsoncto an empty deleted-label listreset_github_default_labels: resetconfig/github-default-labels.jsoncto the standard GitHub default label specsreset_labels: resetconfig/labels.jsoncto an empty managed-label listreset_label_test_workflow_config: resetconfig/label-test-workflow-config.jsoncto empty label-test rules and empty workflow distribution listsreset_repository_filter: resetconfig/repository-filter.jsoncto empty whitelist mode with automatic sync disabledconfirmation: must be exactlyCONFIRM(will fail otherwise)
reset_labels clears the managed label source of truth. The reset commit is made by github-actions[bot], so Reverse-Config-Label-Sync ignores it.