Skip to content

Commit 8f58a16

Browse files
a-orenclaude
andcommitted
fix: address PR review feedback for DockerfileAnnotator (TC-4811)
- Catch MalformedPackageURLException in PURL filters instead of re-throwing - Restore UBIIntentionAction as unconditional quick-fix (regression fix) - Fix inconsistent withFix() builder pattern (missing reassignment) - Remove redundant hasIssue(report) guard condition - Extract shared PURL matching logic into generic findMatchingRecommendation() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d38a838 commit 8f58a16

1 file changed

Lines changed: 52 additions & 52 deletions

File tree

src/main/java/org/jboss/tools/intellij/image/DockerfileAnnotator.java

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,17 @@
4040
import org.jetbrains.annotations.NotNull;
4141
import org.jetbrains.annotations.Nullable;
4242

43+
import io.github.guacsec.trustifyda.api.PackageRef;
44+
4345
import java.util.Collection;
4446
import java.util.HashSet;
4547
import java.util.List;
4648
import java.util.Map;
4749
import java.util.Objects;
4850
import java.util.Optional;
51+
import java.util.function.Function;
4952
import java.util.stream.Collectors;
53+
import java.util.stream.Stream;
5054

5155
public class DockerfileAnnotator extends ExternalAnnotator<DockerfileAnnotator.Info, Map<BaseImage, DockerfileAnnotator.Result>> {
5256

@@ -243,57 +247,55 @@ static boolean hasIssue(AnalysisReport report) {
243247

244248
/** Returns the UBI image recommendation (from source-level dependencies), or null if none. */
245249
static String getRecommendation(AnalysisReport report, ImageRef imageRef) {
246-
return Optional.ofNullable(report.getProviders())
247-
.flatMap(provider -> provider.values()
248-
.stream()
249-
.filter(Objects::nonNull)
250-
.map(ProviderReport::getSources)
251-
.filter(Objects::nonNull)
252-
.map(Map::values)
253-
.flatMap(Collection::stream)
254-
.filter(Objects::nonNull)
255-
.map(Source::getDependencies)
256-
.filter(Objects::nonNull)
257-
.flatMap(Collection::stream)
258-
.filter(r -> r.getRef() != null)
259-
.filter(r -> {
260-
try {
261-
return imageRef.getPackageURL().equals(r.getRef().purl());
262-
} catch (MalformedPackageURLException e) {
263-
throw new RuntimeException(e);
264-
}
265-
})
266-
.map(DependencyReport::getRecommendation)
267-
.filter(Objects::nonNull)
268-
.findAny())
269-
.map(DockerfileAnnotator::toImageName)
270-
.orElse(null);
250+
var deps = Optional.ofNullable(report.getProviders())
251+
.stream()
252+
.flatMap(provider -> provider.values().stream())
253+
.filter(Objects::nonNull)
254+
.map(ProviderReport::getSources)
255+
.filter(Objects::nonNull)
256+
.map(Map::values)
257+
.flatMap(Collection::stream)
258+
.filter(Objects::nonNull)
259+
.map(Source::getDependencies)
260+
.filter(Objects::nonNull)
261+
.flatMap(Collection::stream);
262+
return findMatchingRecommendation(deps, imageRef, DependencyReport::getRef, DependencyReport::getRecommendation);
271263
}
272264

273265
/** Returns the hardened image recommendation (from provider-level recommendations), or null if none. */
274266
static String getHardenedRecommendation(AnalysisReport report, ImageRef imageRef) {
275-
return Optional.ofNullable(report.getProviders())
276-
.flatMap(provider -> provider.values()
277-
.stream()
278-
.filter(Objects::nonNull)
279-
.map(ProviderReport::getRecommendations)
280-
.filter(Objects::nonNull)
281-
.flatMap(recs -> recs.entrySet().stream())
282-
.filter(entry -> entry.getValue() != null)
283-
.map(entry -> entry.getValue().getDependencies())
284-
.filter(Objects::nonNull)
285-
.flatMap(Collection::stream)
286-
.filter(r -> r.getRef() != null)
287-
.filter(r -> {
288-
try {
289-
return imageRef.getPackageURL().equals(r.getRef().purl());
290-
} catch (MalformedPackageURLException e) {
291-
throw new RuntimeException(e);
292-
}
293-
})
294-
.map(r -> r.getRecommendation())
295-
.filter(Objects::nonNull)
296-
.findAny())
267+
var deps = Optional.ofNullable(report.getProviders())
268+
.stream()
269+
.flatMap(provider -> provider.values().stream())
270+
.filter(Objects::nonNull)
271+
.map(ProviderReport::getRecommendations)
272+
.filter(Objects::nonNull)
273+
.flatMap(recs -> recs.entrySet().stream())
274+
.filter(entry -> entry.getValue() != null)
275+
.map(entry -> entry.getValue().getDependencies())
276+
.filter(Objects::nonNull)
277+
.flatMap(Collection::stream);
278+
return findMatchingRecommendation(deps, imageRef,
279+
io.github.guacsec.trustifyda.api.v5.RecommendationReport::getRef,
280+
io.github.guacsec.trustifyda.api.v5.RecommendationReport::getRecommendation);
281+
}
282+
283+
private static <T> String findMatchingRecommendation(Stream<T> items, ImageRef imageRef,
284+
Function<T, PackageRef> refExtractor,
285+
Function<T, PackageRef> recommendationExtractor) {
286+
return items
287+
.filter(r -> refExtractor.apply(r) != null)
288+
.filter(r -> {
289+
try {
290+
return imageRef.getPackageURL().equals(refExtractor.apply(r).purl());
291+
} catch (MalformedPackageURLException e) {
292+
LOG.warn("Skipping recommendation with malformed PURL", e);
293+
return false;
294+
}
295+
})
296+
.map(recommendationExtractor)
297+
.filter(Objects::nonNull)
298+
.findAny()
297299
.map(DockerfileAnnotator::toImageName)
298300
.orElse(null);
299301
}
@@ -338,7 +340,7 @@ private static HighlightSeverity getHighlightSeverity(AnalysisReport report, Str
338340
String hardenedRecommendation, boolean hasIssue,
339341
@NotNull PsiElement context) {
340342
// Recommendation-only (no vulnerabilities): use INFORMATION severity (blue)
341-
if (!hasIssue && !hasIssue(report)) {
343+
if (!hasIssue) {
342344
boolean hasAnyRecommendation = recommendation != null || hardenedRecommendation != null;
343345
if (hasAnyRecommendation) {
344346
return HighlightSeverity.INFORMATION;
@@ -466,11 +468,9 @@ public void apply(@NotNull PsiFile file, Map<BaseImage, Result> annotationResult
466468
builder = builder.enforcedTextAttributes(attrs);
467469
}
468470
builder = builder.withFix(new ImageReportIntentionAction());
469-
if (recommendation != null) {
470-
builder.withFix(new UBIIntentionAction());
471-
}
471+
builder = builder.withFix(new UBIIntentionAction());
472472
if (hardenedRecommendation != null) {
473-
builder.withFix(new HardenedImageIntentionAction());
473+
builder = builder.withFix(new HardenedImageIntentionAction());
474474
}
475475
builder.create();
476476
}

0 commit comments

Comments
 (0)