Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: add linter and auto-labeler action #79

Merged
merged 7 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
run:
concurrency: 8
timeout: 10m
issue-exit-code: 1
tests: true
skip-dirs-use-default: true
modules-download-mode: readonly
allow-parallel-runners: false
go: ""

output:
uniq-by-line: false
path-prefix: ""
sort-results: true

linters:
fast: false
disable-all: true
enable:
- whitespace # Tool for detection of leading and trailing whitespace
- unconvert # Unnecessary type conversions
- tparallel # Detects inappropriate usage of t.Parallel() method in your Go test codes
- thelper # Detects golang test helpers without t.Helper() call and checks the consistency of test helpers
- stylecheck # Stylecheck is a replacement for golint
- prealloc # Finds slice declarations that could potentially be pre-allocated
- predeclared # Finds code that shadows one of Go's predeclared identifiers
- nolintlint # Ill-formed or insufficient nolint directives
- misspell # Misspelled English words in comments
- makezero # Finds slice declarations with non-zero initial length
- importas # Enforces consistent import aliases
- gosec # Security problems
- gofmt # Whether the code was gofmt-ed
- goimports # Unused imports
- goconst # Repeated strings that could be replaced by a constant
- dogsled # Checks assignments with too many blank identifiers (e.g. x, , , _, := f())
- errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13
- gofumpt # Stricter gofmt
- unused # Checks Go code for unused constants, variables, functions and types
- gomodguard # Enforces an allow and block list for direct Go module dependencies
- forbidigo # Forbids some custom-set identifiers, like regexp.MatchString

linters-settings:
gofmt:
simplify: true
goconst:
min-len: 3
min-occurrences: 3
gosec:
excludes:
- G204 # Subprocess launched with a potential tainted input or cmd arguments
- G306 # Expect WriteFile permissions to be 0600 or less
stylecheck:
checks: [ "all", "-ST1022", "-ST1003" ]
errorlint:
asserts: false
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
forbidigo:
forbid:
- p: '^regexp\.(Match|MatchString)$'
msg: it will re-compile the regexp for each execution; compile the regexp with regexp.Compile and store it as a singleton

issues:
whole-files: true
max-issues-per-linter: 0
max-same-issues: 0
new: false
fix: false
exclude-rules:
- path: _test\.go
linters:
- gosec # Disabled linting of weak number generators
- makezero # Disabled linting of intentional slice appends
- goconst # Disabled linting of common mnemonics and test case strings
- path: _\.gno
linters:
- errorlint # Disabled linting of error comparisons, because of lacking std lib support
43 changes: 43 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: "Pull Request Labeler"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: .github/labeler.yml

---

A-Action:
- '**/*.yml'

A-documentation:
- '**/*.md'
- 'internal/lints/README.md'

A-lint:
- 'internal/lints/**/*'

T-engine:
- 'internal/engine/**/*'

T-fixer:
- 'internal/fixer/**/*'

T-format:
- 'formatter/**/*'

T-CLI:
- 'cmd/**/*'

L-test:
- '**/*_test.go'
- 'testdata/**/*'
28 changes: 0 additions & 28 deletions .github/workflows/go.yml

This file was deleted.

21 changes: 21 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
on:
workflow_call:
workflow_dispatch:

jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x

- name: Checkout code
uses: actions/checkout@v4

- name: Lint
uses: golangci/golangci-lint-action@v6
with:
args:
--config=./.github/golangci.yml
20 changes: 20 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

lint:
name: Go linter
uses: ./.github/workflows/lint.yml

test:
name: Go test
uses: ./.github/workflows/test.yml
32 changes: 32 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
on:
workflow_call:
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x

- name: Checkout code
uses: actions/checkout@v4

- name: Go test
run: go test -shuffle=on -coverprofile coverage.out -timeout 5m ./...

test-with-race:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x

- name: Checkout code
uses: actions/checkout@v4

- name: Go race test
run: go test -race -shuffle=on -timeout 5m ./...
2 changes: 1 addition & 1 deletion cmd/tlin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func printIssues(logger *zap.Logger, issues []tt.Issue, isJson bool, jsonOutput
issuesByFile[issue.Filename] = append(issuesByFile[issue.Filename], issue)
}

var sortedFiles []string
sortedFiles := make([]string, 0, len(issuesByFile))
for filename := range issuesByFile {
sortedFiles = append(sortedFiles, filename)
}
Expand Down
21 changes: 6 additions & 15 deletions cmd/tlin/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func TestRunAutoFix(t *testing.T) {
defer os.RemoveAll(tempDir)

testFile := filepath.Join(tempDir, "test.go")
err = os.WriteFile(testFile, []byte(sliceRangeIssueExample), 0644)
err = os.WriteFile(testFile, []byte(sliceRangeIssueExample), 0o644)
assert.NoError(t, err)

expectedIssues := []types.Issue{
Expand Down Expand Up @@ -240,7 +240,7 @@ func main() {
assert.Contains(t, output, "Fixed issues in")

// dry run test
err = os.WriteFile(testFile, []byte(sliceRangeIssueExample), 0644)
err = os.WriteFile(testFile, []byte(sliceRangeIssueExample), 0o644)
assert.NoError(t, err)

output = captureOutput(t, func() {
Expand Down Expand Up @@ -299,7 +299,7 @@ func TestRunJsonOutput(t *testing.T) {
fmt.Println(tempDir)

testFile := filepath.Join(tempDir, "test.go")
err = os.WriteFile(testFile, []byte(sliceRangeIssueExample), 0644)
err = os.WriteFile(testFile, []byte(sliceRangeIssueExample), 0o644)
assert.NoError(t, err)

expectedIssues := []types.Issue{
Expand All @@ -320,18 +320,8 @@ func TestRunJsonOutput(t *testing.T) {
runNormalLintProcess(ctx, logger, mockEngine, []string{testFile}, true, jsonOutput)
}

func createTempFiles(t *testing.T, dir string, fileNames ...string) []string {
var paths []string
for _, fileName := range fileNames {
filePath := filepath.Join(dir, fileName)
_, err := os.Create(filePath)
assert.NoError(t, err)
paths = append(paths, filePath)
}
return paths
}

func createTempFileWithContent(t *testing.T, content string) string {
t.Helper()
tempFile, err := os.CreateTemp("", "test*.go")
assert.NoError(t, err)
defer tempFile.Close()
Expand All @@ -342,7 +332,8 @@ func createTempFileWithContent(t *testing.T, content string) string {
return tempFile.Name()
}

func captureOutput(_ *testing.T, f func()) string {
func captureOutput(t *testing.T, f func()) string {
t.Helper()
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
Expand Down
2 changes: 1 addition & 1 deletion internal/analysis/cfg/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (b *builder) buildLoop(stmt ast.Stmt) {
// flows as such (range same w/o init & post):
// previous -> [ init -> ] for -> body -> [ post -> ] for -> next

var post ast.Stmt = stmt // post in for loop, or for stmt itself; body flows to this
post := stmt // post in for loop, or for stmt itself; body flows to this

switch stmt := stmt.(type) {
case *ast.ForStmt:
Expand Down
23 changes: 17 additions & 6 deletions internal/analysis/cfg/cfg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ type CFGWrapper struct {
// w/ some other convenient fields for printing in test
// cases when need be...
func getWrapper(t *testing.T, str string) *CFGWrapper {
t.Helper()
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", str, 0)
if err != nil {
Expand Down Expand Up @@ -891,6 +892,7 @@ func expectFromMaps(actual, exp map[ast.Stmt]struct{}) (dnf, found map[ast.Stmt]
}

func (c *CFGWrapper) expectDefers(t *testing.T, exp ...int) {
t.Helper()
actualDefers := make(map[ast.Stmt]struct{})
for _, d := range c.cfg.Defers {
actualDefers[d] = struct{}{}
Expand All @@ -909,6 +911,7 @@ func (c *CFGWrapper) expectDefers(t *testing.T, exp ...int) {
}

func (c *CFGWrapper) expectSuccs(t *testing.T, s int, exp ...int) {
t.Helper()
if _, ok := c.cfg.blocks[c.exp[s]]; !ok {
t.Error("did not find parent", s)
return
Expand All @@ -933,6 +936,7 @@ func (c *CFGWrapper) expectSuccs(t *testing.T, s int, exp ...int) {
}

func (c *CFGWrapper) expectPreds(t *testing.T, s int, exp ...int) {
t.Helper()
if _, ok := c.cfg.blocks[c.exp[s]]; !ok {
t.Error("did not find parent", s)
}
Expand Down Expand Up @@ -969,9 +973,8 @@ func TestPrintDot(t *testing.T) {
c.cfg.PrintDot(&buf, c.fset, func(s ast.Stmt) string {
if _, ok := s.(*ast.AssignStmt); ok {
return "!"
} else {
return ""
}
return ""
})
dot := buf.String()

Expand All @@ -987,10 +990,18 @@ splines="ortho";
}
// The order of the three lines may vary (they're from a map), so
// just make sure all three lines appear somewhere
for _, re := range expected {
ok, _ := regexp.MatchString(re, dot)
if !ok {
t.Fatalf("[%s]", dot)
regexps := make([]*regexp.Regexp, len(expected))
for i, re := range expected {
var err error
regexps[i], err = regexp.Compile(re)
if err != nil {
t.Fatalf("Failed to compile regex: %v", err)
}
}

for i, re := range regexps {
if !re.MatchString(dot) {
t.Fatalf("Expected pattern not found: [%s] in [%s]", expected[i], dot)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/analysis/cfg/doc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// # Description
//
// Pacakge cfg provides functionality to generate and analyze Control Frow Graph (CFG) for go-like grammar languages.
// Package cfg provides functionality to generate and analyze Control Frow Graph (CFG) for go-like grammar languages.
//
// ## Control Flow Graph (CFG)
//
Expand Down
Loading
Loading