Skip to content

test: use remote coverage #945

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/test_e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ jobs:
- name: Run tests
run: |
source dev/files/env.sh
go test ./tests/e2e -tags e2e -v -race -timeout 60m -coverprofile=coverage.txt
go test ./tests/e2e -tags e2e -v -race -timeout 60m

- name: Fetch coverage data
run: |
source dev/files/env.sh
bash scripts/get-coverage-from-k8s.sh

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
Expand All @@ -84,6 +89,7 @@ jobs:
!startsWith(github.head_ref, 'releaser-pleaser--')
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/coverage.txt

- name: Dump logs & events
if: always()
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ deploy/gen/
hcloud-cloud-controller-manager
*.tgz
hack/.*
coverage/
3 changes: 3 additions & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignore:
- "test"
- "internal/mocks"
3 changes: 2 additions & 1 deletion dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ RUN ls -al
ARG CGO_ENABLED=0
# `skaffold debug` sets SKAFFOLD_GO_GCFLAGS to disable compiler optimizations
ARG SKAFFOLD_GO_GCFLAGS
ARG GO_BUILDFLAGS
ENV GOCACHE=/cache
RUN --mount=type=cache,target="/cache" go build -gcflags="$SKAFFOLD_GO_GCFLAGS" -o hcloud-cloud-controller-manager.bin github.com/hetznercloud/hcloud-cloud-controller-manager
RUN --mount=type=cache,target="/cache" go build -gcflags="$SKAFFOLD_GO_GCFLAGS" $GO_BUILDFLAGS -o hcloud-cloud-controller-manager.bin github.com/hetznercloud/hcloud-cloud-controller-manager

FROM alpine:3.22

Expand Down
26 changes: 26 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ package main

import (
"os"
"os/signal"
"runtime/coverage"
"syscall"

"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/wait"
Expand All @@ -43,6 +46,8 @@ func main() {
klog.Fatalf("unable to initialize command options: %v", err)
}

setupCoverageSignalHandler()

fss := cliflag.NamedFlagSets{}
command := app.NewCloudControllerManagerCommand(ccmOptions, cloudInitializer, app.DefaultInitFuncConstructors, names.CCMControllerAliases(), fss, wait.NeverStop)

Expand Down Expand Up @@ -74,3 +79,24 @@ func cloudInitializer(config *config.CompletedConfig) cloudprovider.Interface {
}
return cloud
}

func setupCoverageSignalHandler() {
coverDir, exists := os.LookupEnv("GOCOVERDIR")
if !exists {
return
}

c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGUSR1)

go func() {
for {
<-c
klog.Info("Writing coverage profile")

if err := coverage.WriteCountersDir(coverDir); err != nil {
klog.Warning("failed to write coverage profile", "err", err)
}
}
}()
}
33 changes: 33 additions & 0 deletions scripts/get-coverage-from-k8s.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -ueo pipefail

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
COVERDIR="$SCRIPT_DIR/../coverage"

# Create/clean coverage directory
if [ -d "$COVERDIR" ]; then
echo "$COVERDIR already exists; cleaning"
rm -r "$COVERDIR"
fi
mkdir -p "$COVERDIR"

signal_coverage_write() {
for i in "${@:2}"; do
echo "Sending USR1 signal to $i"
kubectl -n kube-system exec -t "$i" -- kill -USR1 1
sleep 0.5
echo "Pulling coverage from $i into $1"
kubectl cp -n kube-system "$i:/coverage" "$1"
done

go tool covdata textfmt -i "$1" -o "$1/coverage.txt"
}

PODS=$(
kubectl -n kube-system get pods \
--no-headers -o custom-columns=":metadata.name" \
-l app.kubernetes.io/instance=hccm
)

# shellcheck disable=SC2086
signal_coverage_write "$COVERDIR" $PODS
7 changes: 7 additions & 0 deletions skaffold.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ build:
- image: docker.io/hetznercloud/hcloud-cloud-controller-manager
docker:
dockerfile: dev/Dockerfile
buildArgs:
GO_BUILDFLAGS: -covermode=atomic -coverpkg=github.com/hetznercloud/hcloud-cloud-controller-manager/...
local:
useBuildkit: true
insecureRegistries:
Expand All @@ -24,6 +26,11 @@ manifests:
# We circumvent this by co-locating the registry & HCCM, so it's always a local pull.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].topologyKey: "kubernetes.io/hostname"
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].labelSelector.matchLabels.app: docker-registry
env.GOCOVERDIR.value: "/coverage"
extraVolumes[0].name: coverage
extraVolumes[0].emptyDir: {}
extraVolumeMounts[0].name: coverage
extraVolumeMounts[0].mountPath: "/coverage"

profiles:
# Clusters with Robot Servers do not support the native Routing functionality right now.
Expand Down
Loading