From 1fd39c2a340a581d55aa66983bbfec7eb8933f55 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 12 Feb 2026 17:20:44 +0100 Subject: [PATCH 1/4] feat: enables runtime coverage for services that run in containers --- .github/workflows/go_app_pull_requests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/go_app_pull_requests.yml b/.github/workflows/go_app_pull_requests.yml index 1651b9b..e76bab6 100644 --- a/.github/workflows/go_app_pull_requests.yml +++ b/.github/workflows/go_app_pull_requests.yml @@ -176,11 +176,13 @@ jobs: name: junit-report-${{ strategy.job-index }} token: ${{ secrets.CODECOV_TOKEN }} # Integration tests (conditional, per-module) + # INTEGRATION_COVERAGE=true enables runtime coverage collection for services + # that run in Docker containers (e.g., testcontainers-based tests) - name: integration tests if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} working-directory: ${{ matrix.module }} run: | - go test -v ${{ inputs.GO_TEST_INTEGRATION_TAGS }} -timeout ${{ inputs.GO_TEST_INTEGRATION_TIMEOUT }} ./... \ + INTEGRATION_COVERAGE=true go test -v ${{ inputs.GO_TEST_INTEGRATION_TAGS }} -timeout ${{ inputs.GO_TEST_INTEGRATION_TIMEOUT }} ./... \ | tee integration_test_output.txt - name: Build Integration Test Junit report if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} From f7da1260400c5f86ff03d0d8d80d582d03a5da43 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 13 Feb 2026 10:14:29 +0100 Subject: [PATCH 2/4] chore: merge both reports to send to codecov --- .github/workflows/go_app_pull_requests.yml | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go_app_pull_requests.yml b/.github/workflows/go_app_pull_requests.yml index e76bab6..df3f44c 100644 --- a/.github/workflows/go_app_pull_requests.yml +++ b/.github/workflows/go_app_pull_requests.yml @@ -207,10 +207,27 @@ jobs: - name: build coverage.txt working-directory: ${{ matrix.module }} run: | - if [ -d coverage/int ] && [ "$(ls -A coverage/int)" ]; then - go tool covdata textfmt -i=./coverage/int,./coverage/unit -o coverage.txt - else + HAS_UNIT=false + HAS_INT=false + if [ -d coverage/unit ] && [ "$(ls -A coverage/unit 2>/dev/null)" ]; then + HAS_UNIT=true + fi + if [ -d coverage/int ] && [ "$(ls -A coverage/int 2>/dev/null)" ]; then + HAS_INT=true + fi + + if [ "$HAS_UNIT" = true ] && [ "$HAS_INT" = true ]; then + echo "Combining unit and integration coverage" + go tool covdata textfmt -i=./coverage/unit,./coverage/int -o coverage.txt + elif [ "$HAS_UNIT" = true ]; then + echo "Using unit coverage only" go tool covdata textfmt -i=./coverage/unit -o coverage.txt + elif [ "$HAS_INT" = true ]; then + echo "Using integration coverage only" + go tool covdata textfmt -i=./coverage/int -o coverage.txt + else + echo "No coverage data found" + echo "mode: set" > coverage.txt fi - name: Upload test coverage results to Codecov uses: codecov/codecov-action@v4 From 6cd40afd37e06b29f64e9f899f2b0652722fdf09 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 13 Feb 2026 10:21:35 +0100 Subject: [PATCH 3/4] chore: including go integration test result --- .github/workflows/go_app_pull_requests.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go_app_pull_requests.yml b/.github/workflows/go_app_pull_requests.yml index df3f44c..36b0525 100644 --- a/.github/workflows/go_app_pull_requests.yml +++ b/.github/workflows/go_app_pull_requests.yml @@ -176,14 +176,16 @@ jobs: name: junit-report-${{ strategy.job-index }} token: ${{ secrets.CODECOV_TOKEN }} # Integration tests (conditional, per-module) - # INTEGRATION_COVERAGE=true enables runtime coverage collection for services - # that run in Docker containers (e.g., testcontainers-based tests) + # Coverage is collected from two sources: + # 1. Go integration tests running in-process (via -cover and -test.gocoverdir) + # 2. Services running in Docker containers (via INTEGRATION_COVERAGE=true env var) - name: integration tests if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} working-directory: ${{ matrix.module }} run: | - INTEGRATION_COVERAGE=true go test -v ${{ inputs.GO_TEST_INTEGRATION_TAGS }} -timeout ${{ inputs.GO_TEST_INTEGRATION_TIMEOUT }} ./... \ - | tee integration_test_output.txt + INTEGRATION_COVERAGE=true go test -cover -v ${{ inputs.GO_TEST_INTEGRATION_TAGS }} -timeout ${{ inputs.GO_TEST_INTEGRATION_TIMEOUT }} ./... \ + -args -test.gocoverdir="${{ github.workspace }}/${{ matrix.module }}/coverage/int" \ + 2>&1 | tee integration_test_output.txt - name: Build Integration Test Junit report if: ${{ inputs.GO_TEST_INTEGRATION_ENABLED }} working-directory: ${{ matrix.module }} From c7e4861cf669e4f0cdd7882fabd2109670e3b2dc Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 13 Feb 2026 11:28:47 +0100 Subject: [PATCH 4/4] chore: fix --- .github/workflows/go_app_pull_requests.yml | 54 ++++++++++++---------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/.github/workflows/go_app_pull_requests.yml b/.github/workflows/go_app_pull_requests.yml index 36b0525..bdecc1d 100644 --- a/.github/workflows/go_app_pull_requests.yml +++ b/.github/workflows/go_app_pull_requests.yml @@ -151,11 +151,11 @@ jobs: run: | mkdir -p ${{ matrix.module }}/coverage/unit mkdir -p ${{ matrix.module }}/coverage/int - # Run unit tests for the module. + # Run unit tests with race detector and coverage - name: go test working-directory: ${{ matrix.module }} run: | - go test -cover --race -v ${{ inputs.GO_TEST_UNIT_TAGS }} ./... \ + go test -cover -race -v ${{ inputs.GO_TEST_UNIT_TAGS }} ./... \ -args -test.gocoverdir="${{ github.workspace }}/${{ matrix.module }}/coverage/unit" \ 2>&1 | tee unit_test_output.txt - name: Build Unit Test Junit report @@ -205,39 +205,45 @@ jobs: files: ${{ matrix.module }}/junit_integration_report.xml name: junit-integration-report-${{ strategy.job-index }} token: ${{ secrets.CODECOV_TOKEN }} - # Coverage handling - - name: build coverage.txt + # Coverage handling - upload unit and integration separately + # (they use different coverage modes: atomic vs set, so can't be combined locally) + # Codecov will merge them automatically + - name: build unit coverage working-directory: ${{ matrix.module }} run: | - HAS_UNIT=false - HAS_INT=false if [ -d coverage/unit ] && [ "$(ls -A coverage/unit 2>/dev/null)" ]; then - HAS_UNIT=true + echo "Converting unit coverage to text format" + go tool covdata textfmt -i=./coverage/unit -o coverage-unit.txt + else + echo "No unit coverage data found" fi + - name: build integration coverage + working-directory: ${{ matrix.module }} + run: | if [ -d coverage/int ] && [ "$(ls -A coverage/int 2>/dev/null)" ]; then - HAS_INT=true - fi - - if [ "$HAS_UNIT" = true ] && [ "$HAS_INT" = true ]; then - echo "Combining unit and integration coverage" - go tool covdata textfmt -i=./coverage/unit,./coverage/int -o coverage.txt - elif [ "$HAS_UNIT" = true ]; then - echo "Using unit coverage only" - go tool covdata textfmt -i=./coverage/unit -o coverage.txt - elif [ "$HAS_INT" = true ]; then - echo "Using integration coverage only" - go tool covdata textfmt -i=./coverage/int -o coverage.txt + echo "Converting integration coverage to text format" + go tool covdata textfmt -i=./coverage/int -o coverage-int.txt else - echo "No coverage data found" - echo "mode: set" > coverage.txt + echo "No integration coverage data found" fi - - name: Upload test coverage results to Codecov + - name: Upload unit test coverage to Codecov + if: ${{ hashFiles(format('{0}/coverage-unit.txt', matrix.module)) != '' }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} - files: ${{ matrix.module }}/coverage.txt + files: ${{ matrix.module }}/coverage-unit.txt + flags: unit verbose: true - fail_ci_if_error: true # optional (default = false) + fail_ci_if_error: false + - name: Upload integration test coverage to Codecov + if: ${{ hashFiles(format('{0}/coverage-int.txt', matrix.module)) != '' }} + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ${{ matrix.module }}/coverage-int.txt + flags: integration + verbose: true + fail_ci_if_error: false docker-build: # # ensures the docker image will build without pushing to the registry