Skip to content

Commit 9bf9d97

Browse files
baijumclaude
andcommitted
feat: add governance policies, setup script, and repo templates
Add docs/governance.md as the single source of truth for org-level rulesets, branch protection, labels, and commit conventions. Add scripts/setup-repo.sh to automate repo settings via gh CLI. Add templates/.github/ with PR template, CODEOWNERS, commit convention, and labels.json. Update AGENTS.md, CONTRIBUTING.md, and mkdocs.yml to reference governance docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9c90ff8 commit 9bf9d97

9 files changed

Lines changed: 390 additions & 1 deletion

File tree

AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ docs/ # All documentation (Markdown)
1515
self-hosting.md # Fork model, server requirements, bootstrap
1616
preview-environments.md # PR previews, DNS, cleanup
1717
ecosystem.md # Org structure, app template, multi-app hosting
18+
governance.md # Repository governance policies
1819
roadmap.md # Phased development plan
20+
scripts/
21+
setup-repo.sh # GitHub repo governance setup script
22+
templates/
23+
.github/ # Template files for app repos (PR template, CODEOWNERS, etc.)
1924
mkdocs.yml # MkDocs Material site configuration
2025
.github/workflows/
2126
docs.yml # GitHub Pages deployment workflow

CONTRIBUTING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ Thanks for your interest in contributing! This project is a **documentation-only
1414

1515
1. **Fork** the repository.
1616
2. **Create a branch** from `main` with a descriptive name (e.g. `fix/typo-in-deployment`, `docs/add-monitoring-guide`).
17-
3. **Make your changes** — see the documentation conventions below.
17+
3. **Make your changes** — see the documentation conventions below. Follow the [commit conventions](docs/governance.md#commit-conventions) for your commit messages.
1818
4. **Open a pull request** against `main` with a clear description of what changed and why.
1919

20+
All towlion repositories follow standard [governance policies](docs/governance.md) including branch protection, PR templates, and commit conventions.
21+
2022
### Documentation Conventions
2123

2224
- All documentation lives in the `docs/` directory as Markdown files.

docs/governance.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Governance
2+
3+
This document is the single source of truth for repository policies across the Towlion organization.
4+
5+
## Org-Level Rulesets
6+
7+
Org-level rulesets are configured manually in the GitHub UI. They apply to all repositories in the organization.
8+
9+
### Ruleset: `towlion-main-protection`
10+
11+
**Target:** All repositories, default branch (`main`)
12+
13+
**Rules:**
14+
15+
- Require a pull request before merging (1 approval minimum)
16+
- Require status checks to pass (`validate`)
17+
- Block force pushes on `main`
18+
- Block deletions of `main`
19+
20+
### How to Configure
21+
22+
1. Go to the [Towlion org settings](https://github.com/organizations/towlion/settings/rules/rulesets)
23+
2. Navigate to **Settings > Rules > Rulesets**
24+
3. Click **New ruleset > New branch ruleset**
25+
4. Set the name to `towlion-main-protection`
26+
5. Under **Target branches**, select **Default branch**
27+
6. Enable **Restrict deletions**
28+
7. Enable **Require a pull request before merging** — set minimum approvals to `1`
29+
8. Enable **Require status checks to pass** — add `validate` as a required check
30+
9. Enable **Block force pushes**
31+
10. Set enforcement status to **Active**
32+
11. Click **Create**
33+
34+
## Repository Settings
35+
36+
These settings are applied automatically by the [setup script](../scripts/setup-repo.sh).
37+
38+
| Setting | Value |
39+
|---------|-------|
40+
| Default branch | `main` |
41+
| Wiki | Disabled |
42+
| Projects | Disabled |
43+
| Discussions | Disabled |
44+
| Auto-delete head branches | Enabled |
45+
| Allowed merge types | Squash merge only |
46+
47+
## Branch Protection
48+
49+
Branch protection rules complement the org-level rulesets and are applied by the setup script.
50+
51+
Rules applied to `main`:
52+
53+
- Require pull request reviews (1 reviewer minimum)
54+
- Dismiss stale reviews when new commits are pushed
55+
- Require the `validate` status check to pass
56+
- Require the branch to be up to date before merging
57+
- No force pushes
58+
- No deletions
59+
60+
## CODEOWNERS
61+
62+
Every application repository must include a `.github/CODEOWNERS` file. At minimum:
63+
64+
```
65+
* @towlion/maintainers
66+
```
67+
68+
See the [template CODEOWNERS](../templates/.github/CODEOWNERS) for the canonical version.
69+
70+
## PR Template
71+
72+
Every application repository must include a `.github/PULL_REQUEST_TEMPLATE.md` with the following sections:
73+
74+
- **Summary** — What this PR does and why
75+
- **Changes** — List of changes made
76+
- **Testing** — How the changes were tested
77+
- **Checklist** — Standard checklist items
78+
79+
See the [template PR template](../templates/.github/PULL_REQUEST_TEMPLATE.md) for the canonical version.
80+
81+
## Required Labels
82+
83+
All application repositories must have the following labels. The setup script creates these automatically from [`templates/.github/labels.json`](../templates/.github/labels.json).
84+
85+
| Label | Color | Description |
86+
|-------|-------|-------------|
87+
| `bug` | `#d73a4a` | Something isn't working |
88+
| `feature` | `#a2eeef` | New feature or request |
89+
| `docs` | `#0075ca` | Documentation improvements |
90+
| `chore` | `#e4e669` | Maintenance and housekeeping |
91+
| `breaking` | `#b60205` | Breaking change |
92+
| `good first issue` | `#7057ff` | Good for newcomers |
93+
94+
## Commit Conventions
95+
96+
Towlion uses simplified [Conventional Commits](https://www.conventionalcommits.org/).
97+
98+
### Format
99+
100+
```
101+
type: description
102+
```
103+
104+
- Use **lowercase**
105+
- Use **imperative mood** ("add feature" not "added feature")
106+
- Keep the subject under **72 characters**
107+
108+
### Types
109+
110+
| Type | Purpose |
111+
|------|---------|
112+
| `feat` | New feature |
113+
| `fix` | Bug fix |
114+
| `docs` | Documentation changes |
115+
| `chore` | Maintenance and housekeeping |
116+
| `refactor` | Code restructuring (no behavior change) |
117+
| `test` | Adding or updating tests |
118+
| `ci` | CI/CD changes |
119+
120+
### Optional Scope
121+
122+
```
123+
feat(api): add health endpoint
124+
fix(auth): handle expired tokens
125+
```
126+
127+
### Breaking Changes
128+
129+
Append `!` after the type:
130+
131+
```
132+
feat!: change response format
133+
```
134+
135+
### Examples
136+
137+
```
138+
feat: add user registration endpoint
139+
fix(db): prevent duplicate migration runs
140+
docs: update self-hosting guide
141+
chore: upgrade dependencies
142+
ci: add preview environment workflow
143+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ nav:
3636
- Self-Hosting: self-hosting.md
3737
- Preview Environments: preview-environments.md
3838
- Ecosystem: ecosystem.md
39+
- Governance: governance.md
3940
- Roadmap: roadmap.md
4041

4142
markdown_extensions:

scripts/setup-repo.sh

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ORG="towlion"
5+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6+
LABELS_FILE="$SCRIPT_DIR/../templates/.github/labels.json"
7+
8+
# Colors
9+
GREEN='\033[0;32m'
10+
YELLOW='\033[1;33m'
11+
RED='\033[0;31m'
12+
NC='\033[0m'
13+
14+
usage() {
15+
echo "Usage: $(basename "$0") <repo-name>"
16+
echo
17+
echo "Configure governance settings for a towlion repository."
18+
echo "Applies repo settings, branch protection, and standard labels."
19+
echo
20+
echo "Examples:"
21+
echo " $(basename "$0") uku-companion"
22+
echo " $(basename "$0") app-template"
23+
}
24+
25+
info() { echo -e "${GREEN}[OK]${NC} $1"; }
26+
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
27+
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
28+
29+
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
30+
usage
31+
exit 0
32+
fi
33+
34+
if [[ $# -ne 1 ]]; then
35+
usage
36+
exit 1
37+
fi
38+
39+
REPO="$1"
40+
FULL_REPO="$ORG/$REPO"
41+
42+
# --- Preflight ---
43+
44+
if ! command -v gh &>/dev/null; then
45+
error "gh CLI is not installed. Install it from https://cli.github.com"
46+
fi
47+
48+
if ! gh auth status &>/dev/null; then
49+
error "gh CLI is not authenticated. Run 'gh auth login' first."
50+
fi
51+
52+
if ! gh repo view "$FULL_REPO" &>/dev/null; then
53+
error "Repository $FULL_REPO does not exist or is not accessible."
54+
fi
55+
56+
echo "Configuring $FULL_REPO..."
57+
echo
58+
59+
# --- Repo Settings ---
60+
61+
gh api -X PATCH "repos/$FULL_REPO" \
62+
-f has_wiki=false \
63+
-f has_projects=false \
64+
-f has_discussions=false \
65+
-f delete_branch_on_merge=true \
66+
-f allow_squash_merge=true \
67+
-f allow_merge_commit=false \
68+
-f allow_rebase_merge=false \
69+
--silent
70+
71+
info "Repo settings: wiki/projects/discussions disabled, squash-only merge, auto-delete branches"
72+
73+
# --- Branch Protection ---
74+
75+
# Check if main branch exists
76+
if gh api "repos/$FULL_REPO/branches/main" --silent 2>/dev/null; then
77+
gh api -X PUT "repos/$FULL_REPO/branches/main/protection" \
78+
--input - --silent <<'PROTECTION'
79+
{
80+
"required_status_checks": {
81+
"strict": true,
82+
"contexts": ["validate"]
83+
},
84+
"enforce_admins": false,
85+
"required_pull_request_reviews": {
86+
"dismiss_stale_reviews": true,
87+
"require_code_owner_reviews": false,
88+
"required_approving_review_count": 1
89+
},
90+
"restrictions": null
91+
}
92+
PROTECTION
93+
94+
info "Branch protection: PR reviews, status checks, no force push on main"
95+
else
96+
warn "Branch 'main' does not exist yet — skipping branch protection (re-run after first push)"
97+
fi
98+
99+
# --- Labels ---
100+
101+
if [[ ! -f "$LABELS_FILE" ]]; then
102+
error "Labels file not found at $LABELS_FILE"
103+
fi
104+
105+
label_count=0
106+
while IFS= read -r label; do
107+
name=$(echo "$label" | python3 -c "import sys,json; print(json.load(sys.stdin)['name'])")
108+
color=$(echo "$label" | python3 -c "import sys,json; print(json.load(sys.stdin)['color'])")
109+
description=$(echo "$label" | python3 -c "import sys,json; print(json.load(sys.stdin)['description'])")
110+
111+
# Try to create; if it already exists (422), update instead
112+
if gh api -X POST "repos/$FULL_REPO/labels" \
113+
-f name="$name" -f color="$color" -f description="$description" \
114+
--silent 2>/dev/null; then
115+
: # created
116+
else
117+
gh api -X PATCH "repos/$FULL_REPO/labels/$name" \
118+
-f color="$color" -f description="$description" \
119+
--silent 2>/dev/null || true
120+
fi
121+
label_count=$((label_count + 1))
122+
done < <(python3 -c "
123+
import json, sys
124+
with open('$LABELS_FILE') as f:
125+
for item in json.load(f):
126+
print(json.dumps(item))
127+
")
128+
129+
info "Labels: $label_count standard labels created/updated"
130+
131+
# --- Summary ---
132+
133+
echo
134+
echo -e "${GREEN}=== Setup complete for $FULL_REPO ===${NC}"
135+
echo " - Repo settings configured"
136+
if gh api "repos/$FULL_REPO/branches/main" --silent 2>/dev/null; then
137+
echo " - Branch protection applied to main"
138+
else
139+
echo " - Branch protection skipped (no main branch)"
140+
fi
141+
echo " - $label_count labels created/updated"

templates/.github/CODEOWNERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Default code owners for this repository.
2+
# Customize this file for your application — add team-specific paths as needed.
3+
#
4+
# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
5+
6+
* @towlion/maintainers
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Commit Convention
2+
3+
This repository follows simplified [Conventional Commits](https://www.conventionalcommits.org/).
4+
5+
## Format
6+
7+
```
8+
type: description
9+
```
10+
11+
- Lowercase, imperative mood, under 72 characters.
12+
13+
## Types
14+
15+
| Type | Purpose |
16+
|------|---------|
17+
| `feat` | New feature |
18+
| `fix` | Bug fix |
19+
| `docs` | Documentation changes |
20+
| `chore` | Maintenance and housekeeping |
21+
| `refactor` | Code restructuring (no behavior change) |
22+
| `test` | Adding or updating tests |
23+
| `ci` | CI/CD changes |
24+
25+
## Scope (optional)
26+
27+
```
28+
feat(api): add health endpoint
29+
```
30+
31+
## Breaking Changes
32+
33+
```
34+
feat!: change response format
35+
```
36+
37+
For full details, see the [governance policies](https://towlion.github.io/platform/governance/#commit-conventions).
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Summary
2+
3+
<!-- What does this PR do and why? -->
4+
5+
## Changes
6+
7+
<!-- List the changes made in this PR -->
8+
9+
-
10+
11+
## Testing
12+
13+
<!-- How were these changes tested? -->
14+
15+
-
16+
17+
## Checklist
18+
19+
- [ ] Code follows the project's conventions
20+
- [ ] Changes have been tested locally
21+
- [ ] Documentation has been updated (if applicable)
22+
- [ ] No secrets or credentials are included

0 commit comments

Comments
 (0)