Skip to content

Add component detectors for Docker Compose, Helm, and Kubernetes#1759

Open
jpinz wants to merge 40 commits intomainfrom
jupinzer/add_container_detectors
Open

Add component detectors for Docker Compose, Helm, and Kubernetes#1759
jpinz wants to merge 40 commits intomainfrom
jupinzer/add_container_detectors

Conversation

@jpinz
Copy link
Copy Markdown
Member

@jpinz jpinz commented Apr 2, 2026

This pull request adds new detectors for Docker Compose, Helm, and Kubernetes YAML files, enabling the system to automatically discover and register Docker image references found in these types of configuration files. It also updates the service registration and the DetectorClass enum to support these new detectors.

It also adds tests for the new detectors plus the Dockerfile one.

Image references containing unresolved variable placeholders (e.g., ${REGISTRY}/app:${TAG}, {{ .Values.image.tag }}) are silently skipped in all four Docker-related detectors (DockerCompose, Helm, Kubernetes, and Dockerfile) to avoid noisy warnings for otherwise-valid real-world manifests. A shared DockerReferenceUtility.HasUnresolvedVariables helper was added to Microsoft.ComponentDetection.Common to consolidate this logic, and all detectors—including the existing DockerfileComponentDetector—now use it.

The Helm detector uses the combination of a Chart.yaml/Chart.yml file and a *values*.(yaml|yml) file in the same directory to identify Helm charts. Values files found without a co-located Chart file are skipped, avoiding false positives from unrelated values.yaml files in non-Helm projects. The co-location check is implemented via a two-pass OnPrepareDetectionAsync: all matching files are materialized first, chart directories are identified in pass 1, then only values files from those directories are emitted for processing in pass 2. This eliminates any dependency on file enumeration order, so values files are correctly detected regardless of whether they are observed before or after their co-located Chart.yaml.

A bug in DetectorRestrictionService was also fixed: when both AllowedDetectorIds and AllowedDetectorCategories are specified, DefaultOff detectors introduced via category expansion are now also constrained by the ID allow-list, producing an intersection rather than an unintended union.

New Detector Checklist

  • Component type defined (if new ecosystem) in ComponentType.cs and DetectorClass.cs
  • Component class created in TypedComponent/ folder with proper validation
  • Detector class created inheriting from FileComponentDetector and implementing IDefaultOffComponentDetector
  • Detector registered in ServiceCollectionExtensions.cs
  • Constructor properly injects required services
  • SearchPatterns defined for file discovery
  • OnFileFoundAsync() implemented with component registration logic
  • Unit tests created in Detectors.Tests/ using DetectorTestUtilityBuilder
  • Verification test resources added to VerificationTests/resources/
  • Detector tested locally with --DetectorArgs YourDetectorId=EnableIfDefaultOff

@jpinz jpinz self-assigned this Apr 2, 2026
Copilot AI review requested due to automatic review settings April 2, 2026 21:44
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

👋 Hi! It looks like you modified some files in the Detectors folder.
You may need to bump the detector versions if any of the following scenarios apply:

  • The detector detects more or fewer components than before
  • The detector generates different parent/child graph relationships than before
  • The detector generates different devDependencies values than before

If none of the above scenarios apply, feel free to ignore this comment 🙂

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new YAML-based detectors to Component Detection so Docker image references can be discovered from Docker Compose, Helm values, and Kubernetes manifests, plus updates orchestration wiring and expands detector test coverage.

Changes:

  • Introduce new DockerCompose, Helm, and Kubernetes detectors that parse YAML and register DockerReferenceComponent usages.
  • Register the new detectors in Orchestrator DI and extend DetectorClass with new categories.
  • Add MSTest coverage for the new detectors and add/expand tests for the existing Dockerfile detector.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/Microsoft.ComponentDetection.Detectors.Tests/KubernetesComponentDetectorTests.cs Adds unit tests for K8s YAML image extraction and non-K8s YAML ignoring behavior.
test/Microsoft.ComponentDetection.Detectors.Tests/HelmComponentDetectorTests.cs Adds unit tests for Helm values.yaml image patterns (scalar, structured, digest, sequences).
test/Microsoft.ComponentDetection.Detectors.Tests/DockerfileComponentDetectorTests.cs Adds Dockerfile detector tests for FROM, multi-stage, digests, COPY --from, and file patterns.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerComposeComponentDetectorTests.cs Adds tests for Compose service images, overrides, digests, and build-only services.
src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs Registers the three new detectors with DI so they can be executed by the orchestrator.
src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs New detector implementation for parsing Kubernetes manifests and extracting container images.
src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs New detector implementation for parsing Helm values.yaml and extracting image references.
src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs New detector implementation for parsing Compose YAML and extracting service image: references.
src/Microsoft.ComponentDetection.Contracts/DetectorClass.cs Adds new detector classes/categories for Docker Compose, Helm, and Kubernetes.
Comments suppressed due to low confidence (5)

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

  • This file is compiled with nullable reference types enabled, but apiVersion/kind are declared as non-nullable string and initialized to null, which will fail the build with warnings-as-errors. Make these string? (and similarly update any other locals/returns that can be null).

    private bool IsKubernetesManifest(YamlMappingNode rootMapping)
    {
        string apiVersion = null;
        string kind = null;

        foreach (var entry in rootMapping.Children)
        {
            var key = (entry.Key as YamlScalarNode)?.Value;
            if (string.Equals(key, "apiVersion", StringComparison.OrdinalIgnoreCase))
            {
                apiVersion = (entry.Value as YamlScalarNode)?.Value;
            }
            else if (string.Equals(key, "kind", StringComparison.OrdinalIgnoreCase))
            {
                kind = (entry.Value as YamlScalarNode)?.Value;
            }

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

  • GetMappingChild returns null when the key isn't present, but the return type is non-nullable YamlMappingNode. With nullable enabled + warnings-as-errors this will fail compilation. Change the return type to YamlMappingNode? (and update call sites accordingly).

    private static YamlMappingNode GetMappingChild(YamlMappingNode parent, string key)
    {
        foreach (var entry in parent.Children)
        {
            if (entry.Key is YamlScalarNode scalarKey && string.Equals(scalarKey.Value, key, StringComparison.OrdinalIgnoreCase))
            {
                return entry.Value as YamlMappingNode;
            }
        }

        return null;

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

  • GetSequenceChild returns null when the key isn't present, but the return type is non-nullable YamlSequenceNode. With nullable enabled + warnings-as-errors this will fail compilation. Change the return type to YamlSequenceNode? (and update call sites accordingly).

    private static YamlSequenceNode GetSequenceChild(YamlMappingNode parent, string key)
    {
        foreach (var entry in parent.Children)
        {
            if (entry.Key is YamlScalarNode scalarKey && string.Equals(scalarKey.Value, key, StringComparison.OrdinalIgnoreCase))
            {
                return entry.Value as YamlSequenceNode;
            }
        }

        return null;

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

  • This method initializes non-nullable string locals (repository, tag, digest, registry) to null. With nullable enabled + TreatWarningsAsErrors, this will fail the build. Use string? for these locals (and keep the subsequent null/whitespace checks).

    private void TryRegisterStructuredImageReference(YamlMappingNode imageMapping, ISingleFileComponentRecorder recorder, string fileLocation)
    {
        string repository = null;
        string tag = null;
        string digest = null;
        string registry = null;

src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs:137

  • GetMappingChild returns null when the key isn't present, but the return type is non-nullable YamlMappingNode. With nullable enabled + warnings-as-errors this will fail compilation. Change the return type to YamlMappingNode? and update call sites accordingly.

    private static YamlMappingNode GetMappingChild(YamlMappingNode parent, string key)
    {
        foreach (var entry in parent.Children)
        {
            if (entry.Key is YamlScalarNode scalarKey && string.Equals(scalarKey.Value, key, StringComparison.OrdinalIgnoreCase))
            {
                return entry.Value as YamlMappingNode;
            }
        }

        return null;


public override int Version => 1;

public override IEnumerable<string> Categories => [Enum.GetName(typeof(DetectorClass), DetectorClass.Kubernetes)];
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enum.GetName(...) returns string? under nullable reference types. Returning it directly here can fail compilation (and can propagate null into Categories). Use the null-forgiving operator (!) or an alternate non-null approach (e.g., nameof(DetectorClass.Kubernetes)).

This issue also appears in the following locations of the same file:

  • line 88
  • line 206
  • line 219
Suggested change
public override IEnumerable<string> Categories => [Enum.GetName(typeof(DetectorClass), DetectorClass.Kubernetes)];
public override IEnumerable<string> Categories => [nameof(DetectorClass.Kubernetes)];

Copilot uses AI. Check for mistakes.

public override int Version => 1;

public override IEnumerable<string> Categories => [Enum.GetName(typeof(DetectorClass), DetectorClass.Helm)];
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enum.GetName(...) returns string? under nullable reference types. Returning it directly here can fail compilation and can propagate null into Categories. Use ! (as some other detectors do) or another guaranteed-non-null approach (e.g., nameof(DetectorClass.Helm)).

This issue also appears on line 129 of the same file.

Suggested change
public override IEnumerable<string> Categories => [Enum.GetName(typeof(DetectorClass), DetectorClass.Helm)];
public override IEnumerable<string> Categories => [nameof(DetectorClass.Helm)];

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +41

public override IEnumerable<ComponentType> SupportedComponentTypes => [ComponentType.DockerReference];

public override int Version => 1;

public override IEnumerable<string> Categories => [Enum.GetName(typeof(DetectorClass), DetectorClass.DockerCompose)];
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enum.GetName(...) returns string? under nullable reference types. Returning it directly here can fail compilation and can propagate null into Categories. Use the null-forgiving operator (!) or an alternate non-null approach.

This issue also appears on line 126 of the same file.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 3, 2026 15:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Comment on lines +50 to +72
this.Logger.LogInformation("Discovered Helm file: {Location}", file.Location);

string contents;
using (var reader = new StreamReader(file.Stream))
{
contents = await reader.ReadToEndAsync(cancellationToken);
}

var yaml = new YamlStream();
yaml.Load(new StringReader(contents));

if (yaml.Documents.Count == 0)
{
return;
}

var fileName = Path.GetFileName(file.Location);

if (fileName.Contains("values", StringComparison.OrdinalIgnoreCase) &&
(fileName.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".yml", StringComparison.OrdinalIgnoreCase)))
{
this.ExtractImageReferencesFromValues(yaml, singleFileComponentRecorder, file.Location);
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method parses YAML for every matched file (including Chart.yaml/Chart.yml) even though only *values*.(yml|yaml) files are actually processed for image extraction. Since the filename decision is based solely on file.Location, you can short-circuit before reading/parsing the stream for non-values files to avoid unnecessary work and noise in logs.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 3, 2026 16:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

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

  • The exception handler logs "Skipping non-Kubernetes YAML file" for any exception, but exceptions here primarily represent YAML parse/processing failures (a file can be a Kubernetes manifest but malformed). Consider adjusting the message to reflect parse errors (or splitting try/catch so non-Kubernetes vs parse-failure are distinguished) to avoid misleading diagnostics.
        catch (Exception e)
        {
            // Not all YAML files are Kubernetes manifests; silently skip parse errors
            this.Logger.LogDebug(e, "Skipping non-Kubernetes YAML file: {Location}", file.Location);
        }

Copilot AI review requested due to automatic review settings April 3, 2026 16:40
@jpinz jpinz marked this pull request as ready for review April 3, 2026 16:41
@jpinz jpinz requested a review from a team as a code owner April 3, 2026 16:41
@jpinz jpinz requested a review from edgarrs April 3, 2026 16:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment on lines +125 to +138
private void TryRegisterImageReference(string imageReference, ISingleFileComponentRecorder recorder, string fileLocation)
{
try
{
var dockerRef = DockerReferenceUtility.ParseFamiliarName(imageReference);
if (dockerRef != null)
{
recorder.RegisterUsage(new DetectedComponent(dockerRef.ToTypedDockerReferenceComponent()));
}
}
catch (Exception e)
{
this.Logger.LogWarning(e, "Failed to parse image reference '{ImageReference}' in {Location}", imageReference, fileLocation);
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docker Compose files commonly use variable interpolation in image (e.g., ${REGISTRY}/app:${TAG}). DockerReferenceUtility.ParseFamiliarName throws on these, which will generate warnings for otherwise valid compose files. Consider skipping registration when the image reference contains unresolved variables (similar to DockerfileComponentDetector.HasUnresolvedVariables) instead of logging a warning for each occurrence.

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +208
private void TryRegisterImageReference(string imageReference, ISingleFileComponentRecorder recorder, string fileLocation)
{
try
{
var dockerRef = DockerReferenceUtility.ParseFamiliarName(imageReference);
if (dockerRef != null)
{
recorder.RegisterUsage(new DetectedComponent(dockerRef.ToTypedDockerReferenceComponent()));
}
}
catch (Exception e)
{
this.Logger.LogWarning(e, "Failed to parse image reference '{ImageReference}' in {Location}", imageReference, fileLocation);
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helm values often use templated/variable image strings (e.g., ${REGISTRY} or {{ .Values.image.tag }} via preprocessing). Passing these through DockerReferenceUtility.ParseFamiliarName will throw and can create noisy warning logs. Consider detecting unresolved variables/templates in imageReference and skipping registration (without logging) to match the Dockerfile detector’s behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +228 to +241
private void TryRegisterImageReference(string imageReference, ISingleFileComponentRecorder recorder, string fileLocation)
{
try
{
var dockerRef = DockerReferenceUtility.ParseFamiliarName(imageReference);
if (dockerRef != null)
{
recorder.RegisterUsage(new DetectedComponent(dockerRef.ToTypedDockerReferenceComponent()));
}
}
catch (Exception e)
{
this.Logger.LogWarning(e, "Failed to parse image reference '{ImageReference}' in {Location}", imageReference, fileLocation);
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kubernetes manifests frequently use variable placeholders in image: (e.g., ${IMAGE}) via kustomize/CI substitution. DockerReferenceUtility.ParseFamiliarName throws on these, so this will log warnings for many real-world manifests. Consider skipping image references containing unresolved variables/templates (rather than logging) before calling ParseFamiliarName, consistent with DockerfileComponentDetector.HasUnresolvedVariables.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 6, 2026 17:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands Component Detection’s container-image coverage by adding DefaultOff detectors for Docker Compose, Helm, and Kubernetes YAML files, plus consolidating Docker image variable-placeholder skipping into a shared utility.

Changes:

  • Added new FileComponentDetector implementations for Docker Compose, Helm values, and Kubernetes manifests to detect/register DockerReference components.
  • Introduced DockerReferenceUtility.HasUnresolvedVariables + TryParse/TryRegisterImageReference and updated the existing Dockerfile detector to use the shared behavior.
  • Registered the new detectors in the orchestrator DI and added docs + MSTest coverage for all four Docker-related detectors.
Show a summary per file
File Description
test/Microsoft.ComponentDetection.Detectors.Tests/KubernetesComponentDetectorTests.cs New unit tests for Kubernetes manifest image extraction + unresolved-variable skipping behavior.
test/Microsoft.ComponentDetection.Detectors.Tests/HelmComponentDetectorTests.cs New unit tests for Helm values image extraction, including co-located Chart behavior.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerfileComponentDetectorTests.cs New unit tests for Dockerfile detector behavior (tags/digests/stages/unresolved vars).
test/Microsoft.ComponentDetection.Detectors.Tests/DockerComposeComponentDetectorTests.cs New unit tests for Docker Compose image extraction, including override-style filenames.
src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs Registers the new detectors in DI so they can run via orchestrator.
src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs New Kubernetes YAML detector that extracts images from container lists in supported workload kinds.
src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs New Helm detector that processes values files co-located with Chart metadata and walks YAML for image keys.
src/Microsoft.ComponentDetection.Detectors/dockerfile/DockerfileComponentDetector.cs Refactors Dockerfile detector to use shared Docker reference parsing/skip logic.
src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs New Docker Compose YAML detector that extracts services.*.image references.
src/Microsoft.ComponentDetection.Contracts/DetectorClass.cs Adds new detector classes for DockerCompose, Helm, and Kubernetes.
src/Microsoft.ComponentDetection.Common/DockerReference/DockerReferenceUtility.cs Adds shared “unresolved variable” detection + safe parse/register helpers.
docs/detectors/README.md Links and lists the new detector docs pages.
docs/detectors/kubernetes.md New documentation for Kubernetes detector behavior/requirements/limitations.
docs/detectors/helm.md New documentation for Helm detector behavior/requirements/limitations.
docs/detectors/dockercompose.md New documentation for Docker Compose detector behavior/requirements/limitations.
.gitignore Ignores .nuget/ directory.

Copilot's findings

  • Files reviewed: 15/16 changed files
  • Comments generated: 9

Comment on lines +1 to +5
namespace Microsoft.ComponentDetection.Detectors.Kubernetes;

using System;
using System.Collections.Generic;
using System.IO;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new detector file is missing the repo’s common #nullable disable header used by most detector implementations. As written, it returns null from non-nullable helper methods (GetMappingChild/GetSequenceChild) and assigns null to non-nullable locals (string apiVersion = null;), which will raise nullable warnings and fail the build with warnings-as-errors. Add #nullable disable (matching other detectors) or make the file fully nullable-annotated.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
namespace Microsoft.ComponentDetection.Detectors.Tests;

using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AwesomeAssertions;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test file is missing the #nullable disable directive that the rest of Microsoft.ComponentDetection.Detectors.Tests uses (e.g., ArtifactComponentFactoryTests.cs:1). Without it, common patterns here (like as casts followed by dereference after Should().NotBeNull()) will produce nullable warnings and can break the build due to warnings-as-errors.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
namespace Microsoft.ComponentDetection.Detectors.Tests;

using System.Linq;
using System.Threading.Tasks;
using AwesomeAssertions;
using Microsoft.ComponentDetection.Contracts;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test file is missing the #nullable disable directive that existing detector tests use. Without it, nullable analysis will flag casts like components.First().Component as DockerReferenceComponent as possibly null even after assertions, and warnings-as-errors can fail the build.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
namespace Microsoft.ComponentDetection.Detectors.Tests;

using System.Linq;
using System.Threading.Tasks;
using AwesomeAssertions;
using Microsoft.ComponentDetection.Contracts;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test file is missing the #nullable disable directive that the rest of the test project uses. In a nullable-enabled, warnings-as-errors build, patterns like as DockerReferenceComponent followed by member access after Should().NotBeNull() will generate warnings and may fail the build.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
namespace Microsoft.ComponentDetection.Detectors.Tests;

using System.Linq;
using System.Threading.Tasks;
using AwesomeAssertions;
using Microsoft.ComponentDetection.Contracts;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test file is missing the #nullable disable directive used across existing detector tests. With nullable enabled + warnings-as-errors, this will likely introduce warnings (e.g., nullable as casts followed by dereference) and fail the build.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +9
Helm detection depends on the following to successfully run:

- One or more Helm values files matching the patterns: `*values*.yaml`, `*values*.yml`
- Chart metadata files (`Chart.yaml`, `Chart.yml`, `chart.yaml`, `chart.yml`) are matched for file discovery but only values files are parsed for image references

Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requirements list *values*.yaml / *values*.yml patterns, but the repo’s file-pattern matcher only supports leading or trailing * (prefix/suffix wildcards). As written, those “contains” patterns won’t match real-world values files like values.production.yaml or myapp-values-dev.yml in production scans, so the docs will be misleading unless the matcher or patterns are updated.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 6, 2026 18:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds several new DefaultOff detectors to discover and register Docker image references from container-related configuration files (Docker Compose, Helm values, Kubernetes manifests) and centralizes “skip unresolved variables” logic in a shared Docker reference utility.

Changes:

  • Added new detectors: DockerComposeComponentDetector, HelmComponentDetector, and KubernetesComponentDetector, plus DI registration.
  • Added/updated shared Docker reference parsing helpers to silently skip image references containing unresolved variable placeholders.
  • Added detector docs and a suite of unit tests for the new detectors (and Dockerfile).
Show a summary per file
File Description
src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs New detector to parse Compose YAML and register image references.
src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs New detector to parse Helm values YAML (with chart co-location filtering) and register image references.
src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs New detector to parse Kubernetes YAML workload manifests and register container image references.
src/Microsoft.ComponentDetection.Common/DockerReference/DockerReferenceUtility.cs Added shared “unresolved variable” detection and safe parse/register helpers.
src/Microsoft.ComponentDetection.Detectors/dockerfile/DockerfileComponentDetector.cs Updated to use the shared Docker reference utility parsing logic.
src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs Registered the new detectors in DI.
src/Microsoft.ComponentDetection.Contracts/DetectorClass.cs Added new detector classes for DockerCompose/Helm/Kubernetes.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerComposeComponentDetectorTests.cs Added tests for Compose image extraction behaviors.
test/Microsoft.ComponentDetection.Detectors.Tests/HelmComponentDetectorTests.cs Added tests for Helm values parsing/co-location behaviors.
test/Microsoft.ComponentDetection.Detectors.Tests/KubernetesComponentDetectorTests.cs Added tests for Kubernetes manifest image extraction behaviors.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerfileComponentDetectorTests.cs Added tests validating Dockerfile image extraction and variable skipping.
docs/detectors/dockercompose.md Added detector documentation.
docs/detectors/helm.md Added detector documentation.
docs/detectors/kubernetes.md Added detector documentation.
docs/detectors/README.md Linked the new detector docs in the detector index.
.gitignore Ignored .nuget/.

Copilot's findings

  • Files reviewed: 15/16 changed files
  • Comments generated: 3

Comment on lines +16 to +28
### Supported Resource Kinds

The detector recognizes the following Kubernetes resource kinds:

- `Pod`
- `Deployment`
- `StatefulSet`
- `DaemonSet`
- `ReplicaSet`
- `Job`
- `CronJob`
- `ReplicationController`

Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc’s “Supported Resource Kinds” list doesn’t include PodTemplate, but the implementation’s KubernetesKinds set does. Please update the documentation to reflect the actual supported kinds (or remove PodTemplate support if it’s not intended).

Copilot uses AI. Check for mistakes.
Comment on lines +199 to +211
[TestMethod]
public async Task TestCompose_OverrideFileAsync()
{
var composeYaml = @"
services:
web:
image: myregistry.io/web:latest
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("docker-compose.override.yml", composeYaml)
.ExecuteDetectorAsync();

Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests appear to validate that override/env-specific filenames (e.g., docker-compose.override.yml, compose.prod.yaml) are discovered via SearchPatterns, but DetectorTestUtilityBuilder injects provided files into the detector even when they don’t match the detector’s patterns (it only affects ComponentStream.Pattern). Consider adding a unit test for PathUtilityService.MatchesPattern/pattern matching with these patterns, or enhancing the test utility to only emit files that actually match SearchPatterns, so file-discovery behavior is covered.

Copilot uses AI. Check for mistakes.
Comment on lines +368 to +397
public async Task TestHelm_ValuesOverrideFileAsync()
{
var valuesYaml = @"
image: redis:7-alpine
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("Chart.yaml", MinimalChartYaml)
.WithFile("values.production.yaml", valuesYaml)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
componentRecorder.GetDetectedComponents().Should().ContainSingle();
}

[TestMethod]
public async Task TestHelm_CustomValuesFilenameAsync()
{
var valuesYaml = @"
image: postgres:15
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("Chart.yaml", MinimalChartYaml)
.WithFile("myapp-values-dev.yml", valuesYaml)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
componentRecorder.GetDetectedComponents().Should().ContainSingle();
}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several tests here use filenames like values.production.yaml / myapp-values-dev.yml to validate Helm file discovery, but DetectorTestUtilityBuilder will execute the detector for any provided file regardless of whether it matches SearchPatterns (pattern matching only influences ComponentStream.Pattern). Consider adding explicit pattern-matching tests (or updating the test utility to filter by SearchPatterns) so the intended file-discovery behavior is actually covered.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 6, 2026 19:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new DefaultOff detectors to discover Docker image references in Docker Compose, Helm values, and Kubernetes manifests, and centralizes Docker image variable-placeholder skipping across Docker-related detectors.

Changes:

  • Introduces DockerComposeComponentDetector, HelmComponentDetector, and KubernetesComponentDetector (plus DI registration and DetectorClass updates).
  • Adds DockerReferenceUtility.HasUnresolvedVariables / TryParseImageReference / TryRegisterImageReference and updates Dockerfile detector to use the shared logic.
  • Adds detector documentation pages and comprehensive unit tests for the new detectors (and Dockerfile).
Show a summary per file
File Description
test/Microsoft.ComponentDetection.Detectors.Tests/KubernetesComponentDetectorTests.cs Adds unit tests for Kubernetes image extraction and variable-skipping behavior.
test/Microsoft.ComponentDetection.Detectors.Tests/HelmComponentDetectorTests.cs Adds unit tests for Helm values parsing, chart co-location behavior, and digests.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerfileComponentDetectorTests.cs Adds unit tests covering Dockerfile image extraction, digests, and unresolved variables.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerComposeComponentDetectorTests.cs Adds unit tests for Docker Compose image extraction and common filename variants.
src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs Registers the new detectors in the orchestrator DI container.
src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs New Kubernetes detector parsing YAML manifests to extract container image references.
src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs New Helm detector scanning values files and enforcing Chart co-location.
src/Microsoft.ComponentDetection.Detectors/dockerfile/DockerfileComponentDetector.cs Updates existing Dockerfile detector to use shared Docker reference parsing/skip logic.
src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs New Docker Compose detector scanning service image: fields.
src/Microsoft.ComponentDetection.Contracts/DetectorClass.cs Adds DockerCompose, Helm, and Kubernetes detector classes.
src/Microsoft.ComponentDetection.Common/DockerReference/DockerReferenceUtility.cs Adds shared helpers to detect unresolved variables and safely parse/register image references.
docs/detectors/README.md Links to new detector documentation pages.
docs/detectors/kubernetes.md Documents Kubernetes detector requirements/strategy/limitations.
docs/detectors/helm.md Documents Helm detector requirements/strategy/limitations.
docs/detectors/dockercompose.md Documents Docker Compose detector requirements/strategy/limitations.
.gitignore Ignores .nuget/ directory.

Copilot's findings

  • Files reviewed: 15/16 changed files
  • Comments generated: 3

Comment on lines +140 to +166
/// <summary>
/// Fast text-based pre-filter. Checks for "apiVersion" and a known "kind: &lt;K8sKind&gt;"
/// pattern using span operations to reject non-Kubernetes YAML without YAML parsing.
/// </summary>
private static bool LooksLikeKubernetesManifest(string contents)
{
var span = contents.AsSpan();

// Must contain apiVersion to be any kind of K8s manifest.
if (span.IndexOf("apiVersion".AsSpan(), StringComparison.Ordinal) < 0)
{
return false;
}

// Check for a known "kind: <K8sResource>" pattern. This is much more specific
// than just checking for "kind" and eliminates non-K8s YAML files (GitHub Actions,
// Azure Pipelines, CloudFormation, etc.) that also contain generic "kind" keys.
foreach (var pattern in KubernetesKindPatterns)
{
if (span.IndexOf(pattern.AsSpan(), StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
}

return false;
}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LooksLikeKubernetesManifest fast-path only looks for exact substrings like kind: Deployment. Valid manifests that quote the value (e.g., kind: "Deployment") won’t match any pattern and will be skipped before YAML parsing, causing missed detections. Consider loosening the prefilter (e.g., detect kind: plus any known kind token, allow optional quotes/whitespace, or fall back to YAML parsing when apiVersion is present).

Copilot uses AI. Check for mistakes.
- **DefaultOff Status**: This detector must be explicitly enabled using `--DetectorArgs Kubernetes=EnableIfDefaultOff`
- **Broad File Matching**: The `*.yaml` and `*.yml` search patterns match all YAML files, so the detector relies on content-based filtering (`apiVersion` and `kind` fields) to identify Kubernetes manifests
- **Variable Resolution**: Image references containing unresolved template variables are not reported
- **Limited Resource Kinds**: Only the eight resource kinds listed above are supported. Custom resources (CRDs) or other workload types are not detected
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The limitations section says “Only the eight resource kinds listed above are supported”, but the document lists nine kinds (Pod, PodTemplate, Deployment, StatefulSet, DaemonSet, ReplicaSet, Job, CronJob, ReplicationController). Please update the count to avoid confusion.

Suggested change
- **Limited Resource Kinds**: Only the eight resource kinds listed above are supported. Custom resources (CRDs) or other workload types are not detected
- **Limited Resource Kinds**: Only the nine resource kinds listed above are supported. Custom resources (CRDs) or other workload types are not detected

Copilot uses AI. Check for mistakes.
Comment on lines +199 to +275
[TestMethod]
public async Task TestCompose_OverrideFileAsync()
{
var composeYaml = @"
services:
web:
image: myregistry.io/web:latest
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("docker-compose.override.yml", composeYaml)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
var components = componentRecorder.GetDetectedComponents();
components.Should().ContainSingle();
}

[TestMethod]
public async Task TestCompose_UnresolvedVariableSkippedAsync()
{
var composeYaml = @"
services:
app:
image: ${REGISTRY}/app:${TAG}
db:
image: postgres:15
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("docker-compose.yml", composeYaml)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
var components = componentRecorder.GetDetectedComponents();

// Only the literal image reference (postgres:15) should be registered;
// the variable-interpolated image (${REGISTRY}/app:${TAG}) should be silently skipped.
components.Should().ContainSingle();
var dockerRef = components.First().Component as DockerReferenceComponent;
dockerRef.Should().NotBeNull();
dockerRef.Repository.Should().Be("library/postgres");
}

[TestMethod]
public async Task TestCompose_ComposeOverrideFileAsync()
{
var composeYaml = @"
services:
web:
image: nginx:1.21
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("compose.override.yml", composeYaml)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
componentRecorder.GetDetectedComponents().Should().ContainSingle();
}

[TestMethod]
public async Task TestCompose_ComposeOverrideYamlAsync()
{
var composeYaml = @"
services:
db:
image: postgres:15
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("compose.prod.yaml", composeYaml)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
componentRecorder.GetDetectedComponents().Should().ContainSingle();
}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The override/variant filename tests here can give a false sense of coverage for real file discovery. DetectorTestUtilityBuilder supplies the file to the detector even if it wouldn’t match SearchPatterns during a real scan, so these tests won’t fail if the wildcard patterns are unsupported by PathUtilityService.MatchesPattern. Consider adding an assertion that the filename matches one of the detector’s SearchPatterns (using the same matcher the walker uses) to ensure these variants are actually discoverable.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 7, 2026 17:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds new DefaultOff detectors to discover and register Docker image references from Docker Compose, Helm values, and Kubernetes YAML manifests, and centralizes “unresolved variable” skipping logic in a shared Docker reference utility.

Changes:

  • Added new detectors: DockerComposeComponentDetector, HelmComponentDetector, and KubernetesComponentDetector, plus DI registration and DetectorClass enum updates.
  • Added/updated Docker image parsing utilities (DockerReferenceUtility) and updated the existing Dockerfile detector to reuse shared parsing/skip logic.
  • Added unit tests and verification-test resources/workflow updates for the new detectors.
Show a summary per file
File Description
test/Microsoft.ComponentDetection.VerificationTests/resources/VerificationTest.ps1 Enables new detectors in verification scan script.
test/Microsoft.ComponentDetection.VerificationTests/resources/kubernetes/statefulset.yaml Adds Kubernetes sample manifest for verification resources.
test/Microsoft.ComponentDetection.VerificationTests/resources/kubernetes/deployment.yaml Adds Kubernetes sample manifest for verification resources.
test/Microsoft.ComponentDetection.VerificationTests/resources/kubernetes/cronjob.yaml Adds Kubernetes sample manifest for verification resources.
test/Microsoft.ComponentDetection.VerificationTests/resources/helm/values.yaml Adds Helm values sample for verification resources.
test/Microsoft.ComponentDetection.VerificationTests/resources/helm/Chart.yaml Adds Helm chart metadata sample for verification resources.
test/Microsoft.ComponentDetection.VerificationTests/resources/dockercompose/docker-compose.yml Adds Docker Compose sample for verification resources.
test/Microsoft.ComponentDetection.VerificationTests/resources/dockercompose/docker-compose.override.yml Adds Docker Compose override sample for verification resources.
test/Microsoft.ComponentDetection.Detectors.Tests/KubernetesComponentDetectorTests.cs Adds unit tests for Kubernetes image extraction and skipping unresolved variables.
test/Microsoft.ComponentDetection.Detectors.Tests/HelmComponentDetectorTests.cs Adds unit tests for Helm values parsing and chart co-location behavior.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerfileComponentDetectorTests.cs Adds/updates unit tests for Dockerfile detector behavior including unresolved variable skipping.
test/Microsoft.ComponentDetection.Detectors.Tests/DockerComposeComponentDetectorTests.cs Adds unit tests for Docker Compose parsing and unresolved variable skipping.
src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs Registers the new detectors in DI.
src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs Implements Kubernetes YAML detection/parsing and image extraction.
src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs Implements Helm detection with chart/values co-location gating and YAML traversal.
src/Microsoft.ComponentDetection.Detectors/dockerfile/DockerfileComponentDetector.cs Refactors Dockerfile parsing to use shared Docker reference utility methods.
src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs Implements Docker Compose YAML detection/parsing and image extraction.
src/Microsoft.ComponentDetection.Contracts/DetectorClass.cs Adds DockerCompose, Helm, and Kubernetes detector classes.
src/Microsoft.ComponentDetection.Common/DockerReference/DockerReferenceUtility.cs Adds shared helpers for unresolved-variable detection and “try-parse/register” behavior.
docs/detectors/README.md Links to new detector documentation pages and adds status entries.
docs/detectors/kubernetes.md Adds documentation for Kubernetes detector behavior/limitations.
docs/detectors/helm.md Adds documentation for Helm detector behavior/limitations.
docs/detectors/dockercompose.md Adds documentation for Docker Compose detector behavior/limitations.
.gitignore Ignores local .nuget/ directory.
.github/workflows/snapshot-verify.yml Enables new detectors during snapshot verification scan.
.github/workflows/snapshot-publish.yml Enables new detectors during snapshot publish scan.

Copilot's findings

  • Files reviewed: 25/26 changed files
  • Comments generated: 2

Copilot AI review requested due to automatic review settings April 8, 2026 16:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends Component Detection’s Docker image reference scanning by adding DefaultOff detectors for Docker Compose, Helm values, and Kubernetes manifests, plus consolidating “unresolved variable” skipping into a shared utility used across Docker-related detectors.

Changes:

  • Added new detectors: DockerComposeComponentDetector, HelmComponentDetector, KubernetesComponentDetector and registered them in DI.
  • Added shared Docker reference helpers (HasUnresolvedVariables, TryParseImageReference, TryRegisterImageReference) and updated the Dockerfile detector to use them.
  • Added unit tests + verification resources/docs and enabled the new detectors in snapshot/verification workflows.
Show a summary per file
File Description
src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs New Docker Compose YAML detector for services.*.image references.
src/Microsoft.ComponentDetection.Detectors/helm/HelmComponentDetector.cs New Helm detector with Chart/values co-location logic and YAML walk for image keys.
src/Microsoft.ComponentDetection.Detectors/kubernetes/KubernetesComponentDetector.cs New Kubernetes detector that parses YAML documents to extract container image references.
src/Microsoft.ComponentDetection.Common/DockerReference/DockerReferenceUtility.cs Adds shared parsing/registration helpers and unresolved-variable skipping.
src/Microsoft.ComponentDetection.Detectors/dockerfile/DockerfileComponentDetector.cs Refactors to use DockerReferenceUtility.TryParseImageReference (removes local regex check).
src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs Registers the new detectors in DI.
src/Microsoft.ComponentDetection.Contracts/DetectorClass.cs Adds DockerCompose, Helm, Kubernetes detector classes.
test/Microsoft.ComponentDetection.Detectors.Tests/* Adds tests for new detectors and expands Dockerfile detector tests.
test/Microsoft.ComponentDetection.VerificationTests/resources/* Adds verification resources for docker-compose/helm/kubernetes detectors.
docs/detectors/* Adds detector documentation pages and links from detectors README.
.github/workflows/snapshot-verify.yml / .github/workflows/snapshot-publish.yml Enables the new DefaultOff detectors for snapshot scans.
test/.../VerificationTest.ps1 Enables the new DefaultOff detectors in the local verification script.
.gitignore Ignores .nuget/.

Copilot's findings

Comments suppressed due to low confidence (4)

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

  • SearchPatterns uses *values*.* (wildcard in the middle), but the repo’s filename matcher (PathUtilityService.MatchesPattern) only supports * as a leading or trailing wildcard. As a result, values files like values.production.yaml / myapp-values-dev.yml won’t be discovered in real scans, so the detector will effectively never run. Consider switching to patterns the matcher supports (e.g., *.yaml/*.yml) and rely on IsValuesFile + the Chart co-location filtering in OnPrepareDetectionAsync.
    public override IList<string> SearchPatterns { get; } =
    [
        "Chart.yaml", "Chart.yml",
        "*values*.yaml", "*values*.yml",
    ];

src/Microsoft.ComponentDetection.Detectors/dockercompose/DockerComposeComponentDetector.cs:36

  • SearchPatterns includes docker-compose.*.yml / compose.*.yaml (wildcard in the middle), but the repo’s filename matcher only supports * at the start or end. These patterns will be treated literally, so override/env-specific compose files (e.g., docker-compose.override.yml, compose.prod.yaml) won’t be discovered in production scans. Please change to supported prefix patterns (e.g., docker-compose.* / compose.*) or broaden to *.yml/*.yaml with a filename/content filter.
    public override IList<string> SearchPatterns { get; } =
    [
        "docker-compose.yml", "docker-compose.yaml",
        "docker-compose.*.yml", "docker-compose.*.yaml",
        "compose.yml", "compose.yaml",
        "compose.*.yml", "compose.*.yaml",
    ];

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

  • LooksLikeKubernetesManifest is likely to produce false negatives because it only returns true when the file contains an exact substring like kind: Deployment (no quotes, no additional whitespace). Valid manifests such as kind: "Deployment" or kind: Deployment will be skipped without YAML parsing, and their images won’t be detected. Consider making the prefilter tolerant of whitespace/quotes (or just check for apiVersion + kind: and let IsKubernetesManifest do the precise validation).
        // Must contain apiVersion to be any kind of K8s manifest.
        if (span.IndexOf("apiVersion".AsSpan(), StringComparison.Ordinal) < 0)
        {
            return false;
        }

        // Check for a known "kind: <K8sResource>" pattern. This is much more specific
        // than just checking for "kind" and eliminates non-K8s YAML files (GitHub Actions,
        // Azure Pipelines, CloudFormation, etc.) that also contain generic "kind" keys.
        foreach (var pattern in KubernetesKindPatterns)
        {
            if (span.IndexOf(pattern.AsSpan(), StringComparison.OrdinalIgnoreCase) >= 0)
            {
                return true;
            }
        }

        return false;
    }

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

  • The apiVersion prefilter uses a case-sensitive IndexOf(..., StringComparison.Ordinal). Even though apiVersion is normally cased this way, using OrdinalIgnoreCase would be more robust and consistent with the rest of the detector’s case-insensitive checks, without materially impacting performance.
        // Must contain apiVersion to be any kind of K8s manifest.
        if (span.IndexOf("apiVersion".AsSpan(), StringComparison.Ordinal) < 0)
        {
            return false;
        }

  • Files reviewed: 25/26 changed files
  • Comments generated: 4

using Microsoft.ComponentDetection.Common;
using Microsoft.ComponentDetection.Contracts;
using Microsoft.ComponentDetection.Contracts.Internal;
using Microsoft.ComponentDetection.Contracts.TypedComponent;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s an unused using Microsoft.ComponentDetection.Contracts.TypedComponent; here. With TreatWarningsAsErrors=true, this is likely to fail the build with CS8019. Please remove the unused using (or reference a type from that namespace if it’s actually needed).

This issue also appears on line 35 of the same file.

Suggested change
using Microsoft.ComponentDetection.Contracts.TypedComponent;

Copilot uses AI. Check for mistakes.
using Microsoft.ComponentDetection.Common;
using Microsoft.ComponentDetection.Contracts;
using Microsoft.ComponentDetection.Contracts.Internal;
using Microsoft.ComponentDetection.Contracts.TypedComponent;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s an unused using Microsoft.ComponentDetection.Contracts.TypedComponent; here. With TreatWarningsAsErrors=true, this can fail the build (CS8019). Please remove the unused using.

This issue also appears on line 30 of the same file.

Suggested change
using Microsoft.ComponentDetection.Contracts.TypedComponent;

Copilot uses AI. Check for mistakes.
using Microsoft.ComponentDetection.Common;
using Microsoft.ComponentDetection.Contracts;
using Microsoft.ComponentDetection.Contracts.Internal;
using Microsoft.ComponentDetection.Contracts.TypedComponent;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s an unused using Microsoft.ComponentDetection.Contracts.TypedComponent; here. With TreatWarningsAsErrors=true, this can fail the build (CS8019). Please remove the unused using.

This issue also appears in the following locations of the same file:

  • line 148
  • line 148
Suggested change
using Microsoft.ComponentDetection.Contracts.TypedComponent;

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +8
Docker Compose detection depends on the following to successfully run:

- One or more Docker Compose files matching the patterns: `docker-compose.yml`, `docker-compose.yaml`, `docker-compose.*.yml`, `docker-compose.*.yaml`, `compose.yml`, `compose.yaml`, `compose.*.yml`, `compose.*.yaml`

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documented patterns include docker-compose.*.yml / compose.*.yaml, but the repo’s file discovery matcher only supports * as a leading or trailing wildcard. These mid-string wildcard patterns won’t match in production, so the docs currently promise support that won’t work. Please update the documented patterns to the supported form (or update the detector + matcher and keep docs in sync).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants