microsoft / codecoverage

MIT License
73 stars 12 forks source link

dotnet-coverage tool with Alpine-based docker images #107

Closed baumheld closed 3 months ago

baumheld commented 3 months ago

I'm trying to use dotnet-coverage as global dotnet tool in an Alpine-based Docker image. But I only get this error

No code coverage data available. Profiler was not initialized. Verify that libxml2 and all .NET dependencies are installed.

According to supported-os.md, Alpine is supported. The packages musl and libxml2 are the mentioned dependencies, which I installed.
Did I miss a dependency?

It does work with Microsofts Dotnet SDK 8 Debian-based image, if you just install glibc-source and libxml2

For an easy reproduction, you can copy the following two files locally to the same folder and run the demo by executing start.ps1

Dockerfile

# Setup OS Alpine with dotnet SDK 
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
RUN cat /etc/os-release
WORKDIR "/app"

# Prepare System Under Test
RUN dotnet new console --no-restore
RUN dotnet build

# Install dotnet-coverage
ENV PATH="${PATH}:/root/.dotnet/tools"
RUN dotnet tool install --global dotnet-coverage

# Install dotnet-coverage dependencies
RUN apk --update-cache add libxml2 musl
RUN apk info libxml2 musl

# Start System Under Test and collect coverage
WORKDIR "/app/bin/Debug/net8.0"
ENTRYPOINT dotnet-coverage collect -ll Verbose -l /out/log.txt -id TestSession -f cobertura -o /out/coverage.xml dotnet app.dll

start.ps1

cls
cd $PSScriptRoot
docker build --no-cache --progress=plain --tag alpine-coverage-image .
docker run --rm --volume ${PWD}/out:/out/ --name alpine-coverage-container alpine-coverage-image 
docker image remove alpine-coverage-image
pause

Here is the full docker log as well as the dotnet-coverage log docker-log.txt dotnet-coverage-log.txt

Relevant versions from logs

jakubch1 commented 3 months ago

@baumheld thanks for reporting this. Issue is that coverage requires libintl dependency which is not dependency of .NET on 3.19.

~/.dotnet/tools/.store/dotnet-coverage/17.10.4/dotnet-coverage/17.10.4/tools/net6.0/any/InstrumentationEngine/alpine/x64 # ldd libInstrumentationEngine.so
        /lib/ld-musl-x86_64.so.1 (0x7f6bd898f000)
Error loading shared library libintl.so.8: No such file or directory (needed by libInstrumentationEngine.so)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f6bd8307000)
        libxml2.so.2 => /usr/lib/libxml2.so.2 (0x7f6bd81f8000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f6bd81d4000)
        libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f6bd898f000)
        libz.so.1 => /lib/libz.so.1 (0x7f6bd81ba000)
        liblzma.so.5 => /usr/lib/liblzma.so.5 (0x7f6bd8183000)
Error relocating libInstrumentationEngine.so: libintl_dgettext: symbol not found
Error relocating libInstrumentationEngine.so: libintl_bindtextdomain: symbol not found
~/.dotnet/tools/.store/dotnet-coverage/17.10.4/dotnet-coverage/17.10.4/tools/net6.0/any/InstrumentationEngine/alpine/x64 # apk add libintl
(1/1) Installing libintl (0.22.3-r0)
OK: 60 MiB in 35 packages
~/.dotnet/tools/.store/dotnet-coverage/17.10.4/dotnet-coverage/17.10.4/tools/net6.0/any/InstrumentationEngine/alpine/x64 # ldd libInstrumentationEngine.so
        /lib/ld-musl-x86_64.so.1 (0x7fc7469bf000)
        libintl.so.8 => /usr/lib/libintl.so.8 (0x7fc7465be000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7fc746325000)
        libxml2.so.2 => /usr/lib/libxml2.so.2 (0x7fc746216000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7fc7461f2000)
        libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc7469bf000)
        libz.so.1 => /lib/libz.so.1 (0x7fc7461d8000)
        liblzma.so.5 => /usr/lib/liblzma.so.5 (0x7fc7461a1000)

I will update documentation.