🔄 GitHub Action to keep files like Action workflows or entire directories in sync between multiple repositories.
Go to file
2021-05-03 00:06:59 +00:00
.github 🔧 Add GitHub Sponsors to funding.yml (#28) 2021-04-20 20:20:11 +02:00
dist 📦 Rebuild files 2021-04-16 15:23:55 +02:00
src Add option to exclude certain files when syncing directories #26 2021-04-16 14:44:38 +02:00
.eslintrc.js 🎉 Initial commit 2021-01-08 21:47:49 +01:00
.gitignore 🙈 Don't version sync.yml 2021-01-08 22:02:41 +01:00
action.yml Add skip PR option #14 2021-03-18 17:35:02 +01:00
CHANGELOG.md 🔖 Release v1.5.1 [skip ci] 2021-05-03 00:06:59 +00:00
LICENSE 🎉 Initial commit 2021-01-08 21:47:49 +01:00
package-lock.json 🔖 Release v1.5.1 [skip ci] 2021-05-03 00:06:59 +00:00
package.json 🔖 Release v1.5.1 [skip ci] 2021-05-03 00:06:59 +00:00
README.md 📝 Add exclude example 2021-04-16 14:50:31 +02:00
release.config.js 🎉 Initial commit 2021-01-08 21:47:49 +01:00

Repo File Sync Action

Build CI GitHub David

Keep files like Action workflows or entire directories in sync between multiple repositories.

👋 Introduction

With repo-file-sync-action you can sync files, like workflow .yml files, configuration files or whole directories between repositories. It works by running a GitHub Action in your main repository everytime you push something to that repo. The action will use a sync.yml config file to figure out which files it should sync where. If it finds a file which is out of sync it will open a pull request in the target repository with the changes.

🚀 Features

  • Keep GitHub Actions workflow files in sync across all your repositories
  • Sync any file or a whole directory to as many repositories as you want
  • Easy configuration for any use case
  • Create a pull request in the target repo so you have the last say on what gets merged
  • Automatically label pull requests to integrate with other actions like automerge-action
  • Assign users to the pull request

📚 Usage

Create a .yml file in your .github/workflows folder (you can find more info about the structure in the GitHub Docs):

.github/workflows/sync.yml

name: Sync Files
on:
  push:
    branches:
      - master
  workflow_dispatch:
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repository
        uses: actions/checkout@master
      - name: Run GitHub File Sync
        uses: BetaHuhn/repo-file-sync-action@v1
        with:
          GH_PAT: ${{ secrets.GH_PAT }}

In order for the Action to access your repositories you have to specify a Personal Access token as the value for GH_PAT.

Note: GITHUB_TOKEN will not work

It is recommneded to set the token as a Repository Secret.

The last step is to create a .yml file in the .github folder of your repository and specify what file(s) to sync to which repositories:

.github/sync.yml

user/repository:
  - .github/workflows/test.yml
  - .github/workflows/lint.yml

user/repository2:
  - source: workflows/stale.yml
    dest: .github/workflows/stale.yml

More info on how to specify what files to sync where below.

Versioning

To always use the latest version of the action add the latest tag to the action name like this:

uses: BetaHuhn/repo-file-sync-action@latest

If you want to make sure that your workflow doesn't suddenly break when a new major version is released, use the v1 tag instead (recommended usage):

uses: BetaHuhn/repo-file-sync-action@v1

With the v1 tag you will always get the latest non-breaking version which will include potential bug fixes in the future. If you use a specific version, make sure to regularly check if a new version is available, or enable Dependabot.

⚙️ Action Inputs

Here are all the inputs repo-file-sync-action takes:

Key Value Required Default
GH_PAT Your Personal Access token Yes N/A
CONFIG_PATH Path to the sync configuration file No .github/sync.yml
PR_LABELS Labels which will be added to the pull request. Set to false to turn off No sync
ASSIGNEES People to assign to the pull request No N/A
COMMIT_PREFIX Prefix for commit message and pull request title No 🔄
COMMIT_EACH_FILE Commit each file seperately No true
GIT_EMAIL The e-mail address used to commit the synced files No the email of the PAT used
GIT_USERNAME The username used to commit the synced files No the username of the PAT used
OVERWRITE_EXISTING_PR Overwrite any existing Sync PR with the new changes No true
TMP_DIR The working directory where all git operations will be done No tmp-${ Date.now().toString() }
DRY_RUN Run everything except that nothing will be pushed No false
SKIP_CLEANUP Skips removing the temporary directory. Useful for debugging No false
SKIP_PR Skips creating a Pull Request and pushes directly to the default branch No false

🛠️ Sync Configuration

In order to tell repo-file-sync-action what files to sync where, you have to create a sync.yml file in the .github directory of your main repository (see action-inputs on how to change the location).

The top-level key should be used to specify the target repository in the format username/repository-name@branch, after that you can list all the files you want to sync to that individual repository:

user/repo:
  - path/to/file.txt
user/repo2@develop:
  - path/to/file2.txt

There are multiple ways to specify which files to sync to each individual repository.

List individual file(s)

The easiest way to sync files is the list them on a new line for each repository:

user/repo:
  - .github/workflows/build.yml
  - LICENSE
  - .gitignore

Different destination path/filename(s)

Using the dest option you can specify a destination path in the target repo and/or change the filename for each source file:

user/repo:
  - source: workflows/build.yml
    dest: .github/workflows/build.yml
  - source: LICENSE.md
    dest: LICENSE

Sync entire directories

You can also specify entire directories to sync:

user/repo:
  - source: workflows/
    dest: .github/workflows/

Exclude certain files when syncing directories

Using the exclude key you can specify files you want to exclude when syncing entire directories (#26).

user/repo:
  - source: workflows/
    dest: .github/workflows/
    exclude: |
      node.yml
      lint.yml      

Note: the exclude file path is relative to the source path

Don't replace existing file(s)

By default if a file already exists in the target repository, it will be replaced. You can change this behaviour by setting the replace option to false:

user/repo:
  - source: .github/workflows/lint.yml
    replace: false

Sync the same files to multiple repositories

Instead of repeating yourself listing the same files for multiple repositories, you can create a group:

group:
  repos: |
    user/repo
    user/repo1    
  files: 
    - source: workflows/build.yml
      dest: .github/workflows/build.yml
    - source: LICENSE.md
      dest: LICENSE

You can create multiple groups like this:

group:
  # first group
  - files:
      - source: workflows/build.yml
        dest: .github/workflows/build.yml
      - source: LICENSE.md
        dest: LICENSE
    repos: |
      user/repo1
      user/repo2      

  # second group
  - files: 
      - source: configs/dependabot.yml
        dest: .github/dependabot.yml
    repos: |
      user/repo3
      user/repo4      

📖 Examples

Here are a few examples to help you get started!

Basic Example

.github/sync.yml

user/repository:
  - LICENSE
  - .gitignore

Sync all workflow files

This example will keep all your .github/workflows files in sync across multiple repositories:

.github/sync.yml

group:
  repos: |
    user/repo1
    user/repo2    
  files:
    - source: .github/workflows/
      dest: .github/workflows/

Custom labels

By default repo-file-sync-action will add the sync label to every PR it creates. You can turn this off by setting PR_LABELS to false, or specify your own labels:

.github/workflows/sync.yml

- name: Run GitHub File Sync
  uses: BetaHuhn/repo-file-sync-action@v1
  with:
    GH_PAT: ${{ secrets.GH_PAT }}
    PR_LABELS: |
      file-sync
      automerge      

Assign a user to the PR

You can tell repo-file-sync-action to assign users to the PR with ASSIGNEES:

.github/workflows/sync.yml

- name: Run GitHub File Sync
  uses: BetaHuhn/repo-file-sync-action@v1
  with:
    GH_PAT: ${{ secrets.GH_PAT }}
    ASSIGNEES: BetaHuhn

Custom GitHub Enterprise Host

If your target repository is hosted on a GitHub Enterprise Server you can specify a custom host name like this:

.github/workflows/sync.yml

https://custom.host/user/repo:
  - path/to/file.txt

# or in a group

group:
  - files:
      - source: path/to/file.txt
        dest: path/to/file.txt
    repos: |
      https://custom.host/user/repo      

Note: The key has to start with http to indicate that you want to use a custom host.

Advanced sync config

Here's how I keep common files in sync across my repositories. The main repository github-files contains all the files I want to sync and the repo-file-sync-action Action which runs on every push.

Using groups I can specify which file(s) should be synced to which repositories:

.github/sync.yml

group:
  # dependabot files
  - files:
      - source: configs/dependabot.yml
        dest: .github/dependabot.yml
      - source: workflows/dependencies/dependabot.yml
        dest: .github/workflows/dependabot.yml
    repos: |
      BetaHuhn/do-spaces-action
      BetaHuhn/running-at
      BetaHuhn/spaces-cli
      BetaHuhn/metadata-scraper
      BetaHuhn/ejs-serve
      BetaHuhn/feedback-js
      BetaHuhn/drkmd.js      

  # GitHub Sponsors config
  - files:
      - source: configs/FUNDING.yml
        dest: .github/FUNDING.yml
    repos: |
      BetaHuhn/do-spaces-action
      BetaHuhn/running-at
      BetaHuhn/spaces-cli
      BetaHuhn/qrgen
      BetaHuhn/metadata-scraper
      BetaHuhn/ejs-serve
      BetaHuhn/feedback-js
      BetaHuhn/drkmd.js      

  # Semantic release
  - files:
      - source: workflows/versioning/release-scheduler.yml
        dest: .github/workflows/release-scheduler.yml
      - source: workflows/versioning/release.yml
        dest: .github/workflows/release.yml
      - source: configs/release.config.js
        dest: release.config.js
    repos: |
      BetaHuhn/do-spaces-action
      BetaHuhn/metadata-scraper
      BetaHuhn/feedback-js
      BetaHuhn/drkmd.js      

  # Stale issues workflow
  - files:
      - source: workflows/issues/stale.yml
        dest: .github/workflows/stale.yml
    repos: |
      BetaHuhn/do-spaces-action
      BetaHuhn/running-at
      BetaHuhn/spaces-cli
      BetaHuhn/qrgen
      BetaHuhn/metadata-scraper
      BetaHuhn/ejs-serve
      BetaHuhn/feedback-js
      BetaHuhn/drkmd.js      

  # Lint CI workflow
  - files:
      - source: workflows/node/lint.yml
        dest: .github/workflows/lint.yml
    repos: |
      BetaHuhn/do-spaces-action
      BetaHuhn/running-at
      BetaHuhn/spaces-cli
      BetaHuhn/metadata-scraper
      BetaHuhn/ejs-serve
      BetaHuhn/feedback-js
      BetaHuhn/drkmd.js      

  # MIT License
  - files:
      - source: LICENSE
        dest: LICENSE
    repos: |
      BetaHuhn/do-spaces-action
      BetaHuhn/running-at
      BetaHuhn/spaces-cli
      BetaHuhn/qrgen
      BetaHuhn/metadata-scraper
      BetaHuhn/ejs-serve
      BetaHuhn/feedback-js
      BetaHuhn/drkmd.js      

💻 Development

Issues and PRs are very welcome!

The actual source code of this library is in the src folder.

  • run yarn lint or npm run lint to run eslint.
  • run yarn start or npm run start to run the Action locally.
  • run yarn build or npm run build to produce a production version of repo-file-sync-action in the dist folder.

About

This project was developed by me (@betahuhn) in my free time. If you want to support me:

Donate via PayPal

ko-fi

Credits

This Action was inspired by:

📄 License

Copyright 2021 Maximilian Schiller

This project is licensed under the MIT License - see the LICENSE file for details.