From b8a4e07d728bddb36b6f9e0ffea4688194e443b7 Mon Sep 17 00:00:00 2001 From: HIMANSHU Date: Tue, 26 Mar 2024 17:01:03 +0530 Subject: [PATCH] Keploy Integration in CI --- .github/workflows/go-template-ci.yml | 2 + .gitignore | 1 + Dockerfile | 2 +- docker-compose.yml | 14 +++++- go.mod | 3 +- go.sum | 9 ++-- keploy-config.yaml | 72 ++++++++++++++++++++++++++++ pkg/api/api.go | 2 + scripts/keploy_ci.sh | 27 +++++++++++ 9 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 keploy-config.yaml create mode 100644 scripts/keploy_ci.sh diff --git a/.github/workflows/go-template-ci.yml b/.github/workflows/go-template-ci.yml index 3d30473c..fea5925f 100644 --- a/.github/workflows/go-template-ci.yml +++ b/.github/workflows/go-template-ci.yml @@ -36,6 +36,8 @@ jobs: run: go build ./... - name: Test run: ./scripts/test.sh + - name: Keploy test + run: chmod +x ./scripts/keploy_ci.sh && ./scripts/keploy_ci.sh # - uses: codecov/codecov-action@v2 # with: # token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 55042779..84e82d6a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ profile.out coverage.out output cmd/seeder/exec/build +keploy-logs.txt \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9940e7c9..b82d2060 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ RUN GOARCH=amd64 \ RUN go run ./cmd/seeder/main.go -RUN go build -o ./output/server ./cmd/server/main.go +RUN go build -cover -o ./output/server ./cmd/server/main.go RUN go build -o ./output/migrations ./cmd/migrations/main.go RUN go build -o ./output/seeder ./cmd/seeder/exec/seed.go diff --git a/docker-compose.yml b/docker-compose.yml index 3e32c5d7..1a73ce27 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,21 +12,28 @@ services: - POSTGRES_PASSWORD=${PSQL_PASS} - POSTGRES_PORT=${PSQL_PORT} - POSTGRES_DB=${PSQL_DBNAME} + networks: + - go-template-network depends_on: - redis redis: image: redis:6-alpine restart: always + networks: + - go-template-network wait-for-db: image: atkrad/wait4x depends_on: - db command: tcp db:${PSQL_PORT} -t 30s -i 250ms + networks: + - go-template-network app: build: . + container_name: go-template-app restart: always env_file: - ./.env.${ENVIRONMENT_NAME} @@ -36,4 +43,9 @@ services: ports: - ${SERVER_PORT}:${SERVER_PORT} environment: - ENVIRONMENT_NAME: ${ENVIRONMENT_NAME} \ No newline at end of file + ENVIRONMENT_NAME: ${ENVIRONMENT_NAME} + networks: + - go-template-network +networks: + go-template-network: + external: false \ No newline at end of file diff --git a/go.mod b/go.mod index c8be99bf..41b22441 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.8.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.8.0 go.opentelemetry.io/otel/sdk v1.8.0 - go.uber.org/zap v1.21.0 + go.uber.org/zap v1.22.0 golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e google.golang.org/grpc v1.46.2 @@ -76,6 +76,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pelletier/go-toml v1.9.4 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect diff --git a/go.sum b/go.sum index 0d281eb1..ea914e3c 100644 --- a/go.sum +++ b/go.sum @@ -80,7 +80,6 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -444,8 +443,9 @@ github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhEC github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -612,7 +612,6 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -621,8 +620,8 @@ go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/keploy-config.yaml b/keploy-config.yaml new file mode 100644 index 00000000..4c087cc9 --- /dev/null +++ b/keploy-config.yaml @@ -0,0 +1,72 @@ +test: + path: "" + # mandatory + command: "./main" + proxyport: 0 + containerName: "" + networkName: "" + # example: "test-set-1": ["test-1", "test-2", "test-3"] + selectedTests: + # to use globalNoise, please follow the guide at the end of this file. + globalNoise: + global: + body: {} + header: {"X-Request-Id":[]} + delay: 5 + buildDelay: 30s + apiTimeout: 5 + ignoreOrdering: false + stubs: + filters: + - path: "" + host: "" + ports: 0 + withCoverage: true + generateTestReport: true + coverageReportPath: "" + +# Example on using tests +#tests: +# filters: +# - path: "/user/app" +# urlMethods: ["GET"] +# headers: { +# "^asdf*": "^test" +# } +# host: "dc.services.visualstudio.com" +#Example on using stubs +#stubs: +# filters: +# - path: "/user/app" +# port: 8080 +# - port: 8081 +# - host: "dc.services.visualstudio.com" +# - port: 8081 +# host: "dc.services.visualstudio.com" +# path: "/user/app" + # +#Example on using globalNoise +#globalNoise: +# global: +# body: { +# # to ignore some values for a field, +# # pass regex patterns to the corresponding array value +# "url": ["https?://\S+", "http://\S+"], +# } +# header: { +# # to ignore the entire field, pass an empty array +# "Date": [], +# } +# # to ignore fields or the corresponding values for a specific test-set, +# # pass the test-set-name as a key to the "test-sets" object and +# # populate the corresponding "body" and "header" objects +# test-sets: +# test-set-1: +# body: { +# # ignore all the values for the "url" field +# "url": [] +# } +# header: { +# # we can also pass the exact value to ignore for a field +# "User-Agent": ["PostmanRuntime/7.34.0"] +# } \ No newline at end of file diff --git a/pkg/api/api.go b/pkg/api/api.go index 2a4a8412..c28f4431 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -23,6 +23,7 @@ import ( "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/playground" "github.com/gorilla/websocket" + "github.com/keploy/go-sdk/v2/keploy" "github.com/labstack/echo/v4" _ "github.com/lib/pq" // here @@ -111,6 +112,7 @@ func Start(cfg *config.Configuration) (*echo.Echo, error) { playgroundHandler.ServeHTTP(res, req) return nil }) + keploy.GracefulShutdown() server.Start(e, &server.Config{ Port: cfg.Server.Port, ReadTimeoutSeconds: cfg.Server.ReadTimeout, diff --git a/scripts/keploy_ci.sh b/scripts/keploy_ci.sh new file mode 100644 index 00000000..0c245957 --- /dev/null +++ b/scripts/keploy_ci.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Download and install keploy +curl --silent --location "https://github.com/keploy/keploy/releases/latest/download/keploy_linux_amd64.tar.gz" | tar xz -C /tmp +sudo mkdir -p /usr/local/bin && sudo mv /tmp/keploy /usr/local/bin && keploy + +# Build the Go server +go build -cover -o main ./cmd/server/main.go + +# Run tests with keploy +sudo -E keploy test -c "./main" --withCoverage --delay 10 + +# Generate coverage profile +go tool covdata textfmt -i="./keploy/coverage-reports" -o coverage-profile + +# Check coverage against threshold +coverage_percentage=$(go tool cover -func=coverage-profile | grep 'total' | tail -n 1 | awk '{print $3}') +coverage_percentage=${coverage_percentage%\%} # Remove the percentage sign +threshold=80 +echo "Required threshold: ${threshold}%" +if (( $(awk -v num="$coverage_percentage" -v thresh="$threshold" 'BEGIN { if (num < thresh) print 1; else print 0 }') )); then + echo "Coverage below threshold: $coverage_percentage%" + exit 1 +else + echo "Coverage meets threshold: $coverage_percentage" +fi +