From 60777a0c29e93bbf3168ce79eaf7703c851c78fa Mon Sep 17 00:00:00 2001 From: lex00 Date: Fri, 19 Jun 2026 15:34:25 -0600 Subject: [PATCH] docs: add examples/ starter config + GitHub App setup checklist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - examples/governance.yml: minimal annotated starter (org/repo settings, branch protection, security) — validated to parse with warden's YAML reader. - examples/README.md: copy-edit-dry-run flow. - docs/github-app-setup.md: one-time App checklist with a cycle→permission map (read for dry-run, write for apply) and the note that unknown-403 cycles skip gracefully. - README: link the starter from the intro + Config, and the checklist from the intro + Auth. Co-Authored-By: Claude Opus 4.8 --- README.md | 12 ++++--- docs/github-app-setup.md | 78 ++++++++++++++++++++++++++++++++++++++++ examples/README.md | 34 ++++++++++++++++++ examples/governance.yml | 43 ++++++++++++++++++++++ 4 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 docs/github-app-setup.md create mode 100644 examples/README.md create mode 100644 examples/governance.yml diff --git a/README.md b/README.md index 9fcbb81..240f481 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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: @@ -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 diff --git a/docs/github-app-setup.md b/docs/github-app-setup.md new file mode 100644 index 0000000..b66477e --- /dev/null +++ b/docs/github-app-setup.md @@ -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//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/`), or via +`gh api /orgs//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`. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..be59137 --- /dev/null +++ b/examples/README.md @@ -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). diff --git a/examples/governance.yml b/examples/governance.yml new file mode 100644 index 0000000..397a28c --- /dev/null +++ b/examples/governance.yml @@ -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