Skip to content

Bulk GitHub Repository Sync

Actions
🔄 Sync GitHub repositories between organizations with visibility control, Actions management, and archiving
v1.0.0
Latest
Star (0)

bulk-github-repo-sync-action

🔄 Sync GitHub repositories from source to target organizations using mirror cloning. Creates target repositories if they don't exist, with support for visibility control, Actions disabling, and archiving.

Features

  • 🔄 Mirror cloning - Complete repository sync including all branches and tags
  • 🏗️ Automatic repository creation - Creates target repos if they don't exist
  • 👁️ Visibility control - Set repository visibility per repo (private/public/internal)
  • 🚫 GitHub Actions management - Disable Actions on target repositories
  • 📦 Repository archiving - Archive repositories after sync (with smart unarchive/re-archive)
  • 🌐 Multi-server support - Sync between github.com and GitHub Enterprise Server
  • 📊 Post-run analysis - Detailed sync summary with statistics

Example Usage

Tip

This example uses personal access tokens for simplicity. See the GitHub Apps section below for the recommended approach using GitHub Apps.

- uses: actions/checkout@v5
- name: Bulk GitHub Repository Sync
  uses: joshjohanning/bulk-github-repo-sync-action@v1
  with:
    repo-list-file: repos.yml
    source-github-token: ${{ secrets.SOURCE_GITHUB_TOKEN }}
    target-github-token: ${{ secrets.TARGET_GITHUB_TOKEN }}
    overwrite-repo-visibility: true # overwrite repo visibility with what is in yml file; defaults to false
    force-push: false # force push to target repos (overwrites history); defaults to false
    ### these parameters are only needed if either your source or target is NOT github.com
    # source-github-url: ${{ github.server_url }} # defaults to https://github.com
    # source-github-api-url: ${{ github.api_url }} # defaults to https://api.github.com
    # target-github-url: ${{ github.server_url }} # defaults to https://github.com
    # target-github-api-url: ${{ github.api_url }} # defaults to https://api.github.com  

Repository List Format

The repository list uses YML format with per-repository configuration:

repos:
  - source: source-org/source-repo-1
    target: target-org/target-repo-1
    visibility: private # Optional: private, public, or internal (defaults to private)
    disable-github-actions: true # Optional: disable Actions on target repo (defaults to true)
    archive-after-sync: false # Optional: archive repo after sync (defaults to false)

Sample Configuration

See sample file.

Usage with GitHub Apps (recommended)

You can use a personal access token, but it is recommended to use GitHub Apps instead:

Note

Required GitHub App Permissions:

  • Source App: Repository Read access to contents and metadata
  • Target App: Repository Read and Write access to actions, administration, contents, and metadata
      - uses: actions/checkout@v5
      # source
      - uses: actions/create-github-app-token@v2
        id: source-app-token
        with:
          app-id: ${{ vars.SOURCE_APP_ID }}
          private-key: ${{ secrets.SOURCE_APP_PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}
      # target
      - uses: actions/create-github-app-token@v2
        id: target-app-token
        with:
          app-id: ${{ vars.TARGET_APP_ID }}
          private-key: ${{ secrets.TARGET_APP_PRIVATE_KEY }}
          owner: joshjohanning-emu
      - name: Bulk GitHub Repository Sync
        uses: joshjohanning/bulk-github-repo-sync-action@v1
        with:
          repo-list-file: repos.yml
          source-github-token: ${{ steps.source-app-token.outputs.token }}
          target-github-token: ${{ steps.target-app-token.outputs.token }}
          overwrite-repo-visibility: true # overwrite repo visibility with what is in yml file; defaults to false
          # force push to target repos (overwrites history); defaults to false

Configuration Options

Per-Repository Settings (YML)

Setting Description Default
source Source repository in owner/repo format -
target Target repository in owner/repo format -
visibility Repository visibility (private/public/internal) private
disable-github-actions Disable GitHub Actions on target repository true
archive-after-sync Archive repository after successful sync false

Action Inputs

Input Description Required Default
repo-list-file YML file with repository configurations No -
source-github-token GitHub PAT for source repositories Yes -
target-github-token GitHub PAT for target repositories No (uses source token if not specified)
source-github-url Source GitHub server URL No ${{ github.server_url }}
target-github-url Target GitHub server URL No ${{ github.server_url }}
source-github-api-url Source GitHub API URL No ${{ github.api_url }}
target-github-api-url Target GitHub API URL No ${{ github.api_url }}
overwrite-repo-visibility Force update visibility of existing repos No false
force-push Force push to target repositories (overwrites history) No false

Local Command Line Usage

You can also run the script directly:

export SOURCE_GITHUB_TOKEN=ghp_abc
export TARGET_GITHUB_TOKEN=ghp_xyz
node src/index.js --file=repos.yml

Sample Output

=== SYNC SUMMARY ===
Total repositories: 5
✅ Successful: 5
❌ Failed: 0
🆕 Created: 2
🔄 Updated: 3
👁️  Visibility updated: 1
📦 Archived: 2

Bulk GitHub Repository Sync is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.

About

🔄 Sync GitHub repositories between organizations with visibility control, Actions management, and archiving
v1.0.0
Latest

Bulk GitHub Repository Sync is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.