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
5 changes: 3 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ For enterprise-level org iteration (GraphQL), use cursor-based pagination — se
Rate limiting delays are calibrated per operation type:
- **Repo-level operations** (permission grants, archival): `sleep 5` between each repository.
- **Code search** (`github-dockerfile-discovery`): configurable via `SEARCH_SLEEP` (default 2 s) and `CONTENT_SLEEP` (default 1 s).
- **gh_api helper** (lib): auto-retries up to 5 times on HTTP 403/429, sleeping 60 s before each retry.
- **gh_api helper** (lib): auto-retries up to 5 times on HTTP 403/429, sleeping 60 s before each retry. Returns the literal string `__404__` or `__422__` (exit 0) for those HTTP statuses instead of failing — every caller must check for these sentinels before passing the result to `jq`. `gh_api_paginate` returns silently with empty output on 404/422.

### Authentication Headers

Expand Down Expand Up @@ -161,7 +161,7 @@ Dismisses open Dependabot, code-scanning, and secret-scanning alerts on all arch

### `github-dockerfile-discovery`

Uses GitHub code-search API to find Dockerfiles across all enterprise orgs, then fetches and parses each file to extract `FROM` instructions (including multi-stage builds). Produces three timestamped reports in `REPORT_DIR`: a detail CSV, a summary CSV, and a plain-text summary. Supports `ORGS` override, `ORG_FILTER`/`ORG_EXCLUDE` regex filters (validated as syntactically correct ERE before use), and configurable sleep intervals (`SEARCH_SLEEP`, `CONTENT_SLEEP`).
Uses GitHub code-search API to find Dockerfiles across all enterprise orgs, then fetches and parses each file to extract `FROM` instructions (including multi-stage builds). Produces three timestamped reports in `REPORT_DIR`: a detail CSV, a summary CSV, and a plain-text summary. Supports `ORGS` override, `ORG_FILTER`/`ORG_EXCLUDE` regex filters (validated as syntactically correct ERE before use), and configurable sleep intervals (`SEARCH_SLEEP`, `CONTENT_SLEEP`). Both `gh_api` call sites handle sentinels: `__422__` or `__404__` on the code-search endpoint skips that org with a warning; `__404__` or `__422__` on the file-contents endpoint skips that individual file.

### `github-enable-issues`

Expand Down Expand Up @@ -270,6 +270,7 @@ When you change one of these files, you must also update the files in the "Also
|------------------|-------------|
| `lib/github-common.sh` — any public function signature or behaviour | All 18 scripts that source it; verify each caller still passes the right arguments. Check with: `grep -r "github-common" . --include="*.sh"` |
| `lib/github-common.sh` — add a new helper function | `AGENTS.md` shared library table; `README.md` if the function affects usage |
| `gh_api_paginate` signature or pagination behaviour | `github-repo-permissions-report.sh` (3 call sites), `github-copilot-report.sh` (`fetch_seats`) — both pipe output through `jq -s '.'` and depend on the `jq_filter`/`api_version` parameter order |
| Any script's required env vars | That script's `# ===` header comment; the corresponding README.md section's env var table; that script's `action.yml` inputs (add/remove required inputs to match) |
| Any script's optional env vars or defaults | Same as above; update the `action.yml` optional inputs and their defaults |
| Any script's `--dry-run` or CLI flag behaviour | README.md usage example for that script; that script's `action.yml` inputs and `run:` step flag construction |
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ Always use `SCRIPT_DIR` to build the path to `lib/github-common.sh`. The library
| `configure_gh_auth [scope_hint]` | Bridge GITHUB_TOKEN→GH_TOKEN or verify gh auth session |
| `validate_github_token [bearer]` | Verify GITHUB_TOKEN via /user endpoint |
| `validate_slug <value> <label>` | Reject values with non-alphanumeric/hyphen/underscore chars |
| `gh_api <path> [curl args...]` | Bearer-auth REST helper with 5-retry rate-limit handling |
| `gh_api_paginate <path> [filter] [version]` | Paginated REST helper, follows Link headers, streams items |
| `gh_api <path> [curl args...]` | Bearer-auth REST helper with 5-retry rate-limit handling; returns literal `__404__` or `__422__` for those HTTP statuses — callers must check for these sentinels |
| `gh_api_paginate <path> [filter] [version]` | Paginated REST helper, follows Link headers, streams items; returns silently with empty output on 404/422 |
| `get_enterprise_orgs` | Three-tier enterprise org resolver (REST → GraphQL → /user/orgs) |
| `get_repo_page_count <url>` | Returns total pages for a paginated endpoint |

Expand All @@ -172,6 +172,7 @@ done
- Repo-level operations (permission grants, archival): `sleep 5` between each repo
- Code search: configurable `SEARCH_SLEEP` (default 2s) and `CONTENT_SLEEP` (default 1s)
- `gh_api` auto-retries on HTTP 403/429 with 60s sleep
- `gh_api` returns the literal string `__404__` or `__422__` (exit 0) for those HTTP statuses — callers must check for these sentinels before passing output to `jq`

---

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -854,11 +854,15 @@ All scripts can leverage a shared utility library for common operations like val
- `require_command <cmd> [hint]` — Exit if command is not in PATH
- `validate_token <VAR_NAME> [bearer]` — Validate GitHub token by calling `/user` endpoint
- `validate_github_token [bearer]` — Convenience wrapper for `GITHUB_TOKEN` validation
- `validate_slug <value> <label>` — Exit if value contains characters other than alphanumeric, hyphen, or underscore

**Auth helpers:**
- `configure_gh_auth [scope_hint]` — Bridge `GITHUB_TOKEN→GH_TOKEN` for scripts that use the `gh` CLI, or verify an active `gh` auth session if no token is set

**API helpers:**
- `get_repo_page_count <url>` — Get total page count from paginated REST endpoint
- `validate_slug <value> <label>` — Exit if value contains characters other than alphanumeric, hyphen, or underscore
- `gh_api <path|url> [curl args...]` — Bearer-auth REST helper with automatic rate-limit retry (up to 5 attempts); returns `__404__` / `__422__` for those status codes instead of failing
- `gh_api <path|url> [curl args...]` — Bearer-auth REST helper with automatic rate-limit retry (up to 5 attempts); returns the literal string `__404__` or `__422__` (exit 0) for those status codes — callers must check for these sentinels before passing the result to `jq`
- `gh_api_paginate <path> [jq_filter] [api_version]` — Paginated REST helper that follows `Link` headers and streams items through `jq_filter` (default `.[]`); silently returns empty output on 404/422; pipe through `jq -s '.'` to collect all items as an array
- `_paginate_orgs_endpoint <jq_filter> <url_template>` — Page through an org-list REST endpoint, printing one login per line; use `PAGE` as a placeholder in the URL template
- `_graphql_enterprise_orgs` — Cursor-based GraphQL pagination for all orgs in `ENTERPRISE`; prints one login per line
- `get_enterprise_orgs` — Three-tier enterprise org resolver: tries REST `/enterprises/{slug}/organizations`, falls back to GraphQL, then falls back to `/user/orgs`
Expand Down
28 changes: 16 additions & 12 deletions lib/github-common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,26 @@
#
# Provides:
# print_status / print_success / print_warning / print_error
# require_env_var <VAR> [description] — exit if variable is unset/empty
# require_command <cmd> — exit if command not found
# configure_gh_auth [scope_hint] — bridge GITHUB_TOKEN→GH_TOKEN or verify gh session
# validate_github_token [bearer] — verify token via /user endpoint
# require_env_var <VAR> [description] — exit if variable is unset/empty
# require_command <cmd> — exit if command not found
# configure_gh_auth [scope_hint] — bridge GITHUB_TOKEN→GH_TOKEN or verify gh session
# validate_github_token [bearer] — verify GITHUB_TOKEN via /user endpoint
# validate_token <VAR_NAME> — verify a secondary token variable
# validate_slug <value> [label] — exit if value contains unsafe chars
# gh_api <path|url> [curl args...] — Bearer-auth REST helper with retry;
# returns "__404__"/"__422__" (exit 0) for those codes
# gh_api_paginate <path> [filter] [version] — paginated REST, follows Link headers;
# silently returns empty output on 404/422
# get_repo_page_count <url> — total page count for a paginated REST endpoint
# _paginate_orgs_endpoint <filter> <url_tpl> — page through an org list (internal)
# _graphql_enterprise_orgs — GraphQL cursor-based enterprise orgs (internal)
# get_enterprise_orgs — three-tier enterprise org resolver
#
# Token auto-resolution (at source time):
# If GITHUB_TOKEN is unset and gh CLI is available, the token is automatically
# resolved from the active gh auth session so curl-based scripts work with
# either a GITHUB_TOKEN env var or a gh CLI session.
# validate_token <VAR_NAME> — verify a secondary token variable
# validate_slug <value> [label] — exit if value contains unsafe chars
# gh_api <path|url> [curl args...] — Bearer-auth REST helper with retry
# gh_api_paginate <path> [filter] [version] — paginated REST, follows Link headers
# _paginate_orgs_endpoint <filter> <url_tpl> — page through an org list
# _graphql_enterprise_orgs — GraphQL cursor-based enterprise orgs
# get_enterprise_orgs — three-tier enterprise org resolver
# either a GITHUB_TOKEN env var or a gh CLI session. GH_TOKEN is also kept
# in sync with GITHUB_TOKEN so gh CLI calls use the same credential.
# =============================================================================

###
Expand Down