diff --git a/.github/badges/tests.svg b/.github/badges/tests.svg index 7afe4fa..7199f22 100644 --- a/.github/badges/tests.svg +++ b/.github/badges/tests.svg @@ -1 +1 @@ -tests: 36 passedtests36 passed +tests: 37 passedtests37 passed diff --git a/code/+matbox/+tasks/+internal/createBadge.m b/code/+matbox/+tasks/+internal/createBadge.m index 60a1c01..83af5f6 100644 --- a/code/+matbox/+tasks/+internal/createBadge.m +++ b/code/+matbox/+tasks/+internal/createBadge.m @@ -1,4 +1,4 @@ -function createBadge(label, message, color, projectRootDirectory) +function createBadge(label, message, color, projectRootDirectory, options) % createBadge - Write a badge as JSON or as a legacy SVG file % % Writes a badge description as a JSON file (docs/reports/badges) when @@ -10,17 +10,23 @@ function createBadge(label, message, color, projectRootDirectory) % pybadges Python package, for callers without a render step: local runs % and repositories pinned to older matbox-actions versions. This % fallback will be removed in a future major release. +% +% Optional name/value arguments: +% Counts - Scalar struct of named counts added to the badge JSON for +% segmented rendering. The legacy SVG fallback ignores it. arguments label (1,1) string message (1,1) string color (1,1) string projectRootDirectory (1,1) string {mustBeFolder} + options.Counts struct {mustBeScalarOrEmpty} = struct.empty end if strcmpi(getenv("MATBOX_BADGE_FORMAT"), "json") matbox.utility.writeBadgeJSONFile(label, message, color, ... - "OutputFolder", fullfile(projectRootDirectory, "docs", "reports", "badges")) + "OutputFolder", fullfile(projectRootDirectory, "docs", "reports", "badges"), ... + "Counts", options.Counts) else matbox.utility.createBadgeSvg(label, message, color, projectRootDirectory) end diff --git a/code/+matbox/+tasks/codecheckToolbox.m b/code/+matbox/+tasks/codecheckToolbox.m index 1fc1dac..d7d4918 100644 --- a/code/+matbox/+tasks/codecheckToolbox.m +++ b/code/+matbox/+tasks/codecheckToolbox.m @@ -93,8 +93,16 @@ function createCodeIssuesBadge(issueCount, projectRootDir) color = "red"; end + % The counts let matbox-actions draw one segment per severity. The + % label, message and color still describe a complete single badge + % for renderers that ignore the counts. + counts = struct( ... + "error", issueCount.Error, ... + "warning", issueCount.Warning, ... + "info", issueCount.Info); + matbox.tasks.internal.createBadge("code issues", ... - string(issueCount.Total), color, projectRootDir) + string(issueCount.Total), color, projectRootDir, "Counts", counts) end function ME = throwUnresolvedCodeIssuesException() diff --git a/code/+matbox/+utility/writeBadgeJSONFile.m b/code/+matbox/+utility/writeBadgeJSONFile.m index b5189b0..1658f2c 100644 --- a/code/+matbox/+utility/writeBadgeJSONFile.m +++ b/code/+matbox/+utility/writeBadgeJSONFile.m @@ -24,6 +24,10 @@ function writeBadgeJSONFile(label, message, color, projectRootDirectory, options % % FileName - Name of file excluding extension % +% Counts - Scalar struct of named counts written to a "counts" field, +% for renderers that draw one segment per count. The field +% is omitted when Counts is empty (default). +% % Example: % % writeBadgeJSONFile("Test Coverage", "90%", "green") creates a file @@ -44,6 +48,7 @@ function writeBadgeJSONFile(label, message, color, projectRootDirectory, options projectRootDirectory (1,1) string = missing options.OutputFolder (1,1) string = missing options.FileName (1,1) string = missing + options.Counts struct {mustBeScalarOrEmpty} = struct.empty end if ismissing(options.OutputFolder) @@ -62,6 +67,9 @@ function writeBadgeJSONFile(label, message, color, projectRootDirectory, options badgeInfo.label = label; badgeInfo.message = message; badgeInfo.color = color; + if ~isempty(options.Counts) + badgeInfo.counts = options.Counts; + end badgeJSON = jsonencode(badgeInfo); if ismissing(options.FileName) diff --git a/tools/tests/+matboxtools/+unittest/TasksTest.m b/tools/tests/+matboxtools/+unittest/TasksTest.m index a6eedb9..d0d795b 100644 --- a/tools/tests/+matboxtools/+unittest/TasksTest.m +++ b/tools/tests/+matboxtools/+unittest/TasksTest.m @@ -55,6 +55,23 @@ function testCodecheckToolboxCreatesBadgeJson(testCase) testCase.verifyEqual(badgeInfo.label, 'code issues') testCase.verifyTrue(ismember(string(badgeInfo.color), ... ["green", "yellow", "red"])) + + % The per-severity counts must add up to the total in the message + testCase.assertTrue(isfield(badgeInfo, "counts"), ... + "Expected badge JSON to contain a counts field.") + counts = badgeInfo.counts; + testCase.verifyEqual(sort(string(fieldnames(counts))), ... + ["error"; "info"; "warning"]) + testCase.verifyEqual(counts.error + counts.warning + counts.info, ... + str2double(badgeInfo.message)) + end + + function testWriteBadgeJSONFileOmitsCountsByDefault(testCase) + matbox.utility.writeBadgeJSONFile("tests", "1 passed", "green", ... + "OutputFolder", pwd) + + badgeInfo = jsondecode(fileread(fullfile(pwd, "tests.json"))); + testCase.verifyFalse(isfield(badgeInfo, "counts")) end function testPackageToolbox(testCase)