Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Before warden does anything useful you provide two things:
repo-level reconcile and `audit`) **or** a **GitHub App** installed on your
org (App ID + installation ID + private key). An App is **required** for
org-level cycles (org settings, members, teams) and the token cycles — see
[Auth](#auth).
[Auth](#auth) and the [App setup checklist](docs/github-app-setup.md).
2. **A config file** — a YAML/JSON file declaring the desired state you want
managed (see [Config format](#config-format)). Declare only what you want
warden to own.
managed. Start from [`examples/governance.yml`](examples/governance.yml) and
see [Config format](#config-format). Declare only what you want warden to own.

Nothing is mutated until you ask: the default mode is `dry-run`, which only
reads and prints a plan. Start there.
Expand Down Expand Up @@ -109,7 +109,8 @@ omit it to run all.

## Config format

Every field is optional — declare only what you want managed.
Every field is optional — declare only what you want managed. A ready-to-edit
starter lives in [`examples/governance.yml`](examples/governance.yml).

```yaml
orgs:
Expand Down Expand Up @@ -201,7 +202,8 @@ Two mutually-exclusive modes (token takes precedence):
2. **GitHub App** — `--app-id-env` + `--installation-id-env`, with the private key in `GOVERNANCE_APP_PRIVATE_KEY` (or `GITHUB_APP_PRIVATE_KEY`).

A **GitHub App** is required for org-level token policy/approval and several
org administration APIs.
org administration APIs. The [App setup checklist](docs/github-app-setup.md)
walks through creating it, the per-cycle permissions, and installation.

## Use as a GitHub Action

Expand Down
78 changes: 78 additions & 0 deletions docs/github-app-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Setting up the GitHub App

warden authenticates either with a **pre-minted installation token**
(`--token-env`) or as a **GitHub App** (`--app-id-env` + `--installation-id-env`
+ a private key). A token is fine for repo-level reconcile and `audit`; an
**App is required** for org-level cycles (org settings, members, teams) and the
token cycles, and is the right choice for unattended/scheduled runs.

This is a one-time checklist. The org-permission steps are web-only (GitHub has
no API to set or change an App's permissions).

## 1. Create the App

Open `https://github.com/organizations/<your-org>/settings/apps/new` and set:

- **Name:** e.g. `org-warden` (must be globally unique)
- **Homepage URL:** anything (e.g. your repo URL)
- **Webhook → Active:** **uncheck** (warden polls; no webhook needed)
- **Where can this be installed:** "Only on this account"

## 2. Grant permissions

Grant only what the cycles you plan to run need. For a **dry-run** the *read*
level is enough; **apply** needs *write*.

| Cycle(s) | Permission | dry-run | apply |
|---|---|---|---|
| branch-protection, repo-settings, rulesets (repo), repo-baseline | Repository → **Administration** | read | write |
| security-features | Repository → **Administration** + **Contents** | read | write |
| dependency-hygiene | Repository → **Contents** | read | write |
| environments | Repository → **Environments** | read | write |
| secrets-variables | Repository → **Secrets** + **Variables** | read | write |
| org-settings, rulesets (org) | Organization → **Administration** | read | write |
| membership, teams | Organization → **Members** | read | write |
| token-governance | Organization → **Personal access tokens** | read | write |
| token-approval | Organization → **Personal access token requests** | read | write |

Repository → **Metadata: read** is mandatory and auto-selected.

> A cycle whose read 403s (a permission you didn't grant, or a feature not on
> your plan) is skipped gracefully rather than crashing — so you can start with
> a narrow grant and widen later. Re-granting requires re-approving the install
> (step 4).

## 3. Generate a key + note the IDs

- **App ID:** shown at the top of the App's settings page.
- **Private keys → Generate a private key** → downloads a `.pem`. Store it as a
secret.

## 4. Install it

**Install App** → install on your org → **All repositories** (or select the
repos warden should manage). After any later permission change, return here and
**approve** the new request.

The **installation ID** is in the install URL
(`…/settings/installations/<id>`), or via
`gh api /orgs/<org>/installations`.

## 5. Wire it up

CLI:

```bash
GOVERNANCE_APP_PRIVATE_KEY="$(cat org-warden.pem)" \
APP_ID=123456 INSTALL_ID=78901234 \
github-warden reconcile --config .github/governance.yml \
--app-id-env APP_ID --installation-id-env INSTALL_ID --mode dry-run
```

GitHub Action — pass `app-id`, `installation-id`, and `private-key` (as a
secret); see the README "Use as a GitHub Action" section.

## 6. Verify

Run a **dry-run** first — it only reads and prints a plan. When the plan looks
right, switch to `--mode apply`.
34 changes: 34 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# examples

Starter configs for github-warden.

## `governance.yml`

A minimal, annotated config covering the most common domains — org settings,
repo settings, branch protection, and security features. It parses with
warden's built-in YAML reader (block-style only; for flow style `[ ]`/`{ }` use
JSON instead).

Copy it, change the org/repo names, and **dry-run** it (reads only, changes
nothing):

```bash
cp examples/governance.yml .github/governance.yml
# edit the org/repo names…

npx @intentius/github-warden reconcile \
--config .github/governance.yml --token-env GH_TOKEN --mode dry-run
```

**Selective-by-omission:** warden manages only what you declare — delete the
blocks you don't want managed, add fields as you grow. The
[config reference](../README.md#config-format) lists every field across all 13
cycles (teams, members, rulesets, environments, secrets/variables, dependency
hygiene, repo provisioning, token governance, …).

## Auth

The example uses `--token-env GH_TOKEN` (a pre-minted installation token), which
is enough for repo-level reconcile and `audit`. Org-level cycles (org settings,
members, teams) and the token cycles need a **GitHub App** — see
[../docs/github-app-setup.md](../docs/github-app-setup.md).
43 changes: 43 additions & 0 deletions examples/governance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# github-warden governance config — a starter. Copy to .github/governance.yml,
# change the org/repo names, then run a dry-run (reads only, changes nothing):
#
# npx @intentius/github-warden reconcile \
# --config .github/governance.yml --token-env GH_TOKEN --mode dry-run
#
# Selective-by-omission: warden manages ONLY what you declare below. Anything
# you leave out is never read, diffed, or touched — so delete the blocks you
# don't want managed, and add fields as you grow. See the README "Config
# format" section for every available field.

orgs:
my-org: # ← your GitHub org login

# ── Org-level settings (needs a GitHub App with org admin) ──────────────
settings:
defaultRepositoryPermission: read
membersCanCreatePublicRepositories: false

repos:
my-repo: # ← a repository in the org

# ── Repository settings ─────────────────────────────────────────────
hasWiki: false
deleteBranchOnMerge: true
topics:
- service
- go

# ── Branch protection on the default branch ─────────────────────────
branchProtection:
- pattern: main
requirePullRequestReviews: true
requiredApprovingReviewCount: 1
requireStatusChecks: true
requiredStatusCheckContexts:
- ci

# ── Security features (GHAS / secret scanning / Dependabot) ──────────
security:
secretScanning: true
secretScanningPushProtection: true
vulnerabilityAlerts: true
Loading