Created
May 12, 2020 19:34
-
-
Save benekastah/072bbdab1e7b3e41ef6e1c5a4090d402 to your computer and use it in GitHub Desktop.
An automated pull request checklist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[alias] | |
# Pushes your branch to a remote branch of the same name | |
up = !git push -u origin "$(git rev-parse --abbrev-ref HEAD)" | |
# open a pull request, echos the url to the pr. | |
# Requires the `hub` command: https://github.com/github/hub. | |
pr = "!f(){ \ | |
checklist -r .pr_checklist || exit 1; \ | |
git up; \ | |
hub pull-request -m \"$(git log -1 --pretty=format:'%B')\" --edit -b master -h \"$(git rev-parse --abbrev-ref HEAD)\"; \ | |
}; f" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is a comment and will be ignored. Blank lines are also ignored. | |
# This can be placed in your repo directory, or in your home directory. | |
Did you review it? | |
Did you test it? | |
A final question? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# See http://redsymbol.net/articles/unofficial-bash-strict-mode/ | |
set -euo pipefail | |
IFS=$'\n\t' | |
SCRIPT_NAME="$(basename $0)" | |
CHECKLIST_NAME= | |
REQUIRE_INTERACTIVE=1 | |
REQUIRE_CHECKLIST=0 | |
VERBOSE=0 | |
usage() { | |
echo "Usage: $SCRIPT_NAME [--required|-r] [--noinput] [--help|-h] CHECKLIST" >&2 | |
echo >&2 | |
echo $'\t'"CHECKLIST"$'\t'"Required. The name of the checklist file. $SCRIPT_NAME will" >&2 | |
echo $'\t\t\t'"search for this file in the current directory and up through" >&2 | |
echo $'\t\t\t'"parent directories until it is found." >&2 | |
echo $'\t'"--required|-r"$'\t'"In required mode, the command fails if no checklist is found" >&2 | |
echo $'\t'"--noinput"$'\t'"Allows this command to be used in scripts" >&2 | |
echo $'\t'"--help|-h"$'\t'"Prints this message and exits" >&2 | |
exit 1 | |
} | |
usage-error() { | |
echo "$1" >&2 | |
usage | |
} | |
info-msg() { | |
if [[ "$VERBOSE" -gt 0 ]]; then | |
echo "$1" >&2 | |
fi | |
} | |
yesno() { | |
read -p "$1 (y/n) " response | |
case "$response" in | |
y*|Y*) ;; | |
*) exit 1 | |
esac | |
} | |
find-up() { | |
# https://unix.stackexchange.com/a/35265 | |
# Arguments are the same as the find utility, but it searches up to the | |
# root dir instead of down into subdirectories. | |
curpath="$1" | |
shift 1 | |
while [[ "$curpath" != / ]]; do | |
find "$curpath" -maxdepth 1 -mindepth 1 "$@" | |
# Try to use realpath first, falling back to readlink if needed | |
curpath="$(realpath -s "$curpath"/.. || readlink -f "$curpath"/..)" | |
done | |
} | |
# Get args | |
while [[ $# -gt 0 ]]; do | |
key="$1" | |
case $key in | |
--noinput) | |
REQUIRE_INTERACTIVE=0 | |
shift | |
;; | |
--required|-r) | |
REQUIRE_CHECKLIST=1 | |
shift | |
;; | |
--help|-h) | |
usage | |
;; | |
--verbose|-v) | |
VERBOSE=1 | |
shift | |
;; | |
*) | |
if [ -z "$CHECKLIST_NAME" ]; then | |
CHECKLIST_NAME="$1" | |
shift | |
else | |
usage-error "Unknown argument" | |
fi | |
;; | |
esac | |
done | |
if [ -z "$CHECKLIST_NAME" ]; then | |
usage-error 'No checklist name specified' | |
fi | |
# This disallows using this checklist in a script | |
if [ ! -t 0 ] && [[ "$REQUIRE_INTERACTIVE" -gt 0 ]]; then | |
echo 'This script must be run interactively' >&2 | |
exit 1 | |
fi | |
CHECKLIST_FILE="$(find-up . -type f -name "$CHECKLIST_NAME" | head -n 1)" | |
if [ -z "$CHECKLIST_FILE" ]; then | |
msg='No checklist file found' | |
if [[ "$REQUIRE_CHECKLIST" -gt 0 ]]; then | |
echo "$msg" >&2 | |
else | |
info-msg "$msg" | |
fi | |
exit "$REQUIRE_CHECKLIST" | |
else | |
info-msg "Found checklist file: $CHECKLIST_FILE" | |
fi | |
# Set up IFS to split input on newlines only | |
OLDIFS="$IFS"; IFS=$'\n' | |
for item in $(cat "$CHECKLIST_FILE"); do | |
item="$(echo -n "$item")" | |
if [ -n "$item" ] && [[ "$item" != '#'* ]]; then | |
yesno "$item" | |
fi | |
done | |
# Put IFS back to the previous setting | |
IFS="$OLDIFS" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
checklist
needs to go in a directory somewhere in your$PATH
..gitconfig
can be found in each git repository, or at~/.gitconfig
for global config (that's what I use)..pr_checklist
can go in your home directory (to make that checklist global), or in a specific repository (applies only to that repo).