Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 1977311

Browse files
authored
Merge pull request #11 from eunomie/lint
Lint code, catch missing errors, and improve style, simplify code. No real change in term of logic, just fixes.
2 parents e776e28 + 719e511 commit 1977311

File tree

27 files changed

+178
-139
lines changed

27 files changed

+178
-139
lines changed

.github/workflows/go.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ jobs:
2323

2424
- name: Test
2525
run: go test -v ./...
26+
27+
- name: Lint
28+
run: docker run --rm -v $(pwd):/app -v $(go env GOPATH)/pkg:/go/pkg -v $(go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -w /app golangci/golangci-lint:v1.50.1 golangci-lint run -v --timeout 10m

.golangci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
linters:
2+
enable: # defaults @ top
3+
- errcheck
4+
- gosimple
5+
- govet
6+
- ineffassign
7+
- staticcheck
8+
- typecheck
9+
- unused
10+
- unconvert
11+
- gofmt
12+
- misspell
13+
- bodyclose
14+
- revive
15+
- gocyclo
16+
- whitespace
17+
- sqlclosecheck
18+
- goimports
19+
- unparam
20+
run:
21+
deadline: 2m
22+
allow-parallel-runners: true
23+
concurrency: 2
24+
tests: true
25+
linters-settings:
26+
gosimple:
27+
go: '1.19'
28+
staticcheck:
29+
go: '1.19'
30+
stylecheck:
31+
go: '1.19'
32+
unused:
33+
go: '1.19'
34+
revive:
35+
rules:
36+
- name: exported
37+
disabled: true
38+
issues:
39+
max-issues-per-linter: 0
40+
max-same-issues: 0
41+
exclude-use-default: false
42+
output:
43+
format: tab

Taskfile.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ tasks:
2525

2626
go:fmt:
2727
cmds:
28-
- goimports -w .
28+
- goimports -w -local github.com/atomist-skills,github.com/docker,github.com/docker/index-cli-plugin .
2929
- gofmt -w .
3030
#- go mod tidy
3131

32+
go:lint:
33+
cmds:
34+
- docker run --rm -v $(pwd):/app -v $(go env GOPATH)/pkg:/go/pkg -v $(go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -w /app golangci/golangci-lint:v1.50.1 golangci-lint run -v --timeout 10m
35+
3236
go:release:
3337
cmds:
3438
- goreleaser release --rm-dist

commands/cmd.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,20 @@ import (
2424
"os"
2525
"strings"
2626

27+
"github.com/moby/term"
28+
"github.com/pkg/errors"
29+
"github.com/sirupsen/logrus"
30+
"github.com/spf13/cobra"
31+
2732
"github.com/atomist-skills/go-skill"
33+
2834
"github.com/docker/cli/cli"
2935
"github.com/docker/cli/cli-plugins/plugin"
3036
"github.com/docker/cli/cli/command"
3137
"github.com/docker/index-cli-plugin/format"
3238
"github.com/docker/index-cli-plugin/query"
3339
"github.com/docker/index-cli-plugin/sbom"
3440
"github.com/docker/index-cli-plugin/types"
35-
"github.com/moby/term"
36-
"github.com/pkg/errors"
37-
"github.com/sirupsen/logrus"
38-
"github.com/spf13/cobra"
3941
)
4042

4143
func NewRootCmd(name string, isPlugin bool, dockerCli command.Cli) *cobra.Command {
@@ -129,7 +131,7 @@ func NewRootCmd(name string, isPlugin bool, dockerCli command.Cli) *cobra.Comman
129131
return err
130132
}
131133
if output != "" {
132-
_ = os.WriteFile(output, js, 0644)
134+
_ = os.WriteFile(output, js, 0o644)
133135
skill.Log.Infof("SBOM written to %s", output)
134136
} else {
135137
fmt.Println(string(js))
@@ -177,9 +179,7 @@ func NewRootCmd(name string, isPlugin bool, dockerCli command.Cli) *cobra.Comman
177179
if err != nil {
178180
return err
179181
}
180-
err = sbom.UploadSbom(sb, workspace, apiKey)
181-
182-
return nil
182+
return sbom.UploadSbom(sb, workspace, apiKey)
183183
},
184184
}
185185
uploadCommandFlags := uploadCommand.Flags()
@@ -254,7 +254,7 @@ func readWorkspace(args []string, cli command.Cli) (string, error) {
254254
} else if v, ok := os.LookupEnv("ATOMIST_WORKSPACE"); v != "" && ok {
255255
workspace = v
256256
} else {
257-
fmt.Fprintf(cli.Out(), "Workspace: ")
257+
_, _ = fmt.Fprintf(cli.Out(), "Workspace: ")
258258

259259
workspace = readInput(cli.In(), cli.Out())
260260
if workspace == "" {
@@ -282,12 +282,12 @@ func readApiKey(apiKeyStdin bool, cli command.Cli) (string, error) {
282282
if err != nil {
283283
return "", err
284284
}
285-
fmt.Fprintf(cli.Out(), "API key: ")
286-
term.DisableEcho(cli.In().FD(), oldState)
285+
_, _ = fmt.Fprintf(cli.Out(), "API key: ")
286+
_ = term.DisableEcho(cli.In().FD(), oldState)
287287

288288
apiKey = readInput(cli.In(), cli.Out())
289-
fmt.Fprint(cli.Out(), "\n")
290-
term.RestoreTerminal(cli.In().FD(), oldState)
289+
_, _ = fmt.Fprint(cli.Out(), "\n")
290+
_ = term.RestoreTerminal(cli.In().FD(), oldState)
291291
if apiKey == "" {
292292
return "", errors.Errorf("Error: API key required")
293293
}
@@ -299,7 +299,7 @@ func readInput(in io.Reader, out io.Writer) string {
299299
reader := bufio.NewReader(in)
300300
line, _, err := reader.ReadLine()
301301
if err != nil {
302-
fmt.Fprintln(out, err.Error())
302+
_, _ = fmt.Fprintln(out, err.Error())
303303
os.Exit(1)
304304
}
305305
return string(line)

format/cve.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func Cves(cve string, cves *[]types.Cve, sb *types.Sbom, remediate bool, dockerC
3535
continue
3636
}
3737

38-
var remediation = make([]string, 0)
38+
remediation := make([]string, 0)
3939
layerIndex := -1
4040
for _, p := range sb.Artifacts {
4141
if p.Purl == c.Purl {
@@ -102,6 +102,6 @@ func Cves(cve string, cves *[]types.Cve, sb *types.Sbom, remediate bool, dockerC
102102
Remediation(remediation)
103103
}
104104
} else {
105-
fmt.Println(fmt.Sprintf("%s not detected", cve))
105+
fmt.Printf("%s not detected\n", cve)
106106
}
107107
}

format/format.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ import (
2121
"strconv"
2222
"strings"
2323

24-
"github.com/docker/index-cli-plugin/internal"
25-
"github.com/docker/index-cli-plugin/types"
2624
"github.com/gookit/color"
2725
"github.com/xeonx/timeago"
26+
27+
"github.com/docker/index-cli-plugin/internal"
28+
"github.com/docker/index-cli-plugin/types"
2829
)
2930

3031
type colors struct {
@@ -173,19 +174,19 @@ func Cve(sb *types.Sbom, c *types.Cve) {
173174
sourceId = c.Cve.SourceId
174175
}
175176
fmt.Println("")
176-
fmt.Println(defaultColors.underline.Sprintf(fmt.Sprintf("Detected %s %s", sourceId, ColorizeSeverity(ToSeverity(*c)))))
177-
fmt.Println(fmt.Sprintf("https://dso.docker.com/cve/%s", sourceId))
177+
defaultColors.underline.Printf("Detected %s %s\n", sourceId, ColorizeSeverity(ToSeverity(*c)))
178+
fmt.Printf("https://dso.docker.com/cve/%s\n", sourceId)
178179
fmt.Println("")
179180
purl := c.Purl
180181
for _, p := range sb.Artifacts {
181182
if p.Purl == purl {
182-
fmt.Println(defaultColors.cyan.Sprintf(p.Purl))
183+
defaultColors.cyan.Println(p.Purl)
183184
loc := p.Locations[0]
184185
for i, l := range sb.Source.Image.Config.RootFS.DiffIDs {
185186
if l.String() == loc.DiffId {
186187
h := sb.Source.Image.Config.History[i]
187188
fmt.Println(formatCreatedBy(h.CreatedBy))
188-
fmt.Println(fmt.Sprintf("%d: %s", i, loc.Digest))
189+
fmt.Printf("%d: %s\n", i, loc.Digest)
189190
}
190191
}
191192
}
@@ -195,9 +196,9 @@ func Cve(sb *types.Sbom, c *types.Cve) {
195196
func Remediation(remediation []string) {
196197
if len(remediation) > 0 {
197198
fmt.Println("")
198-
fmt.Println(defaultColors.underline.Sprintf("Suggested remediation"))
199+
defaultColors.underline.Println("Suggested remediation")
199200
for i, r := range remediation {
200-
fmt.Println(fmt.Sprintf("\n%d. %s", i+1, r))
201+
fmt.Printf("\n%d. %s\n", i+1, r)
201202
}
202203
}
203204
}

internal/spinner.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ import (
2121
"strings"
2222
"time"
2323

24-
"github.com/atomist-skills/go-skill"
2524
"github.com/briandowns/spinner"
2625
"github.com/gookit/color"
2726
"github.com/sirupsen/logrus"
27+
28+
"github.com/atomist-skills/go-skill"
2829
)
2930

3031
type Fields map[string]interface{}
@@ -63,7 +64,7 @@ func StartInfoSpinner(text string, isTerminal bool) *Spinner {
6364
func StartSpinner(level string, text string, isTerminal bool) *Spinner {
6465
if isTerminal {
6566
s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
66-
s.Color("yellow")
67+
_ = s.Color("yellow")
6768

6869
spinner := &Spinner{
6970
level: level,

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"os"
2222

2323
"github.com/atomist-skills/go-skill"
24+
2425
"github.com/docker/cli/cli-plugins/manager"
2526
"github.com/docker/cli/cli-plugins/plugin"
2627
"github.com/docker/cli/cli/command"

query/async.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"sync"
2121

2222
"github.com/atomist-skills/go-skill"
23+
2324
"github.com/docker/index-cli-plugin/types"
2425
)
2526

query/base.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ import (
2626
"sort"
2727
"strings"
2828

29-
"github.com/atomist-skills/go-skill"
30-
"github.com/docker/index-cli-plugin/types"
3129
v1 "github.com/google/go-containerregistry/pkg/v1"
3230
"github.com/hasura/go-graphql-client"
3331
"github.com/opencontainers/go-digest"
3432
"github.com/opencontainers/image-spec/identity"
3533
"github.com/pkg/errors"
3634
"olympos.io/encoding/edn"
35+
36+
"github.com/atomist-skills/go-skill"
37+
38+
"github.com/docker/index-cli-plugin/types"
3739
)
3840

3941
type ImageQueryResult struct {
@@ -99,6 +101,7 @@ func ForBaseImageInIndex(digest digest.Digest, workspace string, apiKey string)
99101

100102
if resp.StatusCode == 200 {
101103
var manifestList []types.IndexManifestList
104+
defer resp.Body.Close() //nolint:errcheck
102105
body, err := io.ReadAll(resp.Body)
103106
if err != nil {
104107
return nil, errors.Wrapf(err, "failed to read response body")
@@ -116,7 +119,7 @@ func ForBaseImageInIndex(digest digest.Digest, workspace string, apiKey string)
116119
}
117120
repository, err := ForRepositoryInDb(manifestList[0].Name, workspace, apiKey)
118121
if err != nil {
119-
return nil, errors.Wrapf(err, "failed to query for respository")
122+
return nil, errors.Wrapf(err, "failed to query for repository")
120123
}
121124
image := types.Image{
122125
Digest: ii.Digest,
@@ -136,8 +139,12 @@ func ForBaseImageInIndex(digest digest.Digest, workspace string, apiKey string)
136139
func ForBaseImageWithoutCve(cve string, name string, sb *types.Sbom, workspace string, apiKey string) (*[]types.Image, error) {
137140
cf := (*sb).Source.Image.Config
138141
resp, err := query(fmt.Sprintf(baseImageCveQuery, cve, name, cf.OS, cf.Architecture, cf.Variant), "base_image_cve_query", workspace, apiKey)
142+
if err != nil {
143+
return nil, errors.Wrapf(err, "failed to query for base image without CVE")
144+
}
139145

140146
var result ImageQueryResult
147+
defer resp.Body.Close() //nolint:errcheck
141148
err = edn.NewDecoder(resp.Body).Decode(&result)
142149
if err != nil {
143150
return nil, errors.Wrapf(err, "failed to unmarshal response")
@@ -174,8 +181,12 @@ func ForBaseImageWithoutCve(cve string, name string, sb *types.Sbom, workspace s
174181
// ForBaseImageInDb returns images with matching digest in :docker.image/blob-digest or :docker.image/diff-chain-id
175182
func ForBaseImageInDb(digest digest.Digest, workspace string, apiKey string) (*[]types.Image, error) {
176183
resp, err := query(fmt.Sprintf(baseImageQuery, digest), "base_image_query", workspace, apiKey)
184+
if err != nil {
185+
return nil, errors.Wrapf(err, "failed to query for base image in DB")
186+
}
177187

178188
var result ImageQueryResult
189+
defer resp.Body.Close() //nolint:errcheck
179190
err = edn.NewDecoder(resp.Body).Decode(&result)
180191
if err != nil {
181192
return nil, errors.Wrapf(err, "failed to unmarshal response")
@@ -204,8 +215,12 @@ func ForBaseImageInDb(digest digest.Digest, workspace string, apiKey string) (*[
204215

205216
func ForRepositoryInDb(repo string, workspace string, apiKey string) (*types.Repository, error) {
206217
resp, err := query(fmt.Sprintf(repositoryQuery, repo), "repository_query", workspace, apiKey)
218+
if err != nil {
219+
return nil, errors.Wrapf(err, "failed to query for repository in DB")
220+
}
207221

208222
var result RepositoryQueryResult
223+
defer resp.Body.Close() //nolint:errcheck
209224
err = edn.NewDecoder(resp.Body).Decode(&result)
210225
if err != nil {
211226
return nil, errors.Wrapf(err, "failed to unmarshal response")
@@ -236,12 +251,11 @@ func ForBaseImageInGraphQL(cfg *v1.ConfigFile) (*types.BaseImagesByDiffIdsQuery,
236251
var q types.BaseImagesByDiffIdsQuery
237252
err := client.Query(context.Background(), &q, variables)
238253
if err != nil {
239-
fmt.Sprintf("error %v", err)
240254
return nil, errors.Wrapf(err, "failed to run query")
241255
}
242256
count := 0
243-
for ii, _ := range q.ImagesByDiffIds {
244-
for bi, _ := range q.ImagesByDiffIds[ii].Images {
257+
for ii := range q.ImagesByDiffIds {
258+
for bi := range q.ImagesByDiffIds[ii].Images {
245259
count++
246260
q.ImagesByDiffIds[ii].Images[bi].Repository = normalizeRepository(&q.ImagesByDiffIds[ii].Images[bi]).Repository
247261
}
@@ -271,7 +285,6 @@ func ForImageInGraphQL(sb *types.Sbom) (*types.ImageByDigestQuery, error) {
271285
var q types.ImageByDigestQuery
272286
err := client.Query(context.Background(), &q, variables)
273287
if err != nil {
274-
fmt.Sprintf("error %v", err)
275288
return nil, errors.Wrapf(err, "failed to run query")
276289
}
277290
if q.ImageDetailsByDigest.Digest != "" {
@@ -282,7 +295,7 @@ func ForImageInGraphQL(sb *types.Sbom) (*types.ImageByDigestQuery, error) {
282295
}
283296

284297
func normalizeRepository(image *types.BaseImage) *types.BaseImage {
285-
if image.Repository.Host == "hub.docker.com" && strings.Index(image.Repository.Repo, "/") < 0 {
298+
if image.Repository.Host == "hub.docker.com" && strings.Contains(image.Repository.Repo, "/") {
286299
image.Repository.Badge = "OFFICIAL"
287300
}
288301
if image.Repository.Badge != "" {

0 commit comments

Comments
 (0)