Skip to content

Migrate governance intent from devantler-tech/maintenance into .github (declarative) and retire the maintenance repo #84

Description

@devantler

🤖 Generated by the Daily AI Assistant

Problem

devantler-tech/maintenance is a custom
Bun/TypeScript CLI toolset that runs three cron governance reports and surfaces violations as
GitHub issues:

Report Policy it checks Schedule
repos-with-no-team every non-archived repo has ≥1 team Wed 09:00 UTC
repos-with-no-admin-team every non-archived repo has an admin team Tue 09:00 UTC
repos-with-multi-admin-teams each repo has exactly one admin team Mon 09:00 UTC

Its own README already declares: "TO BE DEPRECATED. WILL BE MERGED INTO devantler-tech/.github as a
single source of truth for this org's governance, administration and configuration."
This issue
tracks that migration and the follow-up removal — and proposes a less-custom target state.

Key observation — these reports detect drift this repo already prevents

devantler-tech/.github already manages the org declaratively via Crossplane in deploy/:
deploy/team-repositories/grant-maintainers-on-<repo>.yaml (team↔repo admin grants),
deploy/repositories/* (Repository CRs), deploy/teams/*, and 12 deploy/organization-rulesets/*.
Because that layer is Observe-first and reverts out-of-band changes, the three "violation" states
the maintenance repo hunts for are prevented by construction once every repo has its
grant-maintainers-on-* grant: a repo can't be team-less, admin-team-less, or multi-admin-team if its
single admin grant is declared and drift is auto-reverted. The custom app is largely re-detecting
what the source-of-truth should already guarantee.

What of importance to migrate

Migrate the governance intent, not the bespoke app:

  1. The policy invariant — "every non-archived repo has exactly one admin team (maintainers), and
    no team-less repos" — codified as the declarative rule it already is: ensure a
    deploy/team-repositories/grant-maintainers-on-<repo>.yaml exists for every live non-archived
    repo (audit the current set for gaps and backfill).
  2. The one genuinely-useful residual check — a NEW repo created before it's added to deploy/
    wouldn't be caught by Crossplane. Replace the three Bun reports with one thin CI check in
    .github
    : assert every live non-archived org repo appears in deploy/team-repositories/ with
    exactly one admin grant (a small script or a kustomize build + policy check, run on schedule),
    filing an issue only on a genuine gap. This preserves the safety net without the custom app's
    scaffolding (caching layer, per-report orchestration, Octokit wrappers, Bun toolchain).
  3. Drop the rest as standard/no-value-to-migrate: the Bun/ESLint/Prettier toolchain, the
    three-layer report architecture, the coding-convention AGENTS.md, dependabot/ci scaffolding.

Consider less-custom ways to maintain compliance & policy (the ask)

Prefer prevent-by-declaration + industry-standard enforcement over custom detection:

  • Crossplane declarative team/repo grants (already here) — the primary answer. Complete the
    team-repositories coverage so the three drift states are structurally impossible; this deletes most
    of the custom code's reason to exist.
  • OpenSSF Allstar — a maintained GitHub App that continuously
    enforces org security policies (branch protection, outside collaborators, binary artifacts,
    dangerous workflow, SECURITY.md) and files issues on violations — the standard, non-custom version
    of "surface violations as issues" for the security dimension.
  • OpenSSF Scorecard (scorecard-action) — scores each repo on
    security best practices; complements Allstar.
  • Org & repository rulesets + repository custom properties — already have 12 org rulesets; use
    custom properties to target rulesets by repo class instead of per-repo config, further shrinking
    bespoke pieces.
  • GitHub org-level settings — org-default branch protections, org-wide Dependabot/secret-scanning/
    push-protection defaults, and .github community-health defaults (SECURITY.md, issue templates)
    cover policy that needs no custom code.

Net: the org keeps one source of truth (.github/deploy/, Crossplane) for administration/config,
a thin scheduled completeness check for the team-assignment safety net, and off-the-shelf
OpenSSF tooling
for security-policy enforcement — replacing a standalone custom repo.

Removal (afterwards — only once migration is verified)

  1. Land the migration above and confirm the completeness check runs green in .github.
  2. Remove the maintenance repo declaratively: delete deploy/repositories/maintenance.yaml,
    deploy/labels/maintenance.yaml, and any team-repositories/ruleset entries scoped to it — do not
    gh repo delete imperatively (the org is Crossplane-managed; deletion of the Repository CR is the
    declarative removal). Archive first, verify nothing references it, then the maintainer performs the
    irreversible delete (repo deletion cannot be undone).
  3. Drop the three cron report workflows (they live in the maintenance repo and go away with it).

Acceptance criteria

  • Every live non-archived org repo has a deploy/team-repositories/grant-maintainers-on-* grant (gaps backfilled).
  • A single scheduled completeness check in .github replaces the three Bun reports (issue-on-gap).
  • A decision recorded on the OpenSSF Allstar/Scorecard option (adopt or explicitly decline, with reasoning).
  • maintenance archived, then removed declaratively (Repository CR + labels + refs); maintainer executes the final delete.

Size

M–L — the declarative backfill + thin CI check is modest; the Allstar/Scorecard evaluation and the
archive→remove sequencing are the longer tail. Decompose into: (a) audit+backfill team-repositories,
(b) completeness check, (c) OpenSSF-tooling decision, (d) archive+remove.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions