Update repository settings in bulk across multiple GitHub repositories.
- 🔧 Update pull request merge strategies (squash, merge, rebase)
- ✅ Configure auto-merge settings
- 🗑️ Enable automatic branch deletion after merge
- 🔄 Configure pull request branch update suggestions
- 📊 Enable default CodeQL code scanning
- 🏷️ Manage repository topics
- � Sync dependabot.yml files across repositories via pull requests
- �📝 Support multiple repository input methods (comma-separated, YAML file, or all org repos)
- 🔍 Dry-run mode with change preview and intelligent change detection
- 📋 Per-repository overrides via YAML configuration
- 📊 Comprehensive logging showing before/after values for all changes
- name: Update Repository Settings
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ steps.app-token.outputs.token }}
repositories: 'owner/repo1,owner/repo2,owner/repo3'
allow-squash-merge: true
allow-merge-commit: false
delete-branch-on-merge: true
enable-default-code-scanning: true
topics: 'javascript,github-actions,automation'
dry-run: ${{ github.event_name == 'pull_request' }} # dry run if PRCreate a repos.yml file:
repos:
- repo: owner/repo1
allow-squash-merge: false # Override global setting
topics: 'javascript,special-config'
- repo: owner/repo2 # Uses global defaults
- repo: owner/repo3
enable-default-code-scanning: falseUse in workflow:
- name: Update Repository Settings with Overrides
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ steps.app-token.outputs.token }}
repositories-file: 'repos.yml'
# Global defaults (overridden per-repo in YAML)
allow-squash-merge: true
delete-branch-on-merge: true
enable-default-code-scanning: true
topics: 'javascript,github-actions'Sync a dependabot.yml file to .github/dependabot.yml in target repositories via pull requests:
- name: Sync Dependabot Config
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ steps.app-token.outputs.token }}
repositories-file: 'repos.yml'
dependabot-yml: './config/dependabot/npm-actions.yml'
dependabot-pr-title: 'chore: update dependabot.yml'Or with repo-specific overrides in repos.yml:
repos:
- repo: owner/repo1
dependabot-yml: './config/dependabot/npm-actions.yml'
- repo: owner/repo2
dependabot-yml: './config/dependabot/python.yml'
- repo: owner/repo3
dependabot.yml: './github/dependabot.yml' # use the same config that this repo is usingBehavior:
- If
.github/dependabot.ymldoesn't exist, it creates it and opens a PR - If it exists but differs, it updates it via PR
- If content is identical, no PR is created
- PRs are created/updated using the GitHub API so commits are verified
- Updates existing open PRs instead of creating duplicates
- name: Update All Org Repositories
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ steps.app-token.outputs.token }}
repositories: 'all'
owner: 'my-organization'
allow-squash-merge: true
delete-branch-on-merge: truePreview changes without applying them:
- name: Preview Changes
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ steps.app-token.outputs.token }}
repositories: 'owner/repo1,owner/repo2'
allow-squash-merge: true
dry-run: true
# dry-run true in PRs, false otherwise example:
# dry-run: ${{ github.event_name == 'pull_request' }}Output shows what would change:
🔍 Would update owner/repo1
📝 Settings changes:
allow-squash-merge: false → true
delete-branch-on-merge: false → true
📦 Would create .github/dependabot.yml via PR
| Input | Description | Required | Default |
|---|---|---|---|
github-token |
GitHub token for API access (requires repo scope or GitHub App with repository administration) |
Yes | - |
github-api-url |
GitHub API URL (e.g., https://api.github.com for GitHub.com or https://ghes.domain.com/api/v3 for GHES). Instance URL is auto-derived. |
No | ${{ github.api_url }} |
repositories |
Comma-separated list of repositories (owner/repo) or "all" for all org/user repos |
No* | - |
repositories-file |
Path to YAML file containing repository list | No* | - |
owner |
Owner (user or organization) name - required when using repositories: "all" |
No | - |
allow-squash-merge |
Allow squash merging pull requests | No | - |
allow-merge-commit |
Allow merge commits for pull requests | No | - |
allow-rebase-merge |
Allow rebase merging pull requests | No | - |
allow-auto-merge |
Allow auto-merge on pull requests | No | - |
delete-branch-on-merge |
Automatically delete head branches after pull requests are merged | No | - |
allow-update-branch |
Always suggest updating pull request branches | No | - |
enable-default-code-scanning |
Enable default code scanning setup | No | - |
topics |
Comma-separated list of topics to set on repositories (replaces existing topics) | No | - |
dependabot-yml |
Path to a dependabot.yml file to sync to .github/dependabot.yml in target repositories |
No | - |
dependabot-pr-title |
Title for pull requests when updating dependabot.yml | No | chore: update dependabot.yml |
dry-run |
Preview changes without applying them (logs what would be changed) | No | false |
* Either repositories or repositories-file must be provided
| Output | Description |
|---|---|
updated-repositories |
Number of repositories successfully updated |
failed-repositories |
Number of repositories that failed to update |
results |
JSON array of update results for each repository |
For better security and rate limits, use a GitHub App:
- Create a GitHub App with the following permissions:
- Repository Administration: Read and write (required for updating repository settings)
- Contents: Read and write (required if syncing
dependabot.yml) - Pull Requests: Read and write (required if syncing
dependabot.yml)
- Install it to your organization/repositories
- Add
APP_IDandAPP_PRIVATE_KEYas repository secrets
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Update Repository Settings
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ steps.app-token.outputs.token }}
# ... other inputsAlternatively, use a PAT with repo scope:
- name: Update Repository Settings
uses: joshjohanning/bulk-github-repo-settings-sync-action@v1
with:
github-token: ${{ secrets.PAT_TOKEN }}
# ... other inputsThe repositories-file supports both simple lists and per-repository overrides:
repos:
- owner/repo1
- owner/repo2
- owner/repo3repos:
- repo: owner/repo1
allow-squash-merge: false # Override global setting
topics: 'javascript,custom-topic'
- repo: owner/repo2 # Uses global defaults
- repo: owner/repo3
enable-default-code-scanning: false
dependabot-yml: './github/dependabot-configs/custom-dependabot.yml'Priority: Repository-specific settings override global defaults from action inputs.
- Settings not specified will remain unchanged
- Topics replace all existing repository topics
- Dependabot.yml syncing creates pull requests for review before merging
- Dependabot.yml PRs use the GitHub API ensuring verified commits
- Failed updates are logged as warnings but don't fail the action
- Access denied repositories are skipped with warnings - ensure your GitHub App has:
- Repository Administration permissions
- Is installed on all target repositories
- CodeQL scanning may not be available for all languages
See CONTRIBUTING.md for development setup, testing, and contribution guidelines.