@@ -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: <K8sKind>"
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