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_MESSAGEstring,transformfunction, andREPOSlist 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_NAMEline immediately after theapp.environmentline in all files matchingsrc/main/resources/*.propertiesthat don't already contain aspring.application.nameline.-
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, prependbashto 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