| #!/usr/bin/env bash |
| |
| # READ THIS BEFORE MAKING CHANGES: |
| # |
| # If you want to add a new pre-commit check, here are the rules: |
| # |
| # 1. Create a bash function for your check (see e.g. ui_lint below). |
| # NOTE: Each function will be called in a sub-shell so you can freely |
| # change directory without worrying about interference. |
| # 2. Add the name of the function to the CHECKS variable. |
| # 3. If no changes relevant to your new check are staged, then |
| # do not output anything at all - this would be annoying noise. |
| # In this case, call 'return 0' from your check function to return |
| # early without blocking the commit. |
| # 4. If any non-trivial check-specific thing has to be invoked, |
| # then output '==> [check description]' as the first line of |
| # output. Each sub-check should output '--> [subcheck description]' |
| # after it has run, indicating success or failure. |
| # 5. Call 'block [reason]' to block the commit. This ensures the last |
| # line of output calls out that the commit was blocked - which may not |
| # be obvious from random error messages generated in 4. |
| # |
| # At the moment, there are no automated tests for this hook, so please run it |
| # locally to check you have not broken anything - breaking this will interfere |
| # with other peoples' workflows significantly, so be sure, check everything twice. |
| |
| set -euo pipefail |
| |
| # Call block to block the commit with a message. |
| block() { |
| echo "$@" |
| echo "Commit blocked - see errors above." |
| exit 1 |
| } |
| |
| # Add all check functions to this space separated list. |
| # They are executed in this order (see end of file). |
| CHECKS="ui_lint backend_lint" |
| |
| # Run ui linter if changes in that dir detected. |
| ui_lint() { |
| local DIR=ui LINTER=node_modules/.bin/lint-staged |
| |
| # Silently succeed if no changes staged for $DIR |
| if git diff --name-only --cached --exit-code -- $DIR/; then |
| return 0 |
| fi |
| |
| # Silently succeed if the linter has not been installed. |
| # We assume that if you're doing UI dev, you will have installed the linter |
| # by running yarn. |
| if [ ! -x $DIR/$LINTER ]; then |
| return 0 |
| fi |
| |
| echo "==> Changes detected in $DIR/: Running linter..." |
| |
| # Run the linter from the UI dir. |
| cd $DIR |
| $LINTER || block "UI lint failed" |
| } |
| |
| backend_lint() { |
| # Silently succeed if no changes staged for Go code files. |
| staged=$(git diff --name-only --cached --exit-code -- '*.go') |
| ret=$? |
| if [ $ret -eq 0 ]; then |
| return 0 |
| fi |
| |
| # Only run fmtcheck on staged files |
| ./scripts/gofmtcheck.sh "${staged}" || block "Backend linting failed; run 'make fmt' to fix." |
| } |
| |
| for CHECK in $CHECKS; do |
| # Force each check into a subshell to avoid crosstalk. |
| ( $CHECK ) || exit $? |
| done |