Major upgrade coming in safe-settings as part of yadhav/fix-recent-issues
I have been working on a branch which started with a stable version of safe-settings and incorporated several new features as well as reverse merged all the open PRs. In situations where reverse merge did not work, I materially incorporated those changes into the code.
These are the draft release notes for the changes on this branch relative to main-enterprise as of October 1, 2026. The umbrella PR, #990, is still open; They summarize the branch's commits and the directly merged or subsequently adapted PRs rather than treating an incorporated, still-open source PR as separately shipped.
Highlights
- Manage more settings as code. Added custom repository roles, name-based resolution of ruleset bypass actors and required reviewers, organization-scoped rulesets for suborg configurations, and external identity-provider group linking for teams. Added a reverse settings generator that creates repository, organization, or custom-property-based suborg YAML from live settings, either locally or through a PR-opening dispatch flow. (#990, #1071, #994)
- Manage GitHub App repository access. The new
app_installations plugin declares which repositories other apps can access at the org, suborg, or repo layer. Incremental sync responds to config changes; scheduled/manual full sync reconciles drift. Enterprise installation and permission are required. (#1012)
- Control policy ownership.
disable_plugins disables selected plugins at configuration layers; org-level additive_plugins prevents supported plugins from removing unmanaged entries. custom_properties.include/exclude lets operators preserve selected unmanaged property values without suppressing all removals. Team include/exclude repository filters are now schema-valid and documented. (#990, #1038, #1092; adapted from #1009 and #1036)
- Make configuration changes safer to review. Multi-file push/PR changes are batched and deduplicated. Dry-run results report affected subjects and paginated details; an optional
PR_COMMENT_SUMMARY_ENABLED=true adds operation-wide errors, affected plugins, a check-run link when available, and a descriptive review checkbox to each comment page. The default remains unchanged. (#888, #989, #1100)
Reliability and correctness
- Suborg membership is re-evaluated after relevant repository changes; changing or removing suborg targeting also cleans up settings on repositories that no longer match. Single-repository events now resolve team/property membership against that repository rather than scanning every suborg repository. (#990, #1006, #1069; the latter incorporates #1031)
- Full sync processes all repository-owning App installations rather than just the first.
GH_ORG can restrict CLI/cron full sync to one account; a missing match fails instead of silently selecting another. Repository processing is limited to batches of ten, retaining per-repository errors while continuing other work. (#1094, #1095, #1087; adapted from #1044, #1053, and #1029)
- Archived repositories are skipped without issuing child-plugin writes unless configuration explicitly requests unarchiving. Repository configuration is no longer shared mutably across concurrent repositories. (#991, #1099, #943)
- Ruleset comparisons now resolve
{{EXTERNALLY_DEFINED}} values before diffing, preserve consistent array-shaped changes, and converge bypass actors whose IDs GitHub does not use. Branch dry runs retain distinct operations instead of duplicating or discarding results; team comparisons use slugs rather than display names. (#1048, #1090, #1091, #1085, #1098; adapted from #1023, #1030, #1035, #1027, and #1070)
- Repository and environment Actions variables are read across all API pages. Full-sync dry runs no longer require webhook-only check-run fields. Configuration read failures remain visible rather than being masked, with new regression coverage. (#1093, #1047, #1096; adapted from #1042, #1018, and #1052)
- Security-manager teams use the organization roles API and are protected from ordinary team-config changes; external-group matching handles case differences and provisioning delays. Applied changes are logged at info level. Repository default-branch creation is available behind
CREATE_DEFAULT_BRANCH=true, leaving the previous default branch intact instead of renaming it. (#1045, #1016, #1068, #1010, #1021)
Configuration, runtime, and testing
- Node.js 22 is now the minimum runtime (
engines.node >=22); CI covers Node 22 and 24, and the Docker image and release workflows use Node 22. Probot is upgraded to 14.3.2 and REST calls use Octokit's .rest namespace. Review existing runtimes, build environments, and integrations before deploying. (#939, #1049, #949)
- Configuration schemas now cover nullable fields, repository and scoped rulesets, team filters, and newer GitHub API fields.
js-yaml empty documents and custom properties authored with property_name are handled correctly. (#1084, #1066, #978; schema work adapts #1025)
- The Probot 14 integration suite runs under
node:test in CI alongside the Jest unit suite; transport regressions and opt-in live smoke phases cover installations, archived repositories, pagination, team slugs, and rendered PR comments. The comment-markup change adds coverage without restoring obsolete HTML reporting. (#1097, #1101; adapted from #1078)
- Dependency and build maintenance includes patched lodash, updated
js-yaml and other direct/transitive packages, pinned Docker images, reproducible npm ci workflows, proxy support, and an optional Helm priorityClassName. (#992, #1050, #1064, #957, #958, #917, #1004, #1056)
Thank you, contributors
Thank you to everyone whose PRs helped shape these changes, including the authors of fixes and features adapted into this branch. I appreciate the time, care, and expertise you have shared with safe-settings.
| Contributor |
PRs |
| @avelizmu |
#1031 |
| @cdav |
#1042 |
| @DeepDiver1975 |
#1052, #1053 |
| @John15321 |
#943 |
| @jordonpeterson |
#1036 |
| @madkoo |
#989, #991, #1010 |
| @neatcoder |
#1009 |
| @rafaelleonardocruz |
#1044 |
| @roryharness |
#1029 |
| @StephHope |
#1070 |
| @tdabasinskas |
#1018, #1021, #1023, #1025, #1027, #1030, #1035 |
| @TovaBecker |
#1078 |
| @tylerohlsen |
#917 |
| @vish-dawange |
#1016, #1071 |
Major upgrade coming in
safe-settingsas part ofyadhav/fix-recent-issuesI have been working on a branch which started with a stable version of
safe-settingsand incorporated several new features as well as reverse merged all the open PRs. In situations where reverse merge did not work, I materially incorporated those changes into the code.These are the draft release notes for the changes on this branch relative to
main-enterpriseas of October 1, 2026. The umbrella PR, #990, is still open; They summarize the branch's commits and the directly merged or subsequently adapted PRs rather than treating an incorporated, still-open source PR as separately shipped.Highlights
app_installationsplugin declares which repositories other apps can access at the org, suborg, or repo layer. Incremental sync responds to config changes; scheduled/manual full sync reconciles drift. Enterprise installation and permission are required. (#1012)disable_pluginsdisables selected plugins at configuration layers; org-leveladditive_pluginsprevents supported plugins from removing unmanaged entries.custom_properties.include/excludelets operators preserve selected unmanaged property values without suppressing all removals. Teaminclude/excluderepository filters are now schema-valid and documented. (#990, #1038, #1092; adapted from #1009 and #1036)PR_COMMENT_SUMMARY_ENABLED=trueadds operation-wide errors, affected plugins, a check-run link when available, and a descriptive review checkbox to each comment page. The default remains unchanged. (#888, #989, #1100)Reliability and correctness
GH_ORGcan restrict CLI/cron full sync to one account; a missing match fails instead of silently selecting another. Repository processing is limited to batches of ten, retaining per-repository errors while continuing other work. (#1094, #1095, #1087; adapted from #1044, #1053, and #1029){{EXTERNALLY_DEFINED}}values before diffing, preserve consistent array-shaped changes, and converge bypass actors whose IDs GitHub does not use. Branch dry runs retain distinct operations instead of duplicating or discarding results; team comparisons use slugs rather than display names. (#1048, #1090, #1091, #1085, #1098; adapted from #1023, #1030, #1035, #1027, and #1070)CREATE_DEFAULT_BRANCH=true, leaving the previous default branch intact instead of renaming it. (#1045, #1016, #1068, #1010, #1021)Configuration, runtime, and testing
engines.node >=22); CI covers Node 22 and 24, and the Docker image and release workflows use Node 22. Probot is upgraded to 14.3.2 and REST calls use Octokit's.restnamespace. Review existing runtimes, build environments, and integrations before deploying. (#939, #1049, #949)js-yamlempty documents and custom properties authored withproperty_nameare handled correctly. (#1084, #1066, #978; schema work adapts #1025)node:testin CI alongside the Jest unit suite; transport regressions and opt-in live smoke phases cover installations, archived repositories, pagination, team slugs, and rendered PR comments. The comment-markup change adds coverage without restoring obsolete HTML reporting. (#1097, #1101; adapted from #1078)js-yamland other direct/transitive packages, pinned Docker images, reproduciblenpm ciworkflows, proxy support, and an optional HelmpriorityClassName. (#992, #1050, #1064, #957, #958, #917, #1004, #1056)Thank you, contributors
Thank you to everyone whose PRs helped shape these changes, including the authors of fixes and features adapted into this branch. I appreciate the time, care, and expertise you have shared with safe-settings.