Update multiple repositories in with one command
Update multiple repositories in with one command
multi-gitter allows you to make changes in multiple repositories simultaneously. This is achieved by running a script or program in the context of multiple repositories. If any changes are made, a pull request is created that can be merged manually by the set reviewers, or automatically by multi-gitter when CI pipelines have completed successfully.
Are you a bash-guru or simply prefer your scripting in Node.js? It doesn't matter, since multi-gitter support any type of script or program. If you can script it to run in one place, you can run it in all your repositories with one command!
$ multi-gitter run ./my-script.sh -O my-org -m "Commit message" -B branch-name
Make sure the script has execution permissions before running it (chmod +x ./my-script.sh)
If you are running an interpreted language or similar, it's important to specify the path as an absolute value (since the script will be run in the context of each repository). Using the $PWD variable helps with this.
$ multi-gitter run "python $PWD/run.py" -O my-org -m "Commit message" -B branch-name
$ multi-gitter run "node $PWD/script.js" -R repo1 -R repo2 -m "Commit message" -B branch-name
$ multi-gitter run "go run $PWD/main.go" -U my-user -m "Commit message" -B branch-name
You might want to test your changes before creating commits. The --dry-run flag provides an easy way to test without actually making any modifications. It works well when setting the log level to debug, with --log-level=debug, to also print the changes that would have been made.
$ multi-gitter run ./script.sh --dry-run --log-level=debug -O my-org -m "Commit message" -B branch-name
If you are using Mac or Linux, Homebrew is an easy way of installing multi-gitter.
brew install --cask lindell/multi-gitter/multi-gitter
Find the binary for your operating system from the release page and download it.
To automatically install the latest version
curl -s https://raw.githubusercontent.com/lindell/multi-gitter/master/install.sh | sh
You can also install from source with go install, this is not recommended for most cases.
go install github.com/lindell/multi-gitter@latest
To use multi-gitter, a token that is allowed to list repositories and create pull requests is needed. This token can either be set in the GITHUB_TOKEN, GITLAB_TOKEN, GITEA_TOKEN environment variable, or by using the --token flag.
How to generate a GitHub personal access token (classic). Make sure to give it repo permissions.
How to generate a GitLab personal access token. Make sure to give to it the api permission.
In Gitea, access tokens can be generated under Settings -> Applications -> Manage Access Tokens
All configuration in multi-gitter can be done through command line flags, configuration files or a combination of both. If you want to use a configuration file, simply use the --config=./path/to/config.yaml option. You can also specify this flag multiple times, where later files override configs set in earlier files. Multi-gitter will also read from the file ~/.multi-gitter/config and take and configuration from there. The priority of configs are first flags, then defined config file and lastly the static config file.
All available run options
…
All available merge options
…
All available status options
…
All available close options
…
All available print options
…
runThis command will clone down multiple repositories. For each of those repositories, the script will be run in the context of that repository. If the script finished with a zero exit code, and the script resulted in file changes, a pull request will be created.
When the script is invoked, these environment variables are set:
…
mergeMerge pull requests with a specified branch name in an organization and with specified conditions.
…
statusGet the status of all pull requests with a specified branch name in an organization.
…
closeClose pull requests with a specified branch name in an organization and with specified conditions.
…
printThis command will clone down multiple repositories. For each of those repositories, the script will be run in the context of that repository. The output of each script run in each repo will be printed, by default to stdout and stderr, but it can be configured to write to files as well.
When the script is invoked, these environment variables are set:
…
Clone all repositories locally while maintaining their group folder structure
#!/bin/bash
# This script should be used with the print command.
mkdir -p ~/multi-gitter/$REPOSITORY
cp -r . ~/multi-gitter/$REPOSITORY
Replace a file if it exist
#!/bin/bash
REPLACE_FILE=~/test/pull_request_template.md # The file that should replace the file in the repo, must be an absolute path
FILE=.github/pull_request_template.md # Relative from any repos root
# Don't replace this file if it does not already exist in the repo
if [ ! -f "$FILE" ]; then
exit 1
fi
cp $REPLACE_FILE $FILE
Replace text in all files
#!/bin/bash
# Assuming you are using gnu sed, if you are running this on a mac, please see https://stackoverflow.com/questions/4247068/sed-command-with-i-option-failing-on-mac-but-works-on-linux
find ./ -type f -exec sed -i -e 's/apple/orange/g' {} \;
Replace all instances of empty interface with any
#!/bin/bash
gofmt -r 'interface{} -> any' -w **/*.go
Fix the ioutil deprecation
#!/bin/bash
gofmt -w -r 'ioutil.Discard -> io.Discard' .
gofmt -w -r 'ioutil.NopCloser -> io.NopCloser' .
gofmt -w -r 'ioutil.ReadAll -> io.ReadAll' .
gofmt -w -r 'ioutil.ReadFile -> os.ReadFile' .
gofmt -w -r 'ioutil.TempDir -> os.MkdirTemp' .
gofmt -w -r 'ioutil.TempFile -> os.CreateTemp' .
gofmt -w -r 'ioutil.WriteFile -> os.WriteFile' .
gofmt -w -r 'ioutil.ReadDir -> os.ReadDir ' . # (note: returns a slice of os.DirEntry rather than a slice of fs.FileInfo)
goimports -w .
Fix linting problems in all your go repositories
#!/bin/bash
golangci-lint run ./... --fix
Updates a go module to a new (patch/minor) version
#!/bin/bash
### Change these values ###
MODULE=github.com/go-git/go-git/v5
VERSION=v5.1.0
# Check if the module already exist, abort if it does not
go list -m $MODULE &> /dev/null
status_code=$?
if [ $status_code -ne 0 ]; then
echo "Module \"$MODULE\" does not exist"
exit 1
fi
go get $MODULE@$VERSION
Upgrade Go version in go modules
#!/bin/bash
go mod edit -go 1.18
go mod tidy
Updates a npm dependency if it does exist
#!/bin/bash
### Change these values ###
PACKAGE=webpack
VERSION=4.43.0
if [ ! -f "package.json" ]; then
echo "package.json does not exist"
exit 1
fi
# Check if the package already exist (without having to install all packages first), abort if it does not
current_version=`jq ".dependencies[\"$PACKAGE\"]" package.json`
if [ "$current_version" == "null" ];
then
echo "Package \"$PACKAGE\" does not exist"
exit 2
fi
npm install --save $PACKAGE@$VERSION
Simple replace using node
const { readFile, writeFile } = require("fs").promises;
async function replace() {
let data = await readFile("./README.md", "utf8");
data = data.replace("apple", "orange");
await writeFile("./README.md", data, "utf8");
}
replace();
Do you have a nice script that might be useful to others? Please create a PR that adds it to the examples folder.
Bitbucket Cloud
note: bitbucket cloud support is currently in Beta
In order to use bitbucket cloud you will need to create and use an App Password or Workspace Token. The app password or workspace token you create needs sufficient permissions so ensure you grant it Read and Write access to projects, repositories and pull requests and at least Read access to your account and workspace membership.
You will need to configure the bitbucket workspace using the org option for multi-gitter for the repositories you want to make changes to. You will also need to configure the authentication method using the auth-type flag e.g. multi-gitter run examples/go/upgrade-go-version.sh -u your_username --org "your_workspace" --auth-type app-password
Here is an example of using the command line options to run a script from the examples/ directory and make pull-requests for a few repositories in a specified workspace, using app password authentication.
export BITBUCKET_CLOUD_APP_PASSWORD="your_app_password"
multi-gitter run examples/go/upgrade-go-version.sh -u your_username --org "your_workspace" --repo "your_first_repository,your_second_repository" --platform bitbucket_cloud -m "your_commit_message" -B your_branch_name --auth-type app-password
Here is an example of running the script using workspace token authentication.
export BITBUCKET_CLOUD_WORKSPACE_TOKEN="your_workspace_token"
multi-gitter run examples/go/upgrade-go-version.sh -u your_username --org "your_workspace" --repo "your_first_repository,your_second_repository" --platform bitbucket_cloud -m "your_commit_message" -B your_branch_name --auth-type workspace-token
Currently, we add the repositories default reviewers as a reviewer for any pull-request you create. If you want to specify specific reviewers, you will need to add them using their UUID instead of their username since bitbucket does not allow us to look up a UUID using their username. This article has more information about where you can get a users UUID.
We don't support specifying specific projects for bitbucket cloud yet, you should still be able to make changes to the repositories you want but certain functionality, like forking, does not work as well until we implement that feature.
Using fork: true is currently experimental within multi-gitter for Bitbucket Cloud, and will be addressed in future updates.
Here are the known limitations:
No open issues yet, or sync has not completed.