Skip to content

Commit

Permalink
Adds a "SuccessCodeOnNoMatches" Option (#487)
Browse files Browse the repository at this point in the history
  • Loading branch information
gfs authored Aug 3, 2022
1 parent 7dfcecd commit 76476ba
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 27 deletions.
2 changes: 1 addition & 1 deletion AppInspector.CLI/AppInspector.CLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

<ItemGroup>
<PackageReference Include="DotLiquid" Version="2.2.656" />
<PackageReference Include="Sarif.Sdk" Version="2.4.15" />
<PackageReference Include="Sarif.Sdk" Version="2.4.16" />
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
Expand Down
6 changes: 6 additions & 0 deletions AppInspector.CLI/CLICmdOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public record CLICustomRulesCommandOptions: CLICommandOptions

[Option("disable-require-unique-ids", Required = false, HelpText = "Allow rules with duplicate IDs.")]
public bool DisableRequireUniqueIds { get; set; }
/// <summary>
/// Return a success error code when no matches were found but operation was apparently successful. Useful for CI scenarios
/// </summary>
[Option("success-error-code-with-no-matches", Required = false, HelpText = "When processing is apparently successful but there are no matches return a success error code - useful for CI.")]
public bool SuccessErrorCodeOnNoMatches { get; set; }

}

public record CLIAnalysisSharedCommandOptions : CLICustomRulesCommandOptions
Expand Down
6 changes: 4 additions & 2 deletions AppInspector.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ private static int RunAnalyzeCommand(CLIAnalyzeCmdOptions cliOptions)
DisableCrawlArchives = cliOptions.DisableArchiveCrawling,
EnumeratingTimeout = cliOptions.EnumeratingTimeout,
DisableCustomRuleVerification = cliOptions.DisableCustomRuleValidation,
DisableRequireUniqueIds = cliOptions.DisableRequireUniqueIds
DisableRequireUniqueIds = cliOptions.DisableRequireUniqueIds,
SuccessErrorCodeOnNoMatches = cliOptions.SuccessErrorCodeOnNoMatches
}, adjustedFactory);

AnalyzeResult analyzeResult = command.GetResult();
Expand Down Expand Up @@ -359,7 +360,8 @@ private static int RunTagDiffCommand(CLITagDiffCmdOptions cliOptions)
ScanUnknownTypes = cliOptions.ScanUnknownTypes,
SingleThread = cliOptions.SingleThread,
DisableCustomRuleValidation = cliOptions.DisableCustomRuleValidation,
DisableRequireUniqueIds = cliOptions.DisableRequireUniqueIds
DisableRequireUniqueIds = cliOptions.DisableRequireUniqueIds,
SuccessErrorCodeOnNoMatches = cliOptions.SuccessErrorCodeOnNoMatches
}, loggerFactory);

TagDiffResult tagDiffResult = command.GetResult();
Expand Down
36 changes: 36 additions & 0 deletions AppInspector.Tests/Commands/TestAnalyzeCmd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,42 @@ public void TestExclusionFilter()
Assert.AreEqual(AnalyzeResult.ExitCode.NoMatches, result.ResultCode);
Assert.AreEqual(0, result.Metadata.TotalMatchesCount);
}

[TestMethod]
public void TestNoMatchesOkay()
{
AnalyzeOptions options = new()
{
SourcePath = new string[1] { testFilePath },
FilePathExclusions = new[] { "**/TestFile.js" },
CustomRulesPath = testRulesPath,
IgnoreDefaultRules = true,
SuccessErrorCodeOnNoMatches = true
};

AnalyzeCommand command = new(options, factory);
AnalyzeResult result = command.GetResult();
Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode);
Assert.AreEqual(0, result.Metadata.TotalMatchesCount);
}

[TestMethod]
public async Task TestNoMatchesOkayAsync()
{
AnalyzeOptions options = new()
{
SourcePath = new string[1] { testFilePath },
FilePathExclusions = new[] { "**/TestFile.js" },
CustomRulesPath = testRulesPath,
IgnoreDefaultRules = true,
SuccessErrorCodeOnNoMatches = true
};

AnalyzeCommand command = new(options, factory);
AnalyzeResult result = await command.GetResultAsync();
Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode);
Assert.AreEqual(0, result.Metadata.TotalMatchesCount);
}

[TestMethod]
public async Task ExpectedResultCountsAsync()
Expand Down
52 changes: 30 additions & 22 deletions AppInspector/Commands/AnalyzeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ public class AnalyzeOptions
/// By default, rules must have unique IDs.
/// </summary>
public bool DisableRequireUniqueIds { get; set; }

/// <summary>
/// Return a success error code when no matches were found but operation was apparently successful. Useful for CI scenarios
/// </summary>
public bool SuccessErrorCodeOnNoMatches { get; set; }
}

/// <summary>
Expand Down Expand Up @@ -668,25 +673,29 @@ public async Task<AnalyzeResult> GetResultAsync(CancellationToken? cancellationT
_logger.LogError("MetadataHelper is null");
throw new NullReferenceException("_metaDataHelper");
}

AnalyzeResult analyzeResult = new()
{
AppVersion = Common.Utils.GetVersionString()
};

_ = await PopulateRecordsAsync(cancellationToken.Value);

//wrapup result status
if (!_options.NoFileMetadata && _metaDataHelper.Files.All(x => x.Status == ScanState.Skipped))
if (!_options.SuccessErrorCodeOnNoMatches)
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
else if (!_metaDataHelper.HasFindings)
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
if (!_options.NoFileMetadata && _metaDataHelper.Files.All(x => x.Status == ScanState.Skipped))
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
else if (!_metaDataHelper.HasFindings)
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
}
else if (_metaDataHelper is {Metadata: { }})

if (_metaDataHelper is {Metadata: { }})
{
_metaDataHelper.Metadata.DateScanned = DateScanned.ToString(CultureInfo.InvariantCulture);
_metaDataHelper.PrepareReport();
Expand Down Expand Up @@ -885,19 +894,18 @@ public AnalyzeResult GetResult()
}

//wrapup result status
if (!_options.NoFileMetadata && _metaDataHelper.Files.All(x => x.Status == ScanState.Skipped))
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
else if (!_metaDataHelper.HasFindings)
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
else
if (!_options.SuccessErrorCodeOnNoMatches)
{
analyzeResult.ResultCode = AnalyzeResult.ExitCode.Success;
if (!_options.NoFileMetadata && _metaDataHelper.Files.All(x => x.Status == ScanState.Skipped))
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
else if (!_metaDataHelper.HasFindings)
{
_logger.LogError(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS));
analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches;
}
}

_metaDataHelper.Metadata.DateScanned = DateScanned.ToString(CultureInfo.InvariantCulture);
Expand Down
11 changes: 9 additions & 2 deletions AppInspector/Commands/TagDiffCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public class TagDiffOptions
public string? CustomLanguagesPath { get; set; }
public bool DisableCustomRuleValidation { get; set; }
public bool DisableRequireUniqueIds { get; set; }
/// <summary>
/// Return a success error code when no matches were found but operation was apparently successful. Useful for CI scenarios
/// </summary>
public bool SuccessErrorCodeOnNoMatches { get; set; }

}

/// <summary>
Expand Down Expand Up @@ -156,7 +161,8 @@ public TagDiffResult GetResult()
CustomCommentsPath = _options.CustomCommentsPath,
CustomLanguagesPath = _options.CustomLanguagesPath,
DisableCustomRuleVerification = _options.DisableCustomRuleValidation,
DisableRequireUniqueIds = _options.DisableRequireUniqueIds
DisableRequireUniqueIds = _options.DisableRequireUniqueIds,
SuccessErrorCodeOnNoMatches = _options.SuccessErrorCodeOnNoMatches
}, _factory);
AnalyzeCommand cmd2 = new(new AnalyzeOptions()
{
Expand All @@ -175,7 +181,8 @@ public TagDiffResult GetResult()
SingleThread = _options.SingleThread,
CustomCommentsPath = _options.CustomCommentsPath,
CustomLanguagesPath = _options.CustomLanguagesPath,
DisableCustomRuleVerification = true // Rules are already validated by the first command
DisableCustomRuleVerification = true, // Rules are already validated by the first command
SuccessErrorCodeOnNoMatches = _options.SuccessErrorCodeOnNoMatches
}, _factory);

AnalyzeResult analyze1 = cmd1.GetResult();
Expand Down

0 comments on commit 76476ba

Please sign in to comment.