Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

Commit

Permalink
Refactored pre-commit hooks
Browse files Browse the repository at this point in the history
**Added:**
- New pre-commit hook scripts for checking licenses, running Go tests,
  and running prettier.

**Changed:**
- Updated go-licenses.sh script to include new functions for license
  checking and vendoring.
- Modified go-vet.sh to simplify the vetting process for Go packages.
- Adjusted mdstyle.rb to allow longer lines in code blocks and tables.
- Renamed .yaml-lint.yaml to yamllint.yaml and added comment spacing rule.
- Updated .pre-commit-config.yaml to include new hooks and update
  existing ones.

**Fixed:**
- Removed unnecessary set -ex flags in go-no-replacement.sh and go-vet.sh
  to prevent verbose output.
  • Loading branch information
l50 committed Feb 20, 2024
1 parent a2785f4 commit 0230d3c
Show file tree
Hide file tree
Showing 18 changed files with 803 additions and 167 deletions.
51 changes: 51 additions & 0 deletions .hooks/generate-docs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash
#
# This script is a pre-commit hook that checks if the mage command is
# installed and if not, prompts the user to install it. If mage is
# installed, the script navigates to the repository root by calling the
# `rr` function and runs the `mage generatepackagedocs` command.
# This command generates documentation for all Go packages in the current
# directory and its subdirectories by traversing the file tree and creating
# a new README.md file in each directory containing a Go package.
# The script also ensures the presence of a specific utility bash file
# (bashutils.sh) and sources it if found. If the command fails, the commit
# is stopped, and an error message is shown.
set -e

# Define the URL of bashutils.sh
bashutils_url="https://raw.githubusercontent.com/l50/dotfiles/main/bashutils"

# Define the local path of bashutils.sh
bashutils_path="/tmp/bashutils"

# Check if bashutils.sh exists locally
if [[ ! -f "${bashutils_path}" ]]; then
# bashutils.sh doesn't exist locally, so download it
curl -s "${bashutils_url}" -o "${bashutils_path}"
fi

# Source bashutils
# shellcheck source=/dev/null
source "${bashutils_path}"

rr || exit 1

# Check if mage is installed
if ! command -v mage > /dev/null 2>&1; then
echo -e "mage is not installed\n"
echo -e "Please install mage by running the following command:\n"
echo -e "go install github.com/magefile/mage@latest\n"
exit 1
fi

# Run the mage generatepackagedocs command
mage generatepackagedocs
# Catch the exit code
exit_status=$?

# If the exit code is not zero (i.e., the command failed),
# then stop the commit and show an error message
if [ $exit_status -ne 0 ]; then
echo "failed to generate package docs"
exit 1
fi
45 changes: 45 additions & 0 deletions .hooks/go-licenses.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

# Function to check if go mod vendor should run or not
run_vendor()
{
echo "Running go mod vendor..."
go mod vendor
}

# Function to check licenses
check_licenses()
{
action=$1

go install github.com/google/go-licenses@latest

# Decide action based on input
if [[ $action == "check_forbidden" ]]; then
echo "Checking for forbidden licenses..."
output=$(go-licenses check ./... 2> /dev/null)
if [[ "${output}" == *"ERROR: forbidden license found"* ]]; then
echo "Forbidden licenses found. Please remove them."
exit 1
else
echo "No forbidden licenses found."
fi
elif [[ $action == "output_csv" ]]; then
echo "Outputting licenses to csv..."
status=go-licenses csv ./... 2> /dev/null
elif [[ $action == "vendor" ]]; then
echo "Vendoring dependencies..."
run_vendor
fi
}

# Ensure input is provided
if [[ $# -lt 1 ]]; then
echo "Incorrect number of arguments."
echo "Usage: $0 <licenses action>"
echo "Example: $0 check_forbidden"
exit 1
fi

# Run checks
check_licenses "${1}"
1 change: 0 additions & 1 deletion .hooks/go-no-replacement.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/bin/bash
set -ex

REPO=$(grep "url" .git/config)

Expand Down
22 changes: 7 additions & 15 deletions .hooks/go-vet.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
#!/bin/bash
set -ex
set -e

pkg=$(go list ./...)
for dir in */; do
if [[ "${dir}" != ".mage" ]] \
&& [[ "${dir}" != ".hooks/" ]] \
&& [[ "${dir}" != "config/" ]] \
&& [[ "${dir}" != "docs/" ]] \
&& [[ "${dir}" != "magefiles/" ]] \
&& [[ "${dir}" != "cmd/" ]] \
&& [[ "${dir}" != "bin/" ]] \
&& [[ "${dir}" != "images/" ]] \
&& [[ "${dir}" != "resources/" ]] \
&& [[ "${dir}" != "files/" ]] \
&& [[ "${dir}" != "logs/" ]]; then
go vet "${pkg}/${dir}"
pkgs=$(go list ./...)

for pkg in $pkgs; do
dir="$(basename "$pkg")/"
if [[ "${dir}" != .*/ ]] && [[ "${dir}" != "magefiles/" ]]; then
go vet "${pkg}"
fi
done
6 changes: 4 additions & 2 deletions .hooks/linters/mdstyle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
# Override default parameters for some built-in rules.
# https://github.com/markdownlint/markdownlint/blob/master/docs/creating_styles.md#parameters

# Ignore line length in code blocks.
rule 'MD013', :ignore_code_blocks => true
exclude_tag :line_length
# Allow long lines in code blocks and tables
rule 'MD013', line_length: 120, ignore_code_blocks: true, tables: false

#===============================================================================
# Exclude the rules I disagree with.
Expand All @@ -27,6 +28,7 @@
# - second indent
# * Another major bullet
exclude_rule 'MD004' # Unordered list style

exclude_rule 'MD007' # Unordered list indentation

# Ordered lists are fine.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ rules:
max: 200
level: warning
truthy: false
comments:
min-spaces-from-content: 1
38 changes: 38 additions & 0 deletions .hooks/prettier.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
set -exo pipefail

# Check if npm is installed
if ! [ -x "$(command -v npm)" ]; then
echo 'Error: npm is not installed.' >&2
exit 1
else
# Check if Prettier is installed
if ! [ -x "$(command -v prettier)" ]; then
echo 'Error: Prettier is not installed.' >&2
echo 'Installing Prettier...'
npm install -g prettier
fi
fi

# Check if Prettier is installed
if ! [ -x "$(command -v prettier)" ]; then
echo 'Error: Prettier is not installed.' >&2
exit 1
fi

# Run Prettier on staged .json, .yaml, and .yml files
echo "Running Prettier on staged files..."

# List all staged files, filter for the desired extensions, and run Prettier
git diff --cached --name-only --diff-filter=d \
| grep -E '\.(json|ya?ml)$' \
| xargs -I {} prettier --write {}

# Add the files back to staging area as Prettier may have modified them
git diff --name-only --diff-filter=d \
| grep -E '\.(json|ya?ml)$' \
| xargs git add

echo "Prettier formatting completed."

exit 0
76 changes: 76 additions & 0 deletions .hooks/run-go-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash

set -e

TESTS_TO_RUN=$1
RETURN_CODE=0

TIMESTAMP=$(date +"%Y%m%d%H%M%S")
LOGFILE="/tmp/goutils-unit-test-results-$TIMESTAMP.log"
MODULE_ROOT=$(go list -m -f "{{.Dir}}")

if [[ -z "${TESTS_TO_RUN}" ]]; then
echo "No tests input" | tee -a "$LOGFILE"
echo "Example - Run all shorter collection of tests: bash run-go-tests.sh short" | tee -a "$LOGFILE"
echo "Example - Run all tests: bash run-go-tests.sh all" | tee -a "$LOGFILE"
echo "Example - Run coverage for a specific version: bash run-go-tests.sh coverage" | tee -a "$LOGFILE"
echo "Example - Run tests for modified files: bash run-go-tests.sh modified" | tee -a "$LOGFILE"
exit 1
fi

run_tests()
{
local coverage_file=$1
repo_root=$(git rev-parse --show-toplevel 2> /dev/null) || exit
pushd "${repo_root}" || exit
echo "Logging output to ${LOGFILE}" | tee -a "$LOGFILE"
echo "Run the following command to see the output in real time:" | tee -a "$LOGFILE"
echo "tail -f ${LOGFILE}" | tee -a "$LOGFILE"
echo "Running tests..." | tee -a "$LOGFILE"

if [[ "${TESTS_TO_RUN}" == 'coverage' ]]; then
go test -v -race -failfast -tags=integration -coverprofile="${coverage_file}" ./... 2>&1 | tee -a "$LOGFILE"
elif [[ "${TESTS_TO_RUN}" == 'all' ]]; then
go test -v -race -failfast ./... 2>&1 | tee -a "$LOGFILE"
elif [[ "${TESTS_TO_RUN}" == 'short' ]] && [[ "${GITHUB_ACTIONS}" != "true" ]]; then
go test -v -short -failfast -race ./... 2>&1 | tee -a "$LOGFILE"
elif [[ "${TESTS_TO_RUN}" == 'modified' ]]; then
# Run tests for modified files
local modified_files
IFS=$'\n' read -r -a modified_files <<< "$(git diff --name-only --cached | grep '\.go$')"

local pkg_dirs=()

for file in "${modified_files[@]}"; do
local pkg_dir
pkg_dir=$(dirname "$file")
pkg_dir=${pkg_dir#"$MODULE_ROOT/"}
pkg_dirs+=("$pkg_dir")
done

# Remove duplicate package directories
IFS=$'\n' read -r -a pkg_dirs <<< "$(sort -u <<< "${pkg_dirs[*]}")"
unset IFS

for dir in "${pkg_dirs[@]}"; do
go test -v -race -failfast "./$dir/..." 2>&1 | tee -a "$LOGFILE"
done
else
if [[ "${GITHUB_ACTIONS}" != 'true' ]]; then
go test -v -failfast -race "./.../${TESTS_TO_RUN}" 2>&1 | tee -a "$LOGFILE"
fi
fi

RETURN_CODE=$?
}

if [[ "${TESTS_TO_RUN}" == 'coverage' ]]; then
run_tests 'coverage-all.out'
else
run_tests
fi

if [[ "${RETURN_CODE}" -ne 0 ]]; then
echo "unit tests failed" | tee -a "$LOGFILE"
exit 1
fi
64 changes: 39 additions & 25 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,24 @@ repos:
hooks:
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-added-large-files
- id: detect-private-key
- id: check-shebang-scripts-are-executable

- repo: https://github.com/adrienverge/yamllint.git
rev: v1.32.0
rev: v1.35.1
hooks:
- id: yamllint
entry: yamllint --strict -c .hooks/linters/.yaml-lint.yaml

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
hooks:
- id: prettier
files: \.(json|md|yaml|yml)$

- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
- id: script-must-have-extension
name: Ensure shell scripts end with .sh
types: [shell]
- id: shellcheck
- id: shfmt
# Configuration in .mdlrc and .hooks/linters/mdstyle.rb
- id: markdownlint
entry: yamllint --strict -c .hooks/linters/yamllint.yaml

- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
- id: codespell
entry: codespell -q 3 -f --skip=".git,.github" README.md cmd/*
entry: codespell -q 3 -f --skip=".git,.github,go.*,magefiles/go.*" README.md

- repo: https://github.com/dnephin/pre-commit-golang
rev: v0.5.1
Expand All @@ -46,12 +31,25 @@ repos:
- id: go-lint
- id: go-imports
- id: go-cyclo
args: [-over=20]
args: [-over=15]
- id: golangci-lint
- id: go-critic
- id: go-build
- id: go-mod-tidy

- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
- id: script-must-have-extension
name: Ensure shell scripts end with .sh
types: [shell]
exclude: .bats
- id: shellcheck
- id: shfmt
# Configuration in .mdlrc and .hooks/linters/mdstyle.rb
- id: markdownlint
exclude: README.md

- repo: local
hooks:
- id: go-no-replacement
Expand All @@ -60,14 +58,30 @@ repos:
language: script
files: go.mod

- id: go-unit-tests
name: Go unit tests
language: script
entry: .hooks/run-go-tests.sh modified
files: '\.go$'
pass_filenames: true

- id: go-vet
name: Run go vet
language: script
entry: .hooks/go-vet.sh
files: '\.go$'
always_run: true
pass_filenames: true
require_serial: true
log_file: /tmp/go-vet.log

- id: go-unit-tests
name: Go unit tests
- id: go-licenses
name: Run go-licenses
language: script
entry: .hooks/go-unit-tests.sh all
files: '\.go$'
entry: .hooks/go-licenses.sh check_forbidden

- id: prettier
name: Run prettier
entry: .hooks/prettier-hook.sh
language: script
types: [json, yaml]
Loading

0 comments on commit 0230d3c

Please sign in to comment.