---
title: "Staying Evergreen: How we automated secure access and repo hygiene in a shared org"
description: "Managing outside collaborator access and stale repositories in a shared GitHub organization becomes harder to keep up with as projects grow. Evergreen is a GitHub App built with native GitHub features—scheduled actions, webhooks, issues, and custom properties—that automates two workflows: quarterly outside collaborator access reviews and stale repository detection and archival. Its design principles are fail secure, revoking access if no one responds, and never destroy anything, keeping archived repos recoverable and every change tracked in issues. The app is a Go webhook server that stores state as JSON files in a controller repo, using git history as the audit trail, and interacts via checklist issues in each repository. Rollout included dry-run mode, overcommunication, Splunk observability, and proactive rate-limit pacing; the pattern is adaptable using native GitHub features."
---

# Staying Evergreen: How we automated secure access and repo hygiene in a shared org

[Github](https://yomu.fyi/company/github) · Greg Mohler · Oct 15, 2026

**Type:** Problem & solution

## Summary

Managing outside collaborator access and stale repositories in a shared GitHub organization becomes harder to keep up with as projects grow. Evergreen is a GitHub App built with native GitHub features—scheduled actions, webhooks, issues, and custom properties—that automates two workflows: quarterly outside collaborator access reviews and stale repository detection and archival. Its design principles are fail secure, revoking access if no one responds, and never destroy anything, keeping archived repos recoverable and every change tracked in issues. The app is a Go webhook server that stores state as JSON files in a controller repo, using git history as the audit trail, and interacts via checklist issues in each repository. Rollout included dry-run mode, overcommunication, Splunk observability, and proactive rate-limit pacing; the pattern is adaptable using native GitHub features.

## Context

In a shared GitHub organization where GitHub employees (Hubbers) collaborate with customers and partners on product trials and professional services, manually tracking outside collaborator access and stale repositories became unsustainable as the org grew to 1,400+ Hubbers and many external collaborators. Repository owners needed to confirm who still needed access, change permissions as projects evolved, and archive repos after use, but this manual housekeeping was easy to defer. The goal was to automate these hygiene tasks securely and considerately, using native GitHub features rather than external tools.

## Approach / What changed

Evergreen is a Go webhook server running as a GitHub App. A controller repo holds four scheduled GitHub Actions workflows that fire repository\_dispatch events quarterly: stale repo review, access review, stale cleanup, and access cleanup. It opens checklist issues in each repo; when closed, it reads checkboxes and revokes unchecked collaborators. State is stored as JSON files committed to the controller repo, making git history the audit trail. The app fails secure: no response revokes all; if any removal fails, the review stays pending. It respects GitHub’s rate limits by batching and pacing content-creating calls.

## Takeaways

- Evergreen uses a controller repo with scheduled GitHub Actions to trigger repository\_dispatch events on a quarterly cadence for access reviews and stale repo cleanup.
- State is stored as JSON files committed to the controller repo, making git history the audit trail; no separate database is needed.
- The app fails closed: if any collaborator removal fails due to API error, the review stays pending and retries on the next run, ensuring consistency.

## FAQ

### How does Evergreen determine who to notify for an access review?

Evergreen uses a fallback chain: first checks a custom property \`evergreen\_repo\_owner\` (a @user or @org/team), then looks at recent issue and commit authors who are on the access review team (Hubbers). This avoids maintaining a separate ownership spreadsheet.

### What happens if an unauthorized person closes an access review issue?

Evergreen listens for the issues.closed webhook event. If the person who closed the issue is not a Hubber, the app quietly reopens the issue and posts a note explaining why. Only decisions from authorized Hubbers are accepted.

### How does Evergreen handle GitHub's rate limits when opening issues across many repos?

It processes repos in batches, spaces out each content-creating call by a couple of seconds, and sleeps between batches to let the rolling window clear. It only counts repos that actually create content, so quiet quarters run fast.

**Tags:** [Automation](https://yomu.fyi/topic/automation), [GitHub](https://yomu.fyi/topic/github), [GitHub Actions](https://yomu.fyi/topic/github-actions), [IAM](https://yomu.fyi/topic/iam), [Security](https://yomu.fyi/topic/security)

- Source: [Github](https://github.blog/engineering/platform-security/staying-evergreen-how-we-automated-secure-access-and-repo-hygiene-in-a-shared-org)
- Source URL: https://github.blog/engineering/platform-security/staying-evergreen-how-we-automated-secure-access-and-repo-hygiene-in-a-shared-org
- Ingested by Yomu: 2026-10-16T00:00:20.816Z

[Read original post](https://github.blog/engineering/platform-security/staying-evergreen-how-we-automated-secure-access-and-repo-hygiene-in-a-shared-org)
