Last active
May 14, 2024 04:28
-
-
Save itchyny/e2257b1f1b35b9440d78a89852a3cb5e to your computer and use it in GitHub Desktop.
A checker for my own Go product repositories
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 | |
set -euo pipefail | |
git status >/dev/null || exit 1 | |
err= | |
error_message() { | |
printf '%s\n\n' "$*" >&2 | |
err=1 | |
} | |
shopt -s nullglob | |
for f in .github/workflows/*.yaml; do | |
git grep -F "push, pull_request" "$f" && | |
error_message "Fix CI triggers in $f (do not make actions run duplicately)." | |
git grep -q -F "actions/setup-go" "$f" && | |
! git grep -q -E 'go-version: (1\.x|.*matrix\.go|\$\{\{)' "$f" && { | |
git grep -F "go-version:" "$f" && | |
error_message "Fix 'go-version' in $f to use 1.x or matrix." | |
} | |
for action in \ | |
actions/checkout@v4 \ | |
actions/cache@v4 \ | |
actions/setup-go@v5 \ | |
actions/upload-artifact@v4 \ | |
actions/download-artifact@v4 \ | |
docker/metadata-action@v5 \ | |
docker/setup-qemu-action@v3 \ | |
docker/setup-buildx-action@v3 \ | |
docker/login-action@v3 \ | |
docker/build-push-action@v5 \ | |
docker/bake-action@v4; do | |
git grep -q -F "${action%@v*}" "$f" && | |
! git grep -q -F "$action" "$f" && { | |
git grep -F "${action%@v*}" "$f" | |
error_message "Update to '$action' in $f." | |
} | |
done | |
git grep -F "actions/create-release" "$f" && | |
error_message "Stop using deprecated 'actions/create-release' in $f." | |
git grep -F "actions/upload-release-asset" "$f" && | |
error_message "Stop using deprecated 'actions/upload-release-asset' in $f." | |
git grep -E "@(master|main)" "$f" && | |
error_message "Fix action version in $f" \ | |
"(use @v1 or @v2, otherwise updates in actions may break your CI)". | |
git grep -q -F "runs-on:" "$f" && | |
git grep -P 'ubuntu-\d+\.\d+' "$f" && | |
error_message "Fix ubuntu version in $f" \ | |
"(use 'ubuntu-latest', otherwise you will forget to update)." | |
git grep -q -F "matrix:" "$f" && | |
! git grep -q "fail-fast:" "$f" && | |
error_message "Specify 'fail-fast: false' in $f." | |
git grep -F "::set-env" "$f" && | |
error_message "Migrate deprecated '::set-env' to \$GITHUB_ENV in $f." | |
git grep -F "::set-output" "$f" && | |
error_message "Migrate deprecated '::set-output' to \$GITHUB_OUTPUT in $f." | |
git grep -F "::save-state" "$f" && | |
error_message "Migrate deprecated '::save-state' to \$GITHUB_STATE in $f." | |
git grep -q "^permissions:" "$f" || | |
error_message "Specify 'permissions' to allow minimum required access in $f." | |
git grep -q "docker/build-push-action" "$f" && | |
! git grep -q "provenance: false" "$f" && | |
error_message "Specify 'provenance: false' on building Docker images in $f." | |
[[ "${f##*/}" =~ ^release.ya?ml$ ]] && | |
error_message "Unify release workflow $f to CI workflow." | |
done | |
if [[ -f LICENSE ]]; then | |
git grep -q -F "The MIT License" LICENSE && | |
git grep -q -F "$(whoami)" LICENSE && | |
git log -1 --format=%cs 2>&1 | grep -q "^$(date +%Y)" && | |
! git grep -q -E "$(date +%Y).*$(whoami)" LICENSE && | |
error_message "Update copyright year in LICENSE." | |
fi | |
if [[ -f README.md ]]; then | |
git grep -F "godoc.org" README.md && | |
error_message "Fix 'godoc.org' to 'pkg.go.dev' in README.md." | |
git grep -F "go get " README.md && | |
error_message "Fix 'go get' to 'go install' in README.md" | |
git grep -P 'http://(?!localhost|\d+\.\d+\.\d+\.\d+)' README.md && | |
error_message "Fix links to https in README.md." | |
git grep -P "(?<=\()https://github.com/[^/]+/[^/]+/workflows/[^/]+/badge.svg" README.md && | |
error_message "Fix Actions badge to switch to actions workflow URL in README.md." | |
git grep -P "(?<=\()https://github.com/[^/]+/[^/]+/(?:actions/)?workflows/[^/]+/badge.svg(?=\))" README.md && | |
error_message "Fix Actions badge to filter by branch in README.md." | |
git grep -P "(?<=\()https://github.com/[^/]+/[^/]+/actions(?=\))" README.md && | |
error_message "Fix Actions link to filter by branch in README.md." | |
git grep -P "(?<=^(\S{,40}) \()https://github.com/\1(?=\))" README.md && | |
error_message "Fix link to the author in README.md to wrap by <...>." | |
fi | |
if [[ -f Makefile ]]; then | |
git grep -E "clean +build" Makefile && | |
error_message "Fix 'make all' in Makefile ('make all' should not 'clean')." | |
git grep -P '\bgo test\b' Makefile | grep -v -- -race && | |
error_message "Add '-race' to 'go test' in Makefile." | |
git grep -q -F "/motemen/gobump/cmd/gobump" Makefile && | |
error_message "Fix 'gobump' path in Makefile." | |
git grep -F "GO111MODULE=on" Makefile && | |
error_message "Remove 'GO111MODULE=on' in Makefile." | |
git grep -E "cd .* go get " Makefile && | |
error_message "Fix 'go get' to 'go install' in Makefile." | |
git grep -q "golint" Makefile && | |
error_message "Migrate deprecated 'golint' to 'staticcheck'." | |
git grep -q "staticcheck" Makefile && | |
! git grep -q "staticcheck.*-checks all" Makefile && | |
error_message "Specify '-checks all(,-ST1000)?' to staticcheck." | |
git grep "staticcheck@master" Makefile && | |
error_message "Specify '@latest' of staticcheck." | |
git grep -q "cross:" Makefile && | |
! git grep -q "CREDITS:" Makefile && | |
error_message "Add 'CREDITS' to the artifacts." | |
git grep -q "goxz" Makefile && | |
git grep "[-]arch=amd64,arm64" Makefile && | |
error_message "Remove '-arch=amd64,arm64' from 'goxz' flags, since it is by default." | |
git grep -q "bump:" Makefile && | |
git grep "ifneq.*shell git status --porcelain" Makefile && | |
error_message "Delay git invocation." | |
git grep -q "CREDITS:" Makefile && | |
! git grep -q "/CREDITS" .gitignore && | |
! git ls-files --error-unmatch CREDITS &>/dev/null && | |
error_message "Add '/CREDITS' to .gitignore." | |
test -f .dockerignore && | |
git grep -q "CREDITS:" Makefile && | |
! git grep -q "/CREDITS" .dockerignore && | |
! git ls-files --error-unmatch CREDITS &>/dev/null && | |
error_message "Add '/CREDITS' to .dockerignore." | |
git grep -q "CREDITS:" Makefile && | |
test -f go.sum && | |
! git grep -q -E "CREDITS:.*go.sum" Makefile && | |
error_message "Add 'go.sum' to CREDITS dependency in Makefile." | |
fi | |
if [[ -f go.mod ]]; then | |
git grep -E '^go 1\.(1[0-9]|2[0-1])$' go.mod && | |
error_message "Bump up Go version in go.mod." | |
git grep -E '^go 1\.[0-9]+\.[0-9]+$' go.mod && | |
error_message "Do not specify Go patch version in go.mod." | |
[[ -f go.sum ]] || | |
error_message "Add go.sum (run 'go mod tidy && touch go.sum'," \ | |
"even empty go.sum is important for dependency caching)." | |
go vet ./... || | |
error_message "go vet ./..." | |
command -v golint &>/dev/null || | |
go install golang.org/x/lint/golint@latest | |
golint -set_exit_status ./... || | |
error_message "golint -set_exit_status ./..." | |
command -v staticcheck &>/dev/null || | |
go install honnef.co/go/tools/cmd/staticcheck@latest | |
staticcheck -checks all,-ST1000 ./... || | |
error_message "staticcheck -checks all,-ST1000 ./..." | |
command -v gocritic &>/dev/null || | |
go install github.com/go-critic/go-critic/cmd/gocritic@latest | |
gocritic check -disable=ifElseChain,appendAssign ./... || | |
error_message "gocritic check -disable=ifElseChain ./..." | |
command -v revive &>/dev/null || | |
go install github.com/mgechev/revive@latest | |
revive -config "${XDG_CONFIG_HOME:-$HOME}/revive.toml" -set_exit_status -formatter=friendly ./... || | |
error_message "revive -set_exit_status -formatter=friendly ./..." | |
command -v gosec &>/dev/null || | |
go install github.com/securego/gosec/v2/cmd/gosec@latest | |
gosec -quiet -exclude-generated -severity=high ./... || | |
error_message "gosec -exclude-generated -severity=high ./..." | |
git grep -E '\bio/ioutil\b' && | |
error_message "Stop using deprecated 'io/ioutil' package." | |
repo="$(git config --get remote.origin.url | sed -E 's#^.*github.com[:/]|.git$##g')" && { | |
url="https://goreportcard.com/report/github.com/$repo" | |
response=$(curl -sSfL "$url" | sed -n 's/var response *= \(.*\);/console.log(JSON.stringify(\1))/p' | node) | |
if [[ "$response" != "false" ]]; then | |
echo "$response" | jq -cr '.checks[] | select(.name != "gocyclo" and .percentage < 1) | | |
"\(.name): \(.percentage * 100)%"' | grep ^ && | |
error_message "See goreportcard." && open "$url" | |
fi | |
} | |
elif git ls-files --error-unmatch '*.go' &>/dev/null; then | |
error_message "Use Go modules (add go.mod)." | |
fi | |
if [[ -z "$err" ]]; then | |
printf '\e[0;30;46m \e[0m\n' | |
printf '\e[0;30;46m OK \e[0m\n' | |
printf '\e[0;30;46m \e[0m\n' | |
else | |
printf '\e[0;30;41m \e[0m\n' | |
printf '\e[0;30;41m NG \e[0m\n' | |
printf '\e[0;30;41m \e[0m\n' | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment