GitHub Action
Manage Files in Multiple Repositories
GitHub Action that introduces support for global workflows. Global workflows are the ones that you update in just one repo, and then they are automatically updated in other repositories in your organization or user account.
Action is released under v0.2.0, and I plan to extend it forward, add tests and release under v1 once I get other people using it. Feel free to create an issue about it.
- Why I Created This Action?
- Supported Event Triggers
- Action Flow
- Configuration
- Examples
- Development
- Known Limitations/Hardcodes
- Debug
It seems like GitHub is not going to support global workflows anytime soon. I decided to create this action as I was just super tired of manually editing the same workflow files in over 30 repositories. To be honest, I never did it; I never did it manually and could not imagine I do it 😃
Maybe GitHub will support global workflows someday. Take it into account and put global workflows in a repository called .github
because once GitHub starts supporting global workflows, they will surely have to be located there. Read more about .github
repository here.
This action can be triggered by:
-
push event and only files that were changed in the commit are replicated to other repositories.
-
workflow_dispatch event and then all files from workflow directory (except of ignored ones) are replicated to other repositories. Use case for this event is when you create new repositories in your organization that need to get global workflows. Then you can manually trigger the action and all global workflows will be updated in all repositories. Below screen shots shows how manual triggering works.
This action also allows you to specify a single repository that action should run against. You can add the following input trigger in your workflow:
workflow_dispatch: inputs: repo_name: description: | You can specify name of the repository where workflows should be pushed manually. As long as repository is not ignored by workflow settings. If you do not specify exact repository name, the workflow will try to replicate all missing changes to all repositories. required: false
As a result you will be able to run your workflow manually by providing specific repository name. If name is not provided, action will fallback to run against all repositores. If wrong repo name is provided under
repo_name
, the action will fail.
Name | Description | Required | Default |
---|---|---|---|
github_token | Token to use GitHub API. It must have "repo" and "workflow" scopes so it can push to repo and edit workflows. It cannot be the default GitHub Actions token GITHUB_TOKEN. GitHub Action token's permissions are limited to the repository that contains your workflows. Provide token of the user who has the right to push to the repos that this action is supposed to update. The same token is used for pulling repositories - important to know for those that want to use this action with private repositories. | true | - |
files_to_ignore | Comma-separated list of workflow files that should be ignored by this action and not updated in other repositories. You must provide here at least the name of the workflow file that uses this action. In the format file.yml,another_file.yml . |
true | - |
committer_username | The username (not display name) of the committer will be used to commit changes in the workflow file in a specific repository. In the format web-flow . |
false | web-flow |
committer_email | The committer's email that will be used in the commit of changes in the workflow file in a specific repository. In the format [email protected] . |
false | [email protected] |
commit_message | It is used as a commit message when pushing changes with global workflows. It is also used as a title of the pull request that is created by this action. | false | Update global workflows |
repos_to_ignore | Comma-separated list of repositories that should not get updates from this action. Action already ignores the repo in which the action is triggered so you do not need to add it explicitly. In the format repo1,repo2 . |
false | - |
topics_to_include | Comma-separated list of topics that should get updates from this action. Repos that do not contain one of the specified topics will get appended to the repos_to_ignore list. In the format topic1,topic2 . |
false | - |
exclude_private | Boolean value on whether to exclude private repositories from this action. | false | false |
exclude_forked | Boolean value on whether to exclude forked repositories from this action. | false | false |
branches | By default, action creates branch from default branch and opens PR only against default branch. With this property you can override this behaviour. You can provide a comma-separated list of branches this action shoudl work against. You can also provide regex, but without comma as list of branches is split in code by comma. | false | default branch is used |
name: Global workflow to rule them all
on:
push:
branches: [ master ] #or main
workflow_dispatch: {} #to enable manual triggering of the action
jobs:
replicate_changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: derberg/[email protected]
with:
github_token: ${{ secrets.CUSTOM_TOKEN }}
files_to_ignore: name_of_file_where_this_action_is_used.yml
- In your
.github
repo you could have the following workflow:name: Global workflow to rule them all on: push: branches: [ master ] #or main jobs: replicate_changes: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 - name: Replicating global workflow uses: derberg/[email protected] with: github_token: ${{ secrets.CUSTOM_TOKEN }} files_to_ignore: name_of_file_where_this_action_is_used.yml repos_to_ignore: repo1,repo2 topics_to_include: topic1,topic2 exclude_private: true exclude_forked: true branches: .*-release,main committer_username: santiago-bernabeu committer_email: [email protected] commit_message: "ci: update global workflows"
- In repositories that will be updated by this workflow, you can have the following auto-merge workflow file:
name: Automerge release bump PR on: pull_request: types: - labeled - unlabeled - synchronize - opened - edited - ready_for_review - reopened - unlocked pull_request_review: types: - submitted check_suite: types: - completed status: {} jobs: automerge: runs-on: ubuntu-latest steps: - name: Automerging uses: pascalgn/[email protected] #the actor that created pr if: github.actor == 'github-username-that-owns-token-used-in-global-workflow' env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" GITHUB_LOGIN: santiago-bernabeu MERGE_LABELS: "" MERGE_METHOD: "squash" MERGE_COMMIT_MESSAGE: "pull-request-title" MERGE_RETRIES: "10" MERGE_RETRY_SLEEP: "10000"
# GITHUB_TOKEN provide personal GitHub token with scope to push to repos
# GITHUB_REPOSITORY provide name of org/user and the repo in which this workflow is suppose to run
# GITHUB_EVENT_PATH is a path to local file with dummy event payload for testing
# GITHUB_EVENT_NAME is the name of the event that triggers the event
GITHUB_TOKEN=token GITHUB_EVENT_NAME=push GITHUB_EVENT_PATH="../test/fake-event.json" GITHUB_REPOSITORY="lukasz-lab/.github" npm start
- Action looks for file changes only in
.github/workflows
because it intends to support only global workflows and not any files. This is, of course something that can be changed. Please create an issue to discuss this change further. - Action assumes that when triggered by push event, it has information only about one commit. It is very common for many projects and organizations to merge only of single commit or merging and squashing commits into one. If you see a need to support multiple commits on a push event, please open an issue and describe your use case and expected behavior.
- Action requires you to provide
files_to_ignore
as you need to remember to put there the name of the workflow file where you use this action. Yes, you need to manually provide the file's name as I did not find a nice way how, in the workflow, I can access information about the name of the workflow file. The only idea I have, which is not the best and requires some additional effort, is to readGITHUB_WORKFLOW
variable and then read the workflow files' contents to match the name. I hope you have something better.
In case something ain't right, the action doesn't work as expected, enable debugging. Add to Secrets of the repository a secret called ACTIONS_STEP_DEBUG
with value true
. Now, once you run the action again, there will be additional logs visible that start with DEBUG:
.