Every platform team hits the same wall: you ship an upgrade, and now twenty product repos need the same change. Chase them by hand and you spend your week nagging. Force-push into their repos and you break the one rule GitOps exists to protect. The repo is the source of truth, owned by the team.
So we built a small agent that threads the needle. When a platform release lands on main, it opens a pull request into each product team’s DevOps repo with exactly the change they need, and stops there. The team reviews and merges on their own schedule.
Desired state: proposed, not imposed
The mental model is the same reconciliation loop we use everywhere else. The platform declares a desired state; the agent computes the diff for each consumer; the pull request proposes convergence. Merge authority stays with the people who own the service.
The platform proposes. The product team disposes. Nobody wakes up to a change they didn’t approve.
What the agent actually does
- Watches platform release tags and renders the per-repo delta.
- Opens (or updates) a single PR per repo, with a clear changelog and rollback note.
- Labels and routes it to the right CODEOWNERS.
- Closes stale PRs automatically when a newer release supersedes them.
# the whole contract, roughly
on platform_release:
for repo in consumers:
diff = render(repo, release)
pr = upsert_pull_request(repo, diff)
route(pr, codeowners(repo))
Why not just automate the merge?
Because trust is the platform’s real product. The first time an auto-merge breaks someone’s prod, teams route around your platform for good. Keeping a human in the loop costs a few minutes per upgrade and buys years of goodwill.
Six months in, platform upgrades that used to take two weeks of chasing now propagate in a day, and not once have we surprised a team. That’s the whole game.