This is an automated email from the ASF dual-hosted git repository.

exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 49d0760430 NIFI-14442 Show Bundle Version Changes with other Versioned 
Flow Differences (#9967)
49d0760430 is described below

commit 49d0760430816c3e3c169ae112906dc59d531d30
Author: Michael Moser <[email protected]>
AuthorDate: Wed Oct 22 15:56:51 2025 -0400

    NIFI-14442 Show Bundle Version Changes with other Versioned Flow 
Differences (#9967)
    
    Signed-off-by: David Handermann <[email protected]>
---
 .../apache/nifi/util/FlowDifferenceFilters.java    |  6 ++-
 .../apache/nifi/web/StandardNiFiServiceFacade.java |  7 +---
 .../org/apache/nifi/web/api/dto/DtoFactory.java    | 49 +++++++++++++++++++---
 .../local-changes-table/local-changes-table.ts     |  2 +-
 .../diff/ConciseEvolvingDifferenceDescriptor.java  | 23 +++++++---
 5 files changed, 68 insertions(+), 19 deletions(-)

diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
index ea4e8d0ad9..5f8da2e20e 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
@@ -83,7 +83,7 @@ public class FlowDifferenceFilters {
     public static boolean isEnvironmentalChange(final FlowDifference 
difference, final VersionedProcessGroup localGroup, final FlowManager 
flowManager,
                                                 final 
EnvironmentalChangeContext context) {
         final EnvironmentalChangeContext evaluatedContext = 
Objects.requireNonNull(context, "EnvironmentalChangeContext required");
-        return difference.getDifferenceType() == DifferenceType.BUNDLE_CHANGED
+        return isBundleChange(difference)
             || isSensitivePropertyDueToGhosting(difference, flowManager)
             || isRpgUrlChange(difference)
             || isAddedOrRemovedRemotePort(difference)
@@ -106,6 +106,10 @@ public class FlowDifferenceFilters {
             || isSelectedRelationshipChangeForNewRelationship(difference, 
flowManager);
     }
 
+    public static boolean isBundleChange(final FlowDifference difference) {
+        return difference.getDifferenceType() == DifferenceType.BUNDLE_CHANGED;
+    }
+
     private static boolean isSensitivePropertyDueToGhosting(final 
FlowDifference difference, final FlowManager flowManager) {
         final DifferenceType differenceType = difference.getDifferenceType();
         if (differenceType != DifferenceType.PROPERTY_SENSITIVITY_CHANGED && 
differenceType != DifferenceType.PROPERTY_ADDED) {
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 05c9f63c17..a50cfed673 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -5601,12 +5601,7 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
                     + " but cannot find a Flow Registry with that identifier");
         }
 
-        VersionedProcessGroup registryGroup = null;
-        final VersionControlInformation vci = 
processGroup.getVersionControlInformation();
-        if (vci != null) {
-            registryGroup = vci.getFlowSnapshot();
-        }
-
+        VersionedProcessGroup registryGroup = 
versionControlInfo.getFlowSnapshot();
         if (registryGroup == null) {
             try {
                 final FlowVersionLocation flowVersionLocation = new 
FlowVersionLocation(versionControlInfo.getBranch(), 
versionControlInfo.getBucketIdentifier(),
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 1c401ba690..684435065f 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -2799,6 +2799,7 @@ public final class DtoFactory {
 
    public Set<ComponentDifferenceDTO> 
createComponentDifferenceDtosForLocalModifications(final FlowComparison 
comparison, final VersionedProcessGroup localGroup, final FlowManager 
flowManager) {
        final Map<ComponentDifferenceDTO, List<DifferenceDTO>> 
differencesByComponent = new HashMap<>();
+       final Map<ComponentDifferenceDTO, Set<DifferenceDTO>> 
bundleDifferencesByComponent = new HashMap<>();
 
        final Map<String, VersionedProcessGroup> versionedGroups = 
flattenProcessGroups(comparison.getFlowA().getContents());
 
@@ -2807,6 +2808,13 @@ public final class DtoFactory {
                
FlowDifferenceFilters.buildEnvironmentalChangeContext(comparisonDifferences, 
flowManager);
 
        for (final FlowDifference difference : comparisonDifferences) {
+           // capture bundle differences and dedupe those differences
+           if (FlowDifferenceFilters.isBundleChange(difference)) {
+               final ComponentDifferenceDTO componentDiff = 
createBundleDifference(difference);
+               final Set<DifferenceDTO> differences = 
bundleDifferencesByComponent.computeIfAbsent(componentDiff, key -> new 
HashSet<>());
+               differences.add(createDifferenceDto(difference));
+           }
+
            // Ignore any environment-specific change
            if (FlowDifferenceFilters.isEnvironmentalChange(difference, 
localGroup, flowManager, environmentalContext)) {
                continue;
@@ -2820,12 +2828,19 @@ public final class DtoFactory {
 
            final ComponentDifferenceDTO componentDiff = 
createComponentDifference(difference);
            final List<DifferenceDTO> differences = 
differencesByComponent.computeIfAbsent(componentDiff, key -> new ArrayList<>());
-
-           final DifferenceDTO dto = new DifferenceDTO();
-           
dto.setDifferenceType(difference.getDifferenceType().getDescription());
-           dto.setDifference(difference.getDescription());
-
-           differences.add(dto);
+           differences.add(createDifferenceDto(difference));
+       }
+
+       if (!differencesByComponent.isEmpty()) {
+           // differences were found, so now let's add back in any 
BUNDLE_CHANGED differences
+           // since they were initially filtered out as an 
environment-specific change
+           bundleDifferencesByComponent.forEach((key, value) -> {
+               List<DifferenceDTO> values = value.stream().toList();
+               differencesByComponent.merge(key, values, (v1, v2) -> {
+                   v1.addAll(v2);
+                   return v1;
+               });
+           });
        }
 
        for (final Map.Entry<ComponentDifferenceDTO, List<DifferenceDTO>> entry 
: differencesByComponent.entrySet()) {
@@ -2835,6 +2850,16 @@ public final class DtoFactory {
        return differencesByComponent.keySet();
    }
 
+   /*
+    * Create a custom difference with a simpler difference description, only 
for matching descriptions.
+    */
+   DifferenceDTO createDifferenceDto(final FlowDifference difference) {
+       final DifferenceDTO dto = new DifferenceDTO();
+       dto.setDifferenceType(difference.getDifferenceType().getDescription());
+       dto.setDifference(difference.getDescription());
+       return dto;
+   }
+
    private Map<String, VersionedProcessGroup> flattenProcessGroups(final 
VersionedProcessGroup group) {
        final Map<String, VersionedProcessGroup> flattened = new HashMap<>();
        flattenProcessGroups(group, flattened);
@@ -2849,6 +2874,18 @@ public final class DtoFactory {
        }
    }
 
+   private ComponentDifferenceDTO createBundleDifference(final FlowDifference 
difference) {
+       VersionedComponent component = difference.getComponentB();
+
+       final ComponentDifferenceDTO dto = new ComponentDifferenceDTO();
+       dto.setComponentType(component.getComponentType().toString());
+       // bundle difference could apply to many components, but use the 
Process Group identifier as
+       // the Component Identifier here so that many similar component 
differences can be easily deduped
+       dto.setComponentId(component.getGroupIdentifier());
+
+       return dto;
+   }
+
    private ComponentDifferenceDTO createComponentDifference(final 
FlowDifference difference) {
        VersionedComponent component = difference.getComponentA();
        if (component == null || difference.getComponentB() instanceof 
InstantiatedVersionedComponent) {
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
index e7123f8057..6d38b44c7d 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/items/flow/local-changes-dialog/local-changes-table/local-changes-table.ts
@@ -125,7 +125,7 @@ export class LocalChangesTable implements AfterViewInit {
     }
 
     canGoTo(item: LocalChange): boolean {
-        return item.differenceType !== 'Component Removed';
+        return (item.differenceType !== 'Component Removed') && 
(item.differenceType !== 'Component Bundle Changed');
     }
 
     formatDifference(item: LocalChange): string {
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/ConciseEvolvingDifferenceDescriptor.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/ConciseEvolvingDifferenceDescriptor.java
index 2e6cf79a7e..1a26441cc7 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/ConciseEvolvingDifferenceDescriptor.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/ConciseEvolvingDifferenceDescriptor.java
@@ -20,6 +20,7 @@ package org.apache.nifi.registry.flow.diff;
 import org.apache.nifi.flow.ScheduledState;
 import org.apache.nifi.flow.VersionedComponent;
 import org.apache.nifi.flow.VersionedFlowCoordinates;
+import org.apache.nifi.flow.VersionedProcessor;
 
 import java.util.Objects;
 
@@ -72,9 +73,7 @@ public class ConciseEvolvingDifferenceDescriptor implements 
DifferenceDescriptor
                 description = "Connection Bendpoints changed";
                 break;
             case VERSIONED_FLOW_COORDINATES_CHANGED:
-                if (valueA instanceof VersionedFlowCoordinates && valueB 
instanceof VersionedFlowCoordinates) {
-                    final VersionedFlowCoordinates coordinatesA = 
(VersionedFlowCoordinates) valueA;
-                    final VersionedFlowCoordinates coordinatesB = 
(VersionedFlowCoordinates) valueB;
+                if (valueA instanceof VersionedFlowCoordinates coordinatesA && 
valueB instanceof VersionedFlowCoordinates coordinatesB) {
 
                     // If the two vary only by version, then use a more 
concise message. If anything else is different, then use a fully explanation.
                     if (Objects.equals(coordinatesA.getStorageLocation(), 
coordinatesB.getStorageLocation()) && 
Objects.equals(coordinatesA.getBucketId(), coordinatesB.getBucketId())
@@ -85,14 +84,28 @@ public class ConciseEvolvingDifferenceDescriptor implements 
DifferenceDescriptor
                     }
                 }
 
-                description = String.format("From '%s' to '%s'", valueA, 
valueB);
+                description = defaultDescription(valueA, valueB);
+                break;
+            case BUNDLE_CHANGED:
+                if (componentA instanceof VersionedProcessor processorA && 
componentB instanceof VersionedProcessor processorB) {
+                    String artifact = processorA.getBundle().getArtifact();
+                    String versionA = processorA.getBundle().getVersion();
+                    String versionB = processorB.getBundle().getVersion();
+                    description = String.format("%s version %s to %s", 
artifact, versionA, versionB);
+                    break;
+                }
+
+                description = defaultDescription(valueA, valueB);
                 break;
             default:
-                description = String.format("From '%s' to '%s'", valueA, 
valueB);
+                description = defaultDescription(valueA, valueB);
                 break;
         }
 
         return description;
     }
 
+    private String defaultDescription(Object valueA, Object valueB) {
+        return String.format("From '%s' to '%s'", valueA, valueB);
+    }
 }

Reply via email to