diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 0000000..88cef99 --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,69 @@ +name: bench +on: + push: + tags: + - v* + branches: + - master + - main + pull_request: +env: + GO111MODULE: "on" +jobs: + bench: + strategy: + matrix: + go-version: [ 1.16.x ] + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: Restore vendor + uses: actions/cache@v2 + with: + path: | + vendor + key: ${{ runner.os }}-go${{ matrix.go-version }}-vendor-${{ hashFiles('**/go.mod') }} + - name: Populate dependencies + run: | + (test -d vendor && echo vendor found) || (go mod vendor && du -sh vendor && du -sh ~/go/pkg/mod) + - name: Restore benchstat + uses: actions/cache@v2 + with: + path: ~/go/bin/benchstat + key: ${{ runner.os }}-benchstat + - name: Restore base benchmark result + uses: actions/cache@v2 + with: + path: | + bench-master.txt + bench-main.txt + # Use base sha for PR or new commit hash for master/main push in benchmark result key. + key: ${{ runner.os }}-bench-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }} + - name: Benchmark + id: bench + run: | + export REF_NAME=${GITHUB_REF##*/} + BENCH_COUNT=5 make bench-run bench-stat + OUTPUT=$(make bench-stat) + OUTPUT="${OUTPUT//'%'/'%25'}" + OUTPUT="${OUTPUT//$'\n'/'%0A'}" + OUTPUT="${OUTPUT//$'\r'/'%0D'}" + echo "::set-output name=result::$OUTPUT" + - name: Comment Benchmark Result + uses: marocchino/sticky-pull-request-comment@v2 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + header: bench + message: | + ### Benchmark Result +
Benchmark diff with base branch + + ``` + ${{ steps.bench.outputs.result }} + ``` +
diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml new file mode 100644 index 0000000..c857562 --- /dev/null +++ b/.github/workflows/test-unit.yml @@ -0,0 +1,75 @@ +name: test-unit +on: + push: + branches: + - master + - main + pull_request: +env: + GO111MODULE: "on" +jobs: + test: + strategy: + matrix: + go-version: [ 1.16.x ] + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: Restore base test coverage + uses: actions/cache@v2 + with: + path: | + unit-base.txt + # Use base sha for PR or new commit hash for master/main push in test result key. + key: ${{ runner.os }}-unit-test-coverage-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }} + - name: Restore vendor + uses: actions/cache@v2 + with: + path: | + vendor + key: ${{ runner.os }}-go${{ matrix.go-version }}-vendor-${{ hashFiles('**/go.mod') }} + - name: Populate dependencies + run: | + (test -d vendor && echo vendor found) || (go mod vendor && du -sh vendor && du -sh ~/go/pkg/mod) + - name: Test + id: test + run: | + make test-unit + go tool cover -func=./unit.coverprofile | sed -e 's/.go:[0-9]*:\t/.go\t/g' | sed -e 's/\t\t*/\t/g' > unit.txt + OUTPUT=$(test -e unit-base.txt && (diff unit-base.txt unit.txt || exit 0) || cat unit.txt) + OUTPUT="${OUTPUT//'%'/'%25'}" + OUTPUT="${OUTPUT//$'\n'/'%0A'}" + OUTPUT="${OUTPUT//$'\r'/'%0D'}" + TOTAL=$(grep 'total:' unit.txt) + echo "::set-output name=diff::$OUTPUT" + echo "::set-output name=total::$TOTAL" + - name: Store base coverage + if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' }} + run: cp unit.txt unit-base.txt + - name: Comment Test Coverage + if: matrix.go-version == '1.16.x' + uses: marocchino/sticky-pull-request-comment@v2 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + header: unit-test + message: | + ### Unit Test Coverage + ${{ steps.test.outputs.total }} +
Coverage diff with base branch + + ```diff + ${{ steps.test.outputs.diff }} + ``` +
+ + - name: Upload code coverage + if: matrix.go-version == '1.16.x' + uses: codecov/codecov-action@v1 + with: + file: ./unit.coverprofile + flags: unittests diff --git a/.golangci.yml b/.golangci.yml index 29af06a..4e30af6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -26,6 +26,7 @@ linters: - goerr113 - wrapcheck - exhaustivestruct + - cyclop issues: exclude-use-default: false diff --git a/Makefile b/Makefile index 664b505..527347c 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ endif -include $(DEVGO_PATH)/makefiles/main.mk -include $(DEVGO_PATH)/makefiles/test-unit.mk -include $(DEVGO_PATH)/makefiles/lint.mk +-include $(DEVGO_PATH)/makefiles/bench.mk -include $(DEVGO_PATH)/makefiles/github-actions.mk ## Run tests diff --git a/README.md b/README.md index c9fd569..5488dc1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # statigz - +[![Build Status](https://github.com/vearutop/statigz/workflows/test-unit/badge.svg)](https://github.com/vearutop/statigz/actions?query=branch%3Amaster+workflow%3Atest-unit) +[![Coverage Status](https://codecov.io/gh/vearutop/statigz/branch/master/graph/badge.svg)](https://codecov.io/gh/vearutop/statigz) [![GoDevDoc](https://img.shields.io/badge/dev-doc-00ADD8?logo=go)](https://pkg.go.dev/github.com/vearutop/statigz) [![Time Tracker](https://wakatime.com/badge/github/vearutop/statigz.svg)](https://wakatime.com/badge/github/vearutop/statigz) ![Code lines](https://sloc.xyz/github/vearutop/statigz/?category=code) diff --git a/go.mod b/go.mod index 264f015..fe75bc3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/andybalholm/brotli v1.0.1 - github.com/bool64/dev v0.1.13 + github.com/bool64/dev v0.1.18 github.com/davecgh/go-spew v1.1.1 // indirect github.com/stretchr/testify v1.7.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..aa3408a --- /dev/null +++ b/go.sum @@ -0,0 +1,19 @@ +github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= +github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/bool64/dev v0.1.18 h1:uMN5MsHrVWmtRoauefI8wD86b8vbXYnrCZlIhFGyuXI= +github.com/bool64/dev v0.1.18/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server_test.go b/server_test.go index f4e6c65..e3f388f 100644 --- a/server_test.go +++ b/server_test.go @@ -150,6 +150,23 @@ func TestServer_ServeHTTP_head_gz(t *testing.T) { assert.Len(t, rw.Body.String(), 0) } +func BenchmarkServer_ServeHTTP(b *testing.B) { + s := statigz.FileServer(v, statigz.EncodeOnInit) + + req, err := http.NewRequest(http.MethodGet, "/_testdata/swagger.json", nil) + require.NoError(b, err) + + req.Header.Set("Accept-Encoding", "gzip, br") + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + rw := httptest.NewRecorder() + s.ServeHTTP(rw, req) + } +} + func TestServer_ServeHTTP_get_gz(t *testing.T) { s := statigz.FileServer(v, statigz.EncodeOnInit)