Skip to content

Commit 57466dd

Browse files
authored
feat: add golangci-lint (local) version check (#467)
* feat: add golangci-lint version check Add golangci-lint version check to compare the local version against the workflow version. Adds associated test workflow for mac, ubuntu and windows. Signed-off-by: mikeee <[email protected]> * fix: add install linter step Signed-off-by: mikeee <[email protected]> * fix: return the raw output of the command run Signed-off-by: mikeee <[email protected]> * fix: change regex to pick up versions not prefixed Signed-off-by: mikeee <[email protected]> * formatting: gofumpt'ed workspace Signed-off-by: mikeee <[email protected]> * fix: convert line endings to LF on checkout Signed-off-by: mikeee <[email protected]> * fix: encapsulate any spaces in the argument Signed-off-by: mikeee <[email protected]> --------- Signed-off-by: mikeee <[email protected]>
1 parent 30a51be commit 57466dd

File tree

12 files changed

+329
-8
lines changed

12 files changed

+329
-8
lines changed

.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.go text eol=lf

.github/workflows/test-tooling.yml

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Test Tooling
2+
3+
on:
4+
push:
5+
paths: # Explicitly declare which paths
6+
- ".github/workflows/test-tooling.yml"
7+
- "tools/*"
8+
pull_request:
9+
branches:
10+
- main
11+
paths: # Explicitly declare which paths
12+
- ".github/workflows/test-tooling.yml"
13+
- "tools/*"
14+
15+
jobs:
16+
build:
17+
name: Test (${{ matrix.os}}) go ${{ matrix.gover }}
18+
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
gover:
23+
- "1.21"
24+
os:
25+
- "ubuntu-latest"
26+
- "windows-latest"
27+
- "macos-latest"
28+
runs-on: ${{ matrix.os }}
29+
env:
30+
GOVER: ${{ matrix.gover }}
31+
GOLANGCILINT_VER: v1.54.2 # Make sure to bump /tools/check-lint-version/main_test.go
32+
33+
steps:
34+
- name: Setup
35+
uses: actions/setup-go@v4
36+
with:
37+
go-version: ${{ env.GOVER }}
38+
39+
- name: Checkout
40+
uses: actions/checkout@v4
41+
42+
- name: Tidy
43+
working-directory: ./tools/check-lint-version
44+
run: make tidy
45+
46+
- name: Lint
47+
uses: golangci/golangci-lint-action@v3
48+
with:
49+
version: ${{ env.GOLANGCILINT_VER }}
50+
working-directory: ./tools/check-lint-version
51+
skip-cache: true
52+
args: --timeout=10m0s --config ../../.golangci.yml
53+
54+
- name: Install Linter
55+
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$(go env GOPATH)/bin" ${{ env.GOLANGCILINT_VER }}
56+
57+
- name: Test
58+
working-directory: ./tools/check-lint-version
59+
run: make test

Makefile

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ cover: ## Displays test coverage in the client and service packages
2929
go test -coverprofile=cover-http.out ./service/http && go tool cover -html=cover-http.out
3030

3131
.PHONY: lint
32-
lint: ## Lints the entire project
32+
lint: check-lint ## Lints the entire project
3333
golangci-lint run --timeout=3m
3434

35+
.PHONY: check-lint
36+
check-lint: ## Compares the locally installed linter with the workflow version
37+
cd ./tools/check-lint-version && \
38+
go mod tidy && \
39+
go run main.go
40+
3541
.PHONY: tag
3642
tag: ## Creates release tag
3743
git tag $(RELEASE_VERSION)

actor/mock/mock_server.go

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/check-lint-version/Makefile

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.PHONY: cover
2+
cover:
3+
go test -coverprofile=cover.out ./ && go tool cover -html=cover.out
4+
5+
.PHONY: tidy
6+
tidy: ## Updates the go modules
7+
go mod tidy
8+
9+
.PHONY: test
10+
test:
11+
go test -count=1 \
12+
-race \
13+
-coverprofile=coverage.txt \
14+
-covermode=atomic \
15+
./...
16+
17+
.PHONY: lint
18+
lint: check-lint-version
19+
golangci-lint run --timeout=3m --config ../../.golangci.yml
20+
21+
check-lint-version: tidy
22+
go run main.go

tools/check-lint-version/Readme.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Check Lint Version
2+
3+
This package is designed to check the local golangci-lint version against that of the current github workflow.
4+
5+
## Usage
6+
7+
In the repo root, you can use the `make lint` command which makes use of this to verify the golangci-lint version and
8+
run the linter.
9+
10+
## Workflow
11+
12+
The `test-tooling` workflow is responsible for testing this package.

tools/check-lint-version/go.mod

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module github.com/dapr/go-sdk/tools/check-lint-version
2+
3+
go 1.19
4+
5+
require (
6+
github.com/stretchr/testify v1.8.4
7+
golang.org/x/mod v0.13.0
8+
gopkg.in/yaml.v3 v3.0.1
9+
)
10+
11+
require (
12+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
13+
github.com/kr/pretty v0.3.1 // indirect
14+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
15+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
16+
)

tools/check-lint-version/go.sum

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
3+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
5+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
6+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
7+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
8+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
9+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
10+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
11+
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
12+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
13+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
14+
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
15+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
16+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
17+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
18+
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
19+
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
20+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
21+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
22+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
23+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
24+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

tools/check-lint-version/main.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
"regexp"
8+
9+
"golang.org/x/mod/semver"
10+
"gopkg.in/yaml.v3"
11+
)
12+
13+
type GHWorkflow struct {
14+
Jobs struct {
15+
Build struct {
16+
Env struct {
17+
GOVER string `yaml:"GOVER"`
18+
GOLANGCILINTVER string `yaml:"GOLANGCILINT_VER"`
19+
} `yaml:"env"`
20+
} `yaml:"build"`
21+
} `yaml:"jobs"`
22+
}
23+
24+
func parseWorkflowVersionFromFile(path string) (string, error) {
25+
var ghWorkflow GHWorkflow
26+
27+
raw, err := os.ReadFile(path)
28+
if err != nil {
29+
return "", err
30+
}
31+
err = yaml.Unmarshal(raw, &ghWorkflow)
32+
if err != nil {
33+
return "", err
34+
}
35+
return ghWorkflow.Jobs.Build.Env.GOLANGCILINTVER, err
36+
}
37+
38+
func getCurrentVersion() (string, error) {
39+
out, err := exec.Command("golangci-lint", "--version").Output()
40+
if err != nil {
41+
return "", err
42+
}
43+
44+
regex, err := regexp.Compile(`golangci-lint\shas\sversion\sv?([\d+.]+[\d])`)
45+
if err != nil {
46+
return "", err
47+
}
48+
49+
matches := regex.FindStringSubmatch(string(out))
50+
51+
if matches == nil {
52+
return "", fmt.Errorf("no version found: %v", string(out))
53+
}
54+
return fmt.Sprintf("v%s", matches[1]), err
55+
}
56+
57+
func isVersionValid(workflowVersion, currentVersion string) bool {
58+
res := semver.MajorMinor(workflowVersion) == semver.MajorMinor(currentVersion)
59+
return res
60+
}
61+
62+
func compareVersions(path string) string {
63+
workflowVersion, err := parseWorkflowVersionFromFile(path)
64+
if err != nil {
65+
return fmt.Sprintf("Error parsing workflow version: %v", err)
66+
}
67+
currentVersion, err := getCurrentVersion()
68+
if err != nil {
69+
return fmt.Sprintf("Error getting current version: %v", err)
70+
}
71+
validVersion := isVersionValid(workflowVersion, currentVersion)
72+
if !validVersion {
73+
return fmt.Sprintf("Invalid version, expected: %s, current: %s - See: https://golangci-lint.run/usage/install/ for instructions to update", workflowVersion, currentVersion)
74+
}
75+
return fmt.Sprintf("Linter version is valid (MajorMinor): %s", currentVersion)
76+
}
77+
78+
func main() {
79+
fmt.Println(compareVersions("../../.github/workflows/test-on-push.yaml"))
80+
}

tools/check-lint-version/main_test.go

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package main
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestParseWorkflow(t *testing.T) {
10+
t.Run("parse invalid workflow file", func(t *testing.T) {
11+
parsedVersion, err := parseWorkflowVersionFromFile("../../.github/workflows/invalid.yaml")
12+
assert.Equal(t, "", parsedVersion)
13+
assert.Error(t, err)
14+
})
15+
16+
t.Run("parse workflow file with a missing key", func(t *testing.T) {
17+
parsedVersion, err := parseWorkflowVersionFromFile("./testing/invalid-test.yml")
18+
assert.Equal(t, "", parsedVersion)
19+
assert.NoError(t, err)
20+
})
21+
22+
t.Run("parse an invalid workflow file", func(t *testing.T) {
23+
parsedVersion, err := parseWorkflowVersionFromFile("./testing/invalid-yaml.yml")
24+
assert.Equal(t, "", parsedVersion)
25+
assert.Error(t, err)
26+
})
27+
28+
t.Run("parse testing workflow file", func(t *testing.T) {
29+
parsedVersion, err := parseWorkflowVersionFromFile("../../.github/workflows/test-tooling.yml")
30+
assert.Equal(t, "v1.54.2", parsedVersion)
31+
assert.NoError(t, err)
32+
})
33+
}
34+
35+
func TestGetCurrentVersion(t *testing.T) {
36+
t.Run("get current version from system", func(t *testing.T) {
37+
currentVersion, err := getCurrentVersion()
38+
assert.Equal(t, "v1.54.2", currentVersion)
39+
assert.NoError(t, err)
40+
})
41+
42+
// TODO: test failure to detect current version
43+
44+
// TODO: test failure to compile regex expression
45+
46+
// TODO: test failure finding matches
47+
}
48+
49+
func TestIsVersionValid(t *testing.T) {
50+
t.Run("compare versions - exactly equal to", func(t *testing.T) {
51+
assert.Equal(t, true, isVersionValid("v1.54.2", "v1.54.2"))
52+
})
53+
54+
t.Run("compare versions - patch version greater (workflow)", func(t *testing.T) {
55+
assert.Equal(t, true, isVersionValid("v1.54.3", "v1.54.2"))
56+
})
57+
58+
t.Run("compare versions - patch version greater (installed)", func(t *testing.T) {
59+
assert.Equal(t, true, isVersionValid("v1.54.2", "v1.54.3"))
60+
})
61+
62+
t.Run("compare versions - invalid (installed)", func(t *testing.T) {
63+
assert.Equal(t, false, isVersionValid("v1.54.2", "v1.52.2"))
64+
})
65+
66+
t.Run("compare versions - invalid (workflow)", func(t *testing.T) {
67+
assert.Equal(t, false, isVersionValid("v1.52.2", "v1.54.2"))
68+
})
69+
}
70+
71+
func TestCompareVersions(t *testing.T) {
72+
t.Run("Valid comparison", func(t *testing.T) {
73+
res := compareVersions("../../.github/workflows/test-on-push.yaml")
74+
assert.Contains(t, res, "Linter version is valid")
75+
})
76+
77+
t.Run("Invalid comparison", func(t *testing.T) {
78+
res := compareVersions("./testing/invalid-test.yml")
79+
assert.Contains(t, res, "Invalid version")
80+
})
81+
82+
// TODO: test function for failure to get the current version using getCurrentVersion()
83+
84+
t.Run("Invalid path for comparison", func(t *testing.T) {
85+
res := compareVersions("./testing/invalid-test-incorrect-path.yml")
86+
assert.Contains(t, res, "Error parsing workflow")
87+
})
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
pull_request:
6+
branches:
7+
- main
8+
9+
jobs:
10+
build:
11+
env:
12+
NOGOLANGCILINT_VER: "123.123.123"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testfile

0 commit comments

Comments
 (0)