From 22b2312f6067d8da97cc7c5918df75258db3d438 Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap Date: Thu, 20 Jul 2023 02:03:34 +0530 Subject: [PATCH 01/10] added github actions for golangci-lint & go-test --- .github/workflows/test.yml | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..43c2bf32 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,39 @@ +name: Verify and Test +on: + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + golangci: + strategy: + matrix: + go: ['1.19','1.20'] + os: [ubuntu-latest] + fail-fast: true + name: verify + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.53 + args: --timeout=5m + + - name: Test + run: go test -race --coverprofile=coverage.coverprofile --covermode=atomic -v ./... \ No newline at end of file From b3c9a9f4a873ed58d45b94f97c4a3819c202899d Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap Date: Fri, 21 Jul 2023 01:01:28 +0530 Subject: [PATCH 02/10] bumped go to 1.19 & added github actions --- .circleci/config.yml | 70 ---------------------------- .github/workflows/test.yml | 6 +-- Makefile | 33 +++++++++++++ go.mod | 2 +- middleware_test.go | 95 ++++++++++++++++++++++++++++++-------- mux_httpserver_test.go | 14 ++++-- mux_test.go | 20 ++++++-- regexp.go | 2 +- regexp_test.go | 4 +- route.go | 80 ++++++++++++++++---------------- 10 files changed, 181 insertions(+), 145 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 Makefile diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index ead3e1d4..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,70 +0,0 @@ -version: 2.1 - -jobs: - "test": - parameters: - version: - type: string - default: "latest" - golint: - type: boolean - default: true - modules: - type: boolean - default: true - goproxy: - type: string - default: "" - docker: - - image: "circleci/golang:<< parameters.version >>" - working_directory: /go/src/github.com/gorilla/mux - environment: - GO111MODULE: "on" - GOPROXY: "<< parameters.goproxy >>" - steps: - - checkout - - run: - name: "Print the Go version" - command: > - go version - - run: - name: "Fetch dependencies" - command: > - if [[ << parameters.modules >> = true ]]; then - go mod download - export GO111MODULE=on - else - go get -v ./... - fi - # Only run gofmt, vet & lint against the latest Go version - - run: - name: "Run golint" - command: > - if [ << parameters.version >> = "latest" ] && [ << parameters.golint >> = true ]; then - go get -u golang.org/x/lint/golint - golint ./... - fi - - run: - name: "Run gofmt" - command: > - if [[ << parameters.version >> = "latest" ]]; then - diff -u <(echo -n) <(gofmt -d -e .) - fi - - run: - name: "Run go vet" - command: > - if [[ << parameters.version >> = "latest" ]]; then - go vet -v ./... - fi - - run: - name: "Run go test (+ race detector)" - command: > - go test -v -race ./... - -workflows: - tests: - jobs: - - test: - matrix: - parameters: - version: ["latest", "1.15", "1.14", "1.13", "1.12", "1.11"] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43c2bf32..a5e0fb9c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,8 +14,8 @@ jobs: golangci: strategy: matrix: - go: ['1.19','1.20'] - os: [ubuntu-latest] + go: ['1.18', '1.19','1.20'] + os: [ubuntu-latest, macos-latest, windows-latest] fail-fast: true name: verify runs-on: ${{ matrix.os }} @@ -36,4 +36,4 @@ jobs: args: --timeout=5m - name: Test - run: go test -race --coverprofile=coverage.coverprofile --covermode=atomic -v ./... \ No newline at end of file + run: make test \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..bdf224b0 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +SHELL := /bin/bash + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +# LINT is the path to the golangci-lint binary +LINT = $(shell which golangci-lint) + +.PHONY: golangci-lint +golangci-lint: +ifeq (, $(LINT)) + ifeq (, $(shell which golangci-lint)) + @{ \ + set -e ;\ + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest ;\ + } + override LINT=$(GOBIN)/golangci-lint + else + override LINT=$(shell which golangci-lint) + endif +endif + +.PHONY: verify +verify: golangci-lint + $(LINT) run + +.PHONY: test +test: + go test -race --coverprofile=coverage.coverprofile --covermode=atomic -v ./... diff --git a/go.mod b/go.mod index df170a39..7bcfa026 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/gorilla/mux -go 1.12 +go 1.19 diff --git a/middleware_test.go b/middleware_test.go index e9f0ef55..4963b66f 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -158,7 +158,10 @@ func TestMiddlewareExecution(t *testing.T) { router := NewRouter() router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) t.Run("responds normally without middleware", func(t *testing.T) { @@ -178,7 +181,10 @@ func TestMiddlewareExecution(t *testing.T) { router.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) + _, err := w.Write(mwStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) @@ -196,11 +202,17 @@ func TestMiddlewareNotFound(t *testing.T) { router := NewRouter() router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) router.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) + _, err := w.Write(mwStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) @@ -221,7 +233,10 @@ func TestMiddlewareNotFound(t *testing.T) { req := newRequest("GET", "/notfound") router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Custom 404 handler")) + _, err := rw.Write([]byte("Custom 404 handler")) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) router.ServeHTTP(rw, req) @@ -237,12 +252,18 @@ func TestMiddlewareMethodMismatch(t *testing.T) { router := NewRouter() router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }).Methods("GET") router.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) + _, err := w.Write(mwStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) @@ -262,7 +283,10 @@ func TestMiddlewareMethodMismatch(t *testing.T) { req := newRequest("POST", "/") router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Method not allowed")) + _, err := rw.Write([]byte("Method not allowed")) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) router.ServeHTTP(rw, req) @@ -278,17 +302,26 @@ func TestMiddlewareNotFoundSubrouter(t *testing.T) { router := NewRouter() router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) subrouter := router.PathPrefix("/sub/").Subrouter() subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) router.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) + _, err := w.Write(mwStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) @@ -308,7 +341,10 @@ func TestMiddlewareNotFoundSubrouter(t *testing.T) { req := newRequest("GET", "/sub/notfound") subrouter.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Custom 404 handler")) + _, err := rw.Write([]byte("Custom 404 handler")) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) router.ServeHTTP(rw, req) @@ -324,17 +360,26 @@ func TestMiddlewareMethodMismatchSubrouter(t *testing.T) { router := NewRouter() router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) subrouter := router.PathPrefix("/sub/").Subrouter() subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) + _, err := w.Write(handlerStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }).Methods("GET") router.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) + _, err := w.Write(mwStr) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) @@ -354,7 +399,10 @@ func TestMiddlewareMethodMismatchSubrouter(t *testing.T) { req := newRequest("POST", "/sub/") router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Method not allowed")) + _, err := rw.Write([]byte("Method not allowed")) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) router.ServeHTTP(rw, req) @@ -508,7 +556,10 @@ func TestMiddlewareOnMultiSubrouter(t *testing.T) { secondSubRouter := router.PathPrefix("/").Subrouter() router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte(notFound)) + _, err := rw.Write([]byte(notFound)) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }) firstSubRouter.HandleFunc("/first", func(w http.ResponseWriter, r *http.Request) { @@ -521,14 +572,20 @@ func TestMiddlewareOnMultiSubrouter(t *testing.T) { firstSubRouter.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(first)) + _, err := w.Write([]byte(first)) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) secondSubRouter.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(second)) + _, err := w.Write([]byte(second)) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } h.ServeHTTP(w, r) }) }) diff --git a/mux_httpserver_test.go b/mux_httpserver_test.go index 907ab91d..f55a2de3 100644 --- a/mux_httpserver_test.go +++ b/mux_httpserver_test.go @@ -5,7 +5,7 @@ package mux import ( "bytes" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -14,10 +14,16 @@ import ( func TestSchemeMatchers(t *testing.T) { router := NewRouter() router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("hello http world")) + _, err := rw.Write([]byte("hello http world")) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }).Schemes("http") router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("hello https world")) + _, err := rw.Write([]byte("hello https world")) + if err != nil { + t.Fatalf("Failed writing HTTP response: %v", err) + } }).Schemes("https") assertResponseBody := func(t *testing.T, s *httptest.Server, expectedBody string) { @@ -28,7 +34,7 @@ func TestSchemeMatchers(t *testing.T) { if resp.StatusCode != 200 { t.Fatalf("expected a status code of 200, got %v", resp.StatusCode) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("unexpected error reading body: %v", err) } diff --git a/mux_test.go b/mux_test.go index 2d8d2b3e..4345254b 100644 --- a/mux_test.go +++ b/mux_test.go @@ -10,7 +10,8 @@ import ( "context" "errors" "fmt" - "io/ioutil" + "io" + "log" "net/http" "net/http/httptest" "net/url" @@ -2136,7 +2137,10 @@ type methodsSubrouterTest struct { // methodHandler writes the method string in response. func methodHandler(method string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(method)) + _, err := w.Write([]byte(method)) + if err != nil { + log.Printf("Failed writing HTTP response: %v", err) + } } } @@ -2778,7 +2782,7 @@ func TestSubrouterCustomMethodNotAllowed(t *testing.T) { tt.Errorf("Expected status code 405 (got %d)", w.Code) } - b, err := ioutil.ReadAll(w.Body) + b, err := io.ReadAll(w.Body) if err != nil { tt.Errorf("failed to read body: %v", err) } @@ -2859,7 +2863,10 @@ func stringMapEqual(m1, m2 map[string]string) bool { // http.ResponseWriter. func stringHandler(s string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(s)) + _, err := w.Write([]byte(s)) + if err != nil { + log.Printf("Failed writing HTTP response: %v", err) + } } } @@ -2892,7 +2899,10 @@ func newRequest(method, url string) *http.Request { // Simulate writing to wire var buff bytes.Buffer - req.Write(&buff) + err = req.Write(&buff) + if err != nil { + log.Printf("Failed writing HTTP request: %v", err) + } ioreader := bufio.NewReader(&buff) // Parse request off of 'wire' diff --git a/regexp.go b/regexp.go index 37c11edc..5d05cfa0 100644 --- a/regexp.go +++ b/regexp.go @@ -195,7 +195,7 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { // url builds a URL part using the given values. func (r *routeRegexp) url(values map[string]string) (string, error) { - urlValues := make([]interface{}, len(r.varsN), len(r.varsN)) + urlValues := make([]interface{}, len(r.varsN)) for k, v := range r.varsN { value, ok := values[v] if !ok { diff --git a/regexp_test.go b/regexp_test.go index 0d80e6a5..d7518f3e 100644 --- a/regexp_test.go +++ b/regexp_test.go @@ -54,7 +54,7 @@ func Benchmark_findQueryKey(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - for key, _ := range all { + for key := range all { _, _ = findFirstQueryKey(query, key) } } @@ -79,7 +79,7 @@ func Benchmark_findQueryKeyGoLib(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - for key, _ := range all { + for key := range all { v := u.Query()[key] if len(v) > 0 { _ = v[0] diff --git a/route.go b/route.go index 750afe57..ce1c9bfe 100644 --- a/route.go +++ b/route.go @@ -64,7 +64,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { match.MatchErr = nil } - matchErr = nil + matchErr = nil // nolint:ineffassign return false } } @@ -230,9 +230,9 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { // Headers adds a matcher for request header values. // It accepts a sequence of key/value pairs to be matched. For example: // -// r := mux.NewRouter() -// r.Headers("Content-Type", "application/json", -// "X-Requested-With", "XMLHttpRequest") +// r := mux.NewRouter() +// r.Headers("Content-Type", "application/json", +// "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both request header values match. // If the value is an empty string, it will match any value if the key is set. @@ -255,9 +255,9 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { // HeadersRegexp accepts a sequence of key/value pairs, where the value has regex // support. For example: // -// r := mux.NewRouter() -// r.HeadersRegexp("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") +// r := mux.NewRouter() +// r.HeadersRegexp("Content-Type", "application/(text|json)", +// "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both the request header matches both regular expressions. // If the value is an empty string, it will match any value if the key is set. @@ -283,10 +283,10 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route { // // For example: // -// r := mux.NewRouter() -// r.Host("www.example.com") -// r.Host("{subdomain}.domain.com") -// r.Host("{subdomain:[a-z]+}.domain.com") +// r := mux.NewRouter() +// r.Host("www.example.com") +// r.Host("{subdomain}.domain.com") +// r.Host("{subdomain:[a-z]+}.domain.com") // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). @@ -342,11 +342,11 @@ func (r *Route) Methods(methods ...string) *Route { // // For example: // -// r := mux.NewRouter() -// r.Path("/products/").Handler(ProductsHandler) -// r.Path("/products/{key}").Handler(ProductsHandler) -// r.Path("/articles/{category}/{id:[0-9]+}"). -// Handler(ArticleHandler) +// r := mux.NewRouter() +// r.Path("/products/").Handler(ProductsHandler) +// r.Path("/products/{key}").Handler(ProductsHandler) +// r.Path("/articles/{category}/{id:[0-9]+}"). +// Handler(ArticleHandler) // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). @@ -377,8 +377,8 @@ func (r *Route) PathPrefix(tpl string) *Route { // It accepts a sequence of key/value pairs. Values may define variables. // For example: // -// r := mux.NewRouter() -// r.Queries("foo", "bar", "id", "{id:[0-9]+}") +// r := mux.NewRouter() +// r.Queries("foo", "bar", "id", "{id:[0-9]+}") // // The above route will only match if the URL contains the defined queries // values, e.g.: ?foo=bar&id=42. @@ -473,11 +473,11 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { // // It will test the inner routes only if the parent route matched. For example: // -// r := mux.NewRouter() -// s := r.Host("www.example.com").Subrouter() -// s.HandleFunc("/products/", ProductsHandler) -// s.HandleFunc("/products/{key}", ProductHandler) -// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +// r := mux.NewRouter() +// s := r.Host("www.example.com").Subrouter() +// s.HandleFunc("/products/", ProductsHandler) +// s.HandleFunc("/products/{key}", ProductHandler) +// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) // // Here, the routes registered in the subrouter won't be tested if the host // doesn't match. @@ -497,36 +497,36 @@ func (r *Route) Subrouter() *Router { // It accepts a sequence of key/value pairs for the route variables. For // example, given this route: // -// r := mux.NewRouter() -// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Name("article") // // ...a URL for it can be built using: // -// url, err := r.Get("article").URL("category", "technology", "id", "42") +// url, err := r.Get("article").URL("category", "technology", "id", "42") // // ...which will return an url.URL with the following path: // -// "/articles/technology/42" +// "/articles/technology/42" // // This also works for host variables: // -// r := mux.NewRouter() -// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Host("{subdomain}.domain.com"). -// Name("article") +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Host("{subdomain}.domain.com"). +// Name("article") // -// // url.String() will be "http://news.domain.com/articles/technology/42" -// url, err := r.Get("article").URL("subdomain", "news", -// "category", "technology", -// "id", "42") +// // url.String() will be "http://news.domain.com/articles/technology/42" +// url, err := r.Get("article").URL("subdomain", "news", +// "category", "technology", +// "id", "42") // // The scheme of the resulting url will be the first argument that was passed to Schemes: // -// // url.String() will be "https://example.com" -// r := mux.NewRouter() -// url, err := r.Host("example.com") -// .Schemes("https", "http").URL() +// // url.String() will be "https://example.com" +// r := mux.NewRouter() +// url, err := r.Host("example.com") +// .Schemes("https", "http").URL() // // All variables defined in the route are required, and their values must // conform to the corresponding patterns. From 172bd75767b0b70f066f0f93ad84f7326e3c285b Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap Date: Fri, 21 Jul 2023 11:30:01 +0530 Subject: [PATCH 03/10] referenced make commands in GHA --- .github/workflows/test.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a5e0fb9c..e274eec6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Verify and Test +name: CI on: push: branches: @@ -11,13 +11,12 @@ permissions: contents: read jobs: - golangci: + verify-and-test: strategy: matrix: go: ['1.18', '1.19','1.20'] os: [ubuntu-latest, macos-latest, windows-latest] fail-fast: true - name: verify runs-on: ${{ matrix.os }} steps: - name: Checkout Code @@ -29,11 +28,8 @@ jobs: go-version: ${{ matrix.go }} cache: false - - name: Golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: v1.53 - args: --timeout=5m + - name: Verify + run: make verify - name: Test run: make test \ No newline at end of file From 9ab0dcffbad74c1d1baed87274c97ede68d8dda6 Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap Date: Fri, 21 Jul 2023 15:03:48 +0530 Subject: [PATCH 04/10] Add all the issues to project --- .github/workflows/issues.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/issues.yml diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 00000000..dfe37bee --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,17 @@ +# Add all the issues created to the project. +name: Add all issues to Project + +on: + issues: + types: + - opened + +jobs: + add-to-project: + runs-on: ubuntu-latest + steps: + - name: Add issue to project + uses: actions/add-to-project@v0.5.0 + with: + project-url: https://github.com/orgs/gorilla/projects/mux + github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 8b9c52f8ca49239827a21b997efb7de773067ae3 Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap Date: Fri, 21 Jul 2023 20:02:35 +0530 Subject: [PATCH 05/10] use golangci-lint-action instead of 'make verify' --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e274eec6..18e435af 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,10 @@ jobs: cache: false - name: Verify - run: make verify + uses: golangci/golangci-lint-action@v3 + with: + version: v1.53 + args: --timeout=5m - name: Test run: make test \ No newline at end of file From 3760a49e5daba828f9553541a6cd735c6fc27d75 Mon Sep 17 00:00:00 2001 From: Corey Daley Date: Fri, 21 Jul 2023 11:12:42 -0400 Subject: [PATCH 06/10] Update .github/workflows/issues.yml Signed-off-by: Corey Daley --- .github/workflows/issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml index dfe37bee..fb6eaf78 100644 --- a/.github/workflows/issues.yml +++ b/.github/workflows/issues.yml @@ -13,5 +13,5 @@ jobs: - name: Add issue to project uses: actions/add-to-project@v0.5.0 with: - project-url: https://github.com/orgs/gorilla/projects/mux + project-url: https://github.com/orgs/gorilla/projects/4 github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 66df55cefb4f402bdb0e159f3d4f5fa20deaf875 Mon Sep 17 00:00:00 2001 From: Corey Daley Date: Fri, 21 Jul 2023 11:12:49 -0400 Subject: [PATCH 07/10] Update .github/workflows/issues.yml Signed-off-by: Corey Daley --- .github/workflows/issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml index fb6eaf78..193eb32a 100644 --- a/.github/workflows/issues.yml +++ b/.github/workflows/issues.yml @@ -14,4 +14,4 @@ jobs: uses: actions/add-to-project@v0.5.0 with: project-url: https://github.com/orgs/gorilla/projects/4 - github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }} \ No newline at end of file From d11e39a78ec5b2895572bd1d59b200a5f7a345f0 Mon Sep 17 00:00:00 2001 From: Corey Daley Date: Sat, 22 Jul 2023 00:36:44 -0400 Subject: [PATCH 08/10] Update .github/workflows/test.yml Signed-off-by: Corey Daley --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 18e435af..152cd742 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,4 +35,6 @@ jobs: args: --timeout=5m - name: Test - run: make test \ No newline at end of file + run: go test -race --coverprofile=coverage.txt --covermode=atomic -v ./... + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 \ No newline at end of file From ab7b80ac8d434442ce20c5e6b6bf8aee7eab6774 Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap Date: Sun, 23 Jul 2023 03:03:33 +0530 Subject: [PATCH 09/10] added gosec & govulncheck --- .editorconfig | 20 +++++++++++++++ .github/workflows/issues.yml | 7 ++++-- .github/workflows/test.yml | 35 +++++++++++++++++++-------- .gitignore | 1 + Makefile | 47 ++++++++++++++++++------------------ README.md | 8 +++--- 6 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitignore diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..c6b74c3e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +; https://editorconfig.org/ + +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[{Makefile,go.mod,go.sum,*.go,.gitmodules}] +indent_style = tab +indent_size = 4 + +[*.md] +indent_size = 4 +trim_trailing_whitespace = false + +eclint_indent_style = unset \ No newline at end of file diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml index 193eb32a..055ca822 100644 --- a/.github/workflows/issues.yml +++ b/.github/workflows/issues.yml @@ -1,10 +1,13 @@ -# Add all the issues created to the project. -name: Add all issues to Project +# Add issues or pull-requests created to the project. +name: Add issue or pull request to Project on: issues: types: - opened + pull_request: + types: + - opened jobs: add-to-project: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 152cd742..af48d228 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,5 @@ name: CI -on: +on: push: branches: - main @@ -13,8 +13,8 @@ permissions: jobs: verify-and-test: strategy: - matrix: - go: ['1.18', '1.19','1.20'] + matrix: + go: ['1.19','1.20'] os: [ubuntu-latest, macos-latest, windows-latest] fail-fast: true runs-on: ${{ matrix.os }} @@ -27,14 +27,29 @@ jobs: with: go-version: ${{ matrix.go }} cache: false - - - name: Verify + + - name: Run GolangCI-Lint uses: golangci/golangci-lint-action@v3 - with: + with: version: v1.53 args: --timeout=5m - - - name: Test - run: go test -race --coverprofile=coverage.txt --covermode=atomic -v ./... + + - name: Run GoSec + if: matrix.os == 'ubuntu-latest' + uses: securego/gosec@master + with: + args: ./... + + - name: Run GoVulnCheck + uses: golang/govulncheck-action@v1 + with: + go-version-input: ${{ matrix.go }} + go-package: ./... + + - name: Run Tests + run: go test -race -cover -coverprofile=coverage -covermode=atomic -v ./... + - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 \ No newline at end of file + uses: codecov/codecov-action@v3 + with: + files: ./coverage \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..84039fec --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +coverage.coverprofile diff --git a/Makefile b/Makefile index bdf224b0..98f5ab75 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,34 @@ -SHELL := /bin/bash +GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '') +GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest -# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) -ifeq (,$(shell go env GOBIN)) -GOBIN=$(shell go env GOPATH)/bin -else -GOBIN=$(shell go env GOBIN) -endif +GO_SEC=$(shell which gosec 2> /dev/null || echo '') +GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest -# LINT is the path to the golangci-lint binary -LINT = $(shell which golangci-lint) +GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '') +GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest .PHONY: golangci-lint golangci-lint: -ifeq (, $(LINT)) - ifeq (, $(shell which golangci-lint)) - @{ \ - set -e ;\ - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest ;\ - } - override LINT=$(GOBIN)/golangci-lint - else - override LINT=$(shell which golangci-lint) - endif -endif + $(if $(GO_LINT), ,go install $(GO_LINT_URI)) + @echo "##### Running golangci-lint" + golangci-lint run -v + +.PHONY: gosec +gosec: + $(if $(GO_SEC), ,go install $(GO_SEC_URI)) + @echo "##### Running gosec" + gosec ./... + +.PHONY: govulncheck +govulncheck: + $(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI)) + @echo "##### Running govulncheck" + govulncheck ./... .PHONY: verify -verify: golangci-lint - $(LINT) run +verify: golangci-lint gosec govulncheck .PHONY: test test: - go test -race --coverprofile=coverage.coverprofile --covermode=atomic -v ./... + @echo "##### Running tests" + go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./... \ No newline at end of file diff --git a/README.md b/README.md index f836a4e7..64af2430 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # gorilla/mux -[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) -[![CircleCI](https://circleci.com/gh/gorilla/mux.svg?style=svg)](https://circleci.com/gh/gorilla/mux) -[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) +![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/mux/branch/master/graph/badge.svg)](https://codecov.io/github/gorilla/mux) +[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) + ![Gorilla Logo](https://cloud-cdn.questionable.services/gorilla-icon-64.png) From f7f029debe478cd16b40a62e17d5183daaeae155 Mon Sep 17 00:00:00 2001 From: Apoorva Jagtap <35304110+apoorvajagtap@users.noreply.github.com> Date: Mon, 24 Jul 2023 01:39:45 +0530 Subject: [PATCH 10/10] Update README.md Co-authored-by: Corey Daley Signed-off-by: Apoorva Jagtap <35304110+apoorvajagtap@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 64af2430..551f3c67 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # gorilla/mux ![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg) -[![codecov](https://codecov.io/github/gorilla/mux/branch/master/graph/badge.svg)](https://codecov.io/github/gorilla/mux) +[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux) [![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) [![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)