Repository: kestra-io/kestra
Issue: [UI] The `ForEachItem` task is stuck in a Running state in the logs tab in the UI (even though child Executions finished)
Labels: enhancement

### Feature description

this only happens in the logs tab:

![image](https://github.com/kestra-io/kestra/assets/86264395/0ed10749-0e18-4581-9419-7793c0af522d)


![image](https://github.com/kestra-io/kestra/assets/86264395/b928745d-5e19-4cdc-accc-1d30f86c6fc8)


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/core/src/main/java/io/kestra/core/runners/ExecutableUtils.java b/core/src/main/java/io/kestra/core/runners/ExecutableUtils.java
index 155657bcf8..121256ea82 100644
--- a/core/src/main/java/io/kestra/core/runners/ExecutableUtils.java
+++ b/core/src/main/java/io/kestra/core/runners/ExecutableUtils.java
@@ -135,8 +135,10 @@ public static TaskRun manageIterations(TaskRun taskRun, Execution execution, boo
                     // the final state should be computed based on the iterations
                     return previousTaskRun.withOutputs(Map.of("iterations", iterations));
                 } else if (terminatedIterations == maxIterations && taskRun.getState().isTerminated()) {
+                    var state = transmitFailed ? findTerminalState(iterations) : State.Type.SUCCESS;
                     return previousTaskRun.withOutputs(Map.of("iterations", iterations))
-                        .withState(transmitFailed ? findTerminalState(iterations) : State.Type.SUCCESS);
+                        .withAttempts(Collections.singletonList(TaskRunAttempt.builder().state(new State().withState(state)).build()))
+                        .withState(state);
                 }
                 return taskRun.withOutputs(Map.of("iterations", iterations));
             }


Test patch:
diff --git a/core/src/test/java/io/kestra/core/tasks/flows/ForEachItemCaseTest.java b/core/src/test/java/io/kestra/core/tasks/flows/ForEachItemCaseTest.java
index e6c644bb38..f4000343ad 100644
--- a/core/src/test/java/io/kestra/core/tasks/flows/ForEachItemCaseTest.java
+++ b/core/src/test/java/io/kestra/core/tasks/flows/ForEachItemCaseTest.java
@@ -62,6 +62,8 @@ public void forEachItem() throws TimeoutException, InterruptedException, URISynt
 
         // assert on the main flow execution
         assertThat(execution.getTaskRunList(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts().get(0).getState().getCurrent(), is(State.Type.SUCCESS));
         assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
         Map<String, Object> outputs = execution.getTaskRunList().get(0).getOutputs();
         assertThat(outputs.get("iterations"), notNullValue());
@@ -96,6 +98,8 @@ public void forEachItemNoWait() throws TimeoutException, InterruptedException, U
 
         // assert on the main flow execution
         assertThat(execution.getTaskRunList(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts().get(0).getState().getCurrent(), is(State.Type.SUCCESS));
         assertThat(execution.getState().getCurrent(), is(State.Type.SUCCESS));
         Map<String, Object> outputs = execution.getTaskRunList().get(0).getOutputs();
         assertThat(outputs.get("iterations"), notNullValue());
@@ -140,6 +144,8 @@ public void forEachItemFailed() throws TimeoutException, InterruptedException, U
 
         // assert on the main flow execution
         assertThat(execution.getTaskRunList(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts().get(0).getState().getCurrent(), is(State.Type.FAILED));
         assertThat(execution.getState().getCurrent(), is(State.Type.FAILED));
         Map<String, Object> outputs = execution.getTaskRunList().get(0).getOutputs();
         assertThat(outputs.get("iterations"), notNullValue());