A GitHub Action to sync files from a template repository into other repositories.
name: Sync Template Files
on:
schedule:
- cron: '0 0 * * 0' # Run weekly on Sunday at midnight
workflow_dispatch: # Allow manual triggering
permissions:
contents: write # Needed to push commits
pull-requests: write # Needed to create pull requests
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Sync Template
uses: jebel-quant/[email protected]
with:
source: './template.yml' # Path to your configuration file
branch: 'sync/update-configs'
commit-message: 'chore: sync template files'
token: ${{ secrets.GITHUB_TOKEN }}
automerge: true| Input | Description | Required | Default |
|---|---|---|---|
| token | GitHub token or PAT for authentication | Yes | N/A |
| source | Path to the YAML configuration file containing template settings | Yes | N/A |
| branch | Target branch in the current repo | No | sync/update |
| commit-message | Commit message for sync | No | chore: sync template |
| test-mode | If true, skip push and PR creation | No | false |
| automerge | If true, enable auto-merge for the created PR | No | false |
This action performs the following steps:
- Checks out the template repository with sparse checkout to only include the specified files/folders
- Removes excluded files/folders from the template
- Copies the template files into the target repository
- Commits and pushes the changes to the specified branch in the target repository
- Optionally creates a pull request for the changes
The action uses sparse checkout to minimize the amount of data that needs to be downloaded, making it efficient even with large template repositories.
Pull requests are created using the peter-evans/create-pull-request action, which opens or updates a PR from the sync branch and avoids creating duplicates across runs. When a PR is created, the next step enables auto-merge using GitHub CLI (gh pr merge --merge --auto --delete-branch) so that approved PRs merge automatically and the branch is cleaned up.
After a PR is created, this action enables auto-merge only when you set with.automerge: 'true' and a PR number is available (condition: inputs.automerge == 'true' && steps.create-pr.outputs.pull-request-number != ''). It uses GitHub CLI with:
gh pr merge <number> --merge --auto --delete-branch
This merges the PR once it meets merge requirements and deletes the branch afterward.
When using this action to sync workflow files (files in .github/workflows/), you need to be aware of GitHub's token permission restrictions:
-
Default
GITHUB_TOKEN: Does not have permission to update workflow files in a repository. If you try to sync workflow files using the default token, you'll get an error like:! [remote rejected] HEAD -> sync/update (refusing to allow a GitHub App to create or update workflow without `workflows` permission) -
Personal Access Token (PAT): To sync workflow files, you must use a PAT with the
workflowscope. Configure this in your workflow:with: token: ${{ secrets.PAT_WITH_WORKFLOW_SCOPE }}
-
Repository Settings: Alternatively, you can modify the default token permissions in your repository settings:
- Go to Settings > Actions > General
- Under "Workflow permissions", select "Read and write permissions"
- Check "Allow GitHub Actions to create and approve pull requests"
The action will automatically detect when workflow files are being modified and provide appropriate warnings.
The action reads template configuration from a YAML file
specified by the source parameter.
This allows you to maintain template settings separately
from your workflow files.
Example configuration file (e.g., template.yml):
# Required: Repository to sync from
template-repository: 'organization/template-repo'
# Optional: Branch in the template repository (defaults to 'main')
template-branch: 'main'
# Optional: Files and folders to include
include: |
.github
.devcontainer
CODE_OF_CONDUCT.md
# Optional: Files and folders to exclude
exclude: |
README.md
LICENSEWhen using the configuration file:
- You must specify the path to this file using the
sourceparameter - The file must contain at least the
template-repositoryvalue - Other values (
template-branch,include,exclude) are optional
-
Include: Specifies which files and folders to sync from the template repository. This uses Git's sparse checkout feature to only download the specified files.
-
Exclude: Allows you to remove specific files or subdirectories from folders that were included. For example, if you include
.githubfolder but want to exclude.github/workflows/sync.yml, you can list this specific file in the exclude parameter. This is particularly useful when you want most files from a directory but need to exclude a few specific files.
The action includes comprehensive testing to ensure it works correctly:
-
Unit Tests: A bash script (
tests/test-action.sh) that simulates the action's functionality by:- Setting up source and target repositories
- Performing the sync operations
- Validating the results with assertions
-
Integration Tests: GitHub workflow files that test the action:
.github/workflows/test.yml: Basic test of the action functionality.github/workflows/integration-test.yml: Runs the test script and tests the action in a workflow
The action supports a test mode that can be enabled by setting the test-mode input parameter to true.
In test mode, the action will perform all operations
except the final git push, making it safe to test
in CI environments.
Example:
- name: Test Sync Template Action
uses: jebel-quant/[email protected]
with:
source: './template.yml'
token: ${{ secrets.GITHUB_TOKEN }}
test-mode: "true"To run the test script locally:
chmod +x ./tests/test-action.sh
./tests/test-action.shContributions are welcome! Here's how you can contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run the tests to ensure everything works
- Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure to update tests as appropriate and adhere to the existing coding style.