Skip to content

Commit 6156c00

Browse files
dhasani23David Hasani
andauthored
fix(amazonq): show build logs when pre-build fails (#5173)
* fix(amazonq): show build logs when pre-build fails * fix detekt errors * remove unused imports * fix detektTest --------- Co-authored-by: David Hasani <[email protected]>
1 parent 1fd1279 commit 6156c00

File tree

12 files changed

+123
-46
lines changed

12 files changed

+123
-46
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Amazon Q Code Transformation: show build logs when server-side build fails"
4+
}

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerManager.kt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ import software.aws.toolkits.resources.message
8484
import software.aws.toolkits.telemetry.CodeTransformBuildSystem
8585
import software.aws.toolkits.telemetry.CodeTransformCancelSrcComponents
8686
import software.aws.toolkits.telemetry.CodeTransformPreValidationError
87-
import software.aws.toolkits.telemetry.CodeTransformVCSViewerSrcComponents
8887
import java.io.File
8988
import java.nio.file.Path
9089
import java.time.Instant
@@ -630,7 +629,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo
630629
is CodeModernizerJobCompletedResult.JobPartiallySucceeded -> {
631630
notifyStickyInfo(
632631
message("codemodernizer.notification.info.modernize_partial_complete.title"),
633-
message("codemodernizer.notification.info.modernize_partial_complete.content", result.targetJavaVersion.description),
632+
message("codemodernizer.notification.info.modernize_partial_complete.content"),
634633
project,
635634
listOf(displaySummaryNotificationAction(result.jobId), displayFeedbackNotificationAction()),
636635
)
@@ -770,12 +769,6 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo
770769
codeTransformationSession?.tryOpenTransformationPlanEditor()
771770
}
772771

773-
fun showDiff() {
774-
val job = codeTransformationSession?.getActiveJobId() ?: return
775-
// Use "TreeViewHeader" for Hub
776-
artifactHandler.displayDiffAction(job, CodeTransformVCSViewerSrcComponents.TreeViewHeader)
777-
}
778-
779772
fun handleCredentialsChanged() {
780773
codeTransformationSession?.dispose()
781774
codeModernizerBottomWindowPanelManager.reset()

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,7 @@ class CodeModernizerSession(
493493
message("codemodernizer.notification.warn.unknown_status_response")
494494
)
495495

496-
result.state == TransformationStatus.PARTIALLY_COMPLETED -> CodeModernizerJobCompletedResult.JobPartiallySucceeded(
497-
jobId,
498-
sessionContext.targetJavaVersion
499-
)
496+
result.state == TransformationStatus.PARTIALLY_COMPLETED -> CodeModernizerJobCompletedResult.JobPartiallySucceeded(jobId)
500497

501498
result.state == TransformationStatus.FAILED -> {
502499
if (!passedStart) {

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,11 @@ fun buildTransformStoppedChatContent() = CodeTransformChatMessageContent(
431431
type = CodeTransformChatMessageType.FinalizedAnswer,
432432
)
433433

434+
fun buildTransformFailedChatContent(failureReason: String) = CodeTransformChatMessageContent(
435+
message = message("codemodernizer.chat.message.transform_failed", failureReason),
436+
type = CodeTransformChatMessageType.FinalizedAnswer,
437+
)
438+
434439
fun buildUserSQLConversionSelectionSummaryChatContent(moduleName: String, schema: String) = CodeTransformChatMessageContent(
435440
type = CodeTransformChatMessageType.Prompt,
436441
message = getUserSQLConversionSelectionFormattedMarkdown(moduleName, schema)
@@ -537,7 +542,7 @@ fun buildTransformResumingChatContent() = CodeTransformChatMessageContent(
537542
type = CodeTransformChatMessageType.PendingAnswer,
538543
)
539544

540-
fun buildTransformResultChatContent(result: CodeModernizerJobCompletedResult, totalPatchFiles: Int): CodeTransformChatMessageContent {
545+
fun buildTransformResultChatContent(result: CodeModernizerJobCompletedResult, totalPatchFiles: Int? = null): CodeTransformChatMessageContent {
541546
val resultMessage = when (result) {
542547
is CodeModernizerJobCompletedResult.JobAbortedZipTooLarge -> {
543548
"${message(

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildSt
6161
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformAwaitUserInputChatContent
6262
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformBeginChatContent
6363
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformDependencyErrorChatContent
64+
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformFailedChatContent
6465
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformFindingLocalAlternativeDependencyChatContent
6566
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformInProgressChatContent
6667
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformResultChatContent
@@ -183,7 +184,7 @@ class CodeTransformChatController(
183184
private suspend fun getUserObjective(tabId: String) {
184185
codeTransformChatHelper.addNewMessage(buildChooseTransformationObjectiveChatContent())
185186
codeTransformChatHelper.sendChatInputEnabledMessage(tabId, true)
186-
codeTransformChatHelper.sendUpdatePlaceholderMessage(tabId, message("codemodernizer.chat.message.choose_objective"))
187+
codeTransformChatHelper.sendUpdatePlaceholderMessage(tabId, message("codemodernizer.chat.message.choose_objective_placeholder"))
187188
}
188189

189190
private suspend fun validateAndReplyOnError(transformationType: CodeTransformType): ValidationResult? {
@@ -665,9 +666,21 @@ class CodeTransformChatController(
665666
codeTransformChatHelper.addNewMessage(buildStartNewTransformFollowup())
666667
}
667668

669+
private suspend fun handleCodeTransformJobFailed(failureReason: String) {
670+
codeTransformChatHelper.updateLastPendingMessage(buildTransformFailedChatContent(failureReason))
671+
codeTransformChatHelper.addNewMessage(buildStartNewTransformFollowup())
672+
}
673+
674+
private suspend fun handleCodeTransformJobFailedPreBuild(result: CodeModernizerJobCompletedResult.JobFailedInitialBuild) =
675+
codeTransformChatHelper.addNewMessage(
676+
buildTransformResultChatContent(result)
677+
)
678+
668679
private suspend fun handleCodeTransformResult(result: CodeModernizerJobCompletedResult) {
669680
when (result) {
670681
is CodeModernizerJobCompletedResult.Stopped, CodeModernizerJobCompletedResult.JobAbortedBeforeStarting -> handleCodeTransformStoppedByUser()
682+
is CodeModernizerJobCompletedResult.JobFailed -> handleCodeTransformJobFailed(result.failureReason)
683+
is CodeModernizerJobCompletedResult.JobFailedInitialBuild -> handleCodeTransformJobFailedPreBuild(result)
671684
else -> {
672685
if (result is CodeModernizerJobCompletedResult.ZipUploadFailed && result.failureReason is UploadFailureReason.CREDENTIALS_EXPIRED) {
673686
return

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerJobCompletedResult.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33

44
package software.aws.toolkits.jetbrains.services.codemodernizer.model
55

6-
import com.intellij.openapi.projectRoots.JavaSdkVersion
7-
86
sealed class CodeModernizerJobCompletedResult {
97
data class RetryableFailure(val jobId: JobId, val failureReason: String) : CodeModernizerJobCompletedResult()
108
data class UnableToCreateJob(val failureReason: String, val retryable: Boolean = false) : CodeModernizerJobCompletedResult()
119
data class JobFailed(val jobId: JobId, val failureReason: String) : CodeModernizerJobCompletedResult()
1210
data class ZipUploadFailed(val failureReason: UploadFailureReason) : CodeModernizerJobCompletedResult()
1311
data class JobCompletedSuccessfully(val jobId: JobId) : CodeModernizerJobCompletedResult()
14-
data class JobPartiallySucceeded(val jobId: JobId, val targetJavaVersion: JavaSdkVersion) : CodeModernizerJobCompletedResult()
12+
data class JobPartiallySucceeded(val jobId: JobId) : CodeModernizerJobCompletedResult()
1513

1614
data class JobPaused(val jobId: JobId, val downloadArtifactId: String) : CodeModernizerJobCompletedResult()
1715

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/CodeModernizerBanner.kt

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@ package software.aws.toolkits.jetbrains.services.codemodernizer.panels
55

66
import com.intellij.icons.AllIcons
77
import com.intellij.openapi.project.Project
8-
import com.intellij.serviceContainer.AlreadyDisposedException
98
import com.intellij.ui.JBColor
109
import com.intellij.ui.border.CustomLineBorder
1110
import com.intellij.ui.components.ActionLink
1211
import com.intellij.ui.components.JBLabel
1312
import com.intellij.util.ui.JBInsets
1413
import com.intellij.util.ui.JBUI
1514
import icons.AwsIcons
16-
import software.aws.toolkits.core.utils.getLogger
17-
import software.aws.toolkits.core.utils.warn
1815
import software.aws.toolkits.jetbrains.services.codemodernizer.CodeModernizerManager
16+
import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId
1917
import software.aws.toolkits.jetbrains.services.codewhisperer.layout.CodeWhispererLayoutConfig
2018
import software.aws.toolkits.jetbrains.services.codewhisperer.layout.CodeWhispererLayoutConfig.addHorizontalGlue
2119
import software.aws.toolkits.jetbrains.ui.feedback.CodeTransformFeedbackDialog
@@ -42,11 +40,13 @@ class CodeModernizerBanner(val project: Project) : JPanel(BorderLayout()) {
4240
border = BorderFactory.createEmptyBorder(0, 5, 0, 0)
4341
}
4442

43+
private val infoLabelJobId = JBLabel().apply {
44+
foreground = JBColor.GRAY
45+
border = BorderFactory.createEmptyBorder(0, 5, 0, 0)
46+
}
47+
4548
private val infoPanel = JPanel(GridBagLayout())
4649

47-
val showDiffAction = ActionLink(message("codemodernizer.toolwindow.banner.action.diff")) {
48-
CodeModernizerManager.getInstance(project).showDiff()
49-
}
5050
val showPlanAction = ActionLink(message("codemodernizer.toolwindow.banner.action.plan")) {
5151
CodeModernizerManager.getInstance(project).showTransformationPlan()
5252
}
@@ -84,6 +84,7 @@ class CodeModernizerBanner(val project: Project) : JPanel(BorderLayout()) {
8484
)
8585
}
8686
add(infoLabelRunningTime, CodeWhispererLayoutConfig.kebabMenuConstraints)
87+
add(infoLabelJobId, CodeWhispererLayoutConfig.kebabMenuConstraints)
8788
}
8889
infoPanel.revalidate()
8990
infoPanel.repaint()
@@ -114,28 +115,23 @@ class CodeModernizerBanner(val project: Project) : JPanel(BorderLayout()) {
114115
}
115116

116117
fun updateRunningTime(runTime: Duration?) {
117-
try {
118-
if (runTime == null) {
119-
infoLabelRunningTime.text = ""
120-
} else {
121-
val timeTaken = runTime.toKotlinDuration().inWholeSeconds.seconds.toString()
122-
infoLabelRunningTime.text = message(
123-
"codemodernizer.toolwindow.transformation.progress.running_time",
124-
timeTaken
125-
)
126-
}
127-
} catch (exception: AlreadyDisposedException) {
128-
LOG.warn { "Disposed when about to create the loading panel" }
129-
return
118+
infoLabelRunningTime.text = if (runTime != null) {
119+
message("codemodernizer.toolwindow.transformation.progress.running_time", runTime.toKotlinDuration().inWholeSeconds.seconds.toString())
120+
} else {
121+
""
122+
}
123+
}
124+
125+
fun updateJobId(jobId: JobId?) {
126+
infoLabelJobId.text = if (jobId != null) {
127+
message("codemodernizer.toolwindow.transformation.progress.job_id", jobId.id)
128+
} else {
129+
""
130130
}
131131
}
132132

133133
fun clearActions() {
134134
currentlyShownOptions.clear()
135135
buildContent()
136136
}
137-
138-
companion object {
139-
private val LOG = getLogger<CodeModernizerBanner>()
140-
}
141137
}

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/panels/managers/CodeModernizerBottomWindowPanelManager.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ class CodeModernizerBottomWindowPanelManager(private val project: Project) : JPa
8888
}
8989
}
9090

91+
private fun updateJobId() {
92+
try {
93+
val jobId = CodeModernizerSessionState.getInstance(project).currentJobId
94+
banner.updateJobId(jobId)
95+
} catch (e: AlreadyDisposedException) {
96+
LOG.warn { "Disposed when about to update the jobId" }
97+
return
98+
}
99+
}
100+
91101
fun setJobStartingUI() = setUI {
92102
add(BorderLayout.CENTER, fullSizeLoadingPanel)
93103
banner.clearActions()
@@ -123,6 +133,7 @@ class CodeModernizerBottomWindowPanelManager(private val project: Project) : JPa
123133
fun setJobRunningUI() = setUI {
124134
add(BorderLayout.CENTER, buildProgressSplitterPanelManager)
125135
banner.updateContent(message("codemodernizer.toolwindow.banner.job_is_running"), AllIcons.General.BalloonInformation)
136+
updateJobId()
126137
buildProgressSplitterPanelManager.apply {
127138
reset()
128139
statusTreePanel.setDefaultUI()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.codemodernizer
5+
6+
import org.junit.Assert.assertEquals
7+
import org.junit.Assert.assertNotNull
8+
import org.junit.Assert.assertNull
9+
import org.junit.Assert.fail
10+
import org.junit.Test
11+
import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformResultChatContent
12+
import software.aws.toolkits.jetbrains.services.codemodernizer.messages.CodeTransformButtonId
13+
import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerJobCompletedResult
14+
import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId
15+
import software.aws.toolkits.resources.message
16+
17+
class CodeTransformChatTest {
18+
19+
@Test
20+
fun `test that transform result chat item includes view build log button and message when pre-build fails`() {
21+
val result = CodeModernizerJobCompletedResult.JobFailedInitialBuild(JobId("dummy-job-id-123"), "Build failed in Java 8 sandbox", true)
22+
val chatItem = buildTransformResultChatContent(result)
23+
assertEquals(chatItem.message, message("codemodernizer.chat.message.result.fail_initial_build"))
24+
assertNotNull(chatItem.buttons)
25+
assertEquals(chatItem.buttons?.size ?: fail("buttons is null"), 1)
26+
assertEquals(chatItem.buttons?.get(0)?.id ?: fail("buttons is null"), CodeTransformButtonId.ViewBuildLog.id)
27+
}
28+
29+
@Test
30+
fun `test that transform result chat item includes view summary button and view diff button with correct label when job fully succeeded with 5 patch files`() {
31+
val result = CodeModernizerJobCompletedResult.JobCompletedSuccessfully(JobId("dummy-job-id-123"))
32+
val chatItem = buildTransformResultChatContent(result, 5)
33+
assertEquals(chatItem.message, message("codemodernizer.chat.message.result.success.multiple_diffs"))
34+
assertNotNull(chatItem.buttons)
35+
assertEquals(chatItem.buttons?.size ?: fail("buttons is null"), 2)
36+
assertEquals(chatItem.buttons?.get(0)?.id ?: fail("buttons is null"), CodeTransformButtonId.ViewDiff.id)
37+
assertEquals(chatItem.buttons?.get(0)?.text ?: fail("buttons is null"), "View diff 1/5")
38+
assertEquals(chatItem.buttons?.get(1)?.id ?: fail("buttons is null"), CodeTransformButtonId.ViewSummary.id)
39+
}
40+
41+
@Test
42+
fun `test that transform result chat item includes view summary button and view diff button with correct label when job partially succeeded with 1 patch file`() {
43+
val result = CodeModernizerJobCompletedResult.JobPartiallySucceeded(JobId("dummy-job-id-123"))
44+
val chatItem = buildTransformResultChatContent(result, 1)
45+
assertEquals(chatItem.message, message("codemodernizer.chat.message.result.partially_success"))
46+
assertNotNull(chatItem.buttons)
47+
assertEquals(chatItem.buttons?.size ?: fail("buttons is null"), 2)
48+
assertEquals(chatItem.buttons?.get(0)?.id ?: fail("buttons is null"), CodeTransformButtonId.ViewDiff.id)
49+
assertEquals(chatItem.buttons?.get(0)?.text ?: fail("buttons is null"), "View diff")
50+
assertEquals(chatItem.buttons?.get(1)?.id ?: fail("buttons is null"), CodeTransformButtonId.ViewSummary.id)
51+
}
52+
53+
@Test
54+
fun `test that transform result chat item does not include any buttons when job failed with known reason`() {
55+
val result = CodeModernizerJobCompletedResult.JobFailed(JobId("dummy-job-id-123"), message("codemodernizer.file.invalid_pom_version"))
56+
val chatItem = buildTransformResultChatContent(result)
57+
assertEquals(chatItem.message, message("codemodernizer.chat.message.result.fail_with_known_reason", result.failureReason))
58+
assertNull(chatItem.buttons)
59+
}
60+
}

plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa
532532

533533
doNothing().whenever(testSessionStateSpy).updateJobHistory(any(), any(), any())
534534
val result = testSessionSpy.pollUntilJobCompletion(CodeTransformType.LANGUAGE_UPGRADE, jobId) { _, _ -> }
535-
assertEquals(CodeModernizerJobCompletedResult.JobPartiallySucceeded(jobId, testSessionContextSpy.targetJavaVersion), result)
535+
assertEquals(CodeModernizerJobCompletedResult.JobPartiallySucceeded(jobId), result)
536536
verify(clientAdaptorSpy, times(4)).getCodeModernizationJob(any())
537537
verify(clientAdaptorSpy, atLeastOnce()).getCodeModernizationPlan(any())
538538
}

0 commit comments

Comments
 (0)