Skip to content

Conversation

@klesaulnier
Copy link
Contributor

PR Summary

A param "isDebug" has been added to process execution endpoint to do so

Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a debug mode flag across the execution stack, persists debug metadata to the database, and integrates S3-based export of compressed debug artifacts produced during worker steps.

Changes

Cohort / File(s) Summary
Commons: Run message & S3 helper
monitor-commons/src/main/java/org/gridsuite/monitor/commons/ProcessRunMessage.java, monitor-commons/src/main/java/org/gridsuite/monitor/commons/utils/S3PathUtils.java
Adds isDebug boolean component to ProcessRunMessage and introduces S3PathUtils with delimiter constant and toDebugLocation(...).
Server controller & service API
monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/MonitorController.java, monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java, monitor-server/src/main/java/org/gridsuite/monitor/server/services/NotificationService.java
Adds isDebug parameter to controller endpoint and service APIs; MonitorService.executeProcess(...) now accepts isDebug and propagates it to notifications and execution entity. NotificationService builds ProcessRunMessage including isDebug.
Persistence & changelog
monitor-server/src/main/java/org/gridsuite/monitor/server/entities/ProcessExecutionEntity.java, monitor-server/src/main/resources/db/changelog/changesets/changelog_20260212T082157Z.xml, monitor-server/src/main/resources/db/changelog/db.changelog-master.yaml
Adds isDebug (boolean) and debugFileLocation (String) fields to entity and corresponding Liquibase changesets (new columns, is_debug NOT NULL DEFAULT false).
Worker: context, steps, and S3 integration
monitor-worker-server/src/main/java/.../ProcessExecutionContext.java, .../ProcessStepExecutionContext.java, .../AbstractProcessStep.java, .../ProcessExecutionService.java, .../processes/commons/steps/ApplyModificationsStep.java
Propagates isDebug into ProcessExecutionContext (constructor + field) and exposes via ProcessStepExecutionContext#isDebug(); adds getDebugFilePath helper and wires S3Service into ApplyModificationsStep to export compressed debug artifacts when debug is enabled; ProcessExecutionService passes isDebug from run message.
S3 infra & config
monitor-worker-server/pom.xml, monitor-worker-server/src/main/java/.../config/S3Configuration.java, monitor-worker-server/src/main/java/.../services/S3RestService.java, monitor-worker-server/src/main/java/.../services/S3Service.java, monitor-worker-server/src/main/java/.../dto/S3InputStreamInfos.java, monitor-worker-server/src/main/resources/application-local.yaml
Adds AWS S3 dependency, S3 configuration bean, S3RestService (upload/download using SDK v2), S3Service (exportCompressedToS3 with gzip and upload), DTO for stream metadata, and local S3 endpoint config.
Tests
monitor-server/src/test/java/..., monitor-worker-server/src/test/java/...
Updates tests to new signatures and behaviors: pass isDebug (commonly false) to executeProcess/ProcessRunMessage, add parameterized tests for isDebug, mock S3Service where required, and assert debug-related fields where applicable.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Controller as MonitorController
    participant Service as MonitorService
    participant Notifier as NotificationService
    participant Worker as Worker
    participant S3Srv as S3Service
    participant DB as Database
    participant S3 as S3

    Client->>Controller: POST /executeSecurityAnalysis (isDebug=true)
    Controller->>Service: executeProcess(caseUuid, userId, config, true)
    Service->>DB: persist ProcessExecutionEntity(isDebug=true)
    Service->>Notifier: sendProcessRunMessage(caseUuid, config, true, executionId)
    Notifier->>Worker: publish ProcessRunMessage(..., isDebug=true)
    Worker->>Worker: run steps (checks isDebug)
    alt isDebug == true
        Worker->>S3Srv: exportCompressedToS3(debugPath, debugFileName, writer)
        S3Srv->>S3: upload compressed artifact
    end
    Worker->>Service: update status (COMPLETED/FAILED)
    Service->>DB: setDebugFileLocation(s3Path) when applicable
    DB-->>Client: execution complete (with debugFileLocation)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Save launch parameters #24: Modifies the same controller/service APIs and ProcessExecutionEntity schema — strong overlap with API and persistence changes.
  • Get steps statuses of an execution #32: Touches worker core classes (ProcessExecutionContext, ProcessStepExecutionContext, AbstractProcessStep) that are also changed here.
  • Delete an execution #27: Alters ProcessExecutionEntity and service surfaces that intersect with this PR’s debug/storage changes.

Suggested reviewers

  • antoinebhs

Poem

🐰 I added a flag with a twitch of my nose,

Debug trails now where the process goes.
Compressed and uploaded, each curious trace,
Hopping through logs to the S3 place.
A rabbit’s delight — trouble finds its space! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.13% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Add debug mode to process execution' directly and clearly summarizes the main change: introducing debug mode functionality to the process execution feature.
Description check ✅ Passed The PR description mentions adding an 'isDebug' parameter to the process execution endpoint, which is directly related to the changeset that adds debug mode support across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch process-debug

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java (1)

76-105: Consider verifying isDebug on the persisted entity.

The argThat matcher on Line 90–98 verifies standard fields (type, caseUuid, userId, status, scheduledAt) but doesn't assert that execution.isDebug() == isDebug. Adding this assertion would confirm the flag is persisted correctly.

Proposed addition
         verify(executionRepository).save(argThat(execution ->
                         execution.getId() != null &&
                         ProcessType.SECURITY_ANALYSIS.name().equals(execution.getType()) &&
                         caseUuid.equals(execution.getCaseUuid()) &&
                         userId.equals(execution.getUserId()) &&
                         ProcessStatus.SCHEDULED.equals(execution.getStatus()) &&
                         execution.getScheduledAt() != null &&
-                        execution.getStartedAt() == null
+                        execution.getStartedAt() == null &&
+                        execution.isDebug() == isDebug
         ));

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/securityanalysis/SecurityAnalysisProcess.java (1)

43-50: ⚠️ Potential issue | 🔴 Critical

Critical: applyModificationsStep is listed twice — modifications will be applied twice.

This appears to be a copy-paste error. Applying modifications twice will corrupt network state or produce incorrect results if the modifications are not idempotent.

Proposed fix
     public List<ProcessStep<SecurityAnalysisConfig>> defineSteps() {
         return List.of(
             loadNetworkStep,
             applyModificationsStep,
-            applyModificationsStep,
             runComputationStep
         );
     }
🤖 Fix all issues with AI agents
In
`@monitor-commons/src/main/java/org/gridsuite/monitor/commons/ProcessRunMessage.java`:
- Around line 24-25: The test fails because ProcessRunMessage record now has a
fourth parameter (boolean isDebug); update the instantiation in
ConsumerServiceTest where ProcessRunMessage<ProcessConfig> runMessage is created
to pass an explicit boolean (e.g., false) as the fourth argument so the
constructor call matches ProcessRunMessage(UUID, UUID, T, boolean) and preserves
backward-compatible deserialization behavior.

In
`@monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/MonitorController.java`:
- Around line 47-48: The controller method in MonitorController currently
declares two `@RequestBody` parameters (SecurityAnalysisConfig
securityAnalysisConfig and boolean isDebug) which is invalid; change the boolean
isDebug parameter to a `@RequestParam` (e.g., `@RequestParam` boolean isDebug or
`@RequestParam`(name="isDebug", required=false, defaultValue="false") boolean
isDebug) so only SecurityAnalysisConfig is read from the request body, and
update MonitorControllerTest to call the controller with the isDebug request
parameter (adjust mocked request/URL or controller invocation to supply the
boolean param) to match the new signature.

In
`@monitor-server/src/main/java/org/gridsuite/monitor/server/entities/ProcessExecutionEntity.java`:
- Around line 58-59: Rename the boolean field isDebug in the
ProcessExecutionEntity class to debug to avoid Lombok-generated asymmetric
accessors; update the field declaration (private boolean debug) and, to preserve
DB column name, add `@Column`(name = "is_debug") on the field, then update any
references/usages (getters, setters, builder/DTO mapping, tests) that relied on
isDebug to use the new debug property or its generated isDebug()/setDebug(...)
methods as appropriate so Jackson/JPA/Lombok produce consistent JavaBean
accessors.

In
`@monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java`:
- Around line 82-84: The code currently calls
S3PathUtils.toDebugLocation(executionEnvName, ...) whenever execution.isDebug()
is true, which can produce an invalid path if executionEnvName is null and also
overwrites the debugFileLocation on every status update; modify
updateExecutionStatus so that you only compute and set
execution.setDebugFileLocation(...) once when executionEnvName is available
(e.g., on the transition to RUNNING) and/or when
execution.getDebugFileLocation() is null, and add a null-check for
executionEnvName before calling S3PathUtils.toDebugLocation to avoid passing
null.

In
`@monitor-server/src/main/resources/db/changelog/changesets/changelog_20260212T082157Z.xml`:
- Around line 8-11: Update the Liquibase changeset (id "1770884531328-2") that
adds column "is_debug" to table "process_execution" so the column is NOT NULL
and uses the boolean-specific default; replace the current column definition
with one that includes a NOT NULL constraint and uses
defaultValueBoolean="false" (or add an explicit <addNotNullConstraint> for
column "is_debug" after the <addColumn>) to keep the DB schema consistent with
the primitive boolean field in the entity.

In
`@monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java`:
- Line 82: The test still calls and stubs monitorService.executeProcess with the
old 3-arg signature; update MonitorServiceTest so both the when(...) stub and
the verify(...) call use the new 4-argument signature
monitorService.executeProcess(UUID, String, ProcessConfig, boolean) by adding a
ProcessConfig matcher (e.g., any(ProcessConfig.class) or
any(SecurityAnalysisConfig.class) if compatible) and the boolean matcher (e.g.,
anyBoolean() or eq(false)) to the when(...) and verify(...) invocations for the
symbols monitorService.executeProcess, SecurityAnalysisConfig/ProcessConfig, and
anyBoolean()/eq(false).

In `@monitor-worker-server/pom.xml`:
- Around line 112-116: The pom currently declares
io.awspring.cloud:spring-cloud-aws-starter-s3 with version property
${spring-cloud-aws-starter-s3} which is set to 3.3.1 (incompatible with Spring
Boot 3.3.3); update that property (or the dependency version) to a 3.2.x release
compatible with Spring Boot 3.3.3 so the dependency block for
spring-cloud-aws-starter-s3 uses a 3.2.x version instead of 3.3.1.

In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/commons/steps/ApplyModificationsStep.java`:
- Line 48: The DEBUG_FILENAME constant in ApplyModificationsStep is declared as
an instance final field; change its declaration to a class-level constant by
making it private static final (i.e., update the DEBUG_FILENAME field to be
static final) so it is a true compile-time constant and follows Java convention.
- Around line 77-92: The exportUpdatedNetworkToS3 method currently writes the
gzip to a fixed DEBUG_FILENAME in CWD causing races and leaks; change it to
create a temporary gz file (e.g. Files.createTempFile) instead of
Paths.get(DEBUG_FILENAME), write the gzip into that temp, and ensure both the
.xiidm tmp (tmp) and the temp gz are deleted in a finally block (or
try-with-resources plus finally) regardless of success or exceptions from
s3Service.uploadFile or the GZIPOutputStream; keep using
getDebugFilePath(context, DEBUG_FILENAME) and s3Service.uploadFile but perform
upload from the temp gz file and always call Files.deleteIfExists on both tmp
and the temp gz to avoid leaks and races.

In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/S3Service.java`:
- Around line 37-38: The catch blocks in uploadFile and downloadFile currently
discard the original SdkException by only using e.getMessage(), losing the stack
trace; update both catch clauses to rethrow an IOException that chains the
original SdkException as the cause (e.g., new IOException("Error occurred while
uploading/downloading file to S3", e)) so the original exception and stack trace
are preserved for debugging.

In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/utils/FileUtils.java`:
- Around line 15-17: The loop that uses fileNames directly is vulnerable to path
traversal/zip-slip; in the FileUtils class sanitize each fileName before using
tempDir.resolve(fileName) and new ZipEntry(fileName): reject or normalize names
containing "..", absolute paths, or path separators that would escape tempDir,
compute Path resolved = tempDir.resolve(fileName).normalize() and ensure
resolved.startsWith(tempDir); only proceed if that check passes, and use a safe
entry name (e.g., fileName's normalized relative path or
Files.getFileName(resolved).toString()) when creating sourceFile,
zos.putNextEntry(new ZipEntry(...)) and when reading the file; otherwise throw
or skip the entry. Ensure you reference tempDir, fileNames, sourceFile, zos and
ZipEntry in the change.
🧹 Nitpick comments (13)
monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/utils/FileUtils.java (1)

11-11: Add a private constructor to prevent instantiation of this utility class.

FileUtils is a stateless utility class with only static methods. A private constructor signals intent and prevents accidental instantiation.

Proposed fix
 public class FileUtils {
+    private FileUtils() {
+        // Utility class
+    }
+
     public static Path createZipFile(Path tempDir, String fileOrNetworkName, Set<String> fileNames) throws IOException {
monitor-worker-server/pom.xml (1)

17-17: Property name should follow Maven .version convention.

The property name spring-cloud-aws-starter-s3 should be spring-cloud-aws-starter-s3.version to follow the standard Maven convention for version properties. This improves clarity and consistency with the existing network-modification.version property on Line 16.

Proposed fix
-        <spring-cloud-aws-starter-s3>3.3.1</spring-cloud-aws-starter-s3>
+        <spring-cloud-aws-starter-s3.version>3.3.1</spring-cloud-aws-starter-s3.version>

And update the dependency reference accordingly:

-            <version>${spring-cloud-aws-starter-s3}</version>
+            <version>${spring-cloud-aws-starter-s3.version}</version>
monitor-server/src/test/java/org/gridsuite/monitor/server/services/NotificationServiceTest.java (1)

56-68: Consider adding a test case with isDebug = true.

The test only verifies the false path. A complementary test with isDebug = true would ensure the flag is correctly propagated through the message.

monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/config/S3Configuration.java (1)

27-32: Consider renaming the bean method to follow Java conventions.

The @SuppressWarnings("checkstyle:MethodName") suppression exists solely because the method is named S3Service (uppercase). Renaming to s3Service would eliminate the need for the suppression and follow standard Java method naming. Spring will still wire the bean correctly by type.

♻️ Proposed fix
-    `@SuppressWarnings`("checkstyle:MethodName")
     `@Bean`
-    public S3Service S3Service(S3Client s3Client) {
+    public S3Service s3Service(S3Client s3Client) {
         LOGGER.info("Configuring S3Service with bucket: {}", bucketName);
         return new S3Service(s3Client, bucketName);
     }
monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContext.java (1)

70-72: Naming inconsistency: getExecutionEnvironment() vs parent's getExecutionEnvName().

Other delegating accessors in this class (e.g., getProcessExecutionId()getExecutionId()) already have slight naming differences, but getExecutionEnvironment() vs getExecutionEnvName() diverges more noticeably ("Environment" vs "EnvName"). Consider aligning for discoverability.

monitor-commons/src/main/java/org/gridsuite/monitor/commons/utils/S3PathUtils.java (1)

14-27: Consider adding a private constructor instead of suppressing the checkstyle warning.

A private constructor is the idiomatic way to prevent instantiation of utility classes and would eliminate the suppression.

♻️ Proposed fix
-@SuppressWarnings("checkstyle:HideUtilityClassConstructor")
 public class S3PathUtils {
+    private S3PathUtils() {
+        // utility class
+    }
+
     public static final String S3_DELIMITER = "/";
monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessExecutionContextTest.java (1)

34-47: Missing assertion and coverage for the isDebug flag.

shouldInitializeCorrectly doesn't assert the value of isDebug() after construction, and no test exercises isDebug=true. Consider adding an assertion here and a test case (or parameterize) with true to ensure the flag is correctly stored and retrievable.

♻️ Suggested addition in shouldInitializeCorrectly
         assertThat(processContext.getExecutionEnvName()).isEqualTo(envName);
         assertThat(processContext.getNetwork()).isNull();
+        assertThat(processContext.isDebug()).isFalse();
monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/dto/S3InputStreamInfos.java (1)

1-14: Missing copyright header and fields should be private.

  1. This file lacks the MPL copyright header present in all other files in this PR.
  2. The fields are package-private; prefer private for proper encapsulation (Lombok @Getter will still generate public accessors).
♻️ Proposed fix
+/**
+ * Copyright (c) 2026, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
 package org.gridsuite.monitor.worker.server.dto;
 
 import lombok.Builder;
 import lombok.Getter;
 
 import java.io.InputStream;
 
 `@Builder`
 `@Getter`
 public class S3InputStreamInfos {
-    InputStream inputStream;
-    String fileName;
-    Long fileLength;
+    private InputStream inputStream;
+    private String fileName;
+    private Long fileLength;
 }
monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java (1)

72-100: Test only covers isDebug=false — consider adding a true case.

The executeProcessCreateExecutionAndSendNotification test only exercises the non-debug path. The isDebug=true path triggers distinct behavior in MonitorService.updateExecutionStatus (debug file location via S3PathUtils). A complementary test with isDebug=true would increase confidence.

monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/processes/commons/steps/ApplyModificationsStepTest.java (2)

53-54: Minor: trailing whitespace before semicolon.

-    private S3Service s3Service ;
+    private S3Service s3Service;

79-94: No test coverage for the debug export path.

The test only exercises the non-debug flow (Mockito defaults isDebug() to false). The exportUpdatedNetworkToS3 method performs file I/O and S3 upload — critical logic worth covering with at least one test verifying s3Service.uploadFile is called when context.isDebug() returns true.

Would you like me to draft a test case for the debug export path?

monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionServiceTest.java (1)

118-123: Consider asserting isDebug on the execution context.

The context verification checks executionId, caseUuid, config, and executionEnvName but not isDebug. Adding !context.isDebug() would confirm the flag propagates correctly through ProcessExecutionService.

monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/S3Service.java (1)

17-27: Unused @Service import — class is bean-managed via S3Configuration.

The org.springframework.stereotype.Service import on line 4 is present but @Service is not applied to the class. This is presumably intentional since the bean is created in S3Configuration, but the import is vestigial.

Comment on lines +58 to +59
@Column
private boolean isDebug;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Lombok boolean isDebug generates asymmetric accessor names — potential serialization/mapping issues.

With Lombok, a primitive boolean field named isDebug generates getter isDebug() but setter setDebug(boolean). This asymmetry can cause issues with Jackson deserialization, JPA property access, and @Builder usage. Consider renaming the field to debug so Lombok generates the conventional isDebug() / setDebug() pair consistently.

Proposed fix
     `@Column`
-    private boolean isDebug;
+    private boolean debug;

This will produce isDebug() and setDebug(boolean) — proper JavaBeans convention. Ensure the JPA column mapping still resolves to is_debug (or add @Column(name = "is_debug") explicitly).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Column
private boolean isDebug;
`@Column`(name = "is_debug")
private boolean debug;
🤖 Prompt for AI Agents
In
`@monitor-server/src/main/java/org/gridsuite/monitor/server/entities/ProcessExecutionEntity.java`
around lines 58 - 59, Rename the boolean field isDebug in the
ProcessExecutionEntity class to debug to avoid Lombok-generated asymmetric
accessors; update the field declaration (private boolean debug) and, to preserve
DB column name, add `@Column`(name = "is_debug") on the field, then update any
references/usages (getters, setters, builder/DTO mapping, tests) that relied on
isDebug to use the new debug property or its generated isDebug()/setDebug(...)
methods as appropriate so Jackson/JPA/Lombok produce consistent JavaBean
accessors.

Comment on lines 82 to 84
if (execution.isDebug()) {
execution.setDebugFileLocation(S3PathUtils.toDebugLocation(executionEnvName, execution.getType(), executionId));
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

executionEnvName can be null when computing the debug file location, producing a broken S3 path.

updateExecutionStatus is called multiple times during the lifecycle (RUNNING, COMPLETED, FAILED). The executionEnvName parameter is nullable (as evidenced by the null-check on line 73). When isDebug is true and executionEnvName is null, S3PathUtils.toDebugLocation(null, ...) will produce an invalid path (e.g., "null/SECURITY_ANALYSIS/...").

Additionally, this block runs on every status update, overwriting debugFileLocation each time. It should likely execute only once — when executionEnvName is first known (i.e., the transition to RUNNING).

Proposed fix
-            if (execution.isDebug()) {
-                execution.setDebugFileLocation(S3PathUtils.toDebugLocation(executionEnvName, execution.getType(), executionId));
-            }
+            if (execution.isDebug() && executionEnvName != null && execution.getDebugFileLocation() == null) {
+                execution.setDebugFileLocation(S3PathUtils.toDebugLocation(executionEnvName, execution.getType(), executionId));
+            }
🤖 Prompt for AI Agents
In
`@monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java`
around lines 82 - 84, The code currently calls
S3PathUtils.toDebugLocation(executionEnvName, ...) whenever execution.isDebug()
is true, which can produce an invalid path if executionEnvName is null and also
overwrites the debugFileLocation on every status update; modify
updateExecutionStatus so that you only compute and set
execution.setDebugFileLocation(...) once when executionEnvName is available
(e.g., on the transition to RUNNING) and/or when
execution.getDebugFileLocation() is null, and add a null-check for
executionEnvName before calling S3PathUtils.toDebugLocation to avoid passing
null.

Comment on lines +112 to +116
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-starter-s3</artifactId>
<version>${spring-cloud-aws-starter-s3}</version>
</dependency>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat monitor-worker-server/pom.xml | head -150

Repository: gridsuite/monitor-core

Length of output: 5736


🌐 Web query:

spring-cloud-aws-starter-s3 3.3.1 Maven Central repository

💡 Result:

Artifact coordinates on Maven Central:

  • GroupId: io.awspring.cloud
  • ArtifactId: spring-cloud-aws-starter-s3
  • Version: 3.3.1 [1][2]

Maven dependency

<dependency>
  <groupId>io.awspring.cloud</groupId>
  <artifactId>spring-cloud-aws-starter-s3</artifactId>
  <version>3.3.1</version>
</dependency>

[1]

Maven Central pages

https://central.sonatype.com/artifact/io.awspring.cloud/spring-cloud-aws-starter-s3/3.3.1
https://repo1.maven.org/maven2/io/awspring/cloud/spring-cloud-aws-starter-s3/3.3.1/

[2][3]

All versions directory (repo1)

https://repo1.maven.org/maven2/io/awspring/cloud/spring-cloud-aws-starter-s3/

[3]

Sources: [1] [2] [3]


🏁 Script executed:

rg "spring-cloud-aws-starter-s3" monitor-worker-server/pom.xml -A 2 -B 2

Repository: gridsuite/monitor-core

Length of output: 473


🏁 Script executed:

rg "spring.boot" monitor-worker-server/pom.xml -i

Repository: gridsuite/monitor-core

Length of output: 388


🏁 Script executed:

find . -name "pom.xml" -type f | grep -E "(parent|root|pom\.xml$)" | head -20

Repository: gridsuite/monitor-core

Length of output: 158


🏁 Script executed:

cat pom.xml | grep -A 20 "spring.boot\|Spring Boot" | head -50

Repository: gridsuite/monitor-core

Length of output: 48


🏁 Script executed:

rg "spring-boot" pom.xml -i --max-count 5

Repository: gridsuite/monitor-core

Length of output: 48


🏁 Script executed:

cat pom.xml | head -200

Repository: gridsuite/monitor-core

Length of output: 3477


🏁 Script executed:

rg "spring-boot\|spring.boot" . -t xml --max-count 20

Repository: gridsuite/monitor-core

Length of output: 48


🌐 Web query:

spring-cloud-aws-starter-s3 3.3.1 spring boot version compatibility requirements

💡 Result:

io.awspring.cloud:spring-cloud-aws-starter-s3:3.3.1 is part of Spring Cloud AWS 3.3.x, which is compatible with:

  • Spring Boot: 3.4.x
  • (and aligns with Spring Cloud: 2024.0.x, Spring Framework: 6.2.x)

So you should use Spring Boot 3.4.* with spring-cloud-aws-starter-s3 3.3.1. If you’re on Spring Boot 3.3.*, use Spring Cloud AWS 3.2.x instead. [1]

Sources
[1] Spring Cloud AWS “Compatibility with Spring Project Versions” table (awspring.io) (awspring.io)

Citations:


🌐 Web query:

powsybl-parent-ws 25 spring boot version

💡 Result:

com.powsybl:powsybl-parent-ws:25 sets the Spring Boot version to 3.3.3 (property maven.spring-boot.version). (central.sonatype.com)

Citations:


🏁 Script executed:

rg "spring.boot.version\|<version>" monitor-worker-server/pom.xml | head -20

Repository: gridsuite/monitor-core

Length of output: 48


Version 3.3.1 is incompatible with the project's Spring Boot 3.3.3. Spring Cloud AWS 3.3.1 requires Spring Boot 3.4.x. For Spring Boot 3.3.3, use spring-cloud-aws-starter-s3 version 3.2.x instead.

🤖 Prompt for AI Agents
In `@monitor-worker-server/pom.xml` around lines 112 - 116, The pom currently
declares io.awspring.cloud:spring-cloud-aws-starter-s3 with version property
${spring-cloud-aws-starter-s3} which is set to 3.3.1 (incompatible with Spring
Boot 3.3.3); update that property (or the dependency version) to a 3.2.x release
compatible with Spring Boot 3.3.3 so the dependency block for
spring-cloud-aws-starter-s3 uses a 3.2.x version instead of 3.3.1.

Comment on lines 37 to 38
} catch (SdkException e) {
throw new IOException("Error occurred while uploading file to S3: " + e.getMessage());
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Original exception is not chained — stack trace will be lost.

Both uploadFile (line 38) and downloadFile (line 55) discard the original SdkException by only appending its message. This loses the root-cause stack trace, making S3 failures hard to diagnose in production.

Proposed fix
-            throw new IOException("Error occurred while uploading file to S3: " + e.getMessage());
+            throw new IOException("Error occurred while uploading file to S3: " + e.getMessage(), e);
-            throw new IOException("Error occurred while downloading file from S3: " + e.getMessage());
+            throw new IOException("Error occurred while downloading file from S3: " + e.getMessage(), e);
🤖 Prompt for AI Agents
In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/S3Service.java`
around lines 37 - 38, The catch blocks in uploadFile and downloadFile currently
discard the original SdkException by only using e.getMessage(), losing the stack
trace; update both catch clauses to rethrow an IOException that chains the
original SdkException as the cause (e.g., new IOException("Error occurred while
uploading/downloading file to S3", e)) so the original exception and stack trace
are preserved for debugging.

Comment on lines 15 to 17
for (String fileName : fileNames) {
Path sourceFile = tempDir.resolve(fileName);
zos.putNextEntry(new ZipEntry(fileName));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Sanitize fileName to guard against path traversal.

fileName values from the Set<String> are used directly in tempDir.resolve(fileName) (reading arbitrary files) and new ZipEntry(fileName) (producing a zip-slip archive). If the caller ever passes untrusted or user-influenced file names, this is exploitable. Even for internal callers, a defensive check is cheap insurance.

Proposed fix
         for (String fileName : fileNames) {
             Path sourceFile = tempDir.resolve(fileName);
+            if (!sourceFile.normalize().startsWith(tempDir.normalize())) {
+                throw new IOException("Invalid file name (path traversal detected): " + fileName);
+            }
             zos.putNextEntry(new ZipEntry(fileName));
🤖 Prompt for AI Agents
In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/utils/FileUtils.java`
around lines 15 - 17, The loop that uses fileNames directly is vulnerable to
path traversal/zip-slip; in the FileUtils class sanitize each fileName before
using tempDir.resolve(fileName) and new ZipEntry(fileName): reject or normalize
names containing "..", absolute paths, or path separators that would escape
tempDir, compute Path resolved = tempDir.resolve(fileName).normalize() and
ensure resolved.startsWith(tempDir); only proceed if that check passes, and use
a safe entry name (e.g., fileName's normalized relative path or
Files.getFileName(resolved).toString()) when creating sourceFile,
zos.putNextEntry(new ZipEntry(...)) and when reading the file; otherwise throw
or skip the entry. Ensure you reference tempDir, fileNames, sourceFile, zos and
ZipEntry in the change.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/commons/steps/ApplyModificationsStep.java`:
- Around line 68-74: The debug export in ApplyModificationsStep currently
rethrows a PowsyblException when exportUpdatedNetworkToS3(context) fails, which
aborts the successful step; change the catch block so that IOException is logged
as a warning (include the exception and a clear message) instead of throwing, so
debug export failures don't stop execution when context.isDebug() is true.
Locate the try/catch around exportUpdatedNetworkToS3 in ApplyModificationsStep
and replace the throw new PowsyblException(...) with a warning-level log call
that includes e (stacktrace) and a short message about debug export failure.

In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/S3Service.java`:
- Around line 48-52: S3InputStreamInfos.builder() currently uses
inputStream.response().metadata().get(METADATA_FILE_NAME) without null checks,
which can produce a null fileName; update the single place building the DTO in
S3Service to defensively validate that metadata value and provide a fallback
(e.g., use the S3 object key from inputStream.response() or a safe default like
an empty string) before calling .fileName(...), and ensure the DTO always
receives a non-null value; reference METADATA_FILE_NAME and the
inputStream.response().metadata().get(...) call when making the change.
🧹 Nitpick comments (1)
monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/processes/commons/steps/ApplyModificationsStepTest.java (1)

79-94: No test coverage for the debug export path.

The executeApplyModifications test only exercises the non-debug flow. The new exportUpdatedNetworkToS3 logic (gzip, upload to S3) introduced in ApplyModificationsStep is untested. Consider adding a test where context.isDebug() returns true to verify the S3 upload interaction and temp-file handling.

Comment on lines +68 to +74
if (context.isDebug()) {
try {
exportUpdatedNetworkToS3(context);
} catch (IOException e) {
throw new PowsyblException("An error occurred while saving debug file", e);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Debug export failure aborts the entire step execution.

If the S3 upload fails, the PowsyblException propagates and the step fails — even though the actual modifications were already applied successfully. Consider whether debug export failures should be logged as warnings rather than aborting the step, since debug is a non-essential side effect.

🤖 Prompt for AI Agents
In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/commons/steps/ApplyModificationsStep.java`
around lines 68 - 74, The debug export in ApplyModificationsStep currently
rethrows a PowsyblException when exportUpdatedNetworkToS3(context) fails, which
aborts the successful step; change the catch block so that IOException is logged
as a warning (include the exception and a clear message) instead of throwing, so
debug export failures don't stop execution when context.isDebug() is true.
Locate the try/catch around exportUpdatedNetworkToS3 in ApplyModificationsStep
and replace the throw new PowsyblException(...) with a warning-level log call
that includes e (stacktrace) and a short message about debug export failure.

Comment on lines 48 to 52
return S3InputStreamInfos.builder()
.inputStream(inputStream)
.fileName(inputStream.response().metadata().get(METADATA_FILE_NAME))
.fileLength(inputStream.response().contentLength())
.build();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

metadata().get(METADATA_FILE_NAME) may return null — no defensive check.

If the S3 object was uploaded without the file-name metadata key (e.g., uploaded outside this service), fileName will silently be null in the returned DTO. Consider validating or providing a fallback.

🤖 Prompt for AI Agents
In
`@monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/S3Service.java`
around lines 48 - 52, S3InputStreamInfos.builder() currently uses
inputStream.response().metadata().get(METADATA_FILE_NAME) without null checks,
which can produce a null fileName; update the single place building the DTO in
S3Service to defensively validate that metadata value and provide a fallback
(e.g., use the S3 object key from inputStream.response() or a safe default like
an empty string) before calling .fileName(...), and ensure the DTO always
receives a non-null value; reference METADATA_FILE_NAME and the
inputStream.response().metadata().get(...) call when making the change.

Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
Signed-off-by: LE SAULNIER Kevin <kevin.lesaulnier.pro@gmail.com>
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
22.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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.

1 participant