Skip to content

Commit f795b4b

Browse files
DirectXMan12camilamacedo86
authored andcommitted
📖 re-enable golangci-lint's godoc comment checking
1 parent df180ac commit f795b4b

File tree

19 files changed

+418
-26
lines changed

19 files changed

+418
-26
lines changed

.github/main.workflow

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,14 @@ action "verify-emoji" {
77
uses = "./hack/release"
88
secrets = ["GITHUB_TOKEN"]
99
}
10+
11+
workflow "Linters and Test" {
12+
on = "push"
13+
resolves = ["lint"]
14+
}
15+
16+
action "lint" {
17+
uses = "docker://gcr.io/kubebuilder/lint2check"
18+
secrets = ["GITHUB_TOKEN"]
19+
args = ["./pkg/...", "./examples/..."]
20+
}

.golangci.yml

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
1-
linters:
2-
disable-all: true
3-
enable:
4-
- misspell
5-
- structcheck
6-
- golint
7-
- govet
8-
- deadcode
9-
- errcheck
10-
- varcheck
11-
- goconst
12-
- unparam
13-
- ineffassign
14-
- nakedret
15-
- interfacer
16-
- gocyclo
17-
- lll
18-
- dupl
19-
- goimports
20-
1+
run:
2+
deadline: 5m
213
linters-settings:
224
lll:
235
line-length: 170
246
dupl:
257
threshold: 400
8+
issues:
9+
# don't skip warning about doc comments
10+
exclude-use-default: false
2611

27-
run:
28-
timeout: 5m
12+
# restore some of the defaults
13+
# (fill in the rest as needed)
14+
exclude-rules:
15+
- linters: [errcheck]
16+
text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked"
17+
linters:
18+
disable-all: true
19+
enable:
20+
- misspell
21+
- structcheck
22+
- golint
23+
- govet
24+
- deadcode
25+
- errcheck
26+
- varcheck
27+
- goconst
28+
- unparam
29+
- ineffassign
30+
- nakedret
31+
- interfacer
32+
- gocyclo
33+
- lll
34+
- dupl
35+
- goimports
36+
- golint

hack/lint2check/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM golang
2+
3+
COPY lint2check /usr/bin/lint2check
4+
COPY golangci-lint /usr/bin/golangci-lint
5+
# make sure lint2check can find golangci-lint
6+
ENV GO111MODULE=on
7+
8+
ENTRYPOINT ["/usr/bin/lint2check"]

hack/lint2check/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# lint2check
2+
3+
lint2check runs golangci-lint, converts the results to github check API
4+
results, and submits them as a separate check run.

hack/lint2check/cloudbuild.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
steps:
2+
- name: "golang"
3+
args: ["go", "build", "-o", "lint2check", "."]
4+
env: ["GO111MODULE=on", "CGO_ENABLED=0"]
5+
- name: "golang"
6+
args: ["go", "get", "github.com/golangci/golangci-lint/cmd/[email protected]"]
7+
env: ["GO111MODULE=on", "CGO_ENABLED=0", "GOBIN=/workspace"]
8+
- name: "gcr.io/cloud-builders/docker"
9+
args: ["build", "-t", "gcr.io/$PROJECT_ID/lint2check", "."]
10+
images:
11+
- "gcr.io/$PROJECT_ID/lint2check"

hack/lint2check/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module sigs.k8s.io/controller-runtime/hack/lint2check
2+
3+
go 1.13
4+
5+
require github.com/google/go-github/v30 v30.1.0

hack/lint2check/go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
2+
github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo=
3+
github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
4+
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
5+
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
6+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
7+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
8+
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
9+
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
10+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
11+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
12+
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=

hack/lint2check/lint2check.go

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"encoding/json"
22+
"os/exec"
23+
"os"
24+
"log"
25+
"go/token"
26+
"net/http"
27+
"strings"
28+
"time"
29+
"fmt"
30+
31+
"github.com/google/go-github/v30/github"
32+
)
33+
34+
type lintResults struct {
35+
Issues []issue
36+
Report reportData
37+
}
38+
39+
type issue struct {
40+
FromLinter string
41+
Text string
42+
Pos token.Position
43+
44+
LineRange *lineRange
45+
Replacement *replacement
46+
}
47+
48+
type replacement struct {
49+
NeedOnlyDelete bool
50+
NewLines []string
51+
}
52+
53+
type lineRange struct {
54+
From, To int
55+
}
56+
57+
type reportData struct {
58+
Warnings []warning
59+
Linters []linterData
60+
Error string
61+
}
62+
63+
type linterData struct {
64+
Name string
65+
Enabled bool
66+
}
67+
68+
type warning struct {
69+
Tag string
70+
Text string
71+
}
72+
73+
type bearerTransport struct {
74+
token string
75+
}
76+
77+
func (b *bearerTransport) RoundTrip(req *http.Request) (*http.Response, error) {
78+
req.Header.Set("Authorization", "Bearer "+b.token)
79+
req.Header.Set("Accept", "application/vnd.github.antiope-preview+json")
80+
81+
return http.DefaultTransport.RoundTrip(req)
82+
}
83+
84+
func main() {
85+
if !lintAndSubmit() {
86+
os.Exit(1)
87+
}
88+
}
89+
90+
func lintAndSubmit() (succeeded bool) {
91+
ctx := context.Background()
92+
token := os.Getenv("GITHUB_TOKEN")
93+
if token == "" {
94+
log.Print("must specify a GitHub token in $GITHUB_TOKEN")
95+
return false
96+
}
97+
client := github.NewClient(&http.Client{Transport: &bearerTransport{
98+
token: token,
99+
}})
100+
101+
headSha := os.Getenv("GITHUB_SHA")
102+
if headSha == "" {
103+
log.Print("must specify a SHA to register the check against in $GITHUB_SHA")
104+
return false
105+
}
106+
107+
repoRaw := os.Getenv("GITHUB_REPOSITORY")
108+
if repoRaw == "" || !strings.Contains(repoRaw, "/") {
109+
log.Print("must specify a repository in $GITHUB_REPOSITORY as owner/repo")
110+
return false
111+
}
112+
repoParts := strings.SplitN(repoRaw, "/", 2)
113+
repoOwner := repoParts[0]
114+
repoName := repoParts[1]
115+
116+
defInProgress := "in_progress"
117+
checkRun, _, err := client.Checks.CreateCheckRun(ctx, repoOwner, repoName, github.CreateCheckRunOptions{
118+
Name: "Linters",
119+
HeadSHA: headSha,
120+
Status: &defInProgress,
121+
StartedAt: &github.Timestamp{Time: time.Now()},
122+
})
123+
if err != nil {
124+
log.Print(err)
125+
return false
126+
}
127+
128+
succeeded = true
129+
130+
if err := runLints(checkRun); err != nil {
131+
// don't return immediately -- submit things first
132+
log.Print(err)
133+
succeeded = false
134+
}
135+
136+
defUnknownErr := "**unknown error while linting**"
137+
if checkRun.Output.Title == nil || checkRun.Output.Summary == nil {
138+
checkRun.Output.Title = &defUnknownErr
139+
checkRun.Output.Summary = &defUnknownErr
140+
}
141+
142+
log.Printf("Sending check run results %+v", checkRun)
143+
_, _, err = client.Checks.UpdateCheckRun(ctx, repoOwner, repoName, *checkRun.ID, github.UpdateCheckRunOptions{
144+
Name: *checkRun.Name,
145+
Status: checkRun.Status,
146+
Conclusion: checkRun.Conclusion,
147+
CompletedAt: checkRun.CompletedAt,
148+
Output: checkRun.Output,
149+
})
150+
if err != nil {
151+
log.Print(err)
152+
return false
153+
}
154+
155+
log.Print("done")
156+
return succeeded
157+
}
158+
159+
func runLints(checkRun *github.CheckRun) error {
160+
// TODO(directxman12); there's probably a way to run this directly,
161+
// but this is easiest for now
162+
args := append([]string{"run", "--out-format", "json"}, os.Args[1:]...)
163+
lintOutRaw, checkErrRaw := exec.Command("golangci-lint", args...).Output()
164+
// don't return early, since we might get results
165+
if checkErrRaw != nil {
166+
log.Print(checkErrRaw)
167+
if exitErr, isExitErr := checkErrRaw.(*exec.ExitError); isExitErr {
168+
log.Print(string(exitErr.Stderr))
169+
}
170+
}
171+
172+
// set the completed time so we have a timestamp in case of error return
173+
checkRun.CompletedAt = &github.Timestamp{Time: time.Now()}
174+
175+
var lintRes lintResults
176+
if err := json.Unmarshal(lintOutRaw, &lintRes); err != nil {
177+
defFailure := "failure"
178+
checkRun.Conclusion = &defFailure
179+
return err
180+
}
181+
182+
conclusion := "success"
183+
summary := fmt.Sprintf("%v problems\n\n%v warnings", len(lintRes.Issues), len(lintRes.Report.Warnings))
184+
switch {
185+
case len(lintRes.Issues) > 0 || checkErrRaw != nil || lintRes.Report.Error != "":
186+
conclusion = "failure"
187+
case len(lintRes.Report.Warnings) > 0:
188+
conclusion = "neutral"
189+
}
190+
checkRun.Conclusion = &conclusion
191+
192+
if lintRes.Report.Error != "" {
193+
summary += fmt.Sprintf("\n\nError running linters: %s", lintRes.Report.Error)
194+
}
195+
defTitle := "Linter Runs"
196+
checkRun.Output.Title = &defTitle
197+
checkRun.Output.Summary = &summary
198+
199+
var linterLines []string
200+
for _, linter := range lintRes.Report.Linters {
201+
if !linter.Enabled {
202+
continue
203+
}
204+
linterLines = append(linterLines, "- "+linter.Name)
205+
}
206+
details := fmt.Sprintf("## Enabled Linters\n\n%s\n", strings.Join(linterLines, "\n"))
207+
208+
if len(lintRes.Report.Warnings) > 0 {
209+
var warningLines []string
210+
for _, warning := range lintRes.Report.Warnings {
211+
warningLines = append(warningLines, fmt.Sprintf("- *%s*: %s", warning.Tag, warning.Text))
212+
}
213+
details += fmt.Sprintf("## Warnings\n\n%s\n", strings.Join(warningLines, "\n"))
214+
}
215+
216+
checkRun.Output.Text = &details
217+
218+
var annotations []*github.CheckRunAnnotation
219+
for i := range lintRes.Issues {
220+
// don't take references to the iteration variable
221+
issue := lintRes.Issues[i]
222+
defFailure := "failure"
223+
issueDetails := ""
224+
225+
if issue.Replacement != nil {
226+
if issue.Replacement.NeedOnlyDelete {
227+
issueDetails = "\n\n*delete these lines*"
228+
} else {
229+
issueDetails = fmt.Sprintf("\n\n*replace these lines with*:\n\n```go\n%s\n```", strings.Join(issue.Replacement.NewLines, "\n"))
230+
}
231+
}
232+
233+
msg := issue.Text
234+
msg += issueDetails
235+
236+
annot := &github.CheckRunAnnotation{
237+
Path: &issue.Pos.Filename,
238+
AnnotationLevel: &defFailure,
239+
Message: &msg,
240+
Title: &issue.FromLinter,
241+
RawDetails: nil,
242+
}
243+
244+
if issue.LineRange != nil {
245+
annot.StartLine = &issue.LineRange.From
246+
annot.EndLine = &issue.LineRange.To
247+
} else {
248+
annot.StartLine = &issue.Pos.Line
249+
annot.EndLine = &issue.Pos.Line
250+
annot.StartColumn = &issue.Pos.Column
251+
annot.EndColumn = &issue.Pos.Column
252+
}
253+
254+
annotations = append(annotations, annot)
255+
}
256+
257+
checkRun.Output.Annotations = annotations
258+
return checkErrRaw
259+
}

0 commit comments

Comments
 (0)