Fix PostgreSQL helper test analyzer finding #1919
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| push: | |
| branches: ["master", "release/*", "feature/*"] | |
| pull_request_target: | |
| branches: ["master", "release/*", "feature/*", "devops/*"] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| id-token: write # needed by dorny/test-reporter | |
| checks: write # needed by dorny/test-reporter | |
| # Cancel any in-progress run for the same branch when a new push arrives | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| SOLUTION_NAME: SlimMessageBus.sln | |
| SOLUTION_CONFIGURATION: Release | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| jobs: | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # Build and unit-test (SonarCloud analysis runs separately in the sonar job) | |
| # ────────────────────────────────────────────────────────────────────────── | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout (PR – use fork's head SHA) | |
| if: github.event_name == 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Checkout | |
| if: github.event_name != 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: 10.0.x | |
| cache: false | |
| - name: Restore dependencies | |
| run: dotnet restore $SOLUTION_NAME | |
| working-directory: ./src | |
| - name: Build | |
| run: | | |
| dotnet build $SOLUTION_NAME \ | |
| --configuration $SOLUTION_CONFIGURATION \ | |
| --no-restore | |
| working-directory: ./src | |
| - name: Unit Tests | |
| run: | | |
| dotnet test $SOLUTION_NAME \ | |
| --configuration $SOLUTION_CONFIGURATION \ | |
| --no-build \ | |
| --verbosity normal \ | |
| --logger "trx;LogFilePrefix=Unit" \ | |
| --collect:"XPlat Code Coverage;Format=opencover" \ | |
| --filter "Category!=Integration" | |
| working-directory: ./src | |
| - name: Collect unit test coverage | |
| if: success() || failure() | |
| run: | | |
| mkdir -p ./coverage | |
| find ./src -name "coverage.opencover.xml" | while read file; do | |
| dir=$(basename $(dirname $(dirname "$file"))) | |
| guid=$(basename $(dirname "$file")) | |
| cp "$file" "./coverage/${dir}_${guid}.opencover.xml" | |
| done | |
| - name: Upload unit test coverage | |
| if: success() || failure() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: coverage-unit | |
| path: ./coverage | |
| - name: Collect unit test results | |
| if: success() || failure() | |
| run: | | |
| mkdir -p ./test-results | |
| find ./src -name "*.trx" | while read file; do | |
| grandparent_dir=$(basename $(dirname $(dirname "$file"))) | |
| filename=$(basename "$file") | |
| cp "$file" "./test-results/${grandparent_dir}_${filename}" | |
| done | |
| - name: Upload Unit Test Results | |
| if: success() || failure() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: test-results-unit | |
| path: ./test-results | |
| - name: Copy NuGet packages | |
| shell: bash | |
| run: | | |
| mkdir ./dist | |
| find -name "*.nupkg" -exec cp {} ./dist \; | |
| find -name "*.snupkg" -exec cp {} ./dist \; | |
| find ./dist | |
| - name: Archive NuGet packages | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: nuget-packages | |
| path: "./dist" | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # Integration tests – one parallel runner per transport | |
| # ────────────────────────────────────────────────────────────────────────── | |
| integration-tests: | |
| name: ${{ matrix.name }} | |
| needs: build | |
| # For fork PRs, this job waits for a maintainer to approve the "integration-tests" | |
| # environment before secrets are exposed and the PR's code runs against cloud infra. | |
| environment: ${{ (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository) && 'integration-tests' || '' }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false # don't cancel sibling legs when one fails | |
| matrix: | |
| include: | |
| # In-process transports (no external infrastructure required) | |
| - transport: Memory | |
| name: Memory | |
| filter: "Category=Integration&Transport=Memory" | |
| docker_services: "" | |
| # Local broker transports (started via docker compose) | |
| - transport: Kafka | |
| name: Kafka | |
| filter: "Category=Integration&Transport=Kafka" | |
| docker_services: "zookeeper kafka kafka-init" | |
| - transport: RabbitMQ | |
| name: RabbitMQ | |
| filter: "Category=Integration&Transport=RabbitMQ" | |
| docker_services: "rabbitmq" | |
| - transport: Redis | |
| name: Redis | |
| filter: "Category=Integration&Transport=Redis" | |
| docker_services: "redis" | |
| - transport: MQTT | |
| name: MQTT | |
| filter: "Category=Integration&Transport=MQTT" | |
| docker_services: "mqtt" | |
| # NATS connects to localhost:4222 via the nats_endpoint env var | |
| - transport: NATS | |
| name: NATS | |
| filter: "Category=Integration&Transport=NATS" | |
| docker_services: "nats" | |
| # SQL transports use TestContainers directly | |
| - transport: Sql | |
| name: SQL Server | |
| filter: "Category=Integration&Transport=Sql" | |
| test_path: "Tests/SlimMessageBus.Host.Sql.Test" | |
| docker_services: "" | |
| - transport: PostgreSql | |
| name: PostgreSQL | |
| filter: "Category=Integration&Transport=PostgreSql" | |
| test_path: "Tests/SlimMessageBus.Host.PostgreSql.Test" | |
| docker_services: "" | |
| # Outbox – four parallel sub-legs: | |
| # 1a. Sql.DbContext OutboxTests – AzureSB + Kafka; SQL Server via local docker | |
| - transport: Outbox.SqlDbContext.Tests | |
| name: "Outbox (SqlDbContext Tests)" | |
| filter: "Category=Integration&ClassName=SlimMessageBus.Host.Outbox.Sql.DbContext.Test.OutboxTests" | |
| test_path: "Tests/SlimMessageBus.Host.Outbox.Sql.DbContext.Test" | |
| docker_services: "sqldb zookeeper kafka kafka-init" | |
| local_sql_connection: "Server=localhost;Initial Catalog=SlimMessageBus_Outbox;User ID=sa;Password=SuperSecretP@55word;TrustServerCertificate=true;MultipleActiveResultSets=true;" | |
| # 1b. Sql.DbContext OutboxBenchmarkTests – AzureSB + RabbitMQ; SQL Server via local docker | |
| - transport: Outbox.SqlDbContext.Benchmarks | |
| name: "Outbox (SqlDbContext Benchmarks)" | |
| filter: "Category=Integration&ClassName=SlimMessageBus.Host.Outbox.Sql.DbContext.Test.OutboxBenchmarkTests" | |
| test_path: "Tests/SlimMessageBus.Host.Outbox.Sql.DbContext.Test" | |
| docker_services: "sqldb rabbitmq" | |
| local_sql_connection: "Server=localhost;Initial Catalog=SlimMessageBus_Outbox;User ID=sa;Password=SuperSecretP@55word;TrustServerCertificate=true;MultipleActiveResultSets=true;" | |
| # 2. PostgreSql.DbContext – PostgreSQL, Kafka, RabbitMQ all via TestContainers | |
| - transport: Outbox.PostgreSqlDbContext | |
| name: "Outbox (PostgreSqlDbContext)" | |
| filter: "Category=Integration" | |
| test_path: "Tests/SlimMessageBus.Host.Outbox.PostgreSql.DbContext.Test" | |
| docker_services: "" | |
| # 3. Repository-layer tests – Sql.Test + PostgreSql.Test + MongoDb.Test, all via TestContainers | |
| - transport: Outbox.Repositories | |
| name: "Outbox (Repositories)" | |
| filter: "Category=Integration&Transport=Outbox.Sql" | |
| test_path: "" | |
| docker_services: "" | |
| # 4. MongoDb outbox repository tests – via TestContainers | |
| - transport: Outbox.MongoDb | |
| name: "Outbox (MongoDb)" | |
| filter: "Category=Integration&Transport=Outbox.MongoDb" | |
| test_path: "Tests/SlimMessageBus.Host.Outbox.MongoDb.Test" | |
| docker_services: "" | |
| # Cloud transports (require repository secrets) | |
| - transport: AmazonSQS | |
| name: AmazonSQS | |
| filter: "Category=Integration&Transport=AmazonSQS" | |
| docker_services: "" | |
| - transport: AzureServiceBus | |
| name: AzureServiceBus | |
| filter: "Category=Integration&Transport=AzureServiceBus" | |
| docker_services: "" | |
| - transport: AzureEventHub | |
| name: AzureEventHub | |
| filter: "Category=Integration&Transport=AzureEventHub" | |
| docker_services: "" | |
| steps: | |
| - name: Checkout (PR – use fork's head SHA) | |
| if: github.event_name == 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Checkout | |
| if: github.event_name != 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: 10.0.x | |
| cache: false | |
| - name: Restore dependencies | |
| run: dotnet restore $SOLUTION_NAME | |
| working-directory: ./src | |
| - name: Build | |
| run: | | |
| dotnet build $SOLUTION_NAME \ | |
| --configuration $SOLUTION_CONFIGURATION \ | |
| --no-restore | |
| working-directory: ./src | |
| - name: Start infrastructure services | |
| if: matrix.docker_services != '' | |
| run: | | |
| docker compose -f src/Infrastructure/docker-compose.yml up --wait --force-recreate -V ${{ matrix.docker_services }} | |
| - name: Integration Tests | |
| run: | | |
| TEST_TARGET="${{ matrix.test_path }}" | |
| [ -z "$TEST_TARGET" ] && TEST_TARGET="$SOLUTION_NAME" | |
| dotnet test "$TEST_TARGET" \ | |
| --configuration $SOLUTION_CONFIGURATION \ | |
| --no-build \ | |
| --verbosity normal \ | |
| --logger "trx;LogFilePrefix=Integration_${{ matrix.transport }}" \ | |
| --collect:"XPlat Code Coverage;Format=opencover" \ | |
| --filter "${{ matrix.filter }}" | |
| working-directory: ./src | |
| env: | |
| # Azure cloud | |
| azure_servicebus_connectionstring: ${{ secrets.azure_servicebus_connectionstring }} | |
| azure_eventhub_connectionstring: ${{ secrets.azure_eventhub_connectionstring }} | |
| azure_storagecontainer_connectionstring: ${{ secrets.azure_storagecontainer_connectionstring }} | |
| # AWS cloud | |
| amazon_access_key: ${{ secrets.amazon_access_key }} | |
| amazon_secret_access_key: ${{ secrets.amazon_secret_access_key }} | |
| # Cloud broker overrides (prefixed with _ so local values take precedence) | |
| _kafka_brokers: ${{ secrets.kafka_brokers }} | |
| _kafka_username: ${{ secrets.kafka_username }} | |
| _kafka_password: ${{ secrets.kafka_password }} | |
| _kafka_secure: ${{ secrets.kafka_secure }} | |
| _mqtt_server: ${{ secrets.mqtt_server }} | |
| _mqtt_port: ${{ secrets.mqtt_port }} | |
| _mqtt_username: ${{ secrets.mqtt_username }} | |
| _mqtt_password: ${{ secrets.mqtt_password }} | |
| _mqtt_secure: ${{ secrets.mqtt_secure }} | |
| _rabbitmq_connectionstring: ${{ secrets.rabbitmq_connectionstring }} | |
| _redis_connectionstring: ${{ secrets.redis_connectionstring }} | |
| # local_sql_connection takes priority (set per matrix leg that uses docker sqldb) | |
| sqlserver_connectionstring: ${{ matrix.local_sql_connection || secrets.sqlserver_connectionstring }} | |
| # Local TestContainers / docker compose values | |
| kafka_brokers: localhost:9092 | |
| kafka_username: user | |
| kafka_password: password | |
| kafka_secure: false | |
| mqtt_server: localhost | |
| mqtt_port: 1883 | |
| mqtt_username: "(empty)" | |
| mqtt_password: "(empty)" | |
| mqtt_secure: false | |
| rabbitmq_connectionstring: amqp://localhost | |
| redis_connectionstring: localhost:6379 | |
| _sqlserver_connectionstring: "Server=localhost;Initial Catalog=SlimMessageBus_Outbox;User ID=sa;Password=SuperSecretP@55word;TrustServerCertificate=true;MultipleActiveResultSets=true;" | |
| nats_endpoint: "nats://localhost:4222" | |
| - name: Collect integration test results | |
| if: success() || failure() | |
| run: | | |
| mkdir -p ./test-results | |
| find ./src -name "*.trx" | while read file; do | |
| grandparent_dir=$(basename $(dirname $(dirname "$file"))) | |
| filename=$(basename "$file") | |
| cp "$file" "./test-results/${grandparent_dir}_${filename}" | |
| done | |
| - name: Upload Test Results | |
| if: success() || failure() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: test-results-${{ matrix.transport }} | |
| path: ./test-results | |
| - name: Collect integration test coverage | |
| if: success() || failure() | |
| run: | | |
| mkdir -p ./coverage | |
| find ./src -name "coverage.opencover.xml" | while read file; do | |
| dir=$(basename $(dirname $(dirname "$file"))) | |
| guid=$(basename $(dirname "$file")) | |
| cp "$file" "./coverage/${dir}_${guid}.opencover.xml" | |
| done | |
| - name: Upload integration test coverage | |
| if: success() || failure() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: coverage-${{ matrix.transport }} | |
| path: ./coverage | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # SonarCloud analysis – runs after all tests so full coverage is included | |
| # ────────────────────────────────────────────────────────────────────────── | |
| sonar: | |
| needs: [build, integration-tests] | |
| if: success() || failure() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout (PR – use fork's head SHA) | |
| if: github.event_name == 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Checkout | |
| if: github.event_name != 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: 10.0.x | |
| cache: false | |
| - name: Restore dependencies | |
| run: dotnet restore $SOLUTION_NAME | |
| working-directory: ./src | |
| - name: Setup Java17 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: "adopt" | |
| java-version: "17" | |
| - name: Install SonarCloud scanner | |
| run: dotnet tool update dotnet-sonarscanner --tool-path ./.sonar/scanner | |
| - name: Download all coverage reports | |
| uses: actions/download-artifact@v6 | |
| with: | |
| pattern: coverage-* | |
| path: ./coverage | |
| merge-multiple: true | |
| - name: SonarScanner Begin | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| run: | | |
| params="" | |
| pr_number="${{ github.event.pull_request.number }}" | |
| if [[ -n "$pr_number" ]]; then | |
| params="/d:sonar.pullrequest.key=${pr_number}" | |
| fi | |
| ../.sonar/scanner/dotnet-sonarscanner begin /k:"zarusz_SlimMessageBus" /o:"zarusz" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="../coverage/*.opencover.xml" /d:sonar.exclusions="Samples/**/*,Tests/**/*" $params | |
| working-directory: ./src | |
| - name: Build | |
| run: | | |
| dotnet build $SOLUTION_NAME \ | |
| --configuration $SOLUTION_CONFIGURATION \ | |
| --no-restore | |
| working-directory: ./src | |
| - name: SonarScanner End | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| run: ../.sonar/scanner/dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" | |
| working-directory: ./src | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # Collect all test results from every job and publish a single report | |
| # ────────────────────────────────────────────────────────────────────────── | |
| report: | |
| needs: [build, integration-tests] | |
| if: success() || failure() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout (PR – use fork's head SHA) | |
| if: github.event_name == 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Checkout | |
| if: github.event_name != 'pull_request_target' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download all test results | |
| uses: actions/download-artifact@v6 | |
| with: | |
| pattern: test-results-* | |
| path: ./test-results | |
| merge-multiple: true | |
| - name: Publish Test Results | |
| uses: dorny/test-reporter@v2 | |
| with: | |
| name: .NET Tests | |
| path: ./test-results/*.trx | |
| reporter: dotnet-trx | |
| fail-on-error: true | |