Skip to content

Commit 4ad71c3

Browse files
committed
feat(precommit): add tasks for registering and running precommit
1 parent eef1963 commit 4ad71c3

File tree

10 files changed

+396
-21
lines changed

10 files changed

+396
-21
lines changed

.examples/python3/installpython3.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//go:build examples
2+
3+
// Overcomplicated example of installing python 3 with built in commands.
4+
// Probably a much better way to do this with other packages, but I wanted to save this as one example.
5+
// Additionally, I've reverted to using asdf or other tooling instead.
6+
package main
7+
8+
import (
9+
"fmt"
10+
"os"
11+
"os/exec"
12+
"runtime"
13+
14+
"github.com/magefile/mage/sh"
15+
"github.com/pterm/pterm"
16+
)
17+
18+
//
19+
// installPython3 is a setup helper to ensure python3 is setup on new systems for pre-commit tooling.
20+
//
21+
// Yes this should be done in Docker, or in OS, but in this case I'm trying to simplify bootstrap of a project and automatically handle pre-commit setup in case the environment doesn't have that already setup.
22+
func installPython3() (string, error) { //nolint: cyclop // cyclop: acceptable as this is a cross platform installation function that tries to help setup a system with python if doesn't exist.
23+
switch runtime.GOOS {
24+
case "linux":
25+
pterm.Info.Println("attempting to sudo install python3-pip")
26+
_, err := os.Stat("apt-get")
27+
if err != nil {
28+
return "", fmt.Errorf(
29+
"linux: automatic setup is only supported on debian based systems with apt-get command available: %w",
30+
err,
31+
)
32+
}
33+
if err := sh.RunV("sudo", "apt-get", "-yqq", "update"); err != nil {
34+
pterm.Error.Println("running apt-get update")
35+
return "", fmt.Errorf("linux: failed to apt-get update: %w", err)
36+
}
37+
pterm.Warning.Println("This can take 5-10 mins, depending on your system.")
38+
if err := sh.RunV("sudo", "apt-get", "-yqq", "install", "python3-pip"); err != nil {
39+
pterm.Error.Println("failed to sudo install python3-pip")
40+
return "", fmt.Errorf("linux: failed to sudo install python3-pip: %w", err)
41+
}
42+
case "darwin":
43+
pterm.Info.Println("will attempt to install with homebrew")
44+
_, err := os.Stat("brew")
45+
if err != nil {
46+
return "", fmt.Errorf(
47+
"darwin: automatic setup only works with homebrew installed. Try again after installing homebrew. https://docs.brew.sh/Installation: %w",
48+
err,
49+
)
50+
}
51+
if err := sh.RunV("brew", "install", "python3@3.10"); err != nil {
52+
return "", fmt.Errorf("failure on: brew install python3@3.10: %w", err)
53+
}
54+
case "windows":
55+
_, err := os.Stat("scoop")
56+
if err != nil {
57+
return "", fmt.Errorf(
58+
"windows: automatic setup only works with Scoop installed. Try again after installing Scoop. https://github.com/ScoopInstaller/Scoop#installation: %w",
59+
err,
60+
)
61+
}
62+
if err := sh.RunV("scoop", "install", "python"); err != nil {
63+
return "", fmt.Errorf("scoop install python3@3.10: %w", err)
64+
}
65+
}
66+
path, err := exec.LookPath("python3")
67+
return path, err
68+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,5 @@ dist/
9797
licensing/.licenses/
9898
docker/.devcontainer
9999
.artifacts/
100+
precommit/.pre-commit.config.yaml
101+
precommit/.pre-commit-config.yaml

.pre-commit-config.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ repos:
118118
#entry: GOTESTS='slow' go test ./... -json -v -shuffle=on -race -tags integration | tparse -notests -smallscreen -pulse 1s
119119
# no race conditions for this because we are doing build tasks here and not threadsafe to run parallel builds on every function
120120
#entry: zsh -c "GOTESTS='superslow' go test ./... -json -v -shuffle=on -tags integration | tparse -notests -smallscreen -pulse 1s"
121-
entry: zsh -c "(mkdir -p .artifacts/ || echo '.artifacts already exists') && GOTESTS='slow' GOTEST_FLAGS='--tags=integration' gotestsum --format pkgname --junitfile .artifacts/junit.xml --jsonfile
122-
.artifacts/gotest.json -- -coverpkg=./... -coverprofile=.artifacts/cover.out -covermode atomic -shuffle=on -tags=integration ./..."
121+
# entry: zsh -c "(mkdir -p .artifacts/ || echo '.artifacts already exists') && GOTESTS='slow' GOTEST_FLAGS='--tags=integration' gotestsum --format pkgname --junitfile .artifacts/junit.xml --jsonfile
122+
# .artifacts/gotest.json -- -coverpkg=./... -coverprofile=.artifacts/cover.out -covermode atomic -shuffle=on -tags=integration ./..."
123123
always_run: true # Always run full tests before push
124+
entry: gotestsum
125+
args: [./...]
124126
stages: [commit]
125127
types: [go]
126128
language: golang

.tool-versions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
mage 1.13.0
2+
golang 1.18.1
3+
go-sdk 1.18.1

.vscode/settings.json

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,5 @@
1414
"go.testEnvVars": {
1515
"GOTESTS": "slow",
1616
},
17-
"workbench.colorCustomizations": {
18-
"sash.hoverBorder": "#f1ba5b",
19-
"statusBar.background": "#eda62c",
20-
"statusBar.foreground": "#15202b",
21-
"statusBarItem.hoverBackground": "#d48d12",
22-
"statusBarItem.remoteBackground": "#eda62c",
23-
"statusBarItem.remoteForeground": "#15202b",
24-
"tab.activeBorder": "#f1ba5b",
25-
"titleBar.activeBackground": "#eda62c",
26-
"titleBar.activeForeground": "#15202b",
27-
"titleBar.inactiveBackground": "#eda62c99",
28-
"titleBar.inactiveForeground": "#15202b99"
29-
},
3017
"peacock.color": "#eda62c"
31-
}
18+
}

gotools/gotools.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,19 @@ func (Go) Lint() error {
267267
return nil
268268
}
269269

270+
// 🔎 Run golangci-lint and apply any auto-fix.
271+
func (Go) Fix() error {
272+
magetoolsutils.CheckPtermDebug()
273+
274+
pterm.Info.Println("Running golangci-lint with --fix flag enabled.")
275+
if err := sh.RunV("golangci-lint", "run", "--fix"); err != nil {
276+
pterm.Error.WithShowLineNumber(true).WithLineNumberOffset(1).Println("golangci-lint failure")
277+
return err
278+
}
279+
pterm.Success.Println("✅ Go Lint")
280+
return nil
281+
}
282+
270283
// ✨ Fmt runs gofumpt. Export SKIP_GOLINES=1 to skip golines.
271284
// Important. Make sure golangci-lint config disables gci, goimports, and gofmt.
272285
// This will perform all the sorting and other linters can cause conflicts in import ordering.
@@ -369,18 +382,23 @@ func (Go) LintConfig() error {
369382
magetoolsutils.CheckPtermDebug()
370383
pterm.DefaultHeader.Println("🏥 LintConfig Diagnostic Checks")
371384
pterm.DefaultSection.Println("🔍 golangci-lint linters with --fast")
372-
if err := sh.RunV("golangci-lint", "linters", "--fast"); err != nil {
385+
var out string // using output instead of formatted colors straight to console so that test output with pterm can suppress.
386+
var err error
387+
out, err = sh.Output("golangci-lint", "linters", "--fast")
388+
if err != nil {
373389
pterm.Error.WithShowLineNumber(true).WithLineNumberOffset(1).Println("unable to run golangci-lint")
374390
tracerr.PrintSourceColor(err)
375391
return err
376392
}
393+
pterm.DefaultBox.Println(out)
377394
pterm.DefaultSection.Println("🔍 golangci-lint linters with plain run")
378-
if err := sh.RunV("golangci-lint", "linters"); err != nil {
395+
out, err = sh.Output("golangci-lint", "linters")
396+
if err != nil {
379397
pterm.Error.WithShowLineNumber(true).WithLineNumberOffset(1).Println("unable to run golangci-lint")
380398
tracerr.PrintSourceColor(err)
381399
return err
382400
}
383-
401+
pterm.DefaultBox.Println(out)
384402
pterm.Success.Println("LintConfig Diagnostic Checks")
385403
return nil
386404
}

magefiles/mage.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ import (
1212
"github.com/sheldonhull/magetools/fancy"
1313

1414
// mage:import
15-
"github.com/sheldonhull/magetools/gotools"
15+
"github.com/sheldonhull/magetools/gittools"
1616

1717
// mage:import
18-
_ "github.com/sheldonhull/magetools/gittools" // gotools provides Git tooling to install git town and bit.
18+
"github.com/sheldonhull/magetools/gotools"
1919

2020
// mage:import
2121
_ "github.com/sheldonhull/magetools/licensing" // licensing provides a license checker and vendor tooling for the project
22+
// mage:import
23+
_ "github.com/sheldonhull/magetools/precommit"
2224
)
2325

2426
// Default target to run when none is specified
@@ -65,6 +67,7 @@ func Init() { //nolint:deadcode // This is not dead code, and I find this insult
6567
Clean,
6668
createDirectories,
6769
gotools.Go{}.Init,
70+
gittools.Gittools{}.Init,
6871
// tooling.SilentInstallTools(toolList),
6972
)
7073
}

precommit/precommit.data.tmpl

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
# IF ERROR ON INSTALL:
3+
# brew uninstall pre-commit
4+
# install with non-admin install this works on mac
5+
# curl https://pre-commit.com/install-local.py | python -
6+
# Setup: pre-commit install
7+
# Upgrade: pre-commit autoupdate
8+
# Run: pre-commit run --all-files
9+
# https://pre-commit.com/hooks.html
10+
11+
default_language_version:
12+
# force all unspecified python hooks to run python3
13+
python: python3
14+
exclude: (.terraform.lock.hcl)|(.devcontainer/)|(.cache/)|(.artifacts/)|(node_modules/)|(.yarn)|(ansible/)|(.licenses/)|(vendor/)
15+
repos:
16+
17+
# https://github.com/jumanjihouse/pre-commit-hook-yamlfmt#override-defaults
18+
# https://yaml.readthedocs.io/en/latest/example.html
19+
20+
- repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt
21+
rev: 0.1.0 # or specific tag
22+
hooks:
23+
- id: yamlfmt
24+
args: [--mapping, '2', --sequence, '4', --offset, '2']
25+
- repo: https://github.com/adrienverge/yamllint.git
26+
rev: v1.26.3 # or higher tag
27+
hooks:
28+
- id: yamllint
29+
args: [--format, parsable, --strict]
30+
31+
# Documentation on the arguments for these hooks https://github.com/pre-commit/pre-commit-hooks
32+
- repo: https://github.com/pre-commit/pre-commit-hooks
33+
rev: v4.0.1 # Use the ref you want to point at
34+
hooks:
35+
- id: trailing-whitespace
36+
args: [--markdown-linebreak-ext=md]
37+
- id: check-byte-order-marker
38+
- id: check-case-conflict
39+
- id: detect-aws-credentials
40+
args: [--allow-missing-credentials]
41+
- id: mixed-line-ending
42+
args: [--fix=lf]
43+
- id: pretty-format-json
44+
exclude: ^.vscode/
45+
args: [--autofix, --no-ensure-ascii]
46+
47+
- id: check-yaml
48+
- id: detect-private-key
49+
- id: end-of-file-fixer
50+
- id: fix-byte-order-marker
51+
- id: check-added-large-files
52+
- id: check-merge-conflict
53+
- id: forbid-new-submodules
54+
- id: name-tests-test
55+
- id: sort-simple-yaml
56+
- id: no-commit-to-branch
57+
args: [--branch, develop, --branch, master, --branch, main]
58+
- id: requirements-txt-fixer
59+
- id: check-toml
60+
# Allows json to have comments which avoids a lot of false errors with things like vscode or other json configuration files.
61+
- repo: https://gitlab.com/bmares/check-json5
62+
rev: v1.0.0
63+
hooks:
64+
- id: check-json5
65+
66+
# https://pre-commit.com/#supported-languages
67+
- repo: local
68+
hooks:
69+
- id: shellcheck
70+
name: shellcheck
71+
entry: zsh -c docker run --rm -v "${PWD}:/mnt" koalaman/shellcheck:stable --format=json
72+
language: system
73+
74+
- repo: https://github.com/tchoedak/pre-commit-sql-format
75+
rev: v0.0.3
76+
hooks:
77+
- id: format-sql
78+
79+
- repo: https://github.com/DavidAnson/markdownlint-cli2
80+
rev: v0.3.2
81+
hooks:
82+
- id: markdownlint-cli2
83+
84+
- repo: local
85+
hooks:
86+
- id: gitleaks
87+
name: gitleaks
88+
entry: gitleaks --commit=latest --no-git --format json --path=. --report=.artifacts/gitleaks.json --quiet
89+
language: system
90+
pass_filenames: false
91+
stages: [push]
92+
93+
# Go Local Hooks
94+
- repo: local
95+
hooks:
96+
- id: golines
97+
name: go-fmt
98+
description: Run formatter against changed files
99+
entry: mage go:wrap
100+
types: [go]
101+
language: golang
102+
pass_filenames: true
103+
104+
- id: golangci-lint
105+
name: golangci-lint
106+
description: Run lint (normal) with fix applied.
107+
entry: mage go:fix
108+
types: [go]
109+
language: golang
110+
pass_filenames: false
111+
112+
# pre-commit run --hook-stage push
113+
# This eventually needs to be tweaked to use the right tags and options for your environment.
114+
# For example: -race might not be appropriate if doing Mage tests since they are designed to be run in parallel.
115+
- id: gotest
116+
name: go-test-all
117+
description: Run integration tests for go
118+
entry: zsh -c "GOTESTS='superslow' go test ./... -json -v -shuffle=on -race -tags integration | tparse -notests -smallscreen -pulse 1s"
119+
always_run: true # Always run full tests before push
120+
stages: [push]
121+
types: [go]
122+
language: golang
123+
pass_filenames: false
124+
verbose: true
125+
126+
# Can use mage task for go testing without integration flag and speed things up.
127+
- id: gotest
128+
name: go-test-fast
129+
description: Run fast unit tests for go
130+
entry: go test ./... -json -v -shuffle=on -race | tparse -notests -smallscreen -pulse 1s
131+
stages: [commit]
132+
types: [go]
133+
language: golang
134+
pass_filenames: false
135+
verbose: true
136+
137+
- repo: local
138+
hooks:
139+
- id: gocover
140+
name: gocover
141+
entry: zsh -c 'go tool cover -func=".artifacts/cover.out" -o=".artifacts/coverage.out"'
142+
language: system
143+
stages: [commit]
144+
145+
- id: gobadge
146+
name: gobadge
147+
entry: gobadge -filename=.artifacts/coverage.out
148+
language: system
149+
stages: [commit]

0 commit comments

Comments
 (0)