diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 13b0063..406131e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: uses: golangci/golangci-lint-action@v2 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.56.0 + version: v1.57.2 # Optional: show only new issues if it's a pull request. The default value is `false`. only-new-issues: true # Run build of the application diff --git a/.goreleaser.yml b/.goreleaser.yml index 0eb1438..f4770f4 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,6 +1,6 @@ builds: - id: gorp - main: ./cmd/gorp + main: ./ binary: gorp env: - CGO_ENABLED=0 diff --git a/Makefile b/Makefile index 1a165e8..00bb397 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ help: @echo "checkstyle - gofmt+golint+misspell" init-deps: - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.56.0 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.57.2 #vendor: # dep ensure --vendor-only @@ -24,7 +24,7 @@ test: $(GO) test -cover ${GODIRS_NOVENDOR} lint: - bin/golangci-lint run --deadline 10m ./... + bin/golangci-lint run ./... fmt: gofumpt -extra -l -w ${GOFILES_NOVENDOR} @@ -32,7 +32,7 @@ fmt: #build: checkstyle test build: - $(GO) build ${BUILD_INFO_LDFLAGS} -o ${BINARY_DIR}/gorp ./cmd/gorp + $(GO) build ${BUILD_INFO_LDFLAGS} -o ${BINARY_DIR}/gorp ./ cross-build: gox ${BUILD_INFO_LDFLAGS} -arch="amd64 arm64" -os="linux windows darwin" -output="dist/{{.Dir}}_{{.OS}}_{{.Arch}}" ./cmd/gorp diff --git a/go.mod b/go.mod index 492e4bc..9f53993 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,13 @@ module github.com/reportportal/goRP/v5 -go 1.18 +go 1.21 require ( - github.com/go-resty/resty/v2 v2.11.0 + github.com/go-resty/resty/v2 v2.12.0 github.com/google/uuid v1.6.0 github.com/manifoldco/promptui v0.9.0 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.1 - go.uber.org/zap v1.27.0 ) require ( @@ -18,8 +17,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 30900b6..d4acd3d 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -8,20 +7,12 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -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/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/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= -github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA= +github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= @@ -30,74 +21,56 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/internal/commands/commands.go b/internal/commands/commands.go index e8c13e3..29cade3 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -3,12 +3,12 @@ package commands import ( "encoding/json" "fmt" + "log/slog" "net/url" "os" "github.com/manifoldco/promptui" "github.com/urfave/cli/v2" - "go.uber.org/zap" "github.com/reportportal/goRP/v5/pkg/gorp" ) @@ -49,14 +49,13 @@ func initConfiguration(c *cli.Context) error { } } - //nolint:nosnakecase // sdk uppercase constants f, err := os.OpenFile(getConfigFile(), os.O_CREATE|os.O_WRONLY, 0o600) if err != nil { return cli.Exit(fmt.Sprintf("Cannot open config file, %s", err), 1) } defer func() { if closeErr := f.Close(); closeErr != nil { - zap.S().Error(closeErr) + slog.Default().Error(closeErr.Error()) } }() diff --git a/internal/commands/report.go b/internal/commands/report.go index 93fd558..961a53d 100644 --- a/internal/commands/report.go +++ b/internal/commands/report.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "os" "path/filepath" "strings" @@ -12,7 +13,6 @@ import ( "time" "github.com/urfave/cli/v2" - "go.uber.org/zap" gorp2 "github.com/reportportal/goRP/v5/pkg/gorp" ) @@ -53,7 +53,8 @@ var ( } ) -func reportTest2json(c *cli.Context) error { +//nolint:nonamedreturns // for readability +func reportTest2json(c *cli.Context) (err error) { rpClient, err := buildClient(c) if err != nil { return err @@ -69,8 +70,9 @@ func reportTest2json(c *cli.Context) error { wg.Add(1) go func() { defer wg.Done() - rep.receive() + err = rep.receive() }() + // wait for report to complete defer wg.Wait() defer close(input) @@ -83,7 +85,7 @@ func reportTest2json(c *cli.Context) error { } defer func() { if cErr := f.Close(); cErr != nil { - zap.S().Error(cErr) + slog.Error(cErr.Error()) } }() reader = f @@ -97,7 +99,7 @@ func reportTest2json(c *cli.Context) error { var ev testEvent if err := json.Unmarshal([]byte(data), &ev); err != nil { - zap.S().Error(err) + slog.Default().Error(err.Error()) return err } input <- &ev @@ -158,42 +160,61 @@ func newReporter(client *gorp2.Client, launchName string, input <-chan *testEven } } -func (r *reporter) receive() { +func (r *reporter) reportEvent(ev *testEvent) error { + var err error + switch ev.Action { + case "run": + _, err = r.startTest(ev) + case "output": + r.log(ev) + case "pass": + err = r.finish(ev, gorp2.Statuses.Passed) + case "fail": + err = r.finish(ev, gorp2.Statuses.Failed) + } + return err +} + +func (r *reporter) receive() error { prevEventTime := time.Now() for ev := range r.input { var err error startTime := ev.Time + + // start launch once + // when first event comes r.launchOnce.Do(func() { if err = r.startLaunch(startTime); err != nil { - zap.S().Error(err) + slog.Error(err.Error()) } }) - - switch ev.Action { - case "run": - _, err = r.startTest(ev) - case "output": - r.log(ev) - case "pass": - err = r.finish(ev, gorp2.Statuses.Passed) - case "fail": - err = r.finish(ev, gorp2.Statuses.Failed) + if err != nil { + return err } + + // report event to ReportPortal + err = r.reportEvent(ev) if err != nil { - zap.S().Fatal(err) + return err } + + // remember last's event time + // for RP's finishLaunch prevEventTime = ev.Time } + // make sure we flush all logs that are left r.flushLogs(true) // wait for requests to get sent r.waitQueue.Wait() + // finish launch of started if r.launchID != "" { if err := r.finishLaunch(gorp2.Statuses.Passed, prevEventTime); err != nil { - zap.S().Fatal(err) + return err } } + return nil } func (r *reporter) startSuite(ev *testEvent) (string, error) { @@ -278,7 +299,7 @@ func (r *reporter) flushLogs(force bool) { defer r.waitQueue.Done() if _, err := r.client.SaveLogs(logs...); err != nil { - zap.S().Errorf("unable to report logs: %v. Batch len: %d", err, len(logs)) + slog.Error("unable to report logs", "error", err, "batch_length", len(logs)) } }(batch) r.logs = []*gorp2.SaveLogRQ{} diff --git a/cmd/gorp/main.go b/main.go similarity index 86% rename from cmd/gorp/main.go rename to main.go index 2e7e3fd..43fb1e7 100644 --- a/cmd/gorp/main.go +++ b/main.go @@ -3,10 +3,10 @@ package main import ( "fmt" "log" + "log/slog" "os" "github.com/urfave/cli/v2" - "go.uber.org/zap" rp "github.com/reportportal/goRP/v5/internal/commands" ) @@ -17,11 +17,12 @@ var ( ) func main() { - logger, _ := zap.NewProduction() - zap.ReplaceGlobals(logger) - defer func() { - _ = logger.Sync() - }() + slog.SetDefault(slog.New( + slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ + Level: slog.LevelError, + AddSource: true, + }), + )) app := cli.NewApp() app.Name = "goRP" diff --git a/pkg/gorp/client.go b/pkg/gorp/client.go index 0b15fc1..2cb6423 100644 --- a/pkg/gorp/client.go +++ b/pkg/gorp/client.go @@ -3,10 +3,8 @@ package gorp import ( "bytes" "encoding/json" + "errors" "fmt" - "mime" - "os" - "path/filepath" "time" "github.com/go-resty/resty/v2" @@ -21,12 +19,12 @@ type Client struct { // NewClient creates new instance of Client // host - server hostname // project - name of the project -// uuid - User Token (see user profile page) -func NewClient(host, project, uuid string) *Client { +// apiKey - User Token (see user profile page) +func NewClient(host, project, apiKey string) *Client { http := resty.New(). // SetDebug(true). SetBaseURL(host). - SetAuthToken(uuid). + SetAuthToken(apiKey). OnAfterResponse(func(client *resty.Client, rs *resty.Response) error { //nolint:gomnd // 4xx errors if (rs.StatusCode() / 100) >= 4 { @@ -181,7 +179,7 @@ func (c *Client) finishTest(id string, body interface{}) (*MsgRS, error) { // SaveLog attaches log in RP func (c *Client) SaveLog(log *SaveLogRQ) (*EntryCreatedRS, error) { var rs EntryCreatedRS - _, err := c.http.SetDebug(true).R(). + _, err := c.http.R(). SetPathParams(map[string]string{ "project": c.project, }). @@ -219,7 +217,7 @@ func (c *Client) SaveLogs(logs ...*SaveLogRQ) (*EntryCreatedRS, error) { // } // // resp, err := client.SaveLogMultipart(log, files) -func (c *Client) SaveLogMultipart(log []*SaveLogRQ, files map[string]*os.File) (*EntryCreatedRS, error) { +func (c *Client) SaveLogMultipart(log []*SaveLogRQ, files []Multipart) (*EntryCreatedRS, error) { var bodyBuf bytes.Buffer err := json.NewEncoder(&bodyBuf).Encode(log) if err != nil { @@ -235,18 +233,16 @@ func (c *Client) SaveLogMultipart(log []*SaveLogRQ, files map[string]*os.File) ( rq.SetMultipartField("json_request_part", "", "application/json", &bodyBuf) // BINARY PART - for k, v := range files { - if v == nil { - return nil, fmt.Errorf("no file for [%s] is provided", k) - } - if _, sErr := os.Stat(v.Name()); os.IsNotExist(sErr) { - return nil, fmt.Errorf("file %s does not exist", v.Name()) + for _, v := range files { + fileName, contentType, reader, lErr := v.Load() + if lErr != nil { + return nil, fmt.Errorf("unable to read multipart: %w", lErr) } - mimeType := mime.TypeByExtension(filepath.Ext(k)) - if mimeType == "" { - mimeType = "application/octet-stream" + if fileName == "" { + return nil, errors.New("no file name is provided") } - rq.SetMultipartField("file", k, mimeType, v) + + rq.SetMultipartField("file", fileName, contentType, reader) } var rs EntryCreatedRS diff --git a/pkg/gorp/example_test.go b/pkg/gorp/example_test.go index 993201e..7e3cb33 100644 --- a/pkg/gorp/example_test.go +++ b/pkg/gorp/example_test.go @@ -3,15 +3,14 @@ package gorp import ( "log" "os" - "path/filepath" "time" "github.com/google/uuid" ) func ExampleClient() { - client := NewClient("", - "", "") + client := NewClient("https://reportportal.epam.com", + "andrei_varabyeu_personal", "gorp-test_MCQZajD8S_ClBSGo-Q6X7KtzBKjFGiw0PPf6oB0-nexU1MSRMMcO_4_Sn4YGTBtk") launchUUID := uuid.New() launch, err := client.StartLaunch(&StartLaunchRQ{ @@ -49,15 +48,18 @@ func ExampleClient() { }) checkErr(err, "unable to save log") - file1, _ := os.Open("../go.mod") - file2, _ := os.Open("../go.sum") + file1, err := os.Open("../../go.mod") + checkErr(err, "unable to read file") + file2, err := os.Open("../../go.sum") + checkErr(err, "unable to read file") + _, err = client.SaveLogMultipart([]*SaveLogRQ{ { LaunchUUID: launchUUID.String(), ItemID: testUUID.String(), Level: LogLevelInfo, Message: "Log with binary one", - Attachment: FileAttachment{ + Attachment: Attachment{ Name: "go.mod", }, }, @@ -66,13 +68,13 @@ func ExampleClient() { ItemID: testUUID.String(), Level: LogLevelInfo, Message: "Log with binary two", - Attachment: FileAttachment{ + Attachment: Attachment{ Name: "go.sum", }, }, - }, map[string]*os.File{ - filepath.Base(file1.Name()): file1, - filepath.Base(file2.Name()): file2, + }, []Multipart{ + &FileMultipart{File: file1}, + &ReaderMultipart{ContentType: "text/plain", FileName: file2.Name(), Reader: file2}, }) checkErr(err, "unable to save log multipart") @@ -91,6 +93,8 @@ func ExampleClient() { EndTime: Timestamp{time.Now()}, }) checkErr(err, "unable to finish launch") + + // Output: } func checkErr(err error, msg string) { diff --git a/pkg/gorp/model_reporting.go b/pkg/gorp/model_reporting.go index 990f07c..f64f25b 100644 --- a/pkg/gorp/model_reporting.go +++ b/pkg/gorp/model_reporting.go @@ -28,12 +28,12 @@ type ( // SaveLogRQ payload representation. SaveLogRQ struct { - LaunchUUID string `json:"launchUuid,omitempty"` - ItemID string `json:"itemUuid,omitempty"` - LogTime Timestamp `json:"time,omitempty"` - Message string `json:"message,omitempty"` - Level string `json:"level,omitempty"` - Attachment FileAttachment `json:"file,omitempty"` + LaunchUUID string `json:"launchUuid,omitempty"` + ItemID string `json:"itemUuid,omitempty"` + LogTime Timestamp `json:"time,omitempty"` + Message string `json:"message,omitempty"` + Level string `json:"level,omitempty"` + Attachment Attachment `json:"file,omitempty"` } // StartTestRQ payload representation @@ -104,8 +104,8 @@ type ( time.Time } - // FileAttachment represents file attachment in log entries - FileAttachment struct { + // Attachment represents file attachment in log entries + Attachment struct { Name string `json:"name,omitempty"` } ) diff --git a/pkg/gorp/multipart.go b/pkg/gorp/multipart.go new file mode 100644 index 0000000..1c37fcf --- /dev/null +++ b/pkg/gorp/multipart.go @@ -0,0 +1,52 @@ +package gorp + +import ( + "errors" + "fmt" + "io" + "mime" + "os" + "path/filepath" +) + +// Multipart is an interface that allows to pass over different types +// of multipart data sources +type Multipart interface { + // Load loads multipart data + Load() (fileName, contentType string, reader io.Reader, err error) +} + +// FileMultipart is a multipart content in form of file +type FileMultipart struct { + *os.File +} + +//nolint:nonamedreturns // for readability +func (fm *FileMultipart) Load() (fileName, contentType string, reader io.Reader, err error) { + if fm.File == nil { + return "", "", nil, errors.New("file shouldn't be nil") + } + fName := fm.File.Name() + if _, sErr := os.Stat(fName); os.IsNotExist(sErr) { + return "", "", nil, fmt.Errorf("file %s does not exist", fName) + } + contentType = mime.TypeByExtension(filepath.Ext(fName)) + if contentType == "" { + contentType = "application/octet-stream" + } + return filepath.Base(fName), contentType, fm.File, nil +} + +// ReaderMultipart is a multipart content in form of io.Reader +type ReaderMultipart struct { + FileName, ContentType string + io.Reader +} + +//nolint:nonamedreturns // for readability +func (fm *ReaderMultipart) Load() (fileName, contentType string, reader io.Reader, err error) { + if fm.FileName == "" { + return "", "", nil, errors.New("multipart filename shouldn't be nil") + } + return fm.FileName, fm.ContentType, fm, nil +}