Skip to content

Commit

Permalink
use newer CI actions (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
torcolvin authored Oct 14, 2024
1 parent 3490e96 commit 73db215
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 96 deletions.
58 changes: 44 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ jobs:
name: addlicense
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.21.3
go-version: 1.22.8
- run: go install github.com/google/addlicense@latest
- uses: actions/checkout@v3
- run: addlicense -check -f licenses/addlicense.tmpl .

test:
Expand All @@ -41,10 +40,10 @@ jobs:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.21.3
go-version: 1.22.8
- name: Build
run: go build -v "./..."
- name: Run Tests
Expand All @@ -61,24 +60,55 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v6
with:
version: v1.52.0
version: v1.61.0

test-race:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.21.3
go-version: 1.22.8
- name: Run Tests
run: go test -race -timeout=30m -count=1 -json -v "./..." | tee test.json | jq -s -jr 'sort_by(.Package,.Time) | .[].Output | select (. != null )'
shell: bash
- name: Annotate Failures
if: always()
uses: guyarb/golang-test-annotations@v0.6.0
uses: guyarb/golang-test-annotations@v0.8.0
with:
test-results: test.json
example-build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.22.8
- name: Build
run: cd example && go build -v "./..."
permissions:
# Required: allow read access to the content for analysis.
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
pull-requests: read
# Optional: allow write access to checks to allow the action to annotate code in the PR.
checks: write
example-golangci:
name: example-lint
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.61.0
working-directory: example
6 changes: 0 additions & 6 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,21 @@ linters:
- gocyclo # Computes and checks the cyclomatic complexity of functions
- godot # Check if comments end in a period
- godox # Tool for detection of FIXME, TODO and other comment keywords
- goerr113 # Golang linter to check the errors handling expressions
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
- gomnd # An analyzer to detect magic numbers.
- gomodguard # Allow and block list linter for direct Go module dependencies.
- interfacer # Linter that suggests narrower interface types
- lll # Reports long lines
- misspell # Finds commonly misspelled English words in comments
- nestif # Reports deeply nested if statements
- nolintlint # Reports ill-formed or insufficient nolint directives
- rowserrcheck # checks whether Err of rows is checked successfully
- scopelint # Scopelint checks for unpinned variables in go programs
- stylecheck # Stylecheck is a replacement for golint
- testpackage # linter that makes you use a separate _test package
- unused # (megacheck) Checks Go code for unused constants, variables, functions and types
- whitespace # Tool for detection of leading and trailing whitespace
- wsl # Whitespace Linter - Forces you to use empty lines!
# Once fixed, should enable
- bodyclose # checks whether HTTP response body is closed successfully
- deadcode # Finds unused code
- dupl # Tool for code clone detection
- goconst # Finds repeated strings that could be replaced by a constant
- gocritic # The most opinionated Go source code linter
Expand All @@ -69,10 +65,8 @@ linters:
- nakedret # Finds naked returns in functions greater than a specified function length
- prealloc # Finds slice declarations that could potentially be preallocated
- revive # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
- structcheck # Finds unused struct fields
- unconvert # Remove unnecessary type conversions
- unparam # Reports unused function parameters
- varcheck # Finds unused global variables and constants

# Don't enable fieldalignment, changing the field alignment requires checking to see if anyone uses constructors
# without names. If there is a memory issue on a specific field, that is best found with a heap profile.
Expand Down
14 changes: 14 additions & 0 deletions dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2024-Present Couchbase, Inc.
#
# Use of this software is governed by the Business Source License included
# in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
# in that file, in accordance with the Business Source License, use of this
# software will be governed by the Apache License, Version 2.0, included in
# the file licenses/APL2.txt.

version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
13 changes: 8 additions & 5 deletions example/cmd/responder.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ package cmd

import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"runtime"
Expand Down Expand Up @@ -51,7 +51,7 @@ func responder() {
runtime.GOMAXPROCS(maxProcs)
log.Printf("Set GOMAXPROCS to %d", maxProcs)

context, err := blip.NewContext(BlipExampleAppProtocolId)
context, err := blip.NewContext(blip.ContextOptions{ProtocolIds: []string{BlipExampleAppProtocolId}})
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -89,10 +89,10 @@ func dispatchEcho(request *blip.Message) {
}

func httpEcho(r http.ResponseWriter, request *http.Request) {
body, err := ioutil.ReadAll(request.Body)
body, err := io.ReadAll(request.Body)
log.Printf("Got HTTP %s %s (%d bytes)", request.Method, request.RequestURI, len(body))
if err != nil {
log.Printf("ERROR reading body of %s: %s", request, err)
log.Printf("ERROR reading body of %+v: %s", request, err)
return
}
if len(body) == 0 {
Expand All @@ -109,5 +109,8 @@ func httpEcho(r http.ResponseWriter, request *http.Request) {

r.Header().Add("Content-Type", "application/octet-stream")
r.WriteHeader(201)
r.Write(body)
_, err = r.Write(body)
if err != nil {
log.Printf("ERROR writing response: %s", err)
}
}
4 changes: 2 additions & 2 deletions example/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import "github.com/spf13/cobra"
var RootCmd = &cobra.Command{
Use: "goblip",
Short: "go-blip examples",
Long: `go-blip examples`,
Long: `go-blip examples`,
Run: func(cmd *cobra.Command, args []string) {
// Do Stuff Here
},
}
}
14 changes: 11 additions & 3 deletions example/cmd/sendtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func sender() {
runtime.GOMAXPROCS(maxProcs)
log.Printf("Set GOMAXPROCS to %d", maxProcs)

context, err := blip.NewContext(BlipExampleAppProtocolId)
context, err := blip.NewContext(blip.ContextOptions{ProtocolIds: []string{BlipExampleAppProtocolId}})
if err != nil {
panic(err)
}
Expand All @@ -83,14 +83,22 @@ func sender() {
if err != nil {
log.Fatal(err)
}
defer pprof.WriteHeapProfile(f)
defer func() {
err := pprof.WriteHeapProfile(f)
if err != nil {
log.Fatalf("Error writing heap profile: %s", err)
}
}()
} else if profilingCPU {
log.Printf("Writing profile to file cpu.pprof")
f, err := os.Create("cpu.pprof")
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
err = pprof.StartCPUProfile(f)
if err != nil {
log.Fatalf("Error starting CPU profile: %s", err)
}
defer pprof.StopCPUProfile()
}

Expand Down
4 changes: 2 additions & 2 deletions example/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ require (

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/klauspost/compress v1.10.3 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/spf13/pflag v1.0.5 // indirect
nhooyr.io/websocket v1.8.7 // indirect
nhooyr.io/websocket v1.8.10 // indirect
)

replace github.com/couchbase/go-blip => ../
66 changes: 7 additions & 59 deletions example/go.sum
Original file line number Diff line number Diff line change
@@ -1,72 +1,20 @@
github.com/couchbaselabs/go.assert v0.0.0-20130325201400-cfb33e3a0dac h1:E8RCOlhM2LnVvZmt08UjaLiMPKPWfH++y6//Z3Crm8E=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
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.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
1 change: 1 addition & 0 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ package main
import (
"fmt"
"os"

"github.com/couchbase/go-blip/example/cmd"
)

Expand Down
5 changes: 2 additions & 3 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"runtime/debug"
"sync"
Expand Down Expand Up @@ -181,7 +180,7 @@ func (m *Message) Body() ([]byte, error) {
if m.readingBody {
panic("Already reading body as a stream")
}
body, err := ioutil.ReadAll(m.reader)
body, err := io.ReadAll(m.reader)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -351,7 +350,7 @@ func (m *Message) ReadFrom(reader io.Reader) error {
return err
}
var err error
m.body, err = ioutil.ReadAll(reader)
m.body, err = io.ReadAll(reader)
return err
}

Expand Down
4 changes: 2 additions & 2 deletions messagequeue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ package blip

import (
"bytes"
"io/ioutil"
"io"
"log"
"sync"
"testing"
Expand Down Expand Up @@ -157,7 +157,7 @@ func TestUrgentMessageOrdering(t *testing.T) { // Test passes, but some assertio
assert.False(t, mq.nextMessageIsUrgent())

// set the msg.encoder to something so that the next urgent message will go to the head of the line
msg.encoder = ioutil.NopCloser(&bytes.Buffer{})
msg.encoder = io.NopCloser(&bytes.Buffer{})

}

Expand Down

0 comments on commit 73db215

Please sign in to comment.