diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..afd2d51 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,97 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/go +{ + "name": "Webhooked", + "dockerComposeFile": "docker-compose.yaml", + "service": "workspace", + "workspaceFolder": "/workspace", + + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": true, + "configureZshAsDefaultShell": true, + "installOhMyZsh": true, + "upgradePackages": true, + "username": "devcontainer", + "userUid": "1001", + "userGid": "1001" + } + }, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "go.toolsManagement.checkForUpdates": "local", + "go.useLanguageServer": true, + "go.gopath": "/go", + "go.coverMode": "atomic", + "go.coverOnSave": true, + "go.disableConcurrentTests": true, + "editor.formatOnSave": true, + "go.lintTool": "golangci-lint", + "editor.tabSize": 2, + "editor.renderWhitespace": "all", + "gopls": { + "ui.completion.usePlaceholders": true, + // Experimental settings + "completeUnimported": true, // autocomplete unimported packages + "deepCompletion": true, // enable deep completion + "staticcheck": true + }, + "editor.codeActionsOnSave": { + "source.organizeImports": true, + "source.fixAll": true + }, + "editor.bracketPairColorization.enabled": true, + "editor.guides.bracketPairs": "active", + "editor.suggestSelection": "first", + "git.autofetch": true, + "files.autoGuessEncoding": true, + "files.encoding": "utf8", + "workbench.editor.decorations.badges": true, + "workbench.editor.decorations.colors": true, + "go.delveConfig": { + "apiVersion": 2, + "showGlobalVariables": false + }, + "editor.inlineSuggest.enabled": true, + "editor.rulers": [80], + "search.useGlobalIgnoreFiles": true, + "search.useParentIgnoreFiles": true, + "workbench.productIconTheme": "fluent-icons", + "[yaml]": { + "editor.defaultFormatter": "redhat.vscode-yaml" + } + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "golang.Go", + "aaron-bond.better-comments", + "IBM.output-colorizer", + "miguelsolorio.fluent-icons", + "jasonnutter.vscode-codeowners", + "cschleiden.vscode-github-actions", + "eamodio.gitlens", + "jinliming2.vscode-go-template", + "quicktype.quicktype" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 8080 // webhooked port + ], + + // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode", + "portsAttributes": { + "8080": { + "label": "Webhooked entrypoint" + } + } +} diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml new file mode 100644 index 0000000..a962d8d --- /dev/null +++ b/.devcontainer/docker-compose.yaml @@ -0,0 +1,47 @@ +version: '3.1' +services: + workspace: + image: mcr.microsoft.com/devcontainers/go:1.0.0-1.20-bookworm + volumes: + - ..:/workspace:cached + environment: + DEBUG: "true" + POSTGRES_DB: postgres + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_HOST: postgres + POSTGRES_PORT: '5432' + REDIS_HOST: redis + REDIS_PORT: '6379' + REDIS_PASSWORD: '' + RABBITMQ_HOST: rabbitmq + RABBITMQ_PORT: '5672' + RABBITMQ_USER: rabbitmq + RABBITMQ_PASSWORD: rabbitmq + ports: + - 8080:8080 + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + redis: + image: redis:6.2.5-alpine + ports: + - 6379:6379 + + rabbitmq: + image: rabbitmq:3.9.7-management-alpine + ports: + - 5672:5672 + - 15672:15672 + environment: + RABBITMQ_DEFAULT_USER: rabbitmq + RABBITMQ_DEFAULT_PASS: rabbitmq + + postgres: + image: postgres:13.4-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 diff --git a/.github/workflows/k6.yaml b/.github/workflows/k6.yaml index 550a334..ab298dc 100644 --- a/.github/workflows/k6.yaml +++ b/.github/workflows/k6.yaml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - goVersion: [ '1.18' ] + goVersion: [ '1.18', '1.19', '1.20' ] steps: - name: Checkout project uses: actions/checkout@v3 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 70aa8e7..3313390 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -24,14 +24,14 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} goos: ${{ matrix.goos }} goarch: ${{ matrix.goarch }} - goversion: "1.17.6" + goversion: "1.20" binary_name: webhooked extra_files: LICENSE README.md docker-image: runs-on: ubuntu-latest strategy: matrix: - goVersion: [ '1.18' ] + goVersion: [ '1.20' ] steps: - name: Checkout project uses: actions/checkout@v3 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 7c88a8d..c1a9802 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -17,7 +17,20 @@ jobs: strategy: fail-fast: false matrix: - goVersion: [ '1.17', '1.18' ] + goVersion: [ '1.18', '1.19', '1.20' ] + env: + REDIS_HOST: '127.0.0.1' + REDIS_PORT: '6379' + REDIS_PASSWORD: '' + RABBITMQ_HOST: '127.0.0.1' + RABBITMQ_PORT: '5672' + RABBITMQ_USER: 'rabbitmq' + RABBITMQ_PASSWORD: 'rabbitmq' + POSTGRES_HOST: '127.0.0.1' + POSTGRES_PORT: '5432' + POSTGRES_USER: 'postgres' + POSTGRES_PASSWORD: 'postgres' + POSTGRES_DB: 'postgres' steps: - name: Checkout project uses: actions/checkout@v3 @@ -30,15 +43,15 @@ jobs: with: rabbitmq version: '3.8.2-management-alpine' host port: 5672 - rabbitmq user: 'user' - rabbitmq password: 'password' + rabbitmq user: 'rabbitmq' + rabbitmq password: 'rabbitmq' - name: Setup PostgreSQL uses: harmon758/postgresql-action@v1 with: postgresql version: '11' - postgresql db: webhook_db - postgresql user: webhook - postgresql password: test + postgresql db: postgres + postgresql user: postgres + postgresql password: postgres - name: Setup go uses: actions/setup-go@v4 with: diff --git a/build/Dockerfile b/build/Dockerfile index 69b13b3..283cba4 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17-alpine AS build +FROM golang:1.20-alpine AS build WORKDIR /build COPY . /build diff --git a/go.mod b/go.mod index f0f574f..97196b9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module atomys.codes/webhooked -go 1.18 +go 1.20 require ( github.com/go-redis/redis/v8 v8.11.5 diff --git a/internal/server/v1alpha1/handlers_test.go b/internal/server/v1alpha1/handlers_test.go index 9dfe9ae..ec334bf 100644 --- a/internal/server/v1alpha1/handlers_test.go +++ b/internal/server/v1alpha1/handlers_test.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" "net/http/httptest" + "os" "strings" "testing" @@ -191,8 +192,8 @@ func TestServer_webhokServiceStorage(t *testing.T) { } pusher, err := storage.Load("redis", map[string]interface{}{ - "host": "127.0.0.1", - "port": "6379", + "host": os.Getenv("REDIS_HOST"), + "port": os.Getenv("REDIS_PORT"), "database": 0, "key": "testKey", }) diff --git a/pkg/storage/postgres/postgres_test.go b/pkg/storage/postgres/postgres_test.go index a8ec62d..0f61427 100644 --- a/pkg/storage/postgres/postgres_test.go +++ b/pkg/storage/postgres/postgres_test.go @@ -2,6 +2,8 @@ package postgres import ( "database/sql" + "fmt" + "os" "testing" "github.com/stretchr/testify/assert" @@ -10,13 +12,24 @@ import ( type PostgresSetupTestSuite struct { suite.Suite - client *sql.DB + client *sql.DB + databaseUrl string } // Create Table for running test func (suite *PostgresSetupTestSuite) BeforeTest(suiteName, testName string) { var err error - if suite.client, err = sql.Open("postgres", "postgresql://webhook:test@127.0.0.1:5432/webhook_db?sslmode=disable"); err != nil { + + suite.databaseUrl = fmt.Sprintf( + "postgresql://%s:%s@%s:%s/%s?sslmode=disable", + os.Getenv("POSTGRES_USER"), + os.Getenv("POSTGRES_PASSWORD"), + os.Getenv("POSTGRES_HOST"), + os.Getenv("POSTGRES_PORT"), + os.Getenv("POSTGRES_DB"), + ) + + if suite.client, err = sql.Open("postgres", suite.databaseUrl); err != nil { suite.T().Error(err) } if _, err := suite.client.Query("CREATE TABLE test (test_field TEXT)"); err != nil { @@ -43,7 +56,7 @@ func (suite *PostgresSetupTestSuite) TestPostgresNewStorage() { assert.Error(suite.T(), err) _, err = NewStorage(map[string]interface{}{ - "databaseUrl": "postgresql://webhook:test@127.0.0.1:5432/webhook_db?sslmode=disable", + "databaseUrl": suite.databaseUrl, "tableName": "test", "dataField": "test_field", }) @@ -52,7 +65,7 @@ func (suite *PostgresSetupTestSuite) TestPostgresNewStorage() { func (suite *PostgresSetupTestSuite) TestPostgresPush() { newClient, _ := NewStorage(map[string]interface{}{ - "databaseUrl": "postgresql://webhook:test@127.0.0.1:5432/webhook_db?sslmode=disable", + "databaseUrl": suite.databaseUrl, "tableName": "Not Exist", "dataField": "Not exist", }) @@ -60,7 +73,7 @@ func (suite *PostgresSetupTestSuite) TestPostgresPush() { assert.Error(suite.T(), err) newClient, err = NewStorage(map[string]interface{}{ - "databaseUrl": "postgresql://webhook:test@127.0.0.1:5432/webhook_db?sslmode=disable", + "databaseUrl": suite.databaseUrl, "tableName": "test", "dataField": "test_field", }) diff --git a/pkg/storage/rabbitmq/rabbitmq_test.go b/pkg/storage/rabbitmq/rabbitmq_test.go index d6d77ff..849b54f 100644 --- a/pkg/storage/rabbitmq/rabbitmq_test.go +++ b/pkg/storage/rabbitmq/rabbitmq_test.go @@ -1,6 +1,8 @@ package rabbitmq import ( + "fmt" + "os" "testing" "github.com/stretchr/testify/assert" @@ -9,6 +11,7 @@ import ( type RabbitMQSetupTestSuite struct { suite.Suite + amqpUrl string } func (suite *RabbitMQSetupTestSuite) TestRabbitMQName() { @@ -16,6 +19,17 @@ func (suite *RabbitMQSetupTestSuite) TestRabbitMQName() { assert.Equal(suite.T(), "rabbitmq", newRabbitMQ.Name()) } +// Create Table for running test +func (suite *RabbitMQSetupTestSuite) BeforeTest(suiteName, testName string) { + suite.amqpUrl = fmt.Sprintf( + "amqp://%s:%s@%s:%s", + os.Getenv("RABBITMQ_USER"), + os.Getenv("RABBITMQ_PASSWORD"), + os.Getenv("RABBITMQ_HOST"), + os.Getenv("RABBITMQ_PORT"), + ) +} + func (suite *RabbitMQSetupTestSuite) TestRabbitMQNewStorage() { _, err := NewStorage(map[string]interface{}{ "databaseUrl": []int{1}, @@ -23,7 +37,7 @@ func (suite *RabbitMQSetupTestSuite) TestRabbitMQNewStorage() { assert.Error(suite.T(), err) _, err = NewStorage(map[string]interface{}{ - "databaseUrl": "amqp://user:password@127.0.0.1:5672", + "databaseUrl": suite.amqpUrl, "queueName": "hello", "durable": false, "deleteWhenUnused": false, @@ -42,7 +56,7 @@ func (suite *RabbitMQSetupTestSuite) TestRabbitMQNewStorage() { func (suite *RabbitMQSetupTestSuite) TestRabbitMQPush() { newClient, err := NewStorage(map[string]interface{}{ - "databaseUrl": "amqp://user:password@127.0.0.1:5672", + "databaseUrl": suite.amqpUrl, "queueName": "hello", "contentType": "text/plain", "durable": false, @@ -73,14 +87,14 @@ func TestContentType(t *testing.T) { assert.Equal(t, "application/json", (&config{DefinedContentType: "application/json"}).ContentType()) } -func TestReconnect(t *testing.T) { +func (suite *RabbitMQSetupTestSuite) TestReconnect() { if testing.Short() { - t.Skip("rabbitmq testing is skiped in short version of test") + suite.T().Skip("rabbitmq testing is skiped in short version of test") return } newClient, err := NewStorage(map[string]interface{}{ - "databaseUrl": "amqp://user:password@127.0.0.1:5672", + "databaseUrl": suite.amqpUrl, "queueName": "hello", "contentType": "text/plain", "durable": false, @@ -90,11 +104,11 @@ func TestReconnect(t *testing.T) { "mandatory": false, "immediate": false, }) - assert.NoError(t, err) + assert.NoError(suite.T(), err) - assert.NoError(t, newClient.Push("Hello")) - assert.NoError(t, newClient.client.Close()) - assert.NoError(t, newClient.Push("Hello")) - assert.NoError(t, newClient.channel.Close()) - assert.NoError(t, newClient.Push("Hello")) + assert.NoError(suite.T(), newClient.Push("Hello")) + assert.NoError(suite.T(), newClient.client.Close()) + assert.NoError(suite.T(), newClient.Push("Hello")) + assert.NoError(suite.T(), newClient.channel.Close()) + assert.NoError(suite.T(), newClient.Push("Hello")) } diff --git a/pkg/storage/redis/redis_test.go b/pkg/storage/redis/redis_test.go index d090266..76498ca 100644 --- a/pkg/storage/redis/redis_test.go +++ b/pkg/storage/redis/redis_test.go @@ -1,6 +1,7 @@ package redis import ( + "os" "testing" "github.com/stretchr/testify/assert" @@ -26,8 +27,8 @@ func (suite *RedisSetupTestSuite) TestRedisNewStorage() { assert.Error(suite.T(), err) _, err = NewStorage(map[string]interface{}{ - "host": "127.0.0.1", - "port": "6379", + "host": os.Getenv("REDIS_HOST"), + "port": os.Getenv("REDIS_PORT"), "database": 0, "key": "testKey", }) @@ -36,8 +37,8 @@ func (suite *RedisSetupTestSuite) TestRedisNewStorage() { func (suite *RedisSetupTestSuite) TestRedisPush() { newClient, err := NewStorage(map[string]interface{}{ - "host": "127.0.0.1", - "port": "6379", + "host": os.Getenv("REDIS_HOST"), + "port": os.Getenv("REDIS_PORT"), "database": 0, "key": "testKey", })