Bulk Update is a script that can automatically copy/update a series of files across multiple git repositories, with the ability to open and merge pull requests. The script is written in Python 3, uses JSON for configuration files, and optionally the GitHub command line tool for opening and managing pull requests. For example, common contributing guides, licenses, lint configurations, etc that are the same across an organization can be automatically copied and merged across all the repositories in an organization, eliminating the need to manually copy and update these files.
- Python >= v3.8
- Git >= v2.39.0
- GitHub CLI >= 2.23.0
- Clone the repository
- Create a Python virtual environment and activate (not required, but good practice)
- Install the requirements
- Configure the
config.json
file as required - Run the
bulkupdate.py
python script. Optionally specify the config file to use, egpython bulkupdate.py config.json
The example.config.json file contains an example configuration as follows:
{
"files": [
{
"filedir": "dir",
"filename": "test.txt",
"action": "copy",
"versioned": true
}
],
"repositories": [
{
"repository": "org/example",
"source_branch": "main",
"version": "v1",
"shallowclone": false
}
],
"dest_branch": "feat/test",
"force_branch_suffix": false,
"msg": "feat: example",
"createpr": true,
"pr_info": {
"title": "PR Title",
"description": "This PR fixes example issue",
"merge": "merge",
"mergedelay": "none",
"cleanup": true
},
"existingbranch": false,
"updatebranch": false,
"sleeptime": 0,
"repoprune": true,
"shallowclone": true,
"secrets_file": "secrets.json"
}
files
(required): array that stores information about the files the script is updatingfiledir
(required): path to the file in the remote repositories (repositories which the script is updating). Leave blank for the root of the repositoryfilename
(required): the full name of the fileaction
(required):copy
: copy the file as-is to the remote repoedit
: copy the file from the remote repo, allow for editing, then copy backremove
: remove the file from the remote reporeset
: reset any changes to the file done on the working branch
versioned
(required):false
: Use the file in thefiles/
directorytrue
: Use the file in thefiles/<version>
directory, where<version>
is specified in the repositories configuration
repositories
(required): array of repositories the script is updatingrepository
(required): The organization/user and repository name of the GitHub repositorysource_branch
(required): The branch of the repository off of which the script worksversion
(optional): If the file is set as versioned, the path under the files directory in which the file is locatedshallowclone
(optional): Whether or not to perform a shallow clone
dest_branch
(required): The branch on which the script will commit files. Will be suffixed by the source branch name to differentiate when there are duplicate repositories with different source branches.force_branch_suffix
(optional): If enabled, will always suffix the destination branch with the source branch name.msg
(required): The commit message and PR titlecreatepr
(required): Whether to create a PRpr_info
(required if createpr is true): Dict holding PR-specific infotitle
(optional): The PR title. Defaults to the commit message if emptydescription
(required): The PR descriptionmerge
(required):draft
: Create a PR in a draft statemerge
: Merge the PR with a merge commitautomerge
: Enable auto-merge, merge with a merge commit when requirements are metrebase
: Rebase merge the PRautorebase
: Enable auto-merge, rebase merge when requirements are metsquash
: Squash merge the PRautosquash
: Enable auto-merge, squash merge when requirements are metskip
: Do not automatically merge the PR
mergedelay
(required):none
: Perform merge action after creating PRwait
: Wait until the created PR has been merged before creating the next oneafter
: Wait until all PRs have been created, then perform merge actionafterinput
: Wait until all PRs have been created, request user input, then perform merge action
cleanup
(optional): Whether or not to delete the PR's branch after merging
existingbranch
(required):true
: Use an existing branch already on the remote repositoriesfalse
: Create a new branch on the remote repositories
updatebranch
(required): Whether or not to update thesource_branch
with new changes on thedest_branch
sleeptime
(optional): The amount of time (in minutes) to wait between actions on each repositoryrepoprune
(optional): Whether or not to delete branches that no longer exist on the remotes of the remote repositoriessecrets_file
(optional): The name of the secrets file. The data in the secrets file can also be provided in this configuration. If not provided, the PR (if created) will not be automatically approved
The example.secrets.json file contains an example configuration as follows:
{
"review_user": "",
"review_token": ""
}
review_user
(optional): Ifmerge
isautosquash
, the username of a second GitHub user to approve the PRreview_token
(optional): A GitHub Personal Access Token for the user
files
: Files that the script copies to the remote repositories under the pathrepos/<version>
if the files are versioned.repos
: Repos that the script has managed under the pathrepos/<org>/<repo>
config.json
: Contains the script configuration, as described in Configurationsecrets.json
: Contains the script secrets, as described in Configuration