From 07e0df959e587755d9e2fb5420050657e85aa3f9 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Tue, 13 Jan 2026 23:36:05 -0800 Subject: [PATCH] ci: generate coverage data for codecov. This adds a new lst2codecov tool that converts DMD *.lst files into a coverage.json file formatted using the documented format from codecov, so that we can upload it to codecov. --- .github/workflows/build.yml | 4 ++ tools/lst2codecov/dub.json | 9 ++++ tools/lst2codecov/source/lst2codecov.d | 64 ++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 tools/lst2codecov/dub.json create mode 100644 tools/lst2codecov/source/lst2codecov.d diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f4899d..ad0e541 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,6 +46,10 @@ jobs: cd ../.. done + - name: Convert code coverage + run: | + dub run --root tools/lst2codecov + - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: diff --git a/tools/lst2codecov/dub.json b/tools/lst2codecov/dub.json new file mode 100644 index 0000000..6f476c3 --- /dev/null +++ b/tools/lst2codecov/dub.json @@ -0,0 +1,9 @@ +{ + "copyright": "Copyright 2026 Garrett D'Amore", + "description": "Convert DMD .lst files to CodeCov JSON", + "name": "lst2codecov", + "targetType": "executable", + "targetName": "lst2codecov", + "targetPath": "bin", + "mainSourceFile": "source/lst2codecov.d" +} diff --git a/tools/lst2codecov/source/lst2codecov.d b/tools/lst2codecov/source/lst2codecov.d new file mode 100644 index 0000000..80f5408 --- /dev/null +++ b/tools/lst2codecov/source/lst2codecov.d @@ -0,0 +1,64 @@ +/** + * Lst2CodeCov module implements logic to convert DMD *.lst coverage + * files into simple codecov custom JSON. + * + * Copyright: Copyright 2026 Garrett D'Amore + * Authors: Garrett D'Amore + * License: + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE or https://www.boost.org/LICENSE_1_0.txt) + * SPDX-License-Identifier: BSL-1.0 + */ +module lst2codecov; + +alias FileData = int[string]; + +// coverage is map of filenames -> line number (as string) -> count +static int[string][string] coverage; + +void main() +{ + import std.conv; + import std.string; + import std.file; + import std.json; + + // Approach - find all the *.lst files. + // The files have a format of: + // count|source + // (count might be empty, if nothing is executed) + // (count might be 0000000 if the line is missed) + // last line is "filename is %% covered" or "filename has no code" + // There will not be a | character on that last line. + + // for now shallow only + foreach (entry; dirEntries(".", "*.lst", SpanMode.shallow)) + { + auto lineNo = 0; + auto fileName = entry.name; + int[string] counts; + auto lst = readText(entry.name); + foreach (line; lst.splitLines()) + { + lineNo++; + auto parts = line.split("|"); + if (parts.length == 1) + { + parts = line.split(" "); + fileName = parts[0].idup; + } + else + { + auto countStr = parts[0].strip; + if (countStr.isNumeric()) { + counts[lineNo.to!string] = countStr.to!int; + } + } + } + coverage[fileName] = counts; + } + + JSONValue js = ["coverage" : JSONValue(coverage)]; + + write("coverage.json", js.toString); +}