diff --git a/.github/workflows/golang.yaml b/.github/workflows/golang.yaml index 5583212..465c4d0 100644 --- a/.github/workflows/golang.yaml +++ b/.github/workflows/golang.yaml @@ -9,25 +9,21 @@ jobs: name: GoLang Basics steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of Sonar scan - - name: FS Permissions - # workaround for permissions with contaner attempting to create directories - run: chmod 777 -R "$(pwd)" - name: Dep run: make dep - name: Lint run: make lint - - name: Coverage Setup - # workaround for permissions with container attempting to create directory - run: mkdir .coverage && chmod 777 .coverage + - name: Coverage Setup + run: mkdir -p .coverage/unit - name: Unit Tests run: make test - name: Integration Tests run: make integration - name: SonarQube Scan - uses: SonarSource/sonarqube-scan-action@v4 + uses: SonarSource/sonarqube-scan-action@v7 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} # run on PRs and once we merge to main, as we need baseline runs for main in Sonar diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..fdb813e --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,89 @@ +version: "2" +run: + build-tags: + - integration + issues-exit-code: 1 + tests: true + timeout: 5m +output: + formats: + text: + path: stdout + print-linter-name: true + print-issued-lines: true +linters: + default: none + enable: + - depguard + - errcheck + - gochecknoinits + - goconst + - gocyclo + - gosec + - govet + - ineffassign + - misspell + - nakedret + - prealloc + - revive + - staticcheck + - unconvert + - unparam + - unused + settings: + depguard: + rules: + main: + deny: + - pkg: github.com/davecgh/go-spew/spew + desc: not allowed to use spew + govet: + enable: + - shadow # Check for possible unintended shadowing of variables. + misspell: + locale: US + prealloc: + for-loops: true + revive: + rules: + - name: package-comments + disabled: true + unparam: + check-exported: false + exclusions: + generated: lax + rules: + - path: (.+)\.go$ + text: Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked + - path: (.+)\.go$ + text: (possible misuse of unsafe.Pointer|should have signature) + - path: (.+)\.go$ + text: ineffective break statement. Did you mean to break out of the outer loop + - path: (.+)\.go$ + text: Use of unsafe calls should be audited + - path: (.+)\.go$ + text: Subprocess launch(ed with variable|ing should be audited) + - path: (.+)\.go$ + text: G104 + - path: (.+)\.go$ + text: (Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less) + - path: (.+)\.go$ + text: Potential file inclusion via variable + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + settings: + gofmt: + simplify: false + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..575338f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +# syntax=docker/dockerfile:1 + +# Build a local Go toolchain image +FROM golang:1.24 AS go +USER root +# Intentionally empty: this stage serves as a runnable Go toolchain container + + diff --git a/Makefile b/Makefile index 79a69ab..df0d19b 100644 --- a/Makefile +++ b/Makefile @@ -1,35 +1,41 @@ +.PHONY: docker-build-go docker-build-lint docker-build dep lint coverage test + TAG := $(shell git rev-parse --short HEAD) DIR := $(shell pwd -L) - -dep: - docker run -i \ - --mount src="$(DIR)",target="$(DIR)",type="bind" \ - -w "$(DIR)" \ - asecurityteam/sdcli:v1 go dep - -lint: - docker run -i \ - --mount src="$(DIR)",target="$(DIR)",type="bind" \ - -w "$(DIR)" \ - asecurityteam/sdcli:v1 go lint - -test: - docker run -i \ - --mount src="$(DIR)",target="$(DIR)",type="bind" \ - -w "$(DIR)" \ - asecurityteam/sdcli:v1 go test - -integration: - docker run -i \ - --mount src="$(DIR)",target="$(DIR)",type="bind" \ - -w "$(DIR)" \ - asecurityteam/sdcli:v1 go integration - -coverage: - docker run -i \ - --mount src="$(DIR)",target="$(DIR)",type="bind" \ - -w "$(DIR)" \ - asecurityteam/sdcli:v1 go coverage +LOCAL_GO_IMAGE ?= rolling-go +LOCAL_LINT_IMAGE ?= rolling-golangci-lint +GODOCKER = docker run --rm -v "$(DIR):$(DIR)" -w "$(DIR)" $(LOCAL_GO_IMAGE) +LINTDOCKER = docker run --rm -v "$(DIR):$(DIR)" -w "$(DIR)" $(LOCAL_LINT_IMAGE) + +COVERAGE_DIR := .coverage +UNIT_COVERAGE_DIR := $(COVERAGE_DIR)/unit +UNIT_COVERAGE_FILE := $(UNIT_COVERAGE_DIR)/unit.cover.out + +docker-build-go: + docker build --target go -t $(LOCAL_GO_IMAGE) . + +docker-build-lint: + docker build --target lint -t $(LOCAL_LINT_IMAGE) -f linter.Dockerfile . + +docker-build: docker-build-go docker-build-lint + +dep: docker-build-go + $(GODOCKER) go mod vendor + +lint: docker-build-lint + $(LINTDOCKER) golangci-lint run --config .golangci.yaml ./... -v + +coverage-setup: + mkdir -p $(UNIT_COVERAGE_DIR) + touch $(UNIT_COVERAGE_FILE) + +test: coverage-setup docker-build-go + $(GODOCKER) go test -coverprofile=$(UNIT_COVERAGE_FILE) -v -race ./... + +integration: ; + +coverage: docker-build-go + $(GODOCKER) go tool cover -func=$(UNIT_COVERAGE_FILE) doc: ; diff --git a/linter.Dockerfile b/linter.Dockerfile new file mode 100644 index 0000000..95d1b39 --- /dev/null +++ b/linter.Dockerfile @@ -0,0 +1,8 @@ +# syntax=docker/dockerfile:1 + +# Build a local golangci-lint image +FROM golangci/golangci-lint:v2.6 AS lint +USER root +# Intentionally empty: this stage serves as a runnable golangci-lint container + + diff --git a/reduce.go b/reduce.go index a71b382..3c33038 100644 --- a/reduce.go +++ b/reduce.go @@ -149,7 +149,7 @@ func FastPercentile(perc float64) func(w Window) float64 { } var k int // k is the target cell to increment switch { - case v < q[0]: + case v < q[0]: // nolint:gosec // G602: q is a fixed-size array [5]float64, bounds are guaranteed q[0] = v k = 0 case q[0] <= v && v < q[1]: @@ -175,7 +175,7 @@ func FastPercentile(perc float64) func(w Window) float64 { for x := 1; x < 4; x = x + 1 { var d = nPrime[x] - float64(n[x]) if (d >= 1 && (n[x+1]-n[x]) > 1) || - (d <= -1 && (n[x-1]-n[x]) < -1) { + (d <= -1 && (n[x-1]-n[x]) < -1) { // nolint:gosec // G602: n is a fixed-size array [5]int, x-1 is safe since x >= 1 var s = sign(d) var si = int(s) var nx = float64(n[x])