Skip to content
This repository was archived by the owner on Oct 22, 2024. It is now read-only.

Commit 50a55e6

Browse files
authored
Merge pull request #1066 from pohly/coverage-jenkins
WIP: code coverage
2 parents 8ed05e3 + df745a8 commit 50a55e6

File tree

18 files changed

+284
-78
lines changed

18 files changed

+284
-78
lines changed

Jenkinsfile

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ pipeline {
6868
TEST_ETCD_TMPFS = "${WORKSPACE}/_work/${env.CLUSTER}/data/pmem-csi-${env.CLUSTER}-master/etcd-tmpfs"
6969
TEST_ETCD_VOLUME = "${env.TEST_ETCD_TMPFS}/etcd-volume"
7070
TEST_ETCD_VOLUME_SIZE = "1073741824" // 1GB
71+
72+
// Tests that will get skipped when collecting coverage information.
73+
//
74+
// The operator itself installs without enabling coverage collection,
75+
// so running those tests doesn't help us. The relevant test is
76+
// "operator API".
77+
//
78+
// Testing with OLM doesn't add much additional coverage.
79+
COVERAGE_SKIP = "[email protected]@Top.Level..olm"
7180
}
7281

7382
stages {
@@ -183,7 +192,21 @@ pipeline {
183192
stage('1.22') {
184193
steps {
185194
// Skip production, i.e. run testing.
186-
TestInVM("", "fedora", "", "1.22", "Top.Level..[[:alpha:]]*-production[[:space:]]")
195+
TestInVM("", "", "fedora", "", "1.22", "Top.Level..[[:alpha:]]*-production[[:space:]]", "")
196+
}
197+
}
198+
199+
// When adding or removing coverage workers, update the "Code Coverage" step below!
200+
stage('coverage-1.22') {
201+
when {
202+
beforeAgent true
203+
not { changeRequest() }
204+
}
205+
agent {
206+
label "pmem-csi"
207+
}
208+
steps {
209+
TestInVM("fedora-coverage-1.22", "coverage-", "fedora", "", "1.22", "", "${env.COVERAGE_SKIP}")
187210
}
188211
}
189212

@@ -197,7 +220,7 @@ pipeline {
197220
label "pmem-csi"
198221
}
199222
steps {
200-
TestInVM("fedora-1.21", "fedora", "", "1.21", "")
223+
TestInVM("fedora-1.21", "", "fedora", "", "1.21", "", "")
201224
}
202225
}
203226
stage('1.20') {
@@ -209,7 +232,7 @@ pipeline {
209232
label "pmem-csi"
210233
}
211234
steps {
212-
TestInVM("fedora-1.20", "fedora", "", "1.20", "")
235+
TestInVM("fedora-1.20", "", "fedora", "", "1.20", "", "")
213236
}
214237
}
215238
stage('1.19') {
@@ -218,7 +241,19 @@ pipeline {
218241
}
219242
steps {
220243
// Skip testing, i.e. run production.
221-
TestInVM("fedora-1.19", "fedora", "", "1.19", "Top.Level..[[:alpha:]]*-testing[[:space:]]")
244+
TestInVM("fedora-1.19", "", "fedora", "", "1.19", "Top.Level..[[:alpha:]]*-testing[[:space:]]", "")
245+
}
246+
}
247+
stage('coverage-1.19') {
248+
when {
249+
beforeAgent true
250+
not { changeRequest() }
251+
}
252+
agent {
253+
label "pmem-csi"
254+
}
255+
steps {
256+
TestInVM("fedora-coverage-1.19", "coverage-", "fedora", "", "1.19", "", "${env.COVERAGE_SKIP}")
222257
}
223258
}
224259
}
@@ -291,6 +326,43 @@ git push origin HEAD:master
291326
sh "${RunInBuilder()} ${env.BUILD_CONTAINER} docker image push ${env.BUILD_IMAGE}"
292327
}
293328
}
329+
330+
// Merge and publish coverage data.
331+
stage('Code Coverage') {
332+
when {
333+
not { changeRequest() }
334+
}
335+
steps {
336+
// Restore <cluster>-coverage.out files.
337+
unstash '1.22-coverage'
338+
unstash '1.19-coverage'
339+
340+
// Merge and convert to Cobertura XML.
341+
sh "${RunInBuilder()} ${env.BUILD_CONTAINER} make _work/gocovmerge _work/gocover-cobertura"
342+
sh "${RunInBuilder()} ${env.BUILD_CONTAINER} _work/gocovmerge *-coverage.out >coverage.out"
343+
sh "${RunInBuilder()} ${env.BUILD_CONTAINER} go tool cover -func coverage.out"
344+
sh "${RunInBuilder()} ${env.BUILD_CONTAINER} _work/gocover-cobertura <coverage.out >coverage.xml"
345+
346+
// Simplify relative paths ("github.com/intel/pmem-csi/...").
347+
// To view source code (https://stackoverflow.com/a/59951809):
348+
// - Jenkins users must be logged in.
349+
// - A job must complete successfully.
350+
sh "sed -i -e 's;filename=\"github.com/intel/pmem-csi/;filename=\";g' coverage.xml"
351+
352+
// The relationship between "Code Coverage API Plugin" and "Cobertura" plugin is not clear
353+
// (https://stackoverflow.com/questions/71133394/what-is-the-relationship-between-the-jenkins-cobertura-and-code-coverage-api).
354+
//
355+
// With just "Code Coverage API Plugin" installed, this here works, but doesn't show source code
356+
// (old UI?):
357+
// publishCoverage adapters: [cobertura(path: 'coverage.xml')], tag: 't'
358+
359+
// When both are installed, this here works (note the different coberura parameter!)
360+
// and shows source code.
361+
publishCoverage adapters: [cobertura(coberturaReportFile: 'coverage.xml')]
362+
363+
// There is also a "coberturaAdapter". That one hasn't been tested.
364+
}
365+
}
294366
}
295367
}
296368

@@ -313,6 +385,7 @@ git push origin HEAD:master
313385
String RunInBuilder() {
314386
"\
315387
docker exec \
388+
-i \
316389
-e CACHEBUST=${env.CACHEBUST} \
317390
-e 'BUILD_ARGS=--cache-from ${env.BUILD_IMAGE} --cache-from ${env.PMEM_CSI_IMAGE}' \
318391
-e DOCKER_CONFIG=${WORKSPACE}/_work/docker-config \
@@ -436,10 +509,13 @@ void RestoreEnv() {
436509
done"
437510
}
438511

439-
void TestInVM(worker, distro, distroVersion, kubernetesVersion, skipIfPR) {
512+
void TestInVM(worker, coverage, distro, distroVersion, kubernetesVersion, skipIfPR, skipAlways) {
440513
if (worker) {
441514
RestoreEnv()
442515
}
516+
if (coverage) {
517+
sh "${RunInBuilder()} -e CLUSTER=${env.CLUSTER} ${env.BUILD_CONTAINER} make kustomize KUSTOMIZE_WITH_COVERAGE=true"
518+
}
443519
try { timeout(unit: "HOURS", time: TestTimeoutHours()) {
444520
/*
445521
We have to run "make start" in the current directory
@@ -463,7 +539,7 @@ void TestInVM(worker, distro, distroVersion, kubernetesVersion, skipIfPR) {
463539
so for now we disable VMX with -vmx.
464540
*/
465541
sh "#!/bin/bash\n \
466-
echo Note: job output is filtered, see joblog-${BUILD_TAG}-test-${kubernetesVersion}.log artifact for full output. && \
542+
echo Note: job output is filtered, see joblog-${BUILD_TAG}-test-${coverage}${kubernetesVersion}.log artifact for full output. && \
467543
set -o pipefail && \
468544
( \
469545
loggers=; \
@@ -508,10 +584,10 @@ void TestInVM(worker, distro, distroVersion, kubernetesVersion, skipIfPR) {
508584
done | sed -e \"s/^/\$hostname: /\" ) & \
509585
loggers=\"\$loggers \$!\"; \
510586
done && \
511-
testrun=\$(echo '${distro}-${distroVersion}-${kubernetesVersion}' | sed -e s/--*/-/g | tr . _ ) && \
587+
testrun=\$(echo '${distro}-${distroVersion}-${coverage}${kubernetesVersion}' | sed -e s/--*/-/g | tr . _ ) && \
512588
make test_e2e TEST_E2E_REPORT_DIR=${WORKSPACE}/build/reports.tmp/\$testrun \
513-
TEST_E2E_SKIP=\$(if [ \"${env.CHANGE_ID}\" ] && [ \"${env.CHANGE_ID}\" != null ]; then echo \\\\[Slow\\\\]@${skipIfPR}; fi) \
514-
') 2>&1 | tee joblog-${BUILD_TAG}-test-${kubernetesVersion}.log | grep --line-buffered -E -e 'checking for test|Passed|FAIL:|^ERROR' \
589+
TEST_E2E_SKIP=${skipAlways}@\$(if [ \"${env.CHANGE_ID}\" ] && [ \"${env.CHANGE_ID}\" != null ]; then echo \\\\[Slow\\\\]@${skipIfPR}; fi) \
590+
') 2>&1 | tee joblog-${BUILD_TAG}-test-${coverage}${kubernetesVersion}.log | grep --line-buffered -E -e 'checking for test|Passed|FAIL:|^ERROR' \
515591
"
516592
} } finally {
517593
echo "Writing cluster state and kubelet logs into files."
@@ -545,6 +621,20 @@ void TestInVM(worker, distro, distroVersion, kubernetesVersion, skipIfPR) {
545621
done'''
546622
archiveArtifacts('**/joblog-*')
547623
junit 'build/reports/**/*.xml'
624+
625+
if (coverage) {
626+
// https://stackoverflow.com/questions/36918370/cobertura-code-coverage-report-for-jenkins-pipeline-jobs
627+
// https://www.jenkins.io/doc/pipeline/steps/cobertura/
628+
sh "${RunInBuilder()} -e CLUSTER=${env.CLUSTER} ${env.BUILD_CONTAINER} make _work/coverage/coverage.txt"
629+
sh "cat _work/coverage/coverage.txt"
630+
631+
// https://plugins.jenkins.io/code-coverage-api/#plugin-content-reports-combining-support
632+
// claims that different reports can be merged, but that didn't work in practice
633+
// (two "coverage reports" listed in the job UI with the same URL and unmerged data from
634+
// one worker). Therefore we stash the individual results and merge later.
635+
sh "mv _work/coverage/coverage.out ${kubernetesVersion}-coverage.out"
636+
stash includes: "${kubernetesVersion}-coverage.out", name: "${kubernetesVersion}-coverage"
637+
}
548638
}
549639
}
550640

Makefile

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,23 @@ KUSTOMIZE_INPUT := $(shell [ ! -d deploy/kustomize ] || find deploy/kustomize -t
159159
# Output files and their corresponding kustomization, in the format <target .yaml>=<kustomization directory>
160160
KUSTOMIZE :=
161161

162+
# Setting this to any non-empty value before "make kustomize" will enable
163+
# collection of coverage profiles in all deployments. This also sets up the
164+
# original deployment files under "deploy/nocoverage" for use as reference when
165+
# testing the operator.
166+
KUSTOMIZE_WITH_COVERAGE =
167+
ifneq "$(KUSTOMIZE_WITH_COVERAGE)" ""
168+
KUSTOMIZE_COVERAGE_SUFFIX = -coverage
169+
endif
170+
162171
# For each supported Kubernetes version, we provide four different flavors.
163172
# The "testing" flavor of the generated files contains both
164173
# the loglevel changes but does not enable coverage data collection.
165174
KUSTOMIZE_KUBERNETES_OUTPUT = \
166-
deploy/kubernetes-X.XX/pmem-csi-direct.yaml=deploy/kustomize/kubernetes-base-direct \
167-
deploy/kubernetes-X.XX/pmem-csi-lvm.yaml=deploy/kustomize/kubernetes-base-lvm \
168-
deploy/kubernetes-X.XX/pmem-csi-direct-testing.yaml=deploy/kustomize/kubernetes-base-direct-testing \
169-
deploy/kubernetes-X.XX/pmem-csi-lvm-testing.yaml=deploy/kustomize/kubernetes-base-lvm-testing \
175+
deploy/kubernetes-X.XX/pmem-csi-direct.yaml=deploy/kustomize/kubernetes-base-direct$(KUSTOMIZE_COVERAGE_SUFFIX) \
176+
deploy/kubernetes-X.XX/pmem-csi-lvm.yaml=deploy/kustomize/kubernetes-base-lvm$(KUSTOMIZE_COVERAGE_SUFFIX) \
177+
deploy/kubernetes-X.XX/pmem-csi-direct-testing.yaml=deploy/kustomize/kubernetes-base-direct-testing$(KUSTOMIZE_COVERAGE_SUFFIX) \
178+
deploy/kubernetes-X.XX/pmem-csi-lvm-testing.yaml=deploy/kustomize/kubernetes-base-lvm-testing$(KUSTOMIZE_COVERAGE_SUFFIX) \
170179

171180
# Kubernetes versions derived from kubernetes-base.
172181
#
@@ -199,14 +208,22 @@ KUSTOMIZE_OUTPUT := $(foreach item,$(KUSTOMIZE),$(firstword $(subst =, ,$(item))
199208
# right one.
200209
KUSTOMIZE_LOOKUP_KUSTOMIZATION = $(strip $(foreach item,$(KUSTOMIZE),$(if $(filter $(1)=%,$(item)),$(word 2,$(subst =, ,$(item))))))
201210

211+
# This is a wrapper around KUSTOMIZE_LOOKUP_KUSTOMIZATION which
212+
# removes the -coverage suffix.
213+
KUSTOMIZE_LOOKUP_KUSTOMIZATION_NO_COVERAGE = $(subst -coverage,,$(call KUSTOMIZE_LOOKUP_KUSTOMIZATION,$(1)))
214+
202215
# This function takes the kustomize binary and the name of an output
203216
# file as arguments and returns the command which produces that file
204217
# as stdout.
205-
KUSTOMIZE_INVOCATION = (echo '\# Generated with "make kustomize", do not edit!'; echo; $(1) build --load-restrictor LoadRestrictionsNone $(call KUSTOMIZE_LOOKUP_KUSTOMIZATION,$(2)))
218+
KUSTOMIZE_INVOCATION = (echo '\# Generated with "make kustomize", do not edit!'; echo; $(1) build --load-restrictor LoadRestrictionsNone $(call $(3),$(2)))
206219

207220
$(KUSTOMIZE_OUTPUT): _work/kustomize $(KUSTOMIZE_INPUT)
208221
mkdir -p ${@D}
209-
$(call KUSTOMIZE_INVOCATION,$<,$@) >$@
222+
$(call KUSTOMIZE_INVOCATION,$<,$@,KUSTOMIZE_LOOKUP_KUSTOMIZATION) >$@
223+
ifneq "$(KUSTOMIZE_WITH_COVERAGE)" ""
224+
mkdir -p $(subst deploy/,deploy/nocoverage/,${@D})
225+
$(call KUSTOMIZE_INVOCATION,$<,$@,KUSTOMIZE_LOOKUP_KUSTOMIZATION_NO_COVERAGE) >$(subst deploy/,deploy/nocoverage/,$@)
226+
endif
210227
if echo "$@" | grep '/pmem-csi-' | grep -qv '\-operator'; then \
211228
dir=$$(echo "$@" | tr - / | sed -e 's;kubernetes/;kubernetes-;' -e 's;/alpha/;-alpha/;' -e 's;/distributed/;-distributed/;' -e 's/.yaml//' -e 's;/pmem/csi/;/;') && \
212229
mkdir -p $$dir && \
@@ -215,9 +232,13 @@ $(KUSTOMIZE_OUTPUT): _work/kustomize $(KUSTOMIZE_INPUT)
215232
fi
216233

217234
kustomize: clean_kustomize_output $(KUSTOMIZE_OUTPUT)
235+
ifneq "$(KUSTOMIZE_WITH_COVERAGE)" ""
236+
sed -i -e 's/embed kubernetes-/embed nocoverage kubernetes-/' deploy/yamls.go
237+
endif
218238

219239
clean_kustomize_output:
220-
rm -rf deploy/kubernetes-*
240+
rm -rf deploy/kubernetes-* deploy/nocoverage
241+
sed -i -e 's/embed nocoverage /embed /' deploy/yamls.go
221242
rm -f $(KUSTOMIZE_OUTPUT)
222243

223244
# Always re-generate the output files because "git rebase" might have
@@ -234,7 +255,7 @@ clean-kustomize:
234255
test: test-kustomize
235256
test-kustomize: $(addprefix test-kustomize-,$(KUSTOMIZE_OUTPUT))
236257
$(addprefix test-kustomize-,$(KUSTOMIZE_OUTPUT)): test-kustomize-%: _work/kustomize
237-
@ if ! diff <($(call KUSTOMIZE_INVOCATION,$<,$*)) $*; then echo "$* was modified manually" && false; fi
258+
@ if ! diff <($(call KUSTOMIZE_INVOCATION,$<,$*,KUSTOMIZE_LOOKUP_KUSTOMIZATION)) $*; then echo "$* was modified manually" && false; fi
238259

239260
# Targets in the makefile can depend on check-go-version-<path to go binary>
240261
# to trigger a warning if the x.y version of that binary does not match
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
bases:
2+
- ../kubernetes-base-direct-testing-coverage
3+
4+
patches:
5+
- ../patches/driverinfo-storage-capacity-patch.yaml
6+
7+
patchesJson6902:
8+
- target:
9+
group: apps
10+
version: v1
11+
kind: DaemonSet
12+
name: pmem-csi-intel-com-node
13+
path: ../patches/external-provisioner-storage-capacity-patch.yaml
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
bases:
2+
- ../kubernetes-base-lvm-testing-coverage
3+
4+
patches:
5+
- ../patches/driverinfo-storage-capacity-patch.yaml
6+
7+
patchesJson6902:
8+
- target:
9+
group: apps
10+
version: v1
11+
kind: DaemonSet
12+
name: pmem-csi-intel-com-node
13+
path: ../patches/external-provisioner-storage-capacity-patch.yaml

deploy/kustomize/kubernetes-base-direct-coverage/kustomization.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
bases:
2-
- ../kubernetes-base-direct-testing/
2+
- ../kubernetes-base-direct/
33

44
patchesJson6902:
55
- target:
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
bases:
2+
- ../kubernetes-base-direct-testing/
3+
4+
patchesJson6902:
5+
- target:
6+
group: apps
7+
version: v1
8+
kind: Deployment
9+
name: pmem-csi-intel-com-controller
10+
path: ../testing/controller-coverage-patch.yaml
11+
12+
- target:
13+
group: apps
14+
version: v1
15+
kind: DaemonSet
16+
name: pmem-csi-intel-com-node
17+
path: ../testing/node-coverage-patch.yaml
18+
19+
images:
20+
- name: intel/pmem-csi-driver
21+
newName: intel/pmem-csi-driver-test

deploy/kustomize/kubernetes-base-lvm-coverage/kustomization.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
bases:
2-
- ../kubernetes-base-lvm-testing/
2+
- ../kubernetes-base-lvm/
33

44
patchesJson6902:
55
- target:
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
bases:
2+
- ../kubernetes-base-lvm-testing/
3+
4+
patchesJson6902:
5+
- target:
6+
group: apps
7+
version: v1
8+
kind: Deployment
9+
name: pmem-csi-intel-com-controller
10+
path: ../testing/controller-coverage-patch.yaml
11+
12+
- target:
13+
group: apps
14+
version: v1
15+
kind: DaemonSet
16+
name: pmem-csi-intel-com-node
17+
path: ../testing/node-coverage-patch.yaml
18+
19+
images:
20+
- name: intel/pmem-csi-driver
21+
newName: intel/pmem-csi-driver-test

deploy/yamls.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"github.com/intel/pmem-csi/pkg/version"
1717
)
1818

19-
//go:embed kubernetes-*/*/pmem-csi.yaml
19+
//go:embed kubernetes-*/pmem-csi-*.yaml
2020
//go:embed kustomize/webhook/webhook.yaml
2121
//go:embed kustomize/scheduler/scheduler-service.yaml
2222
//go:embed kustomize/webhook/webhook-service.yaml
@@ -42,7 +42,7 @@ type YamlFile struct {
4242

4343
var yamls []YamlFile
4444

45-
var re = regexp.MustCompile(`^kubernetes-([0-9\.]*)([^/]*)/([^/]*)$`)
45+
var re = regexp.MustCompile(`^kubernetes-([0-9\.]*)/pmem-csi-(lvm|direct)(.*).yaml$`)
4646

4747
func init() {
4848
deployDir, err := assets.ReadDir(".")
@@ -71,7 +71,7 @@ func init() {
7171
Name: name,
7272
Kubernetes: kubernetes,
7373
Flavor: parts[3],
74-
DeviceMode: api.DeviceMode(parts[3]),
74+
DeviceMode: api.DeviceMode(parts[2]),
7575
})
7676
}
7777
}

examples/cassandra.md

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)