dotnet / dotnet/arcade-services
Support additional fenced JSON blocks in KBE issue bodies
- Dominant language
- C#
- Stars
- 86
- Forks
- 86
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 35
Description
## Problem
Build Analysis currently expects a KBE issue body to contain effectively one fenced JSON object. `KnownIssueHelper.GetKnownIssueJson` uses a greedy expression:
```csharp
```(json)?\s*({.*})\s*```
```
When an issue contains more than one matching fenced JSON object, the expression can capture from the first `{` through the last `}`. That combined content is not valid JSON, so Build Analysis cannot deserialize the KBE match instructions.
This prevents KBEs from using GitHub Agentic Workflows' [`safe-outputs.data`](https://github.github.com/gh-aw/reference/safe-outputs/) feature. For safe outputs with a `body`, the workflow appends the emitted `data` object as fenced JSON to the GitHub issue body, which introduces an additional JSON block.
## `safe-outputs.data` requirements
Per the [Safe Outputs reference](https://github.github.com/gh-aw/reference/safe-outputs/):
- `safe-outputs.data` must be explicitly enabled. Its default is `false`; use `data: true` to accept an arbitrary object, or provide a schema to validate the object.
- The data object is appended to a safe output body as fenced JSON.
- `create-issue.body` must be between 20 and 65,000 characters, including the appended data.
For example:
```yaml
safe-outputs:
create-issue:
labels: [Known Build Error]
data: true
```
A KBE created by such a workflow needs to retain its existing match-instruction JSON while also accepting the workflow-generated JSON data block.
## Proposed behavior
Replace the whole-body greedy JSON extraction with per-fence parsing:
1. Enumerate fenced JSON objects independently, preserving support for both ` ```json ` and untagged ` ``` ` fences.
2. Deserialize each candidate independently.
3. Treat a candidate as KBE match instructions only when it contains `ErrorMessage` or `ErrorPattern`.
4. Ignore unrelated or malformed JSON fences rather than allowing them to invalidate a valid KBE block.
5. When multiple KBE candidates are present, select the last valid one. This matches the existing method documentation and lets a later, intentionally updated KBE block take precedence.
This keeps existing KBEs compatible: a body with one valid KBE JSON block produces the same result as today, while a body containing unrelated fenced JSON—such as `safe-outputs.data`—continues to parse the KBE instructions correctly.
## Acceptance criteria
- A legacy KBE with one fenced JSON match-instruction block continues to parse unchanged.
- A KBE block followed by an unrelated `safe-outputs.data` fenced JSON block still uses the KBE's `ErrorMessage` or `ErrorPattern`.
- An unrelated JSON block before the KBE block does not affect parsing.
- Malformed or unrelated JSON blocks do not prevent a valid KBE block from being found.
- Multiple valid KBE instruction blocks resolve deterministically to the last valid block.
- Tests cover tagged and untagged JSON fences.
---
*This issue was authored with help from AI.*
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.