files-sync-action
files-sync-action copied to clipboard
:package: A customizable action that synchronizes files across multiple repositories.
:package: Files Sync Action
A customizable action that synchronizes files across multiple repositories.
files-sync-action is a GitHub Action that synchronizes files across multiple repositories based on a configuration file written in YAML. It is useful in cases where you want to unify files, such as various tool configuration files or workflow files, across repositories. There are various patterns for motivation to synchronize files, depending on the team. To support these use cases, it allows for detailed configuration.
The following links are the actual PR and Workflow execution result logs:

Features
- :arrows_counterclockwise: Create PRs to synchronize files and directories across multiple repositories
- :hammer_and_wrench: Support flexible configuration of reviewers and labels for PRs
- :checkered_flag: Supports stable file synchronization even in large repositories.
- :pencil: Support file customization using EJS
Usage
In this section, we explain the most common usage of files-sync-action. To start using it, simply create a Workflow file that runs files-sync-action and a configuration file, as shown below:
.github/workflows/files-sync.yml
name: Sync Files
on:
push:
branches:
- main
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: wadackel/files-sync-action@v2
with:
github_token: ${{ secrets.GH_FILES_SYNC_TOKEN }}
GitHub App Tokens (with actions/create-github-app-token)
name: Sync Files
on:
push:
branches:
- main
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: wadackel/files-sync-action@v2
with:
github_token: ${{ steps.generate_token.outputs.token }}
GitHub App Tokens (with tibdex/github-app-token)
name: Sync Files
on:
push:
branches:
- main
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@v1
with:
app_id: ${{ secrets.GH_APP_ID }}
installation_id: ${{ secrets.GH_APP_INSTALLATION_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: wadackel/files-sync-action@v2
with:
github_token: ${{ steps.generate_token.outputs.token }}
.github/files-sync-config.yml
settings:
pull_request:
reviewers:
- 'wadackel'
labels:
- 'files-sync'
patterns:
- files:
- tsconfig.json
- .prettierrc.json
- from: workflows/ci.yml
to: .github/workflows/ci.yml
repositories:
- owner/repo1
- owner/repo2
If you need more customization, please refer to the Sync Configuration section.
Authentication
files-sync-action supports authentication using both Personal Access Tokens and GitHub Apps.
We recommend using Fine-grained personal access tokens for Personal Access Token authentication, as they allow for more granular access control compared to traditional tokens. Authentication using GitHub Apps is useful for team development.
To use files-sync-action, you need to set the following Repository permissions for each respective token:
| Type | Permission |
|---|---|
| Contents | Read and write |
| Pull requests | Read and write |
| Metadata | Read and write |
| Workflows | To synchronize Workflow files: Read and write, Other: No access |
Inputs
github_token
Required: true
Default: n/a
Personal Access Token to use to create file sync and PR. Required if GITHUB_APP_* is not specified.
github_api_url
Required: false
Default: https://api.github.com
API URL of the GitHub server.
config_file
Required: false
Default: .github/files-sync-config.yml
The path for the sync configuration file.
Outputs
pull_request_urls
URL array of PRs created to synchronize files.
synced_files
An array of all synchronized file names.
Sync Configuration
The configuration file for file synchronization can be written in YAML. By default, it refers to .github/files-sync-config.yml. If you want to change the path, please modify the value of inputs.config_file.
The configuration file consists of a settings section, which defines common settings, and a patterns section, which defines individual file synchronization patterns. The contents defined in settings are inherited by all patterns.
| Key | Required | Type | Description |
|---|---|---|---|
settings |
false |
SettingsConfig | Settings to be used commonly across all file synchronization patterns |
patterns |
true |
Array<PatternConfig> | File synchronization patterns |
SettingsConfig
Configure the settings to be used commonly across all file synchronization patterns. You can customize the default commit and branch settings, as well as the contents of the PR.
| Key | Required | Type | Description |
|---|---|---|---|
commit |
false |
CommitConfig | Various settings related to commits |
branch |
false |
BranchConfig | Various settings related to branches |
pull_request |
false |
PullRequestConfig | Various settings related to automatically generated PRs |
Defaults:
settings:
commit:
# defaults to "chore: sync files with `owner/repo`"
format: '<%- prefix %>: <%- subject %>'
prefix: 'chore'
subject: 'sync files with `<%- repository %>`'
branch:
# defaults to "files-sync/owner-repo-0"
format: '<%- prefix %>/<%- repository %>-<%- index %>'
prefix: 'files-sync'
pull_request:
disabled: false
force: true
title: 'Sync files with `<%- repository %>`'
body: |
This PR contains the following updates:
| :chart_with_upwards_trend: Change | :hammer_and_wrench: Synchronizing Repository | :link: Workflow |
| :-- | :-- | :-- |
| <%- changes.length %> files | [<%- repository %>](<%- github %>/<%- repository %>) | [\`<%- workflow %>#<%- run.number %>\`](<%- run.url %>) |
---
### Changed Files
<%_ for (const file of changes) { -%>
- <% if (file.from === file.to) { %>\`<%- file.to %>\`<% } else { %>\`<%- file.from %>\` to \`<%- file.to %>\`<% }%>
<%_ } -%>
reviewers: []
assignees: []
labels: []
PatternConfig
Configure the synchronization pattern for files and directories and the target repositories for synchronization. While inheriting the contents defined in settings, you can customize the commit, branch, and PR settings for each synchronization pattern.
| Key | Required | Type | Description |
|---|---|---|---|
files |
true |
Array<string | FileConfig> | List of files to synchronize. Supports files and directories. |
repositories |
true |
Array |
List of repositories to synchronize the files specified in files |
commit |
false |
CommitConfig | Various settings related to commits |
branch |
false |
BranchConfig | Various settings related to branches |
pull_request |
false |
PullRequestConfig | Various settings related to automatically generated PRs |
template |
false |
Record<string, any> | Template variables to use for the files specified in files. Disables EJS if not specified |
Examples:
patterns:
- files:
- tsconfig.json # file (simple)
- from: workflows/ci.yml # file (details)
to: .github/workflows/ci.yml
- from: shared # directory
to: shared
exclude:
- '*.txt'
repositories:
- owner/repo1
- owner/repo2
- owner/repo3
commit:
prefix: 'build'
pull_request:
reviewers:
- 'team:team_slug'
- 'login_name'
labels:
- 'A-build'
FileConfig
Configure the details of the files to synchronize. When synchronizing a directory, you can use exclude to exclude only certain file patterns.
| Key | Required | Type | Description |
|---|---|---|---|
from |
true |
string |
Source file or directory path for synchronization |
to |
true |
string |
Destination file or directory path for synchronization |
exclude |
false |
string[] |
Glob patterns of files to exclude from the contents of a directory (only valid for directories). Glob patterns use micromatch |
CommitConfig
Configure the commit contents to use when synchronizing files.
| Key | Required | Type | Description |
|---|---|---|---|
format |
false |
string |
Commit message format. Supports EJS templates |
prefix |
false |
string |
Commit message prefix |
subject |
false |
string |
Commit message subject. Supports EJS templates |
The following template variables are available for various keys:
commit.format
| Key | Type | Description |
|---|---|---|
prefix |
string |
Commit message prefix specified in commit.prefix |
subject |
string |
Commit message subject specified in commit.subject |
repository |
string |
Source repository name (the repository where the Action is being executed) |
index |
number |
Index of the file synchronization pattern |
commit.subject
| Key | Type | Description |
|---|---|---|
repository |
string |
Source repository name (the repository where the Action is being executed) |
index |
number |
Index of the file synchronization pattern |
BranchConfig
Configure the branch to commit to when synchronizing files.
| Key | Required | Type | Description |
|---|---|---|---|
format |
false |
string |
Branch name format. Supports EJS templates |
prefix |
false |
string |
Prefix for the branch name |
The following template variables are available for various keys:
branch.format
| Key | Type | Description |
|---|---|---|
prefix |
string |
Branch name prefix specified in branch.prefix |
repository |
string |
Source repository name (the repository where the Action is being executed), encoded in a valid branch name format |
index |
number |
Index of the file synchronization pattern |
PullRequestConfig
| Key | Required | Type | Description |
|---|---|---|---|
disabled |
false |
boolean |
Flag to disable PR when synchronizing files. If disabled, file synchronization will only push without creating a PR |
force |
false |
boolean |
Flag to create a commit from base of existing PR and override existing commits. If disabled, the commit is created from head of existing PR and existing commits are not overridden |
title |
false |
string |
Title of the automatically generated PR. Supports EJS templates |
body |
false |
string |
Content of the automatically generated PR. Supports EJS templates |
reviewers |
false |
string[] |
List of reviewers to set for the automatically generated PR. To specify a team as a reviewer, add team: as a prefix to the team slug |
assignees |
false |
string[] |
List of assignees to set for the automatically generated PR. Team assignment is not supported |
labels |
false |
string[] |
List of labels to set for the automatically generated PR |
The following template variables are available for various keys:
pull_request.title
| Key | Type | Description |
|---|---|---|
repository |
string |
Source repository name (the repository where the Action is being executed) |
index |
number |
Index of the file synchronization pattern |
pull_request.body
| Key | Type | Description |
|---|---|---|
github |
string |
GitHub server URL |
repository |
string |
Source repository name (the repository where the Action is being executed) |
workflow |
string |
Name of the Workflow running the Action |
run |
object |
Object related to the Workflow execution |
run.id |
string |
Execution ID of the Workflow |
run.number |
string |
Execution number of the Workflow |
run.url |
string |
URL of the Workflow execution log |
changes |
{ from: string; to: string }[] |
List of changed files |
index |
number |
Index of the file synchronization pattern |
Credits
files-sync-action is inspired by the following GitHub Actions. Thanks!!
Development
Introducing the steps for developing files-sync-action.
Setup
Using a Node.js Version Manager such as asdf or nodenv, activate the version of Node.js written in .node-version.
Next, activate pnpm using corepack, and install the dependent packages.
$ corepack enable pnpm
$ pnpm i
Local Testing
Introducing cases where you want to verify the operation of files-sync-action on your local machine during development.
Create a configuration file for local testing and a script for running tests. These files are excluded from Git management by .gitignore.
$ touch test.yml test.js
Customize the contents of each created file.
test.js
process.env['INPUT_GITHUB_TOKEN'] = '...';
process.env['INPUT_CONFIG_FILE'] = 'test.yml';
process.env['INPUT_GITHUB_API_URL'] = 'https://api.github.com';
process.env['GITHUB_SERVER_URL'] = 'https://github.com';
process.env['GITHUB_REPOSITORY'] = 'local/test';
process.env['GITHUB_RUN_ID'] = '0';
process.env['GITHUB_RUN_NUMBER'] = '0';
await import('./dist/index.js');
test.yml
patterns:
- files:
- README.md
# ...
repositories:
- your/repo
To modify the implementation of files-sync-action and verify it on your local machine, build the script locally and run it using the configuration file created for testing.
$ pnpm build && node test.js
LICENSE
MIT © wadackel