diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..6f307cf --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,52 @@ +name: coverage + +on: + push: + branches: + - main + workflow_call: + inputs: + go_version: + required: false + type: string + default: "1.20.0" + +permissions: + contents: write + pull-requests: write + +jobs: + coverage: + runs-on: ubuntu-latest + strategy: + matrix: + module: + - "fxgcppubsub" + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 1 + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: ${{ inputs.go_version }} + - name: Install dependencies for module ${{ matrix.module }} + working-directory: ${{ matrix.module }} + run: go mod download + - name: Run tests for module ${{ matrix.module }} + working-directory: ${{ matrix.module }} + run: go test -v -race -failfast -coverpkg=./... -covermode=atomic -coverprofile=coverage.tmp.out ./... + - name: Exclude testdata + working-directory: ${{ matrix.module}} + run: cat coverage.tmp.out | grep -v "testdata" > coverage.out + - name: Clean temp coverage + working-directory: ${{ matrix.module }} + run: rm coverage.tmp.out + - name: Codecov for module ${{ matrix.module }} + uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: false + flags: ${{ matrix.module }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/fxgcppubsub-ci.yml b/.github/workflows/fxgcppubsub-ci.yml new file mode 100644 index 0000000..1ba84ea --- /dev/null +++ b/.github/workflows/fxgcppubsub-ci.yml @@ -0,0 +1,31 @@ +name: "fxgcppubsub-ci" + +on: + push: + branches: + - "feat**" + - "fix**" + - "hotfix**" + - "chore**" + paths: + - "fxgcppubsub/**.go" + - "fxgcppubsub/go.mod" + - "fxgcppubsub/go.sum" + pull_request: + types: + - opened + - synchronize + - reopened + branches: + - main + paths: + - "fxgcppubsub/**.go" + - "fxgcppubsub/go.mod" + - "fxgcppubsub/go.sum" + +jobs: + ci: + uses: ./.github/workflows/common-ci.yml + secrets: inherit + with: + module: "fxgcppubsub" diff --git a/README.md b/README.md index d46152b..abd9012 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ ## Modules -| Module | Description | -|----------|-----------------------------------------------------------| -| fxpubsub | subscribing to [Pub/Sub](https://cloud.google.com/pubsub) | +| Module | Description | +|-------------|--------------------------------------------------------------| +| fxgcppubsub | Module for [Google Pub/Sub](https://cloud.google.com/pubsub) | ## Contributing diff --git a/fxgcppubsub/README.md b/fxgcppubsub/README.md new file mode 100644 index 0000000..b36818d --- /dev/null +++ b/fxgcppubsub/README.md @@ -0,0 +1,145 @@ +# Fx Google Pub/Sub Module + +[![ci](https://github.com/ankorstore/yokai/actions/workflows/fxgcppubsub-ci.yml/badge.svg)](https://github.com/ankorstore/yokai/actions/workflows/fxgcppubsub-ci.yml) +[![go report](https://goreportcard.com/badge/github.com/ankorstore/yokai/fxgcppubsub)](https://goreportcard.com/report/github.com/ankorstore/yokai/fxgcppubsub) +[![codecov](https://codecov.io/gh/ankorstore/yokai/graph/badge.svg?token=ghUBlFsjhR&flag=fxgcppubsub)](https://app.codecov.io/gh/ankorstore/yokai/tree/main/fxgcppubsub) +[![Deps](https://img.shields.io/badge/osi-deps-blue)](https://deps.dev/go/github.com%2Fankorstore%2Fyokai%2Ffxgcppubsub) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/ankorstore/yokai/fxgcppubsub)](https://pkg.go.dev/github.com/ankorstore/yokai/fxgcppubsub) + +> [Fx](https://uber-go.github.io/fx/) module for [Google Pub/Sub](https://cloud.google.com/pubsub). + + +* [Overview](#overview) +* [Installation](#installation) +* [Configuration](#configuration) +* [Health Check](#health-check) +* [Testing](#testing) + + +## Overview + +This module provides to your Fx application a [pubsub.Client](https://pkg.go.dev/cloud.google.com/go/pubsub#Client), +that you can `inject` anywhere to `publish` or `subscribe` on a `Pub/Sub` instance. + +## Installation + +First install the module: + +```shell +go get github.com/ankorstore/yokai-contrib/fxgcppubsub +``` + +Then activate it in your application bootstrapper: + +```go +// internal/bootstrap.go +package internal + +import ( + "github.com/ankorstore/yokai/fxcore" + "github.com/ankorstore/yokai-contrib/fxgcppubsub" +) + +var Bootstrapper = fxcore.NewBootstrapper().WithOptions( + // load fxgcppubsub module + fxgcppubsub.FxGcpPubSubModule, + // ... +) +``` + +## Configuration + +Configuration reference: + +```yaml +# ./configs/config.yaml +app: + name: app + env: dev + version: 0.1.0 + debug: true +modules: + gcppubsub: + project: + id: ${GCP_PROJECT_ID} # GCP project id + healthcheck: + topics: # list of topics to check for the topics probe + - topic1 + - topic2 + subscriptions: # list of subscriptions to check for the subscriptions probe + - subscription1 + - subscription2 +``` + +## Health Check + +This module provides ready to use health check probes, to be used by +the [fxhealthcheck](https://ankorstore.github.io/yokai/modules/fxhealthcheck/) module: + +- [GcpPubSubTopicsProbe](healthcheck/topic.go): to check existence of the topics in `modules.gcppubsub.healthcheck.topics` +- [GcpPubSubSubscriptionsProbe](healthcheck/subscription.go): to check existence of topics in `modules.gcppubsub.healthcheck.subscriptions` + +To activate those probes, you just need to register them: + +```go +// internal/services.go +package internal + +import ( + "github.com/ankorstore/yokai/fxhealthcheck" + "github.com/ankorstore/yokai-contrib/fxgcppubsub/healthcheck" + "go.uber.org/fx" +) + +func ProvideServices() fx.Option { + return fx.Options( + // register the GcpPubSubTopicsProbe + fxhealthcheck.AsCheckerProbe(healthcheck.NewGcpPubSubTopicsProbe), + // register the GcpPubSubSubscriptionsProbe + fxhealthcheck.AsCheckerProbe(healthcheck.NewGcpPubSubSubscriptionsProbe), + // ... + ) +} +``` + +If your application is interested only in `publishing`, activate the `GcpPubSubTopicsProbe` only. + +If it is interested only in `subscribing`, activate the `GcpPubSubSubscriptionsProbe` only. + +## Testing + +In `test` mode, this client is configured to [work with +a ptest.Server](module.go), avoiding the need to run any `Pub/Sub` +instance, for better tests portability. + +```go +// internal/example/example_test.go +package example_test + +import ( + "context" + "testing" + + "cloud.google.com/go/pubsub" + "github.com/foo/bar/internal" + "github.com/stretchr/testify/assert" + "go.uber.org/fx" +) + +func TestExample(t *testing.T) { + var client *pubsub.Client + + internal.RunTest(t, fx.Populate(&client)) + + ctx := context.Background() + + // prepare test topic on test server + topic, err := client.CreateTopic(ctx, "test-topic") + assert.NoError(t, err) + + // public on test topic + topic.Publish(ctx, &pubsub.Message{Data: []byte("test message")}) + + // ... +} +``` diff --git a/fxpubsub/go.mod b/fxgcppubsub/go.mod similarity index 91% rename from fxpubsub/go.mod rename to fxgcppubsub/go.mod index 8c74962..7ef2390 100644 --- a/fxpubsub/go.mod +++ b/fxgcppubsub/go.mod @@ -1,4 +1,4 @@ -module github.com/ankorstore/yokai-contrib/fxpubsub +module github.com/ankorstore/yokai-contrib/fxgcppubsub go 1.20.0 @@ -6,7 +6,6 @@ require ( cloud.google.com/go/pubsub v1.36.1 github.com/ankorstore/yokai/config v1.2.0 github.com/ankorstore/yokai/fxconfig v1.0.0 - github.com/ankorstore/yokai/fxlog v1.0.0 github.com/ankorstore/yokai/healthcheck v1.0.0 github.com/stretchr/testify v1.8.4 go.uber.org/fx v1.20.1 @@ -19,7 +18,6 @@ require ( cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.6 // indirect - github.com/ankorstore/yokai/log v1.0.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -33,13 +31,10 @@ require ( github.com/googleapis/gax-go/v2 v2.12.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect - github.com/rs/zerolog v1.31.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect diff --git a/fxpubsub/go.sum b/fxgcppubsub/go.sum similarity index 93% rename from fxpubsub/go.sum rename to fxgcppubsub/go.sum index ceb5f00..1ca39a1 100644 --- a/fxpubsub/go.sum +++ b/fxgcppubsub/go.sum @@ -15,18 +15,13 @@ github.com/ankorstore/yokai/config v1.2.0 h1:OqgrPGGIWEJoXEKGsveSBwLPGMnI3ZZBvIf github.com/ankorstore/yokai/config v1.2.0/go.mod h1:yDANaMWIOfAUkAMClG22Q4bzQk91NLwWK3WbL5IFnbg= github.com/ankorstore/yokai/fxconfig v1.0.0 h1:zaYOLfpurqFJuS/IHeAXPOzrCNuttsFjJWNOK39opR4= github.com/ankorstore/yokai/fxconfig v1.0.0/go.mod h1:p+x6Jp8aLv1+uE1qO42KF+yahBK+VJdPP1/YReBjJ7M= -github.com/ankorstore/yokai/fxlog v1.0.0 h1:ujq/XxgCK0uwKCNSt86XEYR2vqYbXZX2/lA/pQHZX4A= -github.com/ankorstore/yokai/fxlog v1.0.0/go.mod h1:juQnBYNddDVOa7Ukhw8axLYWyibDDMJAwG7MDpluKnk= github.com/ankorstore/yokai/healthcheck v1.0.0 h1:uX6RrchsvbxCV70dh5d6RX5LEuGIf+Pt+14waV0CzY0= github.com/ankorstore/yokai/healthcheck v1.0.0/go.mod h1:Frz73NuG8ruLDz04vQxzf0bWhKK1Ru2Ktod+3ltaIxs= -github.com/ankorstore/yokai/log v1.0.0 h1:9NsM0J+1O028WuNDW7vr0yeUdWDX1JKYTkuz7hiYCSs= -github.com/ankorstore/yokai/log v1.0.0/go.mod h1:lyBRVA8VkrmlNjaR2jVTH9XjV06ioolWTuDVN6wF0vk= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -46,7 +41,6 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -91,25 +85,16 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -203,9 +188,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/fxgcppubsub/healthcheck/subscription.go b/fxgcppubsub/healthcheck/subscription.go new file mode 100644 index 0000000..9df9e93 --- /dev/null +++ b/fxgcppubsub/healthcheck/subscription.go @@ -0,0 +1,61 @@ +package healthcheck + +import ( + "context" + "fmt" + "strings" + + "cloud.google.com/go/pubsub" + "github.com/ankorstore/yokai/config" + "github.com/ankorstore/yokai/healthcheck" +) + +// SubscriptionsProbeName is the name of the GCP pub/sub subscriptions probe. +const SubscriptionsProbeName = "gcppubsub-subscriptions" + +// GcpPubSubSubscriptionsProbe is a probe compatible with the [healthcheck] module. +// +// [healthcheck]: https://github.com/ankorstore/yokai/tree/main/healthcheck +type GcpPubSubSubscriptionsProbe struct { + config *config.Config + client *pubsub.Client +} + +// NewGcpPubSubSubscriptionsProbe returns a new [GcpPubSubSubscriptionsProbe]. +func NewGcpPubSubSubscriptionsProbe(config *config.Config, client *pubsub.Client) *GcpPubSubSubscriptionsProbe { + return &GcpPubSubSubscriptionsProbe{ + config: config, + client: client, + } +} + +// Name returns the name of the [GcpPubSubSubscriptionsProbe]. +func (p *GcpPubSubSubscriptionsProbe) Name() string { + return SubscriptionsProbeName +} + +// Check returns a successful [healthcheck.CheckerProbeResult] if all configured subscriptions exist. +func (p *GcpPubSubSubscriptionsProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult { + success := true + var messages []string + + for _, subscriptionName := range p.config.GetStringSlice("modules.gcppubsub.healthcheck.subscriptions") { + subscription := p.client.Subscription(subscriptionName) + + exists, err := subscription.Exists(ctx) + if err != nil { + success = false + messages = append(messages, fmt.Sprintf("subscription %s error: %v", subscriptionName, err)) + } else { + if !exists { + success = false + messages = append(messages, fmt.Sprintf("subscription %s does not exist", subscriptionName)) + } else { + messages = append(messages, fmt.Sprintf("subscription %s exists", subscriptionName)) + } + } + + } + + return healthcheck.NewCheckerProbeResult(success, strings.Join(messages, ", ")) +} diff --git a/fxgcppubsub/healthcheck/subscription_test.go b/fxgcppubsub/healthcheck/subscription_test.go new file mode 100644 index 0000000..6cdfdec --- /dev/null +++ b/fxgcppubsub/healthcheck/subscription_test.go @@ -0,0 +1,152 @@ +package healthcheck_test + +import ( + "context" + "testing" + + "cloud.google.com/go/pubsub" + "github.com/ankorstore/yokai-contrib/fxgcppubsub" + fxgcppubsubhealthcheck "github.com/ankorstore/yokai-contrib/fxgcppubsub/healthcheck" + "github.com/ankorstore/yokai/config" + "github.com/ankorstore/yokai/fxconfig" + "github.com/stretchr/testify/assert" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" +) + +func TestWithExistingSubscriptions(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + var client *pubsub.Client + var conf *config.Config + + app := fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart() + + topic, err := client.CreateTopic(context.Background(), "topic1") + assert.NoError(t, err) + + for _, subscription := range conf.GetStringSlice("modules.gcppubsub.healthcheck.subscriptions") { + _, err = client.CreateSubscription(context.Background(), subscription, pubsub.SubscriptionConfig{ + Topic: topic, + }) + assert.NoError(t, err) + } + + p := fxgcppubsubhealthcheck.NewGcpPubSubSubscriptionsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.SubscriptionsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + app.RequireStop() + + assert.True(t, checkResult.Success) + assert.Equal( + t, + "subscription subscription1 exists, subscription subscription2 exists, subscription subscription3 exists", + checkResult.Message, + ) +} + +func TestWithMissingSubscriptions(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + var client *pubsub.Client + var conf *config.Config + + app := fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart() + + topic, err := client.CreateTopic(context.Background(), "topic1") + assert.NoError(t, err) + + for _, subscription := range conf.GetStringSlice("modules.gcppubsub.healthcheck.subscriptions") { + if subscription != "subscription2" { + _, err = client.CreateSubscription(context.Background(), subscription, pubsub.SubscriptionConfig{ + Topic: topic, + }) + assert.NoError(t, err) + } + + } + + p := fxgcppubsubhealthcheck.NewGcpPubSubSubscriptionsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.SubscriptionsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + app.RequireStop() + + assert.False(t, checkResult.Success) + assert.Equal( + t, + "subscription subscription1 exists, subscription subscription2 does not exist, subscription subscription3 exists", + checkResult.Message, + ) +} + +func TestWithEmptySubscriptions(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + // empty the subscriptions list + t.Setenv("MODULES_GCPPUBSUB_HEALTHCHECK_SUBSCRIPTIONS", " ") + + var client *pubsub.Client + var conf *config.Config + + app := fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart() + + p := fxgcppubsubhealthcheck.NewGcpPubSubSubscriptionsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.SubscriptionsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + app.RequireStop() + + assert.True(t, checkResult.Success) +} + +func TestWithFailingSubscriptions(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + var client *pubsub.Client + var conf *config.Config + + fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart().RequireStop() + + p := fxgcppubsubhealthcheck.NewGcpPubSubSubscriptionsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.SubscriptionsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + assert.False(t, checkResult.Success) + assert.Contains(t, checkResult.Message, "subscription subscription1 error: rpc error") + assert.Contains(t, checkResult.Message, "subscription subscription2 error: rpc error") + assert.Contains(t, checkResult.Message, "subscription subscription3 error: rpc error") +} diff --git a/fxgcppubsub/healthcheck/topic.go b/fxgcppubsub/healthcheck/topic.go new file mode 100644 index 0000000..a12f6e4 --- /dev/null +++ b/fxgcppubsub/healthcheck/topic.go @@ -0,0 +1,61 @@ +package healthcheck + +import ( + "context" + "fmt" + "strings" + + "cloud.google.com/go/pubsub" + "github.com/ankorstore/yokai/config" + "github.com/ankorstore/yokai/healthcheck" +) + +// TopicsProbeName is the name of the GCP pub/sub topics probe. +const TopicsProbeName = "gcppubsub-topics" + +// GcpPubSubTopicsProbe is a probe compatible with the [healthcheck] module. +// +// [healthcheck]: https://github.com/ankorstore/yokai/tree/main/healthcheck +type GcpPubSubTopicsProbe struct { + config *config.Config + client *pubsub.Client +} + +// NewGcpPubSubTopicsProbe returns a new [GcpPubSubTopicsProbe]. +func NewGcpPubSubTopicsProbe(config *config.Config, client *pubsub.Client) *GcpPubSubTopicsProbe { + return &GcpPubSubTopicsProbe{ + config: config, + client: client, + } +} + +// Name returns the name of the [GcpPubSubTopicsProbe]. +func (p *GcpPubSubTopicsProbe) Name() string { + return TopicsProbeName +} + +// Check returns a successful [healthcheck.CheckerProbeResult] if all configured topics exist. +func (p *GcpPubSubTopicsProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult { + success := true + var messages []string + + for _, topicName := range p.config.GetStringSlice("modules.gcppubsub.healthcheck.topics") { + topic := p.client.Topic(topicName) + + exists, err := topic.Exists(ctx) + if err != nil { + success = false + messages = append(messages, fmt.Sprintf("topic %s error: %v", topicName, err)) + } else { + if !exists { + success = false + messages = append(messages, fmt.Sprintf("topic %s does not exist", topicName)) + } else { + messages = append(messages, fmt.Sprintf("topic %s exists", topicName)) + } + } + + } + + return healthcheck.NewCheckerProbeResult(success, strings.Join(messages, ", ")) +} diff --git a/fxgcppubsub/healthcheck/topic_test.go b/fxgcppubsub/healthcheck/topic_test.go new file mode 100644 index 0000000..e9f9e93 --- /dev/null +++ b/fxgcppubsub/healthcheck/topic_test.go @@ -0,0 +1,133 @@ +package healthcheck_test + +import ( + "context" + "testing" + + "cloud.google.com/go/pubsub" + "github.com/ankorstore/yokai-contrib/fxgcppubsub" + fxgcppubsubhealthcheck "github.com/ankorstore/yokai-contrib/fxgcppubsub/healthcheck" + "github.com/ankorstore/yokai/config" + "github.com/ankorstore/yokai/fxconfig" + "github.com/stretchr/testify/assert" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" +) + +func TestWithExistingTopics(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + var client *pubsub.Client + var conf *config.Config + + app := fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart() + + for _, topic := range conf.GetStringSlice("modules.gcppubsub.healthcheck.topics") { + _, err := client.CreateTopic(context.Background(), topic) + assert.NoError(t, err) + } + + p := fxgcppubsubhealthcheck.NewGcpPubSubTopicsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.TopicsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + app.RequireStop() + + assert.True(t, checkResult.Success) + assert.Equal(t, "topic topic1 exists, topic topic2 exists, topic topic3 exists", checkResult.Message) +} + +func TestWithMissingTopics(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + var client *pubsub.Client + var conf *config.Config + + app := fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart() + + for _, topic := range conf.GetStringSlice("modules.gcppubsub.healthcheck.topics") { + if topic != "topic2" { + _, err := client.CreateTopic(context.Background(), topic) + assert.NoError(t, err) + } + } + + p := fxgcppubsubhealthcheck.NewGcpPubSubTopicsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.TopicsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + app.RequireStop() + + assert.False(t, checkResult.Success) + assert.Equal(t, "topic topic1 exists, topic topic2 does not exist, topic topic3 exists", checkResult.Message) +} + +func TestWithEmptyTopics(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + // empty the topics list + t.Setenv("MODULES_GCPPUBSUB_HEALTHCHECK_TOPICS", " ") + + var client *pubsub.Client + var conf *config.Config + + app := fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart() + + p := fxgcppubsubhealthcheck.NewGcpPubSubTopicsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.TopicsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + app.RequireStop() + + assert.True(t, checkResult.Success) +} + +func TestWithFailingTopics(t *testing.T) { + t.Setenv("APP_ENV", "test") + t.Setenv("APP_CONFIG_PATH", "../testdata/config") + t.Setenv("GCP_PROJECT_ID", "test-project") + + var client *pubsub.Client + var conf *config.Config + + fxtest.New( + t, + fx.NopLogger, + fxgcppubsub.FxGcpPubSubModule, + fxconfig.FxConfigModule, + fx.Populate(&client, &conf), + ).RequireStart().RequireStop() + + p := fxgcppubsubhealthcheck.NewGcpPubSubTopicsProbe(conf, client) + assert.Equal(t, fxgcppubsubhealthcheck.TopicsProbeName, p.Name()) + checkResult := p.Check(context.Background()) + + assert.False(t, checkResult.Success) + assert.Contains(t, checkResult.Message, "topic topic1 error: rpc error") + assert.Contains(t, checkResult.Message, "topic topic2 error: rpc error") + assert.Contains(t, checkResult.Message, "topic topic3 error: rpc error") +} diff --git a/fxpubsub/module.go b/fxgcppubsub/module.go similarity index 64% rename from fxpubsub/module.go rename to fxgcppubsub/module.go index b94276e..57b0b45 100644 --- a/fxpubsub/module.go +++ b/fxgcppubsub/module.go @@ -1,4 +1,4 @@ -package fxpubsub +package fxgcppubsub import ( "context" @@ -14,42 +14,36 @@ import ( ) // ModuleName is the module name. -const ModuleName = "pubsub" +const ModuleName = "gcppubsub" -// FxPubSubModule is the [Fx] pubsub module. +// FxGcpPubSubModule is the [Fx] pubsub module. // // [Fx]: https://github.com/uber-go/fx -var FxPubSubModule = fx.Module( +var FxGcpPubSubModule = fx.Module( ModuleName, fx.Provide( - NewFxPubSub, + NewFxGcpPubSubClient, ), ) -// FxPubSubParam allows injection of the required dependencies in [NewFxPubSub]. -type FxPubSubParam struct { +// FxGcpPubSubClientParam allows injection of the required dependencies in [NewFxPubSub]. +type FxGcpPubSubClientParam struct { fx.In LifeCycle fx.Lifecycle Config *config.Config } -// NewFxPubSub returns a [pubsub.Client]. -func NewFxPubSub(p FxPubSubParam) (*pubsub.Client, error) { - var client *pubsub.Client - var err error - - // client +// NewFxGcpPubSubClient returns a [pubsub.Client]. +func NewFxGcpPubSubClient(p FxGcpPubSubClientParam) (*pubsub.Client, error) { if p.Config.IsTestEnv() { - client, err = createTestClient(p) + return createTestClient(p) } else { - client, err = createClient(p) + return createClient(p) } - - return client, err } -func createClient(p FxPubSubParam) (*pubsub.Client, error) { - client, err := pubsub.NewClient(context.Background(), p.Config.GetString("modules.pubsub.project.id")) +func createClient(p FxGcpPubSubClientParam) (*pubsub.Client, error) { + client, err := pubsub.NewClient(context.Background(), p.Config.GetString("modules.gcppubsub.project.id")) if err != nil { return nil, fmt.Errorf("failed to create pubsub client: %w", err) } @@ -63,8 +57,9 @@ func createClient(p FxPubSubParam) (*pubsub.Client, error) { return client, nil } -func createTestClient(p FxPubSubParam) (*pubsub.Client, error) { +func createTestClient(p FxGcpPubSubClientParam) (*pubsub.Client, error) { srv := pstest.NewServer() + conn, err := grpc.Dial(srv.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, err @@ -72,7 +67,7 @@ func createTestClient(p FxPubSubParam) (*pubsub.Client, error) { client, err := pubsub.NewClient( context.Background(), - p.Config.GetString("modules.pubsub.project.id"), + p.Config.GetString("modules.gcppubsub.project.id"), option.WithGRPCConn(conn), ) if err != nil { diff --git a/fxpubsub/module_test.go b/fxgcppubsub/module_test.go similarity index 51% rename from fxpubsub/module_test.go rename to fxgcppubsub/module_test.go index e5cec06..adcfc0a 100644 --- a/fxpubsub/module_test.go +++ b/fxgcppubsub/module_test.go @@ -1,11 +1,11 @@ -package fxpubsub_test +package fxgcppubsub_test import ( "context" "testing" "cloud.google.com/go/pubsub" - fxpubsub "github.com/ankorstore/yokai-contrib/fxpubsub" + "github.com/ankorstore/yokai-contrib/fxgcppubsub" "github.com/ankorstore/yokai/config" "github.com/ankorstore/yokai/fxconfig" "github.com/stretchr/testify/assert" @@ -13,11 +13,11 @@ import ( "go.uber.org/fx/fxtest" ) -func TestFxPubSubModule(t *testing.T) { +func TestFxGcpPubSubModule(t *testing.T) { app := fxtest.New( t, fx.NopLogger, - fxpubsub.FxPubSubModule, + fxgcppubsub.FxGcpPubSubModule, fxconfig.FxConfigModule, ) @@ -28,74 +28,53 @@ func TestFxPubSubModule(t *testing.T) { assert.NoError(t, app.Err(), "failed to stop the Fx application") } -func TestNewFxPubSubForTestClientWithoutProjectID(t *testing.T) { - t.Setenv("APP_ENV", "test") - t.Setenv("APP_CONFIG_PATH", "testdata/config/") - - var conf *config.Config - var client *pubsub.Client - - testApp := fxtest.New( - t, - fx.NopLogger, - fxpubsub.FxPubSubModule, - fxconfig.FxConfigModule, - fx.Populate(&conf, &client), - ) - - err := testApp.Start(context.Background()) - assert.Error(t, err, "failed to create test pubsub client: pubsub: projectID string is empty") - assert.Nil(t, client) -} - -func TestNewFxPubSubForTestClient(t *testing.T) { - t.Setenv("APP_ENV", "test") +func TestFxGcpPubSubClient(t *testing.T) { + t.Setenv("APP_ENV", "dev") t.Setenv("APP_CONFIG_PATH", "testdata/config") - t.Setenv("GCP_PROJECT_ID", "pubsub-test") + t.Setenv("GCP_PROJECT_ID", "project-test") + t.Setenv("PUBSUB_EMULATOR_HOST", "localhost") var conf *config.Config var client *pubsub.Client - app := fxtest.New( - t, + app := fx.New( fx.NopLogger, - fxpubsub.FxPubSubModule, fxconfig.FxConfigModule, + fxgcppubsub.FxGcpPubSubModule, fx.Populate(&conf, &client), ) - app.RequireStart() - assert.NoError(t, app.Err(), "failed to create pubsub.Client") + err := app.Start(context.Background()) + assert.NoError(t, err, "failed to create pubsub.Client") assert.NotNil(t, client) - assert.Equal(t, "pubsub-test", client.Project()) + assert.Equal(t, "project-test", client.Project()) - app.RequireStop() + err = app.Stop(context.Background()) assert.NoError(t, app.Err(), "failed to close pubsub.Client") } -func TestNewFxPubSubWithoutProjectID(t *testing.T) { +func TestFxGcpPubSubClientWithoutProjectId(t *testing.T) { t.Setenv("APP_ENV", "dev") t.Setenv("APP_CONFIG_PATH", "testdata/config") var conf *config.Config var client *pubsub.Client - app := fxtest.New( - t, + app := fx.New( fx.NopLogger, - fxpubsub.FxPubSubModule, fxconfig.FxConfigModule, + fxgcppubsub.FxGcpPubSubModule, fx.Populate(&conf, &client), ) - app.RequireStart() - assert.Error(t, app.Err(), "failed to create pubsub client: pubsub: projectID string is empty") + err := app.Start(context.Background()) + assert.Contains(t, err.Error(), "failed to create pubsub client: pubsub: projectID string is empty") } -func TestNewFxPubSubClient(t *testing.T) { - t.Setenv("APP_ENV", "dev") +func TestNewFxGcpPubSubForTestClient(t *testing.T) { + t.Setenv("APP_ENV", "test") t.Setenv("APP_CONFIG_PATH", "testdata/config") - t.Setenv("GCP_PROJECT_ID", "pubsub") + t.Setenv("GCP_PROJECT_ID", "project-test") var conf *config.Config var client *pubsub.Client @@ -103,13 +82,15 @@ func TestNewFxPubSubClient(t *testing.T) { app := fxtest.New( t, fx.NopLogger, - fxpubsub.FxPubSubModule, fxconfig.FxConfigModule, + fxgcppubsub.FxGcpPubSubModule, fx.Populate(&conf, &client), - ).RequireStart() + ) + + app.RequireStart() assert.NoError(t, app.Err(), "failed to create pubsub.Client") assert.NotNil(t, client) - assert.Equal(t, "pubsub", client.Project()) + assert.Equal(t, "project-test", client.Project()) app.RequireStop() assert.NoError(t, app.Err(), "failed to close pubsub.Client") diff --git a/fxgcppubsub/testdata/config/config.dev.yaml b/fxgcppubsub/testdata/config/config.dev.yaml new file mode 100644 index 0000000..d158fdb --- /dev/null +++ b/fxgcppubsub/testdata/config/config.dev.yaml @@ -0,0 +1,6 @@ +app: + env: dev +modules: + log: + level: debug + output: test diff --git a/fxgcppubsub/testdata/config/config.test.yaml b/fxgcppubsub/testdata/config/config.test.yaml new file mode 100644 index 0000000..11807d5 --- /dev/null +++ b/fxgcppubsub/testdata/config/config.test.yaml @@ -0,0 +1,6 @@ +app: + env: test +modules: + log: + level: debug + output: test diff --git a/fxgcppubsub/testdata/config/config.yaml b/fxgcppubsub/testdata/config/config.yaml new file mode 100644 index 0000000..391406e --- /dev/null +++ b/fxgcppubsub/testdata/config/config.yaml @@ -0,0 +1,15 @@ +app: + name: test-app +modules: + gcppubsub: + project: + id: ${GCP_PROJECT_ID} + healthcheck: + topics: + - topic1 + - topic2 + - topic3 + subscriptions: + - subscription1 + - subscription2 + - subscription3 diff --git a/fxpubsub/healthcheck/probe.go b/fxpubsub/healthcheck/probe.go deleted file mode 100644 index 59e8e62..0000000 --- a/fxpubsub/healthcheck/probe.go +++ /dev/null @@ -1,43 +0,0 @@ -package healthcheck - -import ( - "context" - "fmt" - - "cloud.google.com/go/pubsub" - "github.com/ankorstore/yokai/config" - "github.com/ankorstore/yokai/healthcheck" -) - -type PubSubProbe struct { - config *config.Config - client *pubsub.Client -} - -func NewPubSubProbe(config *config.Config, client *pubsub.Client) *PubSubProbe { - return &PubSubProbe{ - config: config, - client: client, - } -} - -func (p *PubSubProbe) Name() string { - return "pubsub" -} - -func (p *PubSubProbe) Check(ctx context.Context) *healthcheck.CheckerProbeResult { - topicName := p.config.GetString("modules.pubsub.healthcheck.topics") - topic := p.client.Topic(topicName) - - exists, err := topic.Exists(ctx) - - if err != nil { - return healthcheck.NewCheckerProbeResult(false, "pubsub unreachable") - } - - if !exists { - return healthcheck.NewCheckerProbeResult(false, fmt.Sprintf("error: topic %s does not exist", topicName)) - } - - return healthcheck.NewCheckerProbeResult(true, fmt.Sprintf("success: topic %s exists", topicName)) -} diff --git a/fxpubsub/healthcheck/probe_test.go b/fxpubsub/healthcheck/probe_test.go deleted file mode 100644 index 599eaa1..0000000 --- a/fxpubsub/healthcheck/probe_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package healthcheck_test - -import ( - "context" - "fmt" - "testing" - "time" - - "cloud.google.com/go/pubsub" - "github.com/ankorstore/yokai-contrib/fxpubsub" - healthcheckpubsub "github.com/ankorstore/yokai-contrib/fxpubsub/healthcheck" - "github.com/ankorstore/yokai/config" - "github.com/ankorstore/yokai/fxconfig" - "github.com/ankorstore/yokai/healthcheck" - "github.com/stretchr/testify/assert" - "go.uber.org/fx" - "go.uber.org/fx/fxtest" -) - -func TestTopicExists(t *testing.T) { - t.Setenv("APP_ENV", "test") - t.Setenv("APP_CONFIG_PATH", "../testdata/config") - t.Setenv("GCP_PROJECT_ID", "worker-test") - - var client *pubsub.Client - var conf *config.Config - - app := fxtest.New( - t, - fx.NopLogger, - fxpubsub.FxPubSubModule, - fxconfig.FxConfigModule, - fx.Populate(&client, &conf), - ).RequireStart() - - topicName := conf.GetString("modules.pubsub.healthcheck.topics") - - _, err := client.CreateTopic(context.Background(), topicName) - - assert.NoError(t, err) - - p := healthcheckpubsub.NewPubSubProbe(conf, client) - check := p.Check(context.Background()) - - assert.Equal(t, healthcheck.NewCheckerProbeResult(true, fmt.Sprintf("success: topic %s exists", topicName)), check) - - app.RequireStop() -} - -func TestTopicMissing(t *testing.T) { - t.Setenv("APP_ENV", "test") - t.Setenv("APP_CONFIG_PATH", "../testdata/config") - t.Setenv("GCP_PROJECT_ID", "worker-test") - - var client *pubsub.Client - var conf *config.Config - - app := fxtest.New( - t, - fx.NopLogger, - fxpubsub.FxPubSubModule, - fxconfig.FxConfigModule, - fx.Populate(&client, &conf), - ).RequireStart() - - topicName := conf.GetString("modules.pubsub.healthcheck.topics") - - p := healthcheckpubsub.NewPubSubProbe(conf, client) - check := p.Check(context.Background()) - - assert.Equal(t, healthcheck.NewCheckerProbeResult(false, fmt.Sprintf("error: topic %s does not exist", topicName)), check) - - app.RequireStop() -} - -func TestPubSubIsFailing(t *testing.T) { - t.Setenv("APP_ENV", "test") - t.Setenv("APP_CONFIG_PATH", "../testdata/config") - t.Setenv("GCP_PROJECT_ID", "worker-test") - - var client *pubsub.Client - var conf *config.Config - - app := fxtest.New( - t, - fx.NopLogger, - fxpubsub.FxPubSubModule, - fxconfig.FxConfigModule, - fx.Populate(&client, &conf), - ).RequireStart() - - app.RequireStop() - - time.Sleep(1 * time.Second) - - p := healthcheckpubsub.NewPubSubProbe(conf, client) - check := p.Check(context.Background()) - - assert.Equal(t, healthcheck.NewCheckerProbeResult(false, "pubsub unreachable"), check) -} diff --git a/fxpubsub/testdata/config/config.dev.yaml b/fxpubsub/testdata/config/config.dev.yaml deleted file mode 100644 index 409f084..0000000 --- a/fxpubsub/testdata/config/config.dev.yaml +++ /dev/null @@ -1,3 +0,0 @@ -app: - name: dev-app - env: dev diff --git a/fxpubsub/testdata/config/config.test.yaml b/fxpubsub/testdata/config/config.test.yaml deleted file mode 100644 index 5bd46c8..0000000 --- a/fxpubsub/testdata/config/config.test.yaml +++ /dev/null @@ -1,3 +0,0 @@ -app: - name: test-app - env: test diff --git a/fxpubsub/testdata/config/config.yaml b/fxpubsub/testdata/config/config.yaml deleted file mode 100644 index 462dde2..0000000 --- a/fxpubsub/testdata/config/config.yaml +++ /dev/null @@ -1,9 +0,0 @@ -modules: - log: - level: debug - output: test - pubsub: - project: - id: ${GCP_PROJECT_ID} - healthcheck: - topics: test-topic diff --git a/release-please-config.json b/release-please-config.json index b6a6d26..7b0294c 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,4 +1,10 @@ { "separate-pull-requests": true, - "packages": {} + "packages": { + "fxgcppubsub": { + "release-type": "go", + "component": "fxgcppubsub", + "tag-separator": "/" + } + } }