Skip to content

feat: adopt safe-settings for repository configuration management#114

Open
marcusburghardt wants to merge 5 commits into
complytime:mainfrom
marcusburghardt:opsx/adopt-safe-settings
Open

feat: adopt safe-settings for repository configuration management#114
marcusburghardt wants to merge 5 commits into
complytime:mainfrom
marcusburghardt:opsx/adopt-safe-settings

Conversation

@marcusburghardt
Copy link
Copy Markdown
Member

@marcusburghardt marcusburghardt commented May 27, 2026

Summary

Adopt github/safe-settings as a complementary tool to peribolos for managing the complytime GitHub org. Peribolos continues to own org membership, teams, and team-to-repo permissions. Safe-settings manages repository settings, rulesets, branch protection, and security configurations via GitOps.

What's included

  • OpenSpec change proposal (openspec/changes/adopt-safe-settings/): design with 10 decisions, 7 specs, phased task list
  • Safe-settings configuration (safe-settings/): org-wide defaults, two rulesets (safe-settings: code repos and safe-settings: non-code repos), complyctl 2-approver override, deployment settings with override validators. Derived from auditing the current GitHub state of all repos.
  • GitHub Actions workflow (safe_settings_sync.yml): workflow_dispatch only with dry-run (default true) and repos (optional filter) inputs
  • Boundary tests (config/boundary_test.go): 5 Go tests validating cross-tool consistency between peribolos and safe-settings
  • Documentation: MAINTAINING.md (tool boundary, workflows, troubleshooting), README.md link, CODEOWNERS path rule, Makefile targets

Related Issues

  • OpenSpec change: openspec/changes/adopt-safe-settings/

Design Note: workflow_dispatch-only Initial Rollout

safe-settings is a GitHub App (Probot-based) that reads its configuration from the admin repo's default branch via the GitHub API, not from the local filesystem. This is an architectural constraint: the ConfigManager fetches settings.yml, suborgs/, and repos/ through octokit.repos.getContent(), and the full-sync entry point (syncInstallation) does not accept a branch ref parameter.

This means:

  • Config must be merged to main before safe-settings can read and apply it
  • There is no local dry-run capability against local config files
  • There is no built-in CONFIG_REF or similar env var to point at a feature branch

Given these constraints, the workflow starts with workflow_dispatch only (no push or schedule triggers) so that after merge:

  1. Admins dry-run against a single repo first (repos=complytime-demos, dry-run=true)
  2. Apply to that single repo (dry-run=false) and verify in the GitHub UI
  3. Expand progressively to more repos
  4. Only after full validation, enable push and schedule triggers in a follow-up PR

The repos input dynamically generates a scoped deployment-settings.yml at workflow runtime, restricting safe-settings to only the specified repositories.

Review Hints

  • Review commits in sequence, each builds on the previous:

    1. docs: spec proposal (design decisions, specs, tasks)
    2. feat: safe-settings YAML config (settings, rulesets, suborgs)
    3. fix: spec review findings (alignment fixes)
    4. feat: implementation (workflow, tests, docs, Makefile)
    5. fix: org admin permission correction (feedback from @sonupreetam)
  • After merge, test with: Actions > "Safe Settings Sync" > Run workflow > dry-run=true, repos=complytime-demos

  • Boundary tests validate cross-tool consistency locally with no credentials needed: make test-unit

  • Full local validation: make sanity

  • Prerequisites already completed: GitHub App registered (ID: 3796583), credentials stored, "verifiy" ruleset renamed to "verify".

@marcusburghardt
Copy link
Copy Markdown
Member Author

@sonupreetam it would be great to have your eyes on this PR since you also researched about alternative solutions. WDYT?

@sonupreetam
Copy link
Copy Markdown
Contributor

@marcusburghardt This looks good to me, thank you for tagging me on this. The org-level rulesets from settings.yml close the enforcement gap I was worried about (repo admins can't delete them).

Previously, I had evaluated repository-settings-action (rejected legacy branch protection API only, per-repo model, doesn't support rulesets), looked at org-level rulesets via direct gh api scripts, and had a phased rollout plan sketched out (central YAML → reconciliation script → Enterprise org-level rulesets for immutability). safe-settings lands in a similar place architecturally but with a maintained engine instead of a custom script, which I think is the right trade-off.

I noticed while briefly reviewing:

  • App permissions: The design doc says Organization Administration: read, but creating org-level rulesets (which is what settings.yml rulesets do via POST ) might require write. May be docs could be stale.

Happy to discuss further or put the formal review on the PR whenever you're ready.

marcusburghardt added a commit to marcusburghardt/complytime.github that referenced this pull request May 28, 2026
Creating org-level rulesets via POST /orgs/{org}/rulesets requires
Organization Administration: write, not read. Update design doc,
deployment spec, and task list to reflect the correct permission.

Addresses PR complytime#114 review feedback from @sonupreetam.

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
@marcusburghardt
Copy link
Copy Markdown
Member Author

Good catch. Creating org-level rulesets via POST /orgs/{org}/rulesets requires Organization Administration: write, not read. Updated the design doc, deployment spec, and task list in 1566739. The GitHub App permissions should also be updated to match — will verify before the first workflow run.

marcusburghardt added a commit to marcusburghardt/complytime.github that referenced this pull request May 28, 2026
Creating org-level rulesets via POST /orgs/{org}/rulesets requires
Organization Administration: write, not read. Update design doc,
deployment spec, and task list to reflect the correct permission.

Addresses PR complytime#114 review feedback from @sonupreetam.

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
@marcusburghardt marcusburghardt force-pushed the opsx/adopt-safe-settings branch from 1566739 to 22f017c Compare May 28, 2026 12:13
@marcusburghardt marcusburghardt marked this pull request as ready for review May 28, 2026 12:29
@marcusburghardt
Copy link
Copy Markdown
Member Author

@jpower432 and @jflowers , I would appreciate your reviews on this. I plan a gradual adoption, starting manually until a few (less critical) repositories are well tested then move to fully automated. This should reduce the maintenance burden while allowing a centralized and transparent enforcement of our relevant settings.

marcusburghardt added a commit to marcusburghardt/complytime.github that referenced this pull request May 28, 2026
Creating org-level rulesets via POST /orgs/{org}/rulesets requires
Organization Administration: write, not read. Update design doc,
deployment spec, and task list to reflect the correct permission.

Addresses PR complytime#114 review feedback from @sonupreetam.

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
@marcusburghardt marcusburghardt force-pushed the opsx/adopt-safe-settings branch from 22f017c to 974bfda Compare May 28, 2026 12:42
@marcusburghardt
Copy link
Copy Markdown
Member Author

Just rebased using GH interface.

Define proposal, design, specs, and tasks for adopting github/safe-settings
as a complementary tool to peribolos. safe-settings will manage repository
settings (auto-merge, delete-branch-on-merge), branch protection rules,
rulesets, and security configurations via GitOps. Peribolos continues to
own org membership, team creation, and team-to-repo permissions.

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
Org-wide defaults, rulesets, and deployment config derived from auditing
the current GitHub state of all complytime repos.

Key decisions:
- Code repos ruleset with 1 approver, stale review dismissal, code
  owner review, last push approval
- Non-code repos ruleset with lighter protection (1 approver only)
- complyctl override requiring 2 approvers
- Override validator prevents lowering approver count below org default
- .github repo excluded (manually managed, avoids circular dependency)
- complyscribe and gemara-content-service excluded (archived/pending)

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
Align specs with implementation decisions:
- required_signatures downgraded to SHOULD (deferred to follow-up)
- required_review_thread_resolution set to false (matches current state)
- Removed archived repos from spec and config repo lists

Harden deployment and boundary specs:
- Pinned commit SHA, workflow timeout, YAML pre-validation
- Suborg/ruleset repo list synchronization requirement
- Override validator falsy-0 bypass fix
- Phases reordered: boundary tests before apply

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
Workflow (workflow_dispatch only, push/schedule added after validation):
- Inputs: dry-run (default true), repos (optional comma-separated filter)
- Generates scoped deployment-settings when repos is specified
- YAML pre-validation, 15 min timeout, concurrency group

Boundary tests (config/boundary_test.go):
- Suborg repos exist in peribolos, no duplicate suborg membership
- No cross-tool field overlap, suborg/ruleset repo list sync

Makefile, docs, and spec updates:
- safe-settings-validate target, extended lint, GOTOOLCHAIN=auto
- MAINTAINING.md, README.md link, CODEOWNERS path rule
- Specs updated for workflow_dispatch-only initial rollout

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
Creating org-level rulesets via POST /orgs/{org}/rulesets requires
Organization Administration: write, not read. Update design doc,
deployment spec, and task list to reflect the correct permission.

Addresses PR complytime#114 review feedback from @sonupreetam.

Signed-off-by: Marcus Burghardt <maburgha@redhat.com>
Assisted-by: OpenCode (claude-opus-4-6)
@marcusburghardt marcusburghardt force-pushed the opsx/adopt-safe-settings branch from 974bfda to 69f1850 Compare May 29, 2026 15:11
@marcusburghardt
Copy link
Copy Markdown
Member Author

Rebased again using the GH Web Interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants