Skip to content

Commit facb9df

Browse files
committed
Add support for multiple Go modules, multiple platforms, and a --makefile flag
Signed-off-by: Thomas Stromberg <[email protected]>
1 parent aa8f668 commit facb9df

File tree

3 files changed

+83
-12
lines changed

3 files changed

+83
-12
lines changed

.golangci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,4 @@ issues:
196196

197197
# Don't hide lint issues just because there are many of them
198198
max-same-issues: 0
199-
max-issues-per-linter: 0
199+
max-issues-per-linter: 0

Makefile.tmpl

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11

22
# BEGIN: lint-install {{.Args}}
3+
# http://github.com/tinkerbell/lint-install
34

4-
GOLINT_VERSION ?= v1.42.0
5-
HADOLINT_VERSION ?= v2.6.1
6-
SHELLCHECK_VERSION ?= v0.7.2
5+
{{ if .Go }}GOLINT_VERSION ?= v1.42.0{{ end }}
6+
{{ if .Dockerfile}}HADOLINT_VERSION ?= v2.7.0{{ end }}
7+
{{ if .Shell}}SHELLCHECK_VERSION ?= v0.7.2{{ end }}
78
LINT_OS := $(shell uname)
8-
LINT_LOWER_OS = $(shell echo $OS | tr '[:upper:]' '[:lower:]')
99
LINT_ARCH := $(shell uname -m)
1010

11+
# shellcheck and hadolint don't have arm64 native binaries: use Rosetta instead
12+
ifeq ($(LINT_OS),Darwin)
13+
ifeq ($(LINT_ARCH),arm64)
14+
LINT_ARCH=x86_64
15+
endif
16+
endif
17+
18+
{{ if .Shell }}LINT_LOWER_OS = $(shell echo $(LINT_OS) | tr '[:upper:]' '[:lower:]'){{ end }}
19+
{{ if .Go }}GOLINT_CONFIG:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))/.golangci.yml{{ end }}
20+
1121
lint: {{ if .Shell }}out/linters/shellcheck-$(SHELLCHECK_VERSION)/shellcheck {{ end }}{{ if .Dockerfile }}out/linters/hadolint-$(HADOLINT_VERSION) {{ end }}{{ if .Go}}out/linters/golangci-lint-$(GOLINT_VERSION){{ end }}
12-
{{ if .Go }}out/linters/golangci-lint-$(GOLINT_VERSION) run{{ if eq .Go "warn" }} || true{{ end }}{{ end }}
13-
{{ if .Shell }}out/linters/shellcheck-$(SHELLCHECK_VERSION)/shellcheck $(shell find . -name "*.sh"){{ if eq .Shell "warn" }} || true{{ end }}{{ end }}
14-
{{ if .Dockerfile }}out/linters/hadolint-$(HADOLINT_VERSION) $(shell find . -name "*Dockerfile"){{ if eq .Dockerfile "warn" }} || true{{ end }}{{ end }}
22+
{{- range .Commands }}
23+
{{ .}}{{ end}}
1524
{{ if .Shell}}
1625
out/linters/shellcheck-$(SHELLCHECK_VERSION)/shellcheck:
1726
mkdir -p out/linters
18-
curl -sfL https://github.com/koalaman/shellcheck/releases/download/v0.7.2/shellcheck-$(SHELLCHECK_VERSION).$(LINT_OS).$(LINT_ARCH).tar.xz | tar -C out/linters -xJf -
27+
curl -sfL https://github.com/koalaman/shellcheck/releases/download/v0.7.2/shellcheck-$(SHELLCHECK_VERSION).$(LINT_LOWER_OS).$(LINT_ARCH).tar.xz | tar -C out/linters -xJf -
1928
{{- end }}
2029
{{ if .Dockerfile}}
2130
out/linters/hadolint-$(HADOLINT_VERSION):
@@ -30,4 +39,4 @@ out/linters/golangci-lint-$(GOLINT_VERSION):
3039
mv out/linters/golangci-lint out/linters/golangci-lint-$(GOLINT_VERSION)
3140
{{- end }}
3241

33-
# END: lint-install {{.Args}}
42+
# END: lint-install {{.Args}}

lint-install.go

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var (
2121
goFlag = flag.String("go", "error", "Level to lint Go with: [ignore, warn, error]")
2222
shellFlag = flag.String("shell", "error", "Level to lint Shell with: [ignore, warn, error]")
2323
dockerfileFlag = flag.String("dockerfile", "error", "Level to lint Dockerfile with: [ignore, warn, error]")
24+
makeFileName = flag.String("makefile", "Makefile", "name of Makefile to update")
2425

2526
//go:embed .golangci.yml
2627
goLintConfig []byte
@@ -38,10 +39,12 @@ const (
3839
)
3940

4041
type Config struct {
42+
Makefile string
4143
Args string
4244
Go string
4345
Dockerfile string
4446
Shell string
47+
Commands []string
4548
}
4649

4750
// applicableLinters returns a list of languages with known linters within a given directory.
@@ -70,7 +73,7 @@ func applicableLinters(root string) (map[Language]bool, error) {
7073

7174
// updateMakefile updates the Makefile within a project with lint rules.
7275
func updateMakefile(root string, cfg Config, dryRun bool) (string, error) {
73-
dest := filepath.Join(root, "Makefile")
76+
dest := filepath.Join(root, cfg.Makefile)
7477
var existing []byte
7578
var err error
7679

@@ -118,6 +121,10 @@ func updateMakefile(root string, cfg Config, dryRun bool) (string, error) {
118121
proposed = append(proposed, newRules.Bytes()...)
119122
}
120123

124+
// trim any accidental trailing newlines
125+
proposed = bytes.TrimRight(proposed, "\n")
126+
proposed = append(proposed, byte('\n'))
127+
121128
edits := myers.ComputeEdits("Makefile", string(existing), string(proposed))
122129
change := gotextdiff.ToUnified(filepath.Base(dest), filepath.Base(dest), string(existing), edits)
123130
if !dryRun {
@@ -155,6 +162,55 @@ func updateGoLint(root string, dryRun bool) (string, error) {
155162
return fmt.Sprint(change), nil
156163
}
157164

165+
// goLintCmd returns the appropriate golangci-lint command to run for a project.
166+
func goLintCmd(root string, level string) string {
167+
klog.Infof("Searching for go modules within %s ...", root)
168+
found := []string{}
169+
170+
err := godirwalk.Walk(root, &godirwalk.Options{
171+
Callback: func(path string, de *godirwalk.Dirent) error {
172+
if strings.HasSuffix(path, "go.mod") {
173+
found = append(found, filepath.Dir(path))
174+
}
175+
return nil
176+
},
177+
Unsorted: true,
178+
})
179+
180+
if err != nil {
181+
klog.Errorf("unable to find go.mod files: %v", err)
182+
}
183+
184+
suffix := ""
185+
if level == "warn" {
186+
suffix = " || true"
187+
}
188+
189+
if len(found) == 1 && found[0] == root {
190+
return fmt.Sprintf("out/linters/golangci-lint-$(GOLINT_VERSION) run%s", suffix)
191+
}
192+
193+
return fmt.Sprintf(`find . -name go.mod | xargs -n1 dirname | xargs -n1 -I{} sh -c "cd {} && golangci-lint run -c $(GOLINT_CONFIG)"%s`, suffix)
194+
}
195+
196+
// shellLintCmd returns the appropriate shell lint command for a project.
197+
func shellLintCmd(_ string, level string) string {
198+
suffix := ""
199+
if level == "warn" {
200+
suffix = " || true"
201+
}
202+
return fmt.Sprintf(`out/linters/shellcheck-$(SHELLCHECK_VERSION)/shellcheck $(shell find . -name "*.sh")%s`, suffix)
203+
}
204+
205+
// dockerLintCmd returns the appropriate docker lint command for a project.
206+
func dockerLintCmd(_ string, level string) string {
207+
threshold := "info"
208+
if level == "warn" {
209+
threshold = "none"
210+
}
211+
return fmt.Sprintf(`out/linters/hadolint-$(HADOLINT_VERSION) -t %s $(shell find . -name "*Dockerfile")`, threshold)
212+
}
213+
158214
// main creates peanut butter & jelly sandwiches with utmost precision.
159215
func main() {
160216
klog.InitFlags(nil)
@@ -185,16 +241,22 @@ func main() {
185241
}
186242
}
187243

188-
cfg := Config{Args: strings.Join(os.Args[1:], " ")}
244+
cfg := Config{
245+
Args: strings.Join(os.Args[1:], " "),
246+
Makefile: *makeFileName,
247+
}
189248

190249
if needs[Go] {
191250
cfg.Go = *goFlag
251+
cfg.Commands = append(cfg.Commands, goLintCmd(root, cfg.Go))
192252
}
193253
if needs[Dockerfile] {
194254
cfg.Dockerfile = *dockerfileFlag
255+
cfg.Commands = append(cfg.Commands, dockerLintCmd(root, cfg.Dockerfile))
195256
}
196257
if needs[Shell] {
197258
cfg.Shell = *shellFlag
259+
cfg.Commands = append(cfg.Commands, shellLintCmd(root, cfg.Shell))
198260
}
199261

200262
diff, err := updateMakefile(root, cfg, *dryRunFlag)

0 commit comments

Comments
 (0)