feat(materials): add MSBUILD_LOG material type for compiler build logs
Merged
JA
10h ago+3035+3035+0123456789012345678901234567890123456789-20-20-01234567890123456789
Summary
Adds an MSBUILD_LOG material type, so that a policy can check the compiler warnings of a build. The material reads:
- MSBuild binary logs (
-bl), format 18 or later (MSBuild 17.8 and later). Older formats are rejected with an "unsupported MSBuild binary log version" error. - MSBuild text logs:
- file loggers (
-fl), console captures anddotnet buildoutput; - several builds in one file;
- translated MSBuild output (de, fr, ja, ko, ru, zh-CN, zh-TW);
- CI line prefixes: ISO 8601 timestamps (GitHub Actions) and
[hh:mm:ss](AppVeyor).
- file loggers (
- Visual C++
BuildLog.htm(vcbuild, UTF-16 or ASCII). - A zip or tar archive of any of these, for example one binary log per solution. One nested archive level is read, and
*.ProjectImports.zipis skipped.
The file is uploaded as is. MSBUILD_LOG is not auto-detected: a contract or --kind must name it.
What a policy gets
{
"tool": {"name": "msbuild", "version": "17.14.40"},
"logs": [
{
"source": "release/build.log", "solution": "C:\\src\\app.sln", "format": "msbuild-text",
"tool": {"name": "msbuild", "version": "17.14.40"}, "result": "succeeded",
"summary": {"warnings": 2, "errors": 0, "by_code": {"C4996": 1, "CA5351": 1}},
"parsed": {"warnings": 4, "errors": 0}, "reported": {"warnings": 4, "errors": 0}
}
],
"skipped": ["release/readme.txt"],
"summary": {"warnings": 2, "errors": 0, "by_code": {"C4996": 1, "CA5351": 1}},
"diagnostics": [
{
"severity": "warning", "code": "C4996", "message": "'strcpy': This function or variable may be unsafe. ...",
"file": "C:\\src\\a.cpp", "line": 5, "column": 3, "project": "C:\\src\\a.vcxproj",
"occurrences": 3, "logs": [0]
}
]
}
parsedcounts every warning and error read, repeats included, whilesummarycounts distinct diagnostics.reportedis what the log says about itself (the summary of a text log, the results line of aBuildLog.htm; a binary log has none), so a policy can detect warnings that could not be read.resultissucceeded,failed, or empty when the log does not show how the build ended (for example, a log that was cut short).- Identical diagnostics are folded into one entry: same severity, code, message, file, project, line and column, where file and project are compared without regard to case.
occurrencescounts them, andlogsholds the indexes of the logs they were seen in, so each diagnostic can be traced back to the build that reported it. skippedlists the archive entries that are not build logs.
Limits
- Archives use the
archiveiolimits: 1024 entries and 4 GiB of content. A nested archive is read up to 512 MiB. - A binary log is streamed: only string, warning, error, project-started and build-finished records are loaded (64 MiB each at most). All other records are skipped without being loaded.
- Input that is not a build log fails with
ErrInvalidMaterialType.
Testing
- Unit tests for each format, archives, folding, logs with several builds, translated and CI-prefixed logs, and malformed or truncated input.
sample.binlogandlib.binlogare real binary logs, built with the .NET 9 SDK from a small synthetic solution. The text and HTML fixtures are synthetic.- Checked locally against 64 public build logs from open-source projects (not committed). Each log was either read, with the warning counts it states, or rejected with an error.
- End to end with a local control plane: a contract with an
MSBUILD_LOGmaterial, a policy evaluated over it, and the attestation pushed.