Skip to content

Commit 057c845

Browse files
authored
fix: cross-module test coverage for mono repo tests (#89)
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
1 parent 4c8a213 commit 057c845

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

.github/workflows/collect-coverage.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ jobs:
2020
with:
2121
ref: ${{ github.event.pull_request.head.ref }}
2222
repository: ${{ github.event.pull_request.head.repo.full_name }}
23+
-
24+
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
25+
with:
26+
go-version: stable
27+
check-latest: true
28+
cache: true
2329
-
2430
name: Download coverage artifacts
2531
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
@@ -28,6 +34,19 @@ jobs:
2834
pattern: "*.coverage.*"
2935
# artifacts resolve as folders
3036
path: coverage/
37+
-
38+
name: Reprocess coverage paths
39+
# on projects with a v2 suffix, the go import path reported by coverage doesn't match
40+
# well the actual path. codecov knows about that for the root module, but is unable
41+
# to find its way with versioned go sub-modules.
42+
# We rewrite paths in coverage paths to match actual repo folders.
43+
run: |
44+
go list -m -f '{"name":{{ printf "%q" .Path }},"path":{{ printf "%q" .Dir }}}'|\
45+
jq -r '[.name,.path] | @tsv' |\
46+
while IFS=$'\t' read -r name path ; do
47+
target="github.com/${GITHUB_REPOSITORY}/${path#${GITHUB_WORKSPACE}/}"
48+
sed -i "s|${name}|${target}|" $(find coverage -type f -name \*.coverage.\*.out)
49+
done
3150
-
3251
name: Upload coverage to codecov
3352
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2

.github/workflows/go-test-monorepo.yml

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ jobs:
2525
bash-paths: ${{ steps.detect-monorepo.outputs.bash-paths }}
2626
bash-subpaths: ${{ steps.detect-monorepo.outputs.bash-subpaths }}
2727
module-names: ${{ steps.detect-monorepo.outputs.names }}
28+
coverpkg: ${{ steps.prepare-tests.outputs.coverpkg }}
29+
all-modules: ${{ steps.prepare-tests.outputs.all-modules }}
2830
steps:
2931
-
3032
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -59,6 +61,18 @@ jobs:
5961
version: latest
6062
only-new-issues: true
6163
skip-cache: true
64+
-
65+
name: Prepare tests
66+
id: prepare-tests
67+
run: |
68+
coverpkg=$(echo '${{ steps.detect-monorepo.outputs.names }}' | jq -rc '.[]|.+"/..."'|tr '\n' ','|head -c -1)
69+
echo "coverpkg=${coverpkg}" >> "${GITHUB_OUTPUT}"
70+
echo "::notice::title=coverpkg::${coverpkg}"
71+
72+
declare -a ALL_MODULES
73+
ALL_MODULES=(${{ steps.detect-monorepo.outputs.bash-subpaths }}) # a bash array with all module folders, suffixed with "/..."
74+
echo "all-modules=${ALL_MODULES[@]}" >> "${GITHUB_OUTPUT}"
75+
echo "::notice::title=Modules found::${ALL_MODULES[@]}"
6276
6377
# Carry out the linting the traditional way, within a shell loop
6478
#-
@@ -105,6 +119,7 @@ jobs:
105119
name: Ensure TMP is created on windows runners
106120
# On windows, some tests require testing.TempDir to reside on the same drive as the code.
107121
# TMP is used by os.TempDir() to determine the location of temporary files.
122+
# This is in particular the case for all programs that use [filepath.Rel].
108123
if: ${{ runner.os == 'Windows' }}
109124
shell: bash
110125
run: |
@@ -117,12 +132,15 @@ jobs:
117132
# with go.work file enabled, go test recognizes sub-modules and collects all packages to be covered
118133
# without specifying -coverpkg.
119134
#
135+
# However, cross-module test coverage is only reported with the appropriate -coverpkg setting.
136+
#
120137
# This requires:
121138
# * go.work properly initialized with use of all known modules
122139
# * go.work committed to git
123140
env:
124141
EXTRA_FLAGS: ${{ inputs.extra-flags }}
125142
run: >
143+
126144
gotestsum
127145
--jsonfile 'unit.report.${{ matrix.os }}-${{ matrix.go }}.json'
128146
--
@@ -133,7 +151,7 @@ jobs:
133151
-timeout=20m
134152
-coverprofile='unit.coverage.${{ matrix.os }}-${{ matrix.go }}.out'
135153
-covermode=atomic
136-
-coverpkg="$(go list)"/... ${EXTRA_FLAGS}
154+
-coverpkg='${{ needs.lint.outputs.coverpkg }}' ${EXTRA_FLAGS}
137155
./...
138156
-
139157
name: Run unit tests on all modules (<go1.25 or no go.work) [monorepo]
@@ -143,22 +161,19 @@ jobs:
143161
}}
144162
env:
145163
EXTRA_FLAGS: ${{ inputs.extra-flags }}
146-
run: |
147-
declare -a ALL_MODULES
148-
ALL_MODULES=(${{ needs.lint.outputs.bash-subpaths }}) # a bash array with all module folders, suffixed with "/..."
149-
echo "::notice title=Modules found::${ALL_MODULES[@]}"
150-
151-
gotestsum \
152-
--jsonfile 'unit.report.${{ matrix.os }}-${{ matrix.go }}.json' \
153-
-- \
154-
-race \
155-
-p 2 \
156-
-count 1 \
157-
-timeout=20m \
158-
-coverprofile='unit.coverage.${{ matrix.os }}-${{ matrix.go }}.out' \
159-
-covermode=atomic \
160-
-coverpkg="$(go list)"/... ${EXTRA_FLAGS} \
161-
${ALL_MODULES[@]}
164+
ALL_MODULES: ${{ needs.lint.outputs.all-modules }}
165+
run: >
166+
gotestsum
167+
--jsonfile 'unit.report.${{ matrix.os }}-${{ matrix.go }}.json'
168+
--
169+
-race
170+
-p 2
171+
-count 1
172+
-timeout=20m
173+
-coverprofile='unit.coverage.${{ matrix.os }}-${{ matrix.go }}.out'
174+
-covermode=atomic
175+
-coverpkg='${{ needs.lint.outputs.coverpkg }}' ${EXTRA_FLAGS}
176+
${ALL_MODULES}
162177
-
163178
name: Run unit tests
164179
if: ${{ needs.lint.outputs.is-monorepo != 'true' }}

0 commit comments

Comments
 (0)