You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c16f40a
Browse filesBrowse the repository at this point in the historyBrowse files
This is a collection of **standalone bash automation scripts** for GitHub organization administration. Each script lives in its own directory with a single `.sh` file. Scripts use `curl` + `jq` to interact with the GitHub REST API v3.
5
+
This is a collection of **standalone bash automation scripts** for GitHub organization and enterprise administration. Each script lives in its own directory with a single `.sh` file. Scripts use `curl` + `jq` to interact with the GitHub REST and GraphQL APIs. A shared utility library lives in `lib/github-common.sh`.
6
6
7
-
**Key principle:** Scripts are independent, self-contained utilities—not a unified codebase. There's no shared library or common framework. Each script is a complete, self-validating executable that manages its own error handling and input validation.
7
+
**Key principle:** Scripts are independent, self-contained utilities. Each script is a complete, self-validating executable that manages its own error handling and input validation. Scripts source `lib/github-common.sh` for shared validation and output helpers where applicable.
8
8
9
9
## Architecture Pattern
10
10
11
11
### Directory Structure
12
12
```
13
13
github-<script-name>/
14
14
└── github-<script-name>.sh # Single executable script
15
+
lib/
16
+
└── github-common.sh # Shared utility functions
15
17
```
16
18
17
19
Each script follows this exact naming convention. Scripts are NOT imported or called by each other.
- Use `${VARIABLE:-''}` for all env vars to provide empty defaults
41
56
- Set `API_URL_PREFIX` and `GIT_URL_PREFIX` for GitHub Enterprise Server compatibility
42
-
- Include `sleep 5` between API calls to avoid rate limits (see `github-add-repo-permissions.sh` line 99)
43
-
- Use pagination helpers for org-level operations (pattern in `github-add-repo-permissions.sh` lines 45-51)
44
-
-**ALWAYS validate required variables** with explicit `if [ -z "${VAR}" ]` checks before any API calls
45
-
-**ALWAYS validate GITHUB_TOKEN** by calling `/user` endpoint and checking for 200 status code
57
+
-**ALWAYS validate required variables** before any API calls — use `require_env_var` from lib or explicit `if [ -z "${VAR}" ]` checks
58
+
-**ALWAYS validate GITHUB_TOKEN** via `validate_github_token` (lib) or the `/user` endpoint pattern
46
59
- Use `curl -s -o /dev/null -w "%{http_code}"` pattern to check HTTP status codes
47
60
- Exit with status code 1 on validation failures with descriptive error messages
61
+
- Rate limiting delays vary by script: `sleep 5` for per-repo team operations, `sleep 2` for archive operations, `sleep 0.5` or `sleep 0.2` for lighter patch operations
48
62
49
63
## GitHub API Patterns
50
64
51
65
### Pagination
52
-
When iterating over all repos in an org, use this pattern:
@@ -61,105 +76,216 @@ for PAGE in $(seq "$(get_repo_pagination)"); do
61
76
done
62
77
```
63
78
79
+
For enterprise-level org iteration (GraphQL), use cursor-based pagination — see `github-add-enterprise-team-read-permissions.sh` and `github-dockerfile-discovery.sh` for examples.
80
+
64
81
### Rate Limiting
65
-
**Always include `sleep 5`** between repository-level operations to stay under GitHub's rate limits. See `github-add-repo-permissions.sh` line 99 or `github-repo-from-template.sh` lines 77, 83.
82
+
83
+
Rate limiting delays are calibrated per operation type:
84
+
-**Per-repo team permission assignments:**`sleep 5` (see `github-add-repo-permissions.sh`, `github-repo-from-template.sh`)
85
+
-**Archive operations:**`sleep 2` (see `github-archive-old-repos.sh`)
86
+
-**Lightweight patch operations:**`sleep 0.5` (see `github-enable-issues.sh`) or `sleep 0.2` (see `github-close-archived-repo-security-alerts.sh`)
87
+
-**Code search + content fetch:** configurable `SEARCH_SLEEP` / `CONTENT_SLEEP` with exponential backoff (see `github-dockerfile-discovery.sh`, `github-get-public-repos.sh`)
66
88
67
89
### Authentication Headers
68
-
- Use `Bearer` token for enterprise endpoints: `-H "Authorization: Bearer ${GITHUB_TOKEN}"`
69
-
- Use `token` for standard API: `-H "Authorization: token ${GITHUB_TOKEN}"`
90
+
91
+
-`token` scheme for standard org/repo API: `-H "Authorization: token ${GITHUB_TOKEN}"`
92
+
-`Bearer` scheme for enterprise endpoints and GraphQL: `-H "Authorization: Bearer ${GITHUB_TOKEN}"`
93
+
- Some scripts use **both** (e.g., `github-dockerfile-discovery.sh`, `github-get-public-repos.sh`)
70
94
- Include API version when specified: `-H "X-GitHub-Api-Version: 2022-11-28"`
71
95
72
96
### Accept Headers (Media Types)
97
+
73
98
Different endpoints require specific Accept headers:
- Retrieves invite ID via `/user/repository_invitations` and accepts via PATCH request
101
-
- Creates repo with `private: true` and `include_all_branches: true` by default
143
+
### `github-archive-old-repos`
144
+
- Identifies repos not updated in the last N years (configurable via `YEARS_THRESHOLD`, default: `5`)
145
+
- Generates a timestamped CSV report in `reports/old_repos_${TIMESTAMP}.csv`
146
+
-**Interactive:** Prompts for confirmation before archiving; shows top 10 oldest repos first
147
+
- Skips already-archived repos; uses `sleep 2` between archive operations
148
+
- macOS (`date -v`) and Linux (`date -d`) compatible date arithmetic
149
+
150
+
### `github-auto-repo-creation`
151
+
- Creates repos with branch protection, a `CODEOWNERS` file, and team assignments
152
+
- Variables: `REPO_NAMES` (comma-separated), `REPO_OWNERS` (comma-separated team slugs with write), `ADMIN_TEAMS` (comma-separated team slugs with admin)
153
+
- Creates repos as `private: true`, with issues enabled, no projects or wiki
154
+
- Encodes CODEOWNERS content via `base64` for API upload
No other dependencies. Keep scripts dependency-minimal.
279
+
Keep new scripts dependency-minimal; document any non-standard dependencies explicitly.
158
280
159
281
## Common Pitfalls
160
282
161
283
1.**Team slugs vs names:** GitHub API uses team slugs (lowercase, hyphenated). Example: "Platform Team" → "platform-team"
162
-
2.**Enterprise vs Org endpoints:** License consumption requires enterprise-level token scopes
163
-
3.**Git URL authentication:** When using `git push --mirror`, ensure token has repo scope
164
-
4.**Space-separated lists:** Some variables like `REPO_ADMIN` accept multiple values separated by spaces (loop over them)
165
-
5.**URL encoding:** Labels in API calls must be URL-encoded (`Linked [AC]` → `Linked%20[AC]`)
284
+
2.**Enterprise vs Org endpoints:** License consumption and enterprise team roles require enterprise-level token scopes
285
+
3.**Bearer vs token auth:** Enterprise endpoints and GraphQL use `Bearer`; standard REST org/repo endpoints use `token`
286
+
4.**Git URL authentication:** When using `git push --mirror`, ensure token has `repo` scope
287
+
5.**Space-separated lists:** Variables like `REPO_ADMIN` and `REPO_WRITE` accept multiple values separated by spaces — loop over them with `for team in ${REPO_ADMIN}; do`
288
+
6.**Comma-separated lists:** Variables like `COLLABORATORS`, `REPO_NAMES`, and `ORGS` use commas — split with `IFS=','`
289
+
7.**URL encoding:** Labels in API calls must be URL-encoded (`Linked [AC]` → `Linked%20[AC]`)
290
+
8.**Public repo filtering:** Do not rely on `?type=public` for enterprise-managed orgs — fetch all and filter in jq
291
+
9.**macOS vs Linux date:**`github-archive-old-repos.sh` handles both BSD `date -v` (macOS) and GNU `date -d` (Linux)
0 commit comments