{"id":32106883,"url":"https://github.com/klcodanr/github-settings-sync","last_synced_at":"2025-10-20T08:39:49.598Z","repository":{"id":296714499,"uuid":"994241020","full_name":"klcodanr/github-settings-sync","owner":"klcodanr","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-15T14:17:34.000Z","size":668,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-15T16:17:25.810Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/klcodanr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-01T14:24:51.000Z","updated_at":"2025-09-15T14:17:37.000Z","dependencies_parsed_at":"2025-07-20T14:25:22.573Z","dependency_job_id":"e753e549-e24a-474c-9772-95a4dde300e1","html_url":"https://github.com/klcodanr/github-settings-sync","commit_stats":null,"previous_names":["klcodanr/github-settings-sync"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/klcodanr/github-settings-sync","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klcodanr%2Fgithub-settings-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klcodanr%2Fgithub-settings-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klcodanr%2Fgithub-settings-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klcodanr%2Fgithub-settings-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/klcodanr","download_url":"https://codeload.github.com/klcodanr/github-settings-sync/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klcodanr%2Fgithub-settings-sync/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279448472,"owners_count":26171962,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-17T02:00:07.504Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-20T08:39:48.596Z","updated_at":"2025-10-20T08:39:49.593Z","avatar_url":"https://github.com/klcodanr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitHub Settings Sync\n\n[![npm version](https://img.shields.io/npm/v/github-settings-sync.svg)](https://www.npmjs.com/package/github-settings-sync)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Release](https://github.com/klcodanr/github-settings-sync/actions/workflows/release.yml/badge.svg)](https://github.com/klcodanr/github-settings-sync/actions/workflows/release.yml)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\nA command-line tool to synchronize repository settings across a GitHub organization.\n\n## Features\n\n- Synchronize repository settings across all repositories in an organization\n- Manage repository collaborators and their roles\n- Configure branch protection rules\n- Synchronize file contents from local files to repositories\n- Customizable settings via JSON file\n- Filter repositories by name pattern, labels, or language\n- Supports pagination for organizations with many repositories\n- Detailed logging of operations\n- Support for GitHub Enterprise via custom base URL\n\n## Prerequisites\n\n- Node.js 18 or higher\n- GitHub Personal Access Token with `repo` and `admin:org` scopes\n\n\n## Global Installation\n\nnpm install -g github-settings-sync\n\n## Local Installation\n\n1. Clone this repository\n2. Install dependencies:\n   ```bash\n   npm install\n   ```\n3. Install the package globally (optional):\n   ```bash\n   npm install -g .\n   ```\n\n## Usage\n\nRun the tool using the global command:\n\n```bash\ngithub-settings-sync --org my-org --settings settings.json [options]\n```\n\n### Command Line Arguments\n\nRequired Arguments:\n\n- `-o, --org \u003corganization\u003e`: GitHub organization name\n- `-s, --settings \u003cpath\u003e`: Path to JSON file with repository settings\n\nAuthentication Options:\n\n- `-t, --token \u003ctoken\u003e`: GitHub Personal Access Token (overrides GITHUB_TOKEN env var)\n- `-u, --base-url \u003curl\u003e`: GitHub API base URL (for GitHub Enterprise)\n\nFilter Options:\n\n- `-n, --name-pattern \u003cpattern\u003e`: Regular expression pattern to match repository names to include\n- `-l, --label \u003clabel\u003e`: Only process repositories that have this label\n- `-lang, --language \u003clanguage\u003e`: Only process repositories with this primary language\n\nExamples:\n\n```bash\n# Basic usage with environment variables\ngithub-settings-sync --org my-org --settings settings.json\n\n# Using CLI token instead of environment variable\ngithub-settings-sync --org my-org --settings settings.json --token ghp_xxxxxxxxxxxx\n\n# Using GitHub Enterprise\ngithub-settings-sync --org my-org --settings settings.json --base-url https://github.enterprise.com/api/v3\n\n# Only process repositories with names containing 'api' or 'service'\ngithub-settings-sync --org my-org --settings settings.json --name-pattern \"api|service\"\n\n# Only process repositories with the 'active' label\ngithub-settings-sync --org my-org --settings settings.json --label active\n\n# Only process Python repositories\ngithub-settings-sync --org my-org --settings settings.json --language python\n\n# Combine multiple filters (repositories must match ALL specified filters)\ngithub-settings-sync --org my-org --settings settings.json --name-pattern \"api\" --language python\n```\n\nNote: If no filters are specified, all repositories will be processed. When multiple filters are specified, repositories must match ALL specified filters to be processed.\n\n### Settings File\n\nCreate a JSON file with your desired repository settings. Here's an example of the configuration format:\n\n```json\n{\n  \"repository\": {\n    \"has_issues\": true,\n    \"has_wiki\": false,\n    \"has_projects\": true,\n    \"allow_squash_merge\": true,\n    \"allow_merge_commit\": false,\n    \"allow_rebase_merge\": true,\n    \"delete_branch_on_merge\": true,\n    \"allow_auto_merge\": true,\n    \"allow_update_branch\": true\n  },\n  \"collaborators\": [\n    {\n      \"username\": \"user1\",\n      \"role\": \"admin\"\n    },\n    {\n      \"username\": \"user2\",\n      \"role\": \"write\"\n    },\n    {\n      \"username\": \"user3\",\n      \"role\": \"read\"\n    }\n  ],\n  \"branch_protection\": {\n    \"main\": {\n      \"enforce_admins\": true,\n      \"required_status_checks\": {\n        \"strict\": true,\n        \"contexts\": [\"ci/build\", \"ci/test\"]\n      },\n      \"required_pull_request_reviews\": {\n        \"required_approving_review_count\": 2,\n        \"dismiss_stale_reviews\": true,\n        \"require_code_owner_reviews\": true\n      },\n      \"allow_force_pushes\": false,\n      \"allow_deletions\": false\n    },\n    \"develop\": {\n      \"enforce_admins\": false,\n      \"required_status_checks\": {\n        \"strict\": true,\n        \"contexts\": [\"ci/build\"]\n      },\n      \"required_pull_request_reviews\": {\n        \"required_approving_review_count\": 1,\n        \"dismiss_stale_reviews\": true\n      },\n      \"allow_force_pushes\": false,\n      \"allow_deletions\": false\n    }\n  },\n  \"files\": [\n    {\n      \"path\": \".gitignore\",\n      \"localPath\": \"./templates/.gitignore\"\n    },\n    {\n      \"path\": \"CONTRIBUTING.md\",\n      \"localPath\": \"./templates/CONTRIBUTING.md\"\n    }\n  ]\n}\n```\n\n#### Repository Settings\n\nThe `repository` object contains all repository-level settings:\n\n- `has_issues`: Enable/disable issues\n- `has_wiki`: Enable/disable wiki\n- `has_projects`: Enable/disable projects\n- `allow_squash_merge`: Enable/disable squash merges\n- `allow_merge_commit`: Enable/disable merge commits\n- `allow_rebase_merge`: Enable/disable rebase merges\n- `delete_branch_on_merge`: Enable/disable automatic branch deletion\n- `allow_auto_merge`: Enable/disable auto-merge\n- `allow_update_branch`: Enable/disable branch updates\n\n#### Collaborator Management\n\nThe `collaborators` array can specify users and their roles. Available roles are:\n\n- `admin`: Full repository access\n- `maintain`: Repository maintenance access\n- `write`: Push access\n- `triage`: Issue and PR triage access\n- `read`: Read-only access\n\nThe script will:\n\n- Add new collaborators with specified roles\n- Update roles for existing collaborators if they've changed\n- Preserve existing collaborators not in the list\n\nNote: The script will not remove any existing collaborators. It only adds new ones and updates roles for existing ones.\n\n#### Branch Protection Rules\n\nThe `branch_protection` object maps branch names to their protection rules. Each branch can have the following settings:\n\n- `enforce_admins`: Whether to enforce restrictions for administrators\n- `required_status_checks`: Status check requirements\n  - `strict`: Require branches to be up to date before merging\n  - `contexts`: Array of required status check contexts\n- `required_pull_request_reviews`: Pull request review requirements\n  - `required_approving_review_count`: Number of required approving reviews\n  - `dismiss_stale_reviews`: Dismiss stale pull request approvals\n  - `require_code_owner_reviews`: Require review from Code Owners\n- `allow_force_pushes`: Allow force pushes to the branch\n- `allow_deletions`: Allow deletion of the branch\n\nExample:\n\n```json\n{\n  \"branch_protection\": {\n    \"main\": {\n      \"enforce_admins\": true,\n      \"required_status_checks\": {\n        \"strict\": true,\n        \"contexts\": [\"ci/build\"]\n      },\n      \"required_pull_request_reviews\": {\n        \"required_approving_review_count\": 2,\n        \"dismiss_stale_reviews\": true\n      },\n      \"allow_force_pushes\": false\n    }\n  }\n}\n```\n\nThe script will:\n\n- Apply protection rules to each specified branch\n- Update existing protection rules if they differ from the configuration\n- Log success or failure for each branch protection update\n\n#### File Synchronization\n\nThe `files` array specifies files to be synchronized from local paths to repositories. Each file configuration requires:\n\n- `path`: Path in the repository where the file should be (e.g., `.gitignore`, `CONTRIBUTING.md`)\n- `localPath`: Path to the local file that contains the desired content\n\nExample:\n\n```json\n{\n  \"files\": [\n    {\n      \"path\": \".gitignore\",\n      \"localPath\": \"./templates/.gitignore\"\n    },\n    {\n      \"path\": \"docs/CONTRIBUTING.md\",\n      \"localPath\": \"./templates/CONTRIBUTING.md\"\n    }\n  ]\n}\n```\n\nThe script will:\n\n- Read the content of each local file\n- Check if the file exists in the repository\n- Create the file if it doesn't exist\n- Update the file if its content differs from the local file\n- Skip the file if its content matches the local file\n- Log success or failure for each file operation\n\nThis is useful for maintaining consistent files across repositories, such as:\n\n- `.gitignore` files\n- `CONTRIBUTING.md` guidelines\n- `README.md` templates\n- Configuration files\n- License files\n\n## Error Handling\n\nThe script will:\n\n- Log errors for individual repository updates but continue processing other repositories\n- Exit with an error code if there are critical failures (e.g., authentication issues, missing settings)\n- Provide detailed error messages for troubleshooting\n- Show a summary of processed and skipped repositories\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklcodanr%2Fgithub-settings-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fklcodanr%2Fgithub-settings-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklcodanr%2Fgithub-settings-sync/lists"}