Skip to content

Commit bac8dc8

Browse files
committed
Address copilot PR comments
1 parent 9b8e1b7 commit bac8dc8

2 files changed

Lines changed: 38 additions & 21 deletions

File tree

src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Microsoft.ComponentDetection.Detectors.Helm;
77
using System.IO;
88
using System.Linq;
99
using System.Reactive.Linq;
10+
using System.Reactive.Threading.Tasks;
1011
using System.Threading;
1112
using System.Threading.Tasks;
1213
using Microsoft.ComponentDetection.Common;
@@ -57,7 +58,7 @@ protected override async Task<IObservable<ProcessRequest>> OnPrepareDetectionAsy
5758
{
5859
// Materialize all matching files first so that chart directories are fully
5960
// known before any values file is decided on, regardless of enumeration order.
60-
var allRequests = await processRequests.ToList();
61+
var allRequests = await processRequests.ToList().ToTask(cancellationToken);
6162

6263
// Pass 1: record every directory that contains a Chart.yaml / Chart.yml.
6364
foreach (var request in allRequests)

src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,6 @@ public class KubernetesComponentDetector : FileComponentDetector, IDefaultOffCom
2929
"ReplicationController",
3030
};
3131

32-
// Pre-computed "kind: <value>" patterns for fast text-based rejection.
33-
// Ordered by prevalence: most common K8s kinds first for early exit.
34-
private static readonly string[] KubernetesKindPatterns = [
35-
"kind: Deployment",
36-
"kind: Pod",
37-
"kind: StatefulSet",
38-
"kind: DaemonSet",
39-
"kind: Job",
40-
"kind: CronJob",
41-
"kind: ReplicaSet",
42-
"kind: PodTemplate",
43-
"kind: ReplicationController",
44-
];
45-
4632
public KubernetesComponentDetector(
4733
IComponentStreamEnumerableFactory componentStreamEnumerableFactory,
4834
IObservableDirectoryWalkerFactory walkerFactory,
@@ -139,7 +125,9 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
139125

140126
/// <summary>
141127
/// Fast text-based pre-filter. Checks for "apiVersion" and a known "kind: &lt;K8sKind&gt;"
142-
/// pattern using span operations to reject non-Kubernetes YAML without YAML parsing.
128+
/// pattern using line-based scanning to reject non-Kubernetes YAML without YAML parsing.
129+
/// Tolerates varied whitespace (e.g. "kind:Deployment", "kind: Deployment") and
130+
/// optional quotes around the value.
143131
/// </summary>
144132
private static bool LooksLikeKubernetesManifest(string contents)
145133
{
@@ -151,12 +139,40 @@ private static bool LooksLikeKubernetesManifest(string contents)
151139
return false;
152140
}
153141

154-
// Check for a known "kind: <K8sResource>" pattern. This is much more specific
155-
// than just checking for "kind" and eliminates non-K8s YAML files (GitHub Actions,
156-
// Azure Pipelines, CloudFormation, etc.) that also contain generic "kind" keys.
157-
foreach (var pattern in KubernetesKindPatterns)
142+
// Scan line-by-line for a "kind: <K8sResource>" entry, tolerating varied
143+
// whitespace and quotes to avoid false negatives on valid manifests.
144+
foreach (var line in span.EnumerateLines())
158145
{
159-
if (span.IndexOf(pattern.AsSpan(), StringComparison.OrdinalIgnoreCase) >= 0)
146+
var trimmed = line.TrimStart();
147+
if (!trimmed.StartsWith("kind", StringComparison.OrdinalIgnoreCase))
148+
{
149+
continue;
150+
}
151+
152+
var afterKind = trimmed.Slice(4).TrimStart();
153+
if (afterKind.IsEmpty || afterKind[0] != ':')
154+
{
155+
continue;
156+
}
157+
158+
var value = afterKind.Slice(1).Trim();
159+
160+
// Strip inline YAML comments (K8s kind values never contain '#').
161+
var commentIdx = value.IndexOf('#');
162+
if (commentIdx >= 0)
163+
{
164+
value = value.Slice(0, commentIdx).TrimEnd();
165+
}
166+
167+
// Strip optional surrounding quotes (e.g. kind: "Deployment").
168+
if (value.Length >= 2 &&
169+
((value[0] == '"' && value[^1] == '"') ||
170+
(value[0] == '\'' && value[^1] == '\'')))
171+
{
172+
value = value.Slice(1, value.Length - 2).Trim();
173+
}
174+
175+
if (!value.IsEmpty && KubernetesKinds.Contains(value.ToString()))
160176
{
161177
return true;
162178
}

0 commit comments

Comments
 (0)