Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/codeql-config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
# CodeQL configuration for SonarMark
# Excludes test code from path-combine security analysis
# Excludes justified generic exception handlers
# Excludes HttpResponseMessage disposal warnings in HttpMessageHandler implementations

name: "SonarMark CodeQL Config"

Expand All @@ -10,3 +12,13 @@ query-filters:
id: cs/path-combine
paths:
- test/**/*.cs
- exclude:
id: cs/catch-of-all-exceptions
paths:
- src/DemaConsulting.SonarMark/Context.cs
- src/DemaConsulting.SonarMark/Program.cs
- src/DemaConsulting.SonarMark/Validation.cs
- exclude:
id: cs/local-not-disposed
paths:
- src/DemaConsulting.SonarMark/Validation.cs
1 change: 1 addition & 0 deletions src/DemaConsulting.SonarMark/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ private void OpenLogFile(string logFile)
{
_logWriter = new StreamWriter(logFile, append: false);
}
// Generic catch is justified here to wrap any file system exception with context
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to open log file '{logFile}': {ex.Message}", ex);
Expand Down
1 change: 1 addition & 0 deletions src/DemaConsulting.SonarMark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ private static void ProcessSonarAnalysis(Context context)
File.WriteAllText(context.ReportFile, markdown);
context.WriteLine("Quality report generated successfully.");
}
// Generic catch is justified here as a top-level handler to log any error without crashing
catch (Exception ex)
{
context.WriteError($"Error: Failed to write report: {ex.Message}");
Expand Down
42 changes: 12 additions & 30 deletions src/DemaConsulting.SonarMark/SonarQubeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,15 @@ private async Task<string> GetProjectNameByKeyAsync(
/// <returns>List of quality gate conditions</returns>
private static List<SonarQualityCondition> ParseQualityGateConditions(JsonElement projectStatus)
{
var conditions = new List<SonarQualityCondition>();

if (!projectStatus.TryGetProperty("conditions", out var conditionsElement) ||
conditionsElement.ValueKind != JsonValueKind.Array)
{
return conditions;
}

foreach (var condition in conditionsElement.EnumerateArray())
{
var parsedCondition = ParseQualityGateCondition(condition);
conditions.Add(parsedCondition);
return [];
}

return conditions;
return conditionsElement.EnumerateArray()
.Select(ParseQualityGateCondition)
.ToList();
}

/// <summary>
Expand Down Expand Up @@ -284,20 +278,14 @@ private async Task<List<SonarIssue>> GetIssuesAsync(
/// <returns>List of parsed issues</returns>
private static List<SonarIssue> ParseIssues(JsonElement issuesElement)
{
var issues = new List<SonarIssue>();

if (issuesElement.ValueKind != JsonValueKind.Array)
{
return issues;
}

foreach (var issue in issuesElement.EnumerateArray())
{
var parsedIssue = ParseIssue(issue);
issues.Add(parsedIssue);
return [];
}

return issues;
return issuesElement.EnumerateArray()
.Select(ParseIssue)
.ToList();
}

/// <summary>
Expand Down Expand Up @@ -365,20 +353,14 @@ private async Task<List<SonarHotSpot>> GetHotSpotsAsync(
/// <returns>List of parsed hot-spots</returns>
private static List<SonarHotSpot> ParseHotSpots(JsonElement hotSpotsElement)
{
var hotSpots = new List<SonarHotSpot>();

if (hotSpotsElement.ValueKind != JsonValueKind.Array)
{
return hotSpots;
}

foreach (var hotSpot in hotSpotsElement.EnumerateArray())
{
var parsedHotSpot = ParseHotSpot(hotSpot);
hotSpots.Add(parsedHotSpot);
return [];
}

return hotSpots;
return hotSpotsElement.EnumerateArray()
.Select(ParseHotSpot)
.ToList();
}

/// <summary>
Expand Down
7 changes: 7 additions & 0 deletions src/DemaConsulting.SonarMark/Validation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
context.WriteError($"✗ {displayName} - FAILED: Exit code {exitCode}");
}
}
// Generic catch is justified here to handle any exception during test execution
catch (Exception ex)
{
HandleTestException(test, context, displayName, ex);
Expand Down Expand Up @@ -370,6 +371,7 @@
File.WriteAllText(context.ResultsFile, content);
context.WriteLine($"Results written to {context.ResultsFile}");
}
// Generic catch is justified here as a top-level handler to log file write errors
catch (Exception ex)
{
context.WriteError($"Error: Failed to write results file: {ex.Message}");
Expand Down Expand Up @@ -427,6 +429,11 @@
/// <summary>
/// Mock HTTP message handler that returns predefined responses for validation testing.
/// </summary>
/// <remarks>
/// HttpResponseMessage objects returned from SendAsync are owned by the HttpClient
/// and will be disposed by the framework. CodeQL warnings about non-disposal here
/// are false positives as this follows the standard HttpMessageHandler pattern.
/// </remarks>
private sealed class MockHttpMessageHandler : HttpMessageHandler
{
/// <summary>
Expand All @@ -452,7 +459,7 @@
""";
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(json, Encoding.UTF8, "application/json")

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 462 in src/DemaConsulting.SonarMark/Validation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal 'application/json' 5 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)
});
}

Expand Down
8 changes: 4 additions & 4 deletions test/DemaConsulting.SonarMark.Tests/ContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ public void Context_Create_UnsupportedArgument_ThrowsException()
public void Context_WriteLine_NormalMode_WritesToConsole()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand All @@ -417,7 +417,7 @@ public void Context_WriteLine_NormalMode_WritesToConsole()
public void Context_WriteLine_SilentMode_DoesNotWriteToConsole()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand All @@ -440,7 +440,7 @@ public void Context_WriteLine_SilentMode_DoesNotWriteToConsole()
public void Context_WriteError_NormalMode_WritesToConsole()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand All @@ -464,7 +464,7 @@ public void Context_WriteError_NormalMode_WritesToConsole()
public void Context_WriteError_SilentMode_DoesNotWriteToConsole()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand Down
10 changes: 5 additions & 5 deletions test/DemaConsulting.SonarMark.Tests/ProgramTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void Program_Version_NotEmpty_IsNotEmpty()
public void Program_Run_VersionFlag_OutputsVersion()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand All @@ -46,7 +46,7 @@ public void Program_Run_VersionFlag_OutputsVersion()
public void Program_Run_HelpFlag_OutputsBannerAndHelp()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand Down Expand Up @@ -86,7 +86,7 @@ public void Program_Run_ValidateFlag_OutputsNotImplemented()
public void Program_Run_NoFlags_OutputsBannerAndRequiresServer()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand All @@ -112,7 +112,7 @@ public void Program_Run_NoFlags_OutputsBannerAndRequiresServer()
public void Program_Run_ServerWithoutProjectKey_OutputsError()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand All @@ -137,7 +137,7 @@ public void Program_Run_ServerWithoutProjectKey_OutputsError()
public void Program_Run_SilentFlag_SuppressesBanner()
{
var originalOut = Console.Out;
var output = new StringWriter();
using var output = new StringWriter();
Console.SetOut(output);

try
Expand Down