pulldozer
pulldozer copied to clipboard
CLI tool for batch editing multiple repos :tractor:
Pulldozer
Pulldozer is a simple CLI tool for batch editing multiple GitHub repos.
You give Pulldozer a transformation script and it spits out pull requests. There are no other side effects - your existing local repos will remain untouched.
Usage
Clone this repo onto any Unix machine that has curl
. Set your GITHUB_TOKEN
environment variable to an access token with repo
scope and SSO enabled.
To perform a batch edit:
-
Specify your desired
COMMIT_MESSAGE
string,transform
function, andREPOS
list in a new shell script:COMMIT_MESSAGE='Fix "langauge" typos' transform() { # Your arbitrary shell commands go here. GitHub org name and repo name are # passed into this `transform` function as vars $1 and $2, respectively. echo "Repo $2 is being edited via Pulldozer!" >> README.md # Pulldozer provides a `replace_all` helper function for replacing text # across all repo files. It's basically glorified sed. replace_all 'langauge' 'language' # Advanced `replace_all` example: regex, capture grouping, multi-line # matching, and file path filtering replace_all '(\nprotobuf==)\S+' '\13.19.4' 'requirements\.(in|txt)$' } REPOS=' artnc/dotfiles duolingo/halflife-regression duolingo/rtl-viewpager ' # Optional: Markdown to include in pull request descriptions DESCRIPTION='[Correct spelling](https://en.wiktionary.org/wiki/language)'
Really want to use some other language? Click here for a Python example.
The transform functions below will add a
spring.application.name=$REPO_NAME
line immediately after theapp.environment
line in all files matchingsrc/main/resources/*.properties
that don't already contain aspring.application.name
line.-
Python version:
transform() { python3 - << EOF import re import subprocess git_paths = subprocess.check_output("git grep --cached -l ''", shell=True) for path in git_paths.decode().splitlines(): if not re.search(r'^src/main/resources/.*\.properties$', path): continue with open(path) as f: contents = f.read() if re.search(r'spring\.application\.name', contents): continue with open(path, 'w') as f: f.write(re.sub(r'(app\.environment=\w*)', r'\1\nspring.application.name=${2}', contents)) EOF }
-
Shell version:
transform() { for path in $(git grep --cached -l ''); do if ! printf %s "${path}" | grep -qE '^src/main/resources/.*\.properties$'; then continue fi if grep -qF 'spring.application.name' "${path}"; then continue fi sed -E -i "s/(app\.environment=\w*)/\1\nspring.application.name=${2}/g" "${path}" done }
-
-
Run
./pulldozer /path/to/script.sh
. (To use Bash in your transformation script, prependbash
to that command - otherwise Pulldozer assumes POSIXsh
.) Pulldozer will ask for confirmation and then open PRs, each of which will contain your transformation script in its description.
Duolingo is hiring! Apply at https://www.duolingo.com/careers