From 9bae788f5e6a6192c9c6a598f3e967d60542a712 Mon Sep 17 00:00:00 2001 From: redowan Date: Thu, 1 Feb 2024 20:48:40 +0100 Subject: [PATCH 1/4] Better error message, closes #12 --- .github/workflows/{test.yml => build.yml} | 12 ++++++ .github/workflows/lint.yml | 38 ------------------ go.mod | 10 ++--- go.sum | 7 ++-- src/cli.go | 23 ++++++++--- src/cli_test.go | 47 +++++++++++++---------- tools.go | 2 +- 7 files changed, 67 insertions(+), 72 deletions(-) rename .github/workflows/{test.yml => build.yml} (67%) delete mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/test.yml b/.github/workflows/build.yml similarity index 67% rename from .github/workflows/test.yml rename to .github/workflows/build.yml index 396a047..3cded14 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/build.yml @@ -25,5 +25,17 @@ jobs: - name: Install dependencies run: make init + - name: Lint + run: make lint + + - name: check-is-dirty + run: | + if [[ -n $(git status --porcelain) ]]; then + echo "Detected uncommitted changes." + git status + git diff + exit 1 + fi + - name: Run tests run: make test diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index da7b25f..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: golangci-lint - -on: - pull_request: - push: - -permissions: - contents: read - - -jobs: - golangci: - name: lint - runs-on: ubuntu-latest - steps: - - uses: actions/setup-go@v5 - with: - go-version: "1.21" - cache: true - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: v1.54 - args: --verbose --timeout 10m --fix=false --new-from-rev=HEAD~ --config=.golangci.yml - - - name: check-is-dirty - run: | - if [[ -n $(git status --porcelain) ]]; then - echo "Detected uncommitted changes." - git status - git diff - exit 1 - fi diff --git a/go.mod b/go.mod index 5e7ba33..cd96150 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,9 @@ require ( github.com/golangci/golangci-lint v1.55.2 github.com/segmentio/golines v0.12.2 github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.27.1 - github.com/yuin/goldmark v1.6.0 + github.com/urfave/cli/v2 v2.27.1 // app dep + github.com/yuin/goldmark v1.6.0 // app dep + honnef.co/go/tools v0.4.6 mvdan.cc/gofumpt v0.5.0 ) @@ -45,7 +46,7 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/chavacava/garif v0.1.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect github.com/daixiang0/gci v0.11.2 // indirect github.com/dave/dst v0.27.3 // indirect @@ -175,7 +176,7 @@ require ( github.com/uudashr/gocognit v1.1.2 // indirect github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect github.com/xen0n/gosmopolitan v1.2.2 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect github.com/ykadowak/zerologlint v0.1.3 // indirect @@ -201,7 +202,6 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.4.6 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect diff --git a/go.sum b/go.sum index 7ef160d..3d81ce4 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,9 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/daixiang0/gci v0.11.2 h1:Oji+oPsp3bQ6bNNgX30NBAVT18P4uBH4sRZnlOlTj7Y= @@ -581,8 +582,8 @@ github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJ github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI= +github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= diff --git a/src/cli.go b/src/cli.go index 7d0c94f..c9d6365 100644 --- a/src/cli.go +++ b/src/cli.go @@ -76,7 +76,8 @@ func findLinks(markdown []byte) ([]string, error) { type linkRecord struct { Location string `json:"location"` StatusCode int `json:"statusCode"` - ErrMsg string `json:"errMsg"` + OK bool `json:"ok"` + Message string `json:"message"` } // checkLink makes an HTTP request to url using the provided timeout. @@ -94,23 +95,34 @@ func checkLink(url string, timeout time.Duration) linkRecord { return linkRecord{ Location: url, StatusCode: 0, - ErrMsg: fmt.Sprintf("Request timed out after %s", timeout), + OK: false, + Message: fmt.Sprintf("Request timed out after %s", timeout), } } return linkRecord{ Location: url, StatusCode: 0, - ErrMsg: err.Error(), + OK: false, + Message: err.Error(), } } defer resp.Body.Close() + statusCode := resp.StatusCode + statusText := http.StatusText(statusCode) + + OK := true + if statusCode >= 400 { + OK = false + } + return linkRecord{ Location: url, StatusCode: resp.StatusCode, - ErrMsg: "", + OK: OK, + Message: statusText, } } @@ -135,7 +147,8 @@ func printLinkRecordJSON(w io.Writer, lr linkRecord) error { func printLinkRecordTab(w io.Writer, lr linkRecord) error { tpl := `- Location : {{.Location}} Status Code: {{if eq .StatusCode 0}}-{{else}}{{.StatusCode}}{{end}} - Error : {{if .ErrMsg}}{{.ErrMsg}}{{else}}-{{end}} + OK : {{.OK}} + Message : {{if .Message}}{{.Message}}{{else}}-{{end}} ` t, err := template.New("record").Parse(tpl) diff --git a/src/cli_test.go b/src/cli_test.go index 65297b9..d930759 100644 --- a/src/cli_test.go +++ b/src/cli_test.go @@ -195,10 +195,9 @@ func TestCheckLink_Success(t *testing.T) { lr := checkLink(ts.URL, 1*time.Second) assert.Equal(t, http.StatusOK, lr.StatusCode, "Status code should be 200") - assert.Empty(t, lr.ErrMsg, "Error message should be empty") + assert.Equal(t, "OK", lr.Message, "Error message should be 'OK'") } - // TestCheckLink_ClientError tests the checkUrl function with a client error func TestCheckLink_ClientError(t *testing.T) { t.Parallel() @@ -217,7 +216,7 @@ func TestCheckLink_ClientError(t *testing.T) { lr.StatusCode, "Status code should be 404", ) - assert.Empty(t, lr.ErrMsg, "Error message should be empty") + assert.Equal(t, "Not Found", lr.Message) } // TestCheckLink_ServerError tests the checkUrl function with a server error @@ -238,7 +237,7 @@ func TestCheckLink_ServerError(t *testing.T) { lr.StatusCode, "Status code should be 500", ) - assert.Empty(t, lr.ErrMsg, "Error message should be empty") + assert.Equal(t, "Internal Server Error", lr.Message) } // TestCheckLink_ConnectionError tests the checkUrl function with a connection error @@ -249,7 +248,7 @@ func TestCheckLink_ConnectionError(t *testing.T) { assert.Equal(t, 0, lr.StatusCode, "Status code should be 0") assert.Contains( t, - lr.ErrMsg, + lr.Message, "connection refused", "Error message should contain 'connection refused'", ) @@ -261,7 +260,7 @@ func TestCheckLink_InvalidLink(t *testing.T) { lr := checkLink(":%", 1*time.Second) assert.Equal(t, 0, lr.StatusCode, "Status code should be 0") - assert.Equal(t, lr.ErrMsg, "parse \":%\": missing protocol scheme") + assert.Equal(t, lr.Message, "parse \":%\": missing protocol scheme") } // Test for printFilepath function @@ -285,10 +284,11 @@ func TestPrintFilepath(t *testing.T) { // Test for printLinkRecordTab function func TestPrintLinkRecordTab(t *testing.T) { t.Parallel() - linkRecord := linkRecord{"http://example.com", 200, "OK"} + linkRecord := linkRecord{"http://example.com", 200, true, "OK"} expectedOutput := "- Location : http://example.com\n" + " Status Code: 200\n" + - " Error : OK\n\n" + " OK : true\n" + + " Message : OK\n\n" var buf bytes.Buffer w := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', 0) @@ -306,11 +306,12 @@ func TestPrintLinkRecordTab(t *testing.T) { // Test for printLinkRecordJSON function func TestPrintLinkRecordJSON(t *testing.T) { t.Parallel() - linkRecord := linkRecord{"http://example.com", 200, "OK"} + linkRecord := linkRecord{"http://example.com", 200, true, "OK"} expectedOutput := "{\n" + " \"location\": \"http://example.com\",\n" + " \"statusCode\": 200,\n" + - " \"errMsg\": \"OK\"\n" + + " \"ok\": true,\n" + + " \"message\": \"OK\"\n" + "}\n" var buf bytes.Buffer @@ -329,10 +330,11 @@ func TestPrintLinkRecordJSON(t *testing.T) { // Test for printLinkRecord function func TestPrintLinkRecord(t *testing.T) { t.Parallel() - linkRecord := linkRecord{"http://example.com", 200, "OK"} + linkRecord := linkRecord{"http://example.com", 200, true, "OK"} expectedOutput := "- Location : http://example.com\n" + " Status Code: 200\n" + - " Error : OK\n\n" + " OK : true\n" + + " Message : OK\n\n" var buf bytes.Buffer w := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', 0) @@ -350,7 +352,8 @@ func TestPrintLinkRecord(t *testing.T) { expectedOutput = "{\n" + " \"location\": \"http://example.com\",\n" + " \"statusCode\": 200,\n" + - " \"errMsg\": \"OK\"\n" + + " \"ok\": true,\n" + + " \"message\": \"OK\"\n" + "}\n" var buf2 bytes.Buffer @@ -371,6 +374,7 @@ func TestCheckLinks(t *testing.T) { // Create a test tabwriter.Writer buf := new(bytes.Buffer) w := tabwriter.NewWriter(buf, 0, 0, 2, ' ', 0) + defer w.Flush() // Create a test server that always returns a specific status code ts := httptest.NewServer( @@ -386,27 +390,30 @@ func TestCheckLinks(t *testing.T) { // Set the timeout and error flag for testing timeout := time.Second errOK := false + asJSON := false // Call the checkLinks function - _ = checkLinks(w, urls, timeout, errOK, false) + _ = checkLinks(w, urls, timeout, errOK, asJSON) - // Flush the tabwriter.Writer to get the output - w.Flush() output := buf.String() // Verify the output expectedOutput1 := "- Location : " + ts.URL + "/ok\n" + " Status Code: 200\n" + - " Error : -\n\n" + + " OK : true\n" + + " Message : OK\n\n" + "- Location : " + ts.URL + "/invalid-url\n" + " Status Code: 200\n" + - " Error : -\n\n" + " OK : true\n" + + " Message : OK\n\n" expectedOutput2 := "- Location : " + ts.URL + "/invalid-url\n" + " Status Code: 200\n" + - " Error : -\n\n" + + " OK : true\n" + + " Message : OK\n\n" + "- Location : " + ts.URL + "/ok\n" + " Status Code: 200\n" + - " Error : -\n\n" + " OK : true\n" + + " Message : OK\n\n" assert.Contains( t, diff --git a/tools.go b/tools.go index b1354cb..bea0d01 100644 --- a/tools.go +++ b/tools.go @@ -1,5 +1,4 @@ //go:build tools -// +build tools package tools @@ -8,6 +7,7 @@ import ( _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/segmentio/golines" _ "mvdan.cc/gofumpt" + _ "honnef.co/go/tools/cmd/staticcheck" // Testing _ "github.com/stretchr/testify/mock" From ae6b1882e6f7110e1a196b6330661a486a78a975 Mon Sep 17 00:00:00 2001 From: redowan Date: Thu, 1 Feb 2024 21:09:46 +0100 Subject: [PATCH 2/4] Improve ci, closes #12 --- .golangci.yml | 3 +++ Makefile | 8 ++++++-- go.mod | 10 ++++++---- src/cli_test.go | 6 +++--- tools.go | 2 -- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5a6aa19..912391a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,8 +2,11 @@ linters: enable: - gofmt - gofumpt + - goimports - nolintlint - lll + - staticcheck + - testifylint issues: max-issues-per-linter: 0 diff --git a/Makefile b/Makefile index 2b422ce..8e45f91 100644 --- a/Makefile +++ b/Makefile @@ -12,9 +12,7 @@ init: lint: @echo "Running lint" @golines -w -m 92 cmd/* src/* - @gofumpt -w cmd/* src/* @golangci-lint run --fix - @go mod tidy @prettier --write . @@ -39,5 +37,11 @@ bench: .PHONY: clean clean: @echo "Cleaning up" + @go clean -x @go clean + @go clean -testcache + @go clean -cache + @go clean -modcache + @go clean -i + @go clean -r @rm -rf ./bin diff --git a/go.mod b/go.mod index cd96150..6834849 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,17 @@ go 1.21.6 require ( github.com/golangci/golangci-lint v1.55.2 - github.com/segmentio/golines v0.12.2 github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.27.1 // app dep github.com/yuin/goldmark v1.6.0 // app dep - honnef.co/go/tools v0.4.6 - mvdan.cc/gofumpt v0.5.0 + honnef.co/go/tools v0.4.6 // indirect + mvdan.cc/gofumpt v0.5.0 // indirect ) +require golang.org/x/tools v0.17.0 // indirect + +require github.com/segmentio/golines v0.12.2 + require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 4d63.com/gochecknoglobals v0.2.1 // indirect @@ -194,7 +197,6 @@ require ( golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.17.0 // indirect google.golang.org/protobuf v1.28.0 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect diff --git a/src/cli_test.go b/src/cli_test.go index d930759..785860b 100644 --- a/src/cli_test.go +++ b/src/cli_test.go @@ -77,7 +77,7 @@ func TestReadMarkdown_NonMarkdownFile(t *testing.T) { _, err = readMarkdown(filepath) // Check if an error was returned - assert.Error(t, err, "Expected an error for non-markdown file") + require.Error(t, err, "Expected an error for non-markdown file") } func TestFindLinks(t *testing.T) { @@ -259,8 +259,8 @@ func TestCheckLink_InvalidLink(t *testing.T) { t.Parallel() lr := checkLink(":%", 1*time.Second) - assert.Equal(t, 0, lr.StatusCode, "Status code should be 0") - assert.Equal(t, lr.Message, "parse \":%\": missing protocol scheme") + assert.Equal(t, 0, "Status code should be 0", lr.StatusCode) + assert.Equal(t, "parse \":%\": missing protocol scheme", lr.Message) } // Test for printFilepath function diff --git a/tools.go b/tools.go index bea0d01..d41231c 100644 --- a/tools.go +++ b/tools.go @@ -6,8 +6,6 @@ import ( // Linters _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/segmentio/golines" - _ "mvdan.cc/gofumpt" - _ "honnef.co/go/tools/cmd/staticcheck" // Testing _ "github.com/stretchr/testify/mock" From 620da4fa401e8e7c22b9f5c507ca4808ce44568e Mon Sep 17 00:00:00 2001 From: redowan Date: Thu, 1 Feb 2024 21:12:02 +0100 Subject: [PATCH 3/4] Improve ci, closes #12 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3cded14..ae6ffac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: run: make init - name: Lint - run: make lint + run: make lint-check - name: check-is-dirty run: | From e80c5dbe3fca2f0dba241ca361fbbf23fae38a47 Mon Sep 17 00:00:00 2001 From: redowan Date: Thu, 1 Feb 2024 21:14:37 +0100 Subject: [PATCH 4/4] Fix failing tests, closes #12 --- src/cli_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli_test.go b/src/cli_test.go index 785860b..3712040 100644 --- a/src/cli_test.go +++ b/src/cli_test.go @@ -259,7 +259,7 @@ func TestCheckLink_InvalidLink(t *testing.T) { t.Parallel() lr := checkLink(":%", 1*time.Second) - assert.Equal(t, 0, "Status code should be 0", lr.StatusCode) + assert.Equal(t, 0, lr.StatusCode, "Status code should be 0") assert.Equal(t, "parse \":%\": missing protocol scheme", lr.Message) }