Skip to content

locus313/github-api-scripts

Repository files navigation

GitHub API Scripts

License Shell GitHub API

⭐ If you like this project, star it on GitHub — it helps a lot!

OverviewGetting startedScriptsShared LibraryGitHub ActionsResources

A collection of standalone bash scripts for GitHub organization administration. Automate common tasks like bulk permission management, repository creation, migration, and reporting using simple, self-contained utilities powered by the GitHub REST API.

Overview

This toolkit provides ready-to-use automation scripts for GitHub organization administrators. Each script is a complete, independent utility that can be run directly or integrated into your GitHub Actions workflows.

What you can do:

  • Grant team permissions across all repositories in bulk
  • Create repositories from templates with pre-configured access
  • Mirror repositories with full git history
  • Generate monthly issue reports with contributor statistics
  • Track license consumption for enterprise accounts
  • Archive old repositories
  • Discover Dockerfiles and base images across an enterprise
  • Organize your starred repositories
  • And much more!

Architecture: Scripts use a shared utility library (lib/github-common.sh) for common validation, error handling, and API helpers. Script directories are grouped by domain (org-admin/, enterprise/, reporting/, personal/) and each script remains a self-contained .sh utility.

Built with simplicity: All scripts use only curl for API requests and jq for JSON processing—no complex dependencies or installation required beyond standard Unix tools.

Note

Scripts follow a convention-over-configuration approach with built-in validation and error handling. Each can be run standalone or integrated into CI/CD pipelines and GitHub Actions workflows.

Getting started

Prerequisites

  • bash 4+
  • curl - HTTP client for API requests
  • jq - Command-line JSON processor
  • git - For repository operations (required by some scripts)
  • gh - GitHub CLI (required by github-organize-stars)
  • GitHub Personal Access Token with appropriate scopes

Installation

Clone the repository:

git clone https://github.com/locus313/github-api-scripts.git
cd github-api-scripts

Alternatively, download individual scripts as needed—each script is standalone and can be used independently.

Authentication

Create a GitHub Personal Access Token at github.com/settings/tokens with these scopes:

  • repo - Full control of repositories
  • admin:org - Organization administration
  • read:enterprise - Read enterprise data (for license scripts)

Export your token as an environment variable:

export GITHUB_TOKEN="ghp_your_token_here"

Tip

Add this export to your ~/.bashrc or ~/.zshrc to persist the token across terminal sessions.

Configuration

Scripts use environment variables for configuration. Common variables include:

Variable Description Required
GITHUB_TOKEN GitHub personal access token Yes
ORG Organization name Yes (most scripts)
API_URL_PREFIX GitHub API base URL (default: https://api.github.com) No
GIT_URL_PREFIX GitHub base URL (default: https://github.com) No

Note

The *_PREFIX variables support GitHub Enterprise Server. Set them to your enterprise domain to use these scripts with GHES.

Pre-commit Hooks

The repository ships versioned pre-commit hooks in .githooks/. Run the installer once after cloning:

./install-hooks.sh

This sets core.hooksPath to .githooks/ so Git picks up the hooks automatically on every commit.

What the hook checks:

Check Tool Fallback
Secret scanning gitleaks Built-in regex patterns for GitHub tokens, AWS keys, private keys, and generic secrets
Shell script security shellcheck Skipped with a warning if not installed

Install the recommended tools for full coverage:

brew install gitleaks shellcheck

Tip

To bypass the hooks in an emergency: git commit --no-verify. Use sparingly — the hooks exist to prevent secrets from reaching the remote.

Scripts

Each script is a self-contained utility designed for a specific task. Navigate to the script's directory, set the required environment variables, and execute.

Folder Layout (Domain-Based)

  • org-admin/: github-add-repo-collaborators-by-pattern, github-add-repo-permissions, github-archive-old-repos, github-auto-repo-creation, github-close-archived-repo-security-alerts, github-enable-issues, github-get-repo-list, github-import-repo, github-migrate-internal-repos-to-private, github-repo-from-template
  • enterprise/: github-add-enterprise-team-read-permissions, github-dockerfile-discovery, github-get-consumed-licenses, github-get-public-repos
  • reporting/: github-monthly-issues-report, github-repo-permissions-report, github-copilot-report
  • personal/: github-organize-stars

Add Repository Permissions

Script: org-admin/github-add-repo-permissions/github-add-repo-permissions.sh

Grants team permissions across all repositories in an organization. Supports multiple permission levels (admin, maintain, push, triage, pull) and multiple teams per permission level.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"

# Set one or more permission levels (space-separated team slugs)
export REPO_ADMIN="platform-team ops-team"      # Admin permissions
export REPO_MAINTAIN="maintainers"              # Maintain permissions
export REPO_PUSH="developers contributors"      # Write/push permissions
export REPO_TRIAGE="support-team"               # Triage permissions
export REPO_PULL="external-auditors"            # Read/pull permissions

# Optional: restrict to repos whose names start with a given prefix
export REPO_NAME_FILTER="my-service-"

Usage:

cd org-admin/github-add-repo-permissions
./github-add-repo-permissions.sh

What it does:

  • Retrieves all repositories in the organization (paginated)
  • Filters to repositories whose names start with REPO_NAME_FILTER (all repos when unset)
  • Grants permissions to specified teams based on permission level
  • Supports multiple teams per permission level (space-separated)
  • Processes all five GitHub permission levels: admin, maintain, push, triage, pull
  • Includes 5-second delays between repos to avoid rate limits

Permission levels:

  • admin - Full repository access including settings and team management
  • maintain - Repository management without admin privileges
  • push - Read and write access to code
  • triage - Read access plus ability to manage issues and pull requests
  • pull - Read-only access to code

Note

At least one permission level must be set. Team slugs should be lowercase and hyphenated (e.g., "Platform Team" → platform-team).


Create Repository from Template

Script: org-admin/github-repo-from-template/github-repo-from-template.sh

Creates a new repository from a template with pre-configured team permissions and collaborator access.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"
export TEMPLATE_REPO="template-repo"
export REPO_ADMIN="admins platform-team"     # Space-separated team slugs
export REPO_WRITE="developers contributors"  # Space-separated team slugs
export CD_USERNAME="ci-bot"
export CD_GITHUB_TOKEN="bot_token"

Usage:

cd org-admin/github-repo-from-template
./github-repo-from-template.sh new-project-name

What it does:

  • Creates a private repository from the specified template
  • Includes all branches from the template
  • Assigns admin permissions to teams in REPO_ADMIN
  • Assigns write permissions to teams in REPO_WRITE
  • Invites CD user as collaborator and auto-accepts the invitation

Import Repository

Script: org-admin/github-import-repo/github-import-repo.sh

Performs a full repository mirror—clones source repo and pushes all branches, tags, and history to a new destination repo.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"
export OWNER_USERNAME="admin-user"

Usage:

cd org-admin/github-import-repo
./github-import-repo.sh source-repo destination-repo

What it does:

  • Creates a new internal repository
  • Performs bare clone of source repository
  • Mirrors all git objects to destination
  • Grants admin permissions to specified owner
  • Cleans up local temporary clone

Warning

This creates a complete copy with full git history. Ensure you have sufficient disk space and network bandwidth for large repositories.


Add Repository Collaborators by Pattern

Script: org-admin/github-add-repo-collaborators-by-pattern/github-add-repo-collaborators-by-pattern.sh

Adds one or more individual collaborators to all repositories in an organisation whose names match a given regex pattern.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"
export COLLABORATORS="alice,bob"
export REPO_NAME_REGEX='^service-'

Usage:

cd org-admin/github-add-repo-collaborators-by-pattern
./github-add-repo-collaborators-by-pattern.sh
Variable Description Default
PERMISSION Permission level: pull|triage|push|maintain|admin push
REPO_EXCLUDE_REGEX ERE regex to exclude matching repository names

What it does:

  • Iterates all repositories in the organization (paginated)
  • Filters to repos matching REPO_NAME_REGEX
  • Optionally excludes repos matching REPO_EXCLUDE_REGEX
  • Adds each specified collaborator with the configured permission level

Archive Old Repositories

Script: org-admin/github-archive-old-repos/github-archive-old-repos.sh

Identifies and archives repositories that have not been updated within a configurable number of years. Generates a timestamped CSV report.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"

Usage:

cd org-admin/github-archive-old-repos
./github-archive-old-repos.sh

What it does:

  • Fetches all repositories in the organization (paginated)
  • Calculates a cutoff date based on YEARS_THRESHOLD
  • Generates a timestamped CSV report in the reports/ subdirectory
  • Displays a summary with the top 10 oldest repositories
  • Prompts for confirmation before archiving
  • Archives qualifying repositories via the GitHub API, skipping already-archived ones
Variable Description Default
YEARS_THRESHOLD Age threshold in years 5

Auto Repository Creation

Script: org-admin/github-auto-repo-creation/github-auto-repo-creation.sh

Creates one or more private GitHub repositories in an organisation with standard configuration: branch protection on the default branch, a CODEOWNERS file, and optional team permissions.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"
export REPO_NAMES="repo1,repo2"
export REPO_OWNERS="platform-team"

Usage:

cd org-admin/github-auto-repo-creation
./github-auto-repo-creation.sh

What it does:

  • Creates each repository listed in REPO_NAMES as private
  • Configures branch protection on the default branch
  • Creates a CODEOWNERS file referencing the REPO_OWNERS teams
  • Grants admin access to teams listed in ADMIN_TEAMS
Variable Description Default
ADMIN_TEAMS Comma-separated team slugs for admin access

Note

Requires base64 in addition to curl and jq (used to encode the CODEOWNERS file content for the API).


Close Archived Repository Security Alerts

Script: org-admin/github-close-archived-repo-security-alerts/github-close-archived-repo-security-alerts.sh

Dismisses or resolves all open security alerts (Dependabot, code scanning, and secret scanning) across all repositories in a GitHub organisation. Generates a CSV report of dismissed alerts.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"

Usage:

cd org-admin/github-close-archived-repo-security-alerts

# Preview which alerts would be dismissed (no changes)
./github-close-archived-repo-security-alerts.sh --dry-run

# Dismiss only Dependabot alerts
./github-close-archived-repo-security-alerts.sh --type dependabot

# Dismiss all alert types
./github-close-archived-repo-security-alerts.sh

Options:

Flag Description Default
--type <type> Alert type: dependabot | code-scanning | secret-scanning | all all
--dry-run List alerts without dismissing them
Variable Description Default
DEPENDABOT_REASON Dismiss reason for Dependabot alerts tolerable_risk
CODE_SCANNING_REASON Dismiss reason for code scanning alerts won't fix
SECRET_SCANNING_RESOLUTION Resolution for secret scanning alerts wont_fix

What it does:

  • Enumerates all repositories in the organization
  • For each configured alert type, pages through all open alerts
  • Dismisses or resolves alerts with the configured reason
  • Generates a timestamped CSV report in the reports/ subdirectory

Important

Requires a token with security_events and repo scope. Use --dry-run first to preview the scope of changes.


Enable Issues

Script: org-admin/github-enable-issues/github-enable-issues.sh

Enables the Issues feature on every repository in a GitHub organisation that currently has it disabled. Skips archived repositories.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"

Usage:

cd org-admin/github-enable-issues
./github-enable-issues.sh --dry-run   # Preview only
./github-enable-issues.sh             # Apply changes
Flag Description
--dry-run List repositories that would be updated without making changes

What it does:

  • Iterates all non-archived repositories in the organization (paginated)
  • Identifies repositories with Issues disabled
  • Enables Issues on each matching repository via the PATCH API

Get Repository List

Script: org-admin/github-get-repo-list/github-get-repo-list.sh

Lists all repositories in a GitHub organisation and outputs their metadata to stdout in CSV format.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"

Usage:

cd org-admin/github-get-repo-list
./github-get-repo-list.sh
./github-get-repo-list.sh > repos.csv

What it does:

  • Fetches all repositories (paginated, 100 per page)
  • Outputs a CSV row per repository with: full name, owner, visibility, URL, description, fork flag, pushed/created/updated timestamps

Migrate Internal Repositories to Private

Script: org-admin/github-migrate-internal-repos-to-private/github-migrate-internal-repos-to-private.sh

Converts all repositories with "internal" visibility to "private" in a GitHub organisation.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"

Usage:

cd org-admin/github-migrate-internal-repos-to-private
./github-migrate-internal-repos-to-private.sh

What it does:

  • Fetches all repositories with internal visibility (paginated)
  • Converts each to private via the PATCH API
  • Logs success or failure for each repository

Warning

Converting repositories from internal to private removes access from members of other organisations in the enterprise. This operation cannot be undone via the API.


Monthly Issues Report

Script: reporting/github-monthly-issues-report/github-monthly-issues-report.sh

Generates HTML-formatted statistics about issues created within a date range, filtered by labels.

Required variables:

export GITHUB_TOKEN="your_token"
export ORG="your-org"
export REPO="your-repo"
export MONTH_START="2025-10-01"
export MONTH_END="2025-10-31"

Usage:

cd reporting/github-monthly-issues-report
./github-monthly-issues-report.sh

What it does:

  • Filters issues by creation date range
  • Filters by label (currently hardcoded to Linked [AC])
  • Uses timeline API to track who applied labels
  • Generates author and contributor statistics
  • Outputs HTML report to output.txt

Note

This script includes a hardcoded label filter. Edit the script to modify the filter criteria.


Repository Permissions Report

Script: reporting/github-repo-permissions-report/github-repo-permissions-report.sh

Exports repository user/team permissions to CSV and identifies who can bypass pull request approval requirements, from both branch protection rules and repository rulesets.

Prerequisites:

  • gh — GitHub CLI (authenticated via gh auth login)
  • jq — JSON processor

Usage:

cd reporting/github-repo-permissions-report
./github-repo-permissions-report.sh -r OWNER/REPO
./github-repo-permissions-report.sh -r OWNER/REPO -b main -o report.csv

Options:

Flag Description Default
-r, --repo OWNER/REPO Target repository (required)
-b, --branch NAME Branch to evaluate Repository default branch
-o, --output FILE Output CSV path OWNER-REPO-permissions-BRANCH-YYYYMMDD.csv

What it does:

  • Fetches all collaborators and teams with repository access
  • Fetches branch protection rules and repository rulesets
  • Identifies every principal that can bypass PR approval requirements
  • Produces a CSV with two record types: permission (all users/teams) and bypass_actor (explicit bypass entries)

Note

Uses the gh CLI for all API calls. Authenticate via gh auth login before running.


Copilot Enterprise Report

Script: reporting/github-copilot-report/github-copilot-report.sh

Generates a GitHub Copilot Enterprise licence and usage report. Shows every licensed user, their plan type, pool credit contribution, and actual AI credit consumption for the current billing month. Optionally enriches data with Entra ID department information.

Prerequisites:

  • gh — GitHub CLI authenticated with read:enterprise and manage_billing:enterprise scopes
  • az — Azure CLI (optional, for Entra ID department enrichment)
  • jq — JSON processor

Required variables:

export GITHUB_ENTERPRISE="your-enterprise-slug"

# Optional: Entra ID UPN domain for users without a public GitHub email
export UPN_DOMAIN="example.com"        # e.g. 'john_example' → john@example.com

# Optional: override the credits-per-seat value shown in your billing portal
export CREDITS_PER_SEAT_OVERRIDE="1900"

Usage:

cd reporting/github-copilot-report

# Authenticate first
gh auth refresh --scopes "read:enterprise,manage_billing:enterprise"
az login   # optional, for department enrichment

./github-copilot-report.sh -e YOUR-ENTERPRISE
./github-copilot-report.sh -e YOUR-ENTERPRISE -d example.com
./github-copilot-report.sh -e YOUR-ENTERPRISE --no-entra

What it does:

  • Fetches all Copilot seats across the enterprise (deduplicated by user)
  • Fetches per-user AI credit consumption for the current billing month
  • Fetches enterprise-level model usage metrics (last 28 days)
  • Optionally enriches each user with Entra ID department and job title via az rest
  • Outputs a CSV and a formatted console summary with department breakdown and model usage tables

Important

Requires an enterprise owner or billing manager token. Run gh auth refresh --scopes "read:enterprise,manage_billing:enterprise" before executing.

Note

Uses the gh CLI and (optionally) the az CLI. The Entra ID enrichment is skipped automatically if az is not logged in, or can be disabled with --no-entra.


Get Consumed Licenses

Script: enterprise/github-get-consumed-licenses/github-get-consumed-licenses.sh

Retrieves license consumption metrics for a GitHub Enterprise account.

Required variables:

export GITHUB_TOKEN="your_enterprise_token"  # Must have read:enterprise scope
export ENTERPRISE="your-enterprise"

Usage:

cd enterprise/github-get-consumed-licenses
./github-get-consumed-licenses.sh

Output:

Total seats consumed: 150
Total seats purchased: 200

What it does:

  • Calls the enterprise consumed-licenses endpoint
  • Uses Bearer token authentication (unlike other scripts)
  • Returns seat consumption and purchase counts

Important

This script requires an enterprise-level token with read:enterprise scope. Organization tokens will not work.


Add Enterprise Team Read Permissions

Script: enterprise/github-add-enterprise-team-read-permissions/github-add-enterprise-team-read-permissions.sh

Assigns the built-in "All-repository read" organisation role to a specified enterprise team in every organisation within a GitHub Enterprise account. This grants read access to all current and future repositories without requiring per-repository assignments.

Required variables:

export GITHUB_TOKEN="your_enterprise_token"   # Must have admin:enterprise scope
export ENTERPRISE="my-enterprise"
export ENTERPRISE_TEAM_SLUG="platform-team"

Usage:

cd enterprise/github-add-enterprise-team-read-permissions
./github-add-enterprise-team-read-permissions.sh

What it does:

  • Enumerates all organizations in the enterprise via GraphQL (cursor-based pagination)
  • Looks up the enterprise team ID and the target org role ID in each organization
  • Assigns the all_repo_read org role to the enterprise team in every organization
Variable Description Default
ALL_REPO_READ_ROLE_NAME Org role name to assign all_repo_read

Important

Requires an enterprise-level token with admin:enterprise scope. Organization tokens will not work.


Dockerfile Discovery

Script: enterprise/github-dockerfile-discovery/github-dockerfile-discovery.sh

Searches all organisations in a GitHub Enterprise account for Dockerfiles, extracts base image references from FROM instructions, and generates CSV reports to identify common base images across the estate.

Required variables:

export GITHUB_TOKEN="your_token"
export ENTERPRISE="my-enterprise"

Usage:

cd enterprise/github-dockerfile-discovery
./github-dockerfile-discovery.sh

What it does:

  • Discovers all orgs in the enterprise via GraphQL, or uses the ORGS override
  • Uses the GitHub code search API to locate Dockerfiles in each org
  • Fetches and parses each Dockerfile to extract FROM instructions (including multi-stage builds)
  • Generates three timestamped reports in REPORT_DIR:
    • dockerfile_discovery_detail_*.csv — one row per image reference
    • dockerfile_discovery_summary_*.csv — image usage counts
    • dockerfile_discovery_summary_*.txt — plain-text summary
Variable Description Default
REPORT_DIR Output directory for reports ./reports
ORGS Comma-separated org list; skips enterprise lookup
ORG_FILTER ERE regex to keep only matching org names
ORG_EXCLUDE ERE regex to drop matching org names
SEARCH_SLEEP Seconds between code-search requests 2
CONTENT_SLEEP Seconds between content-fetch requests 1

Note

Code search is heavily rate-limited. Increase SEARCH_SLEEP and CONTENT_SLEEP if you encounter 403 responses.


Get Public Repositories

Script: enterprise/github-get-public-repos/github-get-public-repos.sh

Lists all repositories with public visibility across every organisation in a GitHub Enterprise account and writes a timestamped CSV report.

Required variables:

export GITHUB_TOKEN="your_token"
export ENTERPRISE="my-enterprise"

Usage:

cd enterprise/github-get-public-repos
./github-get-public-repos.sh
./github-get-public-repos.sh > public_repos.csv

What it does:

  • Discovers all orgs in the enterprise, or uses the ORGS override
  • Fetches all repositories in each org and filters to public visibility
  • Writes a timestamped CSV report in REPORT_DIR with: org, repo name, URL, description, created date, last pushed date
Variable Description Default
REPORT_DIR Output directory for reports ./reports
ORGS Comma-separated org list; skips enterprise lookup
ORG_FILTER ERE regex to keep only matching org names
ORG_EXCLUDE ERE regex to drop matching org names

Organize Starred Repositories

Script: personal/github-organize-stars/github-organize-stars.sh

Fetches all your starred repositories and organizes them into GitHub Lists using customizable categorization rules.

Prerequisites:

  • gh - GitHub CLI (authenticated via gh auth login)
  • jq - Command-line JSON processor

Usage:

cd personal/github-organize-stars
./github-organize-stars.sh              # Interactive (shows plan, asks to confirm)
./github-organize-stars.sh --dry-run    # Preview only, no changes made
./github-organize-stars.sh -y           # Skip confirmation prompt
./github-organize-stars.sh --show-repos # Also list repo names in each category
./github-organize-stars.sh --no-cache   # Force re-fetch stars from GitHub

What it does:

  • Fetches all starred repositories via the GraphQL API (paginated)
  • Categorizes each repo by primary language, GitHub topics, and repo name keywords
  • Creates new GitHub Lists and adds repos in batches of 25
  • Caches fetched stars locally at ~/.cache/gh-star-organizer/stars.json to speed up re-runs
  • Shows a categorization plan and prompts for confirmation before making changes

Customizing categories:

Edit the RULES array in the script. Each rule is a |-delimited string:

"List Name|LANGUAGES|TOPICS|NAME_KEYWORDS"
  • LANGUAGES — comma-separated primary language names (case-insensitive)
  • TOPICS — comma-separated GitHub topic slugs
  • NAME_KEYWORDS — comma-separated substrings matched against the repo name

The first matching rule wins, so order matters. Place more specific rules (e.g., AI) before general ones (e.g., Security).

Note

This script uses the gh CLI for all API calls (GraphQL) rather than curl. Ensure you are authenticated via gh auth login before running.

Shared Library: lib/github-common.sh

All scripts can leverage a shared utility library for common operations like validation, colored output, and API helpers. The library is optional—scripts work standalone without it—but sourcing it reduces code duplication and adds helpful utilities.

Available Functions

Output formatting:

  • print_status <message> — Blue INFO message
  • print_success <message> — Green SUCCESS message
  • print_warning <message> — Yellow WARNING message
  • print_error <message> — Red ERROR message (to stderr)

Validation:

  • require_env_var <VAR_NAME> [description] — Exit if environment variable is empty
  • 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

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

Using the Shared Library in Scripts

Source the library from your script:

#!/bin/bash
set -euo pipefail

GITHUB_TOKEN=${GITHUB_TOKEN:-''}
ORG=${ORG:-''}
API_URL_PREFIX=${API_URL_PREFIX:-'https://api.github.com'}

# Source shared library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=../../lib/github-common.sh
source "${SCRIPT_DIR}/../../lib/github-common.sh"

# Now use library functions
require_env_var GITHUB_TOKEN "GitHub Personal Access Token"
require_env_var ORG "GitHub Organization"
validate_github_token

print_status "Processing organization: ${ORG}"
# ... rest of script

Using Scripts in GitHub Actions

All scripts can be easily integrated into GitHub Actions workflows. Here are practical examples:

Example 1: Grant Team Permissions on Repository Changes

Automatically update team permissions when ownership rules change:

name: Update Repository Permissions
on:
  push:
    branches: [main]
    paths:
      - '.github/CODEOWNERS'  # Trigger when ownership changes

jobs:
  update-permissions:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Grant team permissions to all repos
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ORG: my-org
          REPO_PUSH: developers maintainers
          REPO_TRIAGE: support-team
        run: |
          ./org-admin/github-add-repo-permissions/github-add-repo-permissions.sh

Example 2: Archive Old Repositories Monthly

Schedule automated archival of stale repositories:

name: Archive Old Repositories
on:
  schedule:
    # Run monthly on the 1st at 9 AM UTC
    - cron: '0 9 1 * *'

jobs:
  archive-old:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Archive repositories not updated in 5 years
        env:
          GITHUB_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
          ORG: my-org
          YEARS_THRESHOLD: 5
        run: |
          ./org-admin/github-archive-old-repos/github-archive-old-repos.sh
      
      - name: Upload report as artifact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: archive-report
          path: org-admin/github-archive-old-repos/reports/
          retention-days: 30

Example 3: Create Repositories from Template

Allow manual repository creation with pre-configured settings via workflow dispatch:

name: Create New Repository from Template
on:
  workflow_dispatch:
    inputs:
      repo-name:
        description: 'Repository name'
        required: true
        type: string
      repo-owner:
        description: 'Team slug for admin permissions'
        required: true
        type: string

jobs:
  create-repo:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Create repository from template
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ORG: my-org
          TEMPLATE_REPO: template-repo
          REPO_ADMIN: ${{ github.event.inputs.repo-owner }}
          REPO_WRITE: developers
          CD_USERNAME: github-actions[bot]
          CD_GITHUB_TOKEN: ${{ secrets.CD_TOKEN }}
        run: |
          ./org-admin/github-repo-from-template/github-repo-from-template.sh "${{ github.event.inputs.repo-name }}"
      
      - name: Log success
        if: success()
        run: |
          echo "✅ Repository ${{ github.event.inputs.repo-name }} created successfully!"

Example 4: Weekly Dockerfile Discovery Report

Track base images across your enterprise:

name: Discover Dockerfiles in Enterprise
on:
  schedule:
    # Run weekly on Monday at 12 PM UTC
    - cron: '0 12 * * 1'

jobs:
  discover-dockerfiles:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Discover Dockerfiles across enterprise
        env:
          GITHUB_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
          ENTERPRISE: my-enterprise
          REPORT_DIR: ./reports
        run: |
          mkdir -p ./reports
          ./enterprise/github-dockerfile-discovery/github-dockerfile-discovery.sh
      
      - name: Upload reports as artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: dockerfile-reports
          path: reports/
          retention-days: 60
      
      - name: Commit reports to repository
        if: success()
        run: |
          git add reports/ || true
          git diff --quiet && git diff --staged --quiet || (
            git config user.name "github-actions[bot]"
            git config user.email "github-actions[bot]@users.noreply.github.com"
            git commit -m "chore: update dockerfile discovery reports"
            git push
          )

GitHub Actions Best Practices

Use separate secrets for sensitive operations:

env:
  GITHUB_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}      # For org-level changes
  CD_GITHUB_TOKEN: ${{ secrets.CD_BOT_TOKEN }}      # For CD user operations

Capture logs for audit trails:

- name: Run script with logging
  run: |
    ./org-admin/github-add-repo-permissions/github-add-repo-permissions.sh 2>&1 | tee -a execution.log
    
- name: Upload execution log
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: execution-logs
    path: execution.log

Use workflow_dispatch for manual operations:

on:
  workflow_dispatch:
    inputs:
      org:
        description: 'Organization name'
        required: true

Protect destructive operations: Consider adding approval steps or environment protection rules before running destructive scripts (like archive or delete operations).

Best Practices

Test on a test organization first Always validate on a non-production organization before running against production resources. Several scripts support a --dry-run flag (github-close-archived-repo-security-alerts, github-enable-issues, github-organize-stars) that previews changes without applying them.

Rate limiting Scripts include built-in delays (5 seconds between repository operations) to stay within GitHub's rate limits. For large organizations with hundreds of repos, expect longer execution times.

Audit trails Capture output for compliance and troubleshooting:

./script.sh 2>&1 | tee execution-$(date +%Y%m%d).log

Team slugs vs display names GitHub API uses team slugs (lowercase, hyphenated). Example: "Platform Team" → platform-team. Find team slugs in your organization settings or via the API.

GitHub Enterprise Server These scripts support GHES. Set custom endpoints:

export API_URL_PREFIX="https://github.company.com/api/v3"
export GIT_URL_PREFIX="https://github.company.com"

Resources

About

Bash scripts to work with the Github API

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Contributors

Languages