Skip to content

Commit

Permalink
Add e2e tests (k6) and improve the CI (#588)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarampampam authored Nov 5, 2024
1 parent 2e0b0d2 commit 72ef89e
Show file tree
Hide file tree
Showing 16 changed files with 620 additions and 29 deletions.
33 changes: 28 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@ jobs:
- uses: actions/checkout@v4
- {uses: gacts/github-slug@v1, id: slug}
- id: values
run: echo "binary-name=webhook-tester-${{ matrix.os }}-${{ matrix.arch }}`[ ${{ matrix.os }} = 'windows' ] && echo '.exe'`" >> $GITHUB_OUTPUT
run: |
majorMinorPatch="${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}.${{ steps.slug.outputs.version-patch }}"
echo "version=${majorMinorPatch}" >> $GITHUB_OUTPUT
echo "binary-name=webhook-tester-${{ matrix.os }}-${{ matrix.arch }}`[ ${{ matrix.os }} = 'windows' ] && echo '.exe'`" >> $GITHUB_OUTPUT
echo "deb-name=webhook-tester_${majorMinorPatch}-1_${{ matrix.arch }}" >> $GITHUB_OUTPUT
# build the frontend
- uses: actions/setup-node@v4
with: {node-version: 22, cache: 'npm', cache-dependency-path: ./web/package-lock.json}
- run: npm --prefix "$NPM_PREFIX" install --no-audit
- run: npm --prefix "$NPM_PREFIX" run generate
- run: npm --prefix "$NPM_PREFIX" run build
with: {node-version-file: ./web/package.json, cache: 'npm', cache-dependency-path: ./web/package-lock.json}
- run: |
npm --prefix "$NPM_PREFIX" install --no-audit
npm --prefix "$NPM_PREFIX" run generate
npm --prefix "$NPM_PREFIX" run build
# build the backend
- {uses: actions/setup-go@v5, with: {go-version-file: go.mod}}
- run: go install "github.com/oapi-codegen/oapi-codegen/v2/cmd/[email protected]"
Expand All @@ -45,6 +50,24 @@ jobs:
file: ${{ steps.values.outputs.binary-name }}
asset_name: ${{ steps.values.outputs.binary-name }}
tag: ${{ github.ref }}
# build a Debian package
- if: matrix.os == 'linux' && matrix.arch == 'amd64'
env:
PKG_NAME: ${{ steps.values.outputs.deb-name }}
run: |
mkdir -p ${{ env.PKG_NAME }}/usr/local/bin ${{ env.PKG_NAME }}/DEBIAN
cp ${{ steps.values.outputs.binary-name }} ${{ env.PKG_NAME }}/usr/local/bin/webhook-tester
echo -e "Package: webhook-tester\nVersion: ${{ steps.values.outputs.version }}" > ${{ env.PKG_NAME }}/DEBIAN/control
echo -e "Architecture: ${{ matrix.arch }}\nMaintainer: ${{ github.actor }}" >> ${{ env.PKG_NAME }}/DEBIAN/control
echo -e "Description: Powerful tool for testing WebHooks and more" >> ${{ env.PKG_NAME }}/DEBIAN/control
dpkg-deb --build --root-owner-group ${{ env.PKG_NAME }}
- if: matrix.os == 'linux' && matrix.arch == 'amd64'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.values.outputs.deb-name }}.deb
asset_name: ${{ steps.values.outputs.binary-name }}.deb
tag: ${{ github.ref }}

build-docker-image:
name: Build the docker image
Expand Down
69 changes: 60 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: {node-version: 22, cache: 'npm', cache-dependency-path: ./web/package-lock.json}
with: {node-version-file: ./web/package.json, cache: 'npm', cache-dependency-path: ./web/package-lock.json}
- run: npm --prefix "$NPM_PREFIX" install -dd --no-audit
- run: npm --prefix "$NPM_PREFIX" run generate
- run: npm --prefix "$NPM_PREFIX" run lint
Expand All @@ -63,13 +63,18 @@ jobs:
- uses: actions/checkout@v4
- {uses: gacts/github-slug@v1, id: slug}
- id: values
run: echo "binary-name=webhook-tester-${{ matrix.os }}-${{ matrix.arch }}`[ ${{ matrix.os }} = 'windows' ] && echo '.exe'`" >> $GITHUB_OUTPUT
run: |
majorMinorPatch="${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}.${{ steps.slug.outputs.version-patch }}"
echo "version=${majorMinorPatch}" >> $GITHUB_OUTPUT
echo "binary-name=webhook-tester-${{ matrix.os }}-${{ matrix.arch }}`[ ${{ matrix.os }} = 'windows' ] && echo '.exe'`" >> $GITHUB_OUTPUT
echo "deb-name=webhook-tester_${majorMinorPatch}-1_${{ matrix.arch }}" >> $GITHUB_OUTPUT
# build the frontend
- uses: actions/setup-node@v4
with: {node-version: 22, cache: 'npm', cache-dependency-path: ./web/package-lock.json}
- run: npm --prefix "$NPM_PREFIX" install --no-audit
- run: npm --prefix "$NPM_PREFIX" run generate
- run: npm --prefix "$NPM_PREFIX" run build
with: {node-version-file: ./web/package.json, cache: 'npm', cache-dependency-path: ./web/package-lock.json}
- run: |
npm --prefix "$NPM_PREFIX" install --no-audit
npm --prefix "$NPM_PREFIX" run generate
npm --prefix "$NPM_PREFIX" run build
# build the backend
- {uses: actions/setup-go@v5, with: {go-version-file: go.mod}}
- run: go install "github.com/oapi-codegen/oapi-codegen/v2/cmd/[email protected]"
Expand All @@ -78,17 +83,63 @@ jobs:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
CGO_ENABLED: 0
LDFLAGS: -s -w -X gh.tarampamp.am/webhook-tester/v2/internal/version.version=v0.0.0@${{ steps.slug.outputs.commit-hash-short }}
LDFLAGS: -s -w -X gh.tarampamp.am/webhook-tester/v2/internal/version.version=v${{ steps.values.outputs.version }}@${{ steps.slug.outputs.commit-hash-short }}
run: go build -trimpath -ldflags "$LDFLAGS" -o ./${{ steps.values.outputs.binary-name }} ./cmd/webhook-tester/
# try to run the binary
- if: matrix.os == runner.os && matrix.arch == 'amd64'
- if: matrix.os == runner.os && matrix.arch == 'amd64' # try to run the binary
run: ./${{ steps.values.outputs.binary-name }} -h
# upload the binary
- uses: actions/upload-artifact@v4
with:
name: ${{ steps.values.outputs.binary-name }}
path: ./${{ steps.values.outputs.binary-name }}
if-no-files-found: error
retention-days: 7
# build a Debian package
- if: matrix.os == 'linux' && matrix.arch == 'amd64'
env:
PKG_NAME: ${{ steps.values.outputs.deb-name }}
run: |
mkdir -p ${{ env.PKG_NAME }}/usr/local/bin ${{ env.PKG_NAME }}/DEBIAN
cp ${{ steps.values.outputs.binary-name }} ${{ env.PKG_NAME }}/usr/local/bin/webhook-tester
echo -e "Package: webhook-tester\nVersion: ${{ steps.values.outputs.version }}" > ${{ env.PKG_NAME }}/DEBIAN/control
echo -e "Architecture: ${{ matrix.arch }}\nMaintainer: ${{ github.actor }}" >> ${{ env.PKG_NAME }}/DEBIAN/control
echo -e "Description: Powerful tool for testing WebHooks and more" >> ${{ env.PKG_NAME }}/DEBIAN/control
dpkg-deb --build --root-owner-group ${{ env.PKG_NAME }}
- if: matrix.os == 'linux' && matrix.arch == 'amd64'
uses: actions/upload-artifact@v4
with:
name: ${{ steps.values.outputs.binary-name }}.deb
path: ./${{ steps.values.outputs.deb-name }}.deb
if-no-files-found: error
retention-days: 7

e2e-test:
name: End-to-end tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
storage-driver: [memory, redis]
pubsub-driver: [memory, redis]
services:
redis:
image: docker.io/library/redis:7-alpine
ports: ['6379:6379/tcp']
options: --health-cmd "redis-cli ping" --health-interval 3s --health-timeout 2s --health-retries 3
needs: [build-app]
steps:
- uses: actions/checkout@v4
- {uses: actions/download-artifact@v4, with: {name: webhook-tester-linux-amd64}}
- run: | # start the server in the background
chmod +x ./webhook-tester-linux-amd64
./webhook-tester-linux-amd64 start --port 8081 \
--storage-driver "${{ matrix.storage-driver }}" \
--pubsub-driver "${{ matrix.pubsub-driver }}" \
--redis-dsn "redis://127.0.0.1:6379/0" &
- uses: grafana/setup-k6-action@v1
- uses: grafana/run-k6-action@v1
env: {BASE_URL: 'http://127.0.0.1:8081'}
with: {path: ./tests/k6/run.js}

build-docker-image:
name: Build the docker image
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ node-fmt: ## Format frontend code
lint: ## Run linters
docker compose run $(DC_RUN_ARGS) app golangci-lint run

e2e: ## Run end-to-end tests
docker compose run $(DC_RUN_ARGS) k6 run ./tests/k6/run.js

up: ## Start the application in watch mode
#docker compose build
docker compose up --detach --build --remove-orphans
docker compose kill app-http --remove-orphans 2>/dev/null || true
#docker compose up --detach --wait whoami httpbin
docker compose up app-http

down: ## Stop the application
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ The following flags are supported:
| Name | Description | Default value | Environment variables |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------|:--------------------------:|:----------------------------:|
| `--addr="…"` | IP (v4 or v6) address to listen on (0.0.0.0 to bind to all interfaces) | `0.0.0.0` | `SERVER_ADDR`, `LISTEN_ADDR` |
| `--http-port="…"` | HTTP server port | `8080` | `HTTP_PORT` |
| `--port="…"` | HTTP server port | `8080` | `HTTP_PORT` |
| `--read-timeout="…"` | maximum duration for reading the entire request, including the body (zero = no timeout) | `1m0s` | `HTTP_READ_TIMEOUT` |
| `--write-timeout="…"` | maximum duration before timing out writes of the response (zero = no timeout) | `1m0s` | `HTTP_WRITE_TIMEOUT` |
| `--idle-timeout="…"` | maximum amount of time to wait for the next request (keep-alive, zero = no timeout) | `1m0s` | `HTTP_IDLE_TIMEOUT` |
Expand All @@ -146,9 +146,9 @@ $ app [GLOBAL FLAGS] start healthcheck [COMMAND FLAGS] [ARGUMENTS...]

The following flags are supported:

| Name | Description | Default value | Environment variables |
|-------------------|------------------|:-------------:|:---------------------:|
| `--http-port="…"` | HTTP server port | `8080` | `HTTP_PORT` |
| Name | Description | Default value | Environment variables |
|--------------|------------------|:-------------:|:---------------------:|
| `--port="…"` | HTTP server port | `8080` | `HTTP_PORT` |

<!--/GENERATED:CLI_DOCS-->

Expand Down
4 changes: 1 addition & 3 deletions api/openapi.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json

openapi: 3.0.3
info:
title: WebHook Tester
Expand Down Expand Up @@ -186,7 +184,7 @@ components:
description: HTTP status code
type: integer
example: 301
minimum: 100
minimum: 200
maximum: 530

Base64Encoded:
Expand Down
18 changes: 17 additions & 1 deletion compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,28 @@ services:

app-http:
build: *app-build
command: go run ./cmd/webhook-tester/ start --use-live-frontend --auto-create-sessions --max-requests 8
entrypoint: sh -c 'go build -buildvcs=false -o /var/tmp/app ./cmd/webhook-tester/ && exec $0 "$@"'
command: /var/tmp/app start --use-live-frontend --auto-create-sessions --max-requests 8
volumes: [.:/src:rw]
ports: ['8080:8080/tcp']
healthcheck:
test: ['CMD', '/var/tmp/app', 'start', 'healthcheck']
start_interval: 1s
interval: 10s
start_period: 10s
depends_on: {app-web-dist: {condition: service_healthy}}
security_opt: [no-new-privileges:true]

k6:
image: ghcr.io/grafana/k6:latest
volumes: [.:/src:ro]
working_dir: /src
environment:
BASE_URL: http://app-http:8080
K6_NO_USAGE_REPORT: 'true'
depends_on: {app-http: {condition: service_healthy}}
security_opt: [no-new-privileges:true]

volumes:
app-modules-cache: {}
app-tmp-data: {}
2 changes: 1 addition & 1 deletion internal/cli/start/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func NewCommand(log *zap.Logger, defaultHttpPort uint16) *cli.Command { //nolint
},
}
httpPortFlag = cli.UintFlag{
Name: "http-port",
Name: "port",
Category: httpCategory,
Usage: "HTTP server port",
Value: uint64(defaultHttpPort),
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/start/healthcheck/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func NewCommand(defaultHttpPort uint16) *cli.Command {
var (
httpPortFlag = cli.UintFlag{
Name: "http-port",
Name: "port",
Usage: "HTTP server port",
Value: uint64(defaultHttpPort),
Sources: cli.EnvVars("HTTP_PORT"),
Expand Down
2 changes: 2 additions & 0 deletions internal/http/middleware/webhook/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ func New( //nolint:funlen,gocognit,gocyclo
return
}

w.Header().Set("X-Wh-Request-Id", rID)

// publish the captured request to the pub/sub. important note - we should use the app ctx instead of the req ctx
// because the request context can be canceled before the goroutine finishes (and moreover - before the
// subscribers will receive the event - in this case the event will be lost)
Expand Down
2 changes: 1 addition & 1 deletion internal/http/openapi/models_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func (data CreateSessionRequest) Validate() error {
minHeaderKeyLen, maxHeaderKeyLen = 1, 40
maxHeaderValueLen = 2048
maxResponseBodyLen = 10240
minStatusCode, maxStatusCode = StatusCode(100), StatusCode(530)
minStatusCode, maxStatusCode = StatusCode(200), StatusCode(530)
)

if data.Delay > maxDelaySeconds {
Expand Down
Loading

0 comments on commit 72ef89e

Please sign in to comment.