Skip to content

Commit

Permalink
feat: add golangci-lint (local) version check (#467)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
mikeee authored Oct 20, 2023
1 parent 30a51be commit 57466dd
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.go text eol=lf
59 changes: 59 additions & 0 deletions .github/workflows/test-tooling.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Test Tooling

on:
push:
paths: # Explicitly declare which paths
- ".github/workflows/test-tooling.yml"
- "tools/*"
pull_request:
branches:
- main
paths: # Explicitly declare which paths
- ".github/workflows/test-tooling.yml"
- "tools/*"

jobs:
build:
name: Test (${{ matrix.os}}) go ${{ matrix.gover }}

strategy:
fail-fast: false
matrix:
gover:
- "1.21"
os:
- "ubuntu-latest"
- "windows-latest"
- "macos-latest"
runs-on: ${{ matrix.os }}
env:
GOVER: ${{ matrix.gover }}
GOLANGCILINT_VER: v1.54.2 # Make sure to bump /tools/check-lint-version/main_test.go

steps:
- name: Setup
uses: actions/setup-go@v4
with:
go-version: ${{ env.GOVER }}

- name: Checkout
uses: actions/checkout@v4

- name: Tidy
working-directory: ./tools/check-lint-version
run: make tidy

- name: Lint
uses: golangci/golangci-lint-action@v3
with:
version: ${{ env.GOLANGCILINT_VER }}
working-directory: ./tools/check-lint-version
skip-cache: true
args: --timeout=10m0s --config ../../.golangci.yml

- name: Install Linter
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$(go env GOPATH)/bin" ${{ env.GOLANGCILINT_VER }}

- name: Test
working-directory: ./tools/check-lint-version
run: make test
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@ cover: ## Displays test coverage in the client and service packages
go test -coverprofile=cover-http.out ./service/http && go tool cover -html=cover-http.out

.PHONY: lint
lint: ## Lints the entire project
lint: check-lint ## Lints the entire project
golangci-lint run --timeout=3m

.PHONY: check-lint
check-lint: ## Compares the locally installed linter with the workflow version
cd ./tools/check-lint-version && \
go mod tidy && \
go run main.go

.PHONY: tag
tag: ## Creates release tag
git tag $(RELEASE_VERSION)
Expand Down
14 changes: 7 additions & 7 deletions actor/mock/mock_server.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions tools/check-lint-version/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.PHONY: cover
cover:
go test -coverprofile=cover.out ./ && go tool cover -html=cover.out

.PHONY: tidy
tidy: ## Updates the go modules
go mod tidy

.PHONY: test
test:
go test -count=1 \
-race \
-coverprofile=coverage.txt \
-covermode=atomic \
./...

.PHONY: lint
lint: check-lint-version
golangci-lint run --timeout=3m --config ../../.golangci.yml

check-lint-version: tidy
go run main.go
12 changes: 12 additions & 0 deletions tools/check-lint-version/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Check Lint Version

This package is designed to check the local golangci-lint version against that of the current github workflow.

## Usage

In the repo root, you can use the `make lint` command which makes use of this to verify the golangci-lint version and
run the linter.

## Workflow

The `test-tooling` workflow is responsible for testing this package.
16 changes: 16 additions & 0 deletions tools/check-lint-version/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/dapr/go-sdk/tools/check-lint-version

go 1.19

require (
github.com/stretchr/testify v1.8.4
golang.org/x/mod v0.13.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
24 changes: 24 additions & 0 deletions tools/check-lint-version/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
80 changes: 80 additions & 0 deletions tools/check-lint-version/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main

import (
"fmt"
"os"
"os/exec"
"regexp"

"golang.org/x/mod/semver"
"gopkg.in/yaml.v3"
)

type GHWorkflow struct {
Jobs struct {
Build struct {
Env struct {
GOVER string `yaml:"GOVER"`
GOLANGCILINTVER string `yaml:"GOLANGCILINT_VER"`
} `yaml:"env"`
} `yaml:"build"`
} `yaml:"jobs"`
}

func parseWorkflowVersionFromFile(path string) (string, error) {
var ghWorkflow GHWorkflow

raw, err := os.ReadFile(path)
if err != nil {
return "", err
}
err = yaml.Unmarshal(raw, &ghWorkflow)
if err != nil {
return "", err
}
return ghWorkflow.Jobs.Build.Env.GOLANGCILINTVER, err
}

func getCurrentVersion() (string, error) {
out, err := exec.Command("golangci-lint", "--version").Output()
if err != nil {
return "", err
}

regex, err := regexp.Compile(`golangci-lint\shas\sversion\sv?([\d+.]+[\d])`)
if err != nil {
return "", err
}

matches := regex.FindStringSubmatch(string(out))

if matches == nil {
return "", fmt.Errorf("no version found: %v", string(out))
}
return fmt.Sprintf("v%s", matches[1]), err
}

func isVersionValid(workflowVersion, currentVersion string) bool {
res := semver.MajorMinor(workflowVersion) == semver.MajorMinor(currentVersion)
return res
}

func compareVersions(path string) string {
workflowVersion, err := parseWorkflowVersionFromFile(path)
if err != nil {
return fmt.Sprintf("Error parsing workflow version: %v", err)
}
currentVersion, err := getCurrentVersion()
if err != nil {
return fmt.Sprintf("Error getting current version: %v", err)
}
validVersion := isVersionValid(workflowVersion, currentVersion)
if !validVersion {
return fmt.Sprintf("Invalid version, expected: %s, current: %s - See: https://golangci-lint.run/usage/install/ for instructions to update", workflowVersion, currentVersion)
}
return fmt.Sprintf("Linter version is valid (MajorMinor): %s", currentVersion)
}

func main() {
fmt.Println(compareVersions("../../.github/workflows/test-on-push.yaml"))
}
88 changes: 88 additions & 0 deletions tools/check-lint-version/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package main

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestParseWorkflow(t *testing.T) {
t.Run("parse invalid workflow file", func(t *testing.T) {
parsedVersion, err := parseWorkflowVersionFromFile("../../.github/workflows/invalid.yaml")
assert.Equal(t, "", parsedVersion)
assert.Error(t, err)
})

t.Run("parse workflow file with a missing key", func(t *testing.T) {
parsedVersion, err := parseWorkflowVersionFromFile("./testing/invalid-test.yml")
assert.Equal(t, "", parsedVersion)
assert.NoError(t, err)
})

t.Run("parse an invalid workflow file", func(t *testing.T) {
parsedVersion, err := parseWorkflowVersionFromFile("./testing/invalid-yaml.yml")
assert.Equal(t, "", parsedVersion)
assert.Error(t, err)
})

t.Run("parse testing workflow file", func(t *testing.T) {
parsedVersion, err := parseWorkflowVersionFromFile("../../.github/workflows/test-tooling.yml")
assert.Equal(t, "v1.54.2", parsedVersion)
assert.NoError(t, err)
})
}

func TestGetCurrentVersion(t *testing.T) {
t.Run("get current version from system", func(t *testing.T) {
currentVersion, err := getCurrentVersion()
assert.Equal(t, "v1.54.2", currentVersion)
assert.NoError(t, err)
})

// TODO: test failure to detect current version

// TODO: test failure to compile regex expression

// TODO: test failure finding matches
}

func TestIsVersionValid(t *testing.T) {
t.Run("compare versions - exactly equal to", func(t *testing.T) {
assert.Equal(t, true, isVersionValid("v1.54.2", "v1.54.2"))
})

t.Run("compare versions - patch version greater (workflow)", func(t *testing.T) {
assert.Equal(t, true, isVersionValid("v1.54.3", "v1.54.2"))
})

t.Run("compare versions - patch version greater (installed)", func(t *testing.T) {
assert.Equal(t, true, isVersionValid("v1.54.2", "v1.54.3"))
})

t.Run("compare versions - invalid (installed)", func(t *testing.T) {
assert.Equal(t, false, isVersionValid("v1.54.2", "v1.52.2"))
})

t.Run("compare versions - invalid (workflow)", func(t *testing.T) {
assert.Equal(t, false, isVersionValid("v1.52.2", "v1.54.2"))
})
}

func TestCompareVersions(t *testing.T) {
t.Run("Valid comparison", func(t *testing.T) {
res := compareVersions("../../.github/workflows/test-on-push.yaml")
assert.Contains(t, res, "Linter version is valid")
})

t.Run("Invalid comparison", func(t *testing.T) {
res := compareVersions("./testing/invalid-test.yml")
assert.Contains(t, res, "Invalid version")
})

// TODO: test function for failure to get the current version using getCurrentVersion()

t.Run("Invalid path for comparison", func(t *testing.T) {
res := compareVersions("./testing/invalid-test-incorrect-path.yml")
assert.Contains(t, res, "Error parsing workflow")
})
}
12 changes: 12 additions & 0 deletions tools/check-lint-version/testing/invalid-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Test

on:
push:
pull_request:
branches:
- main

jobs:
build:
env:
NOGOLANGCILINT_VER: "123.123.123"
1 change: 1 addition & 0 deletions tools/check-lint-version/testing/invalid-yaml.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testfile

0 comments on commit 57466dd

Please sign in to comment.