Skip to content

Commit 3a9116f

Browse files
kirillkbcpeinhardt
andauthoredFeb 20, 2025··
setup script can communicate an error message to the end user (#538)
* setup script can communicate an error message to the end user * review fixes * custom exception class for setup command * better title * changelog update --------- Co-authored-by: Benjamin Peinhardt <[email protected]> Co-authored-by: Benjamin <[email protected]>
1 parent 7d8ad4b commit 3a9116f

File tree

6 files changed

+107
-14
lines changed

6 files changed

+107
-14
lines changed
 

‎CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
## Unreleased
66

7+
### Added
8+
9+
- Added functionality to show setup script error message to the end user.
10+
711
### Fixed
812

913
- Fix bug where wildcard configs would not be written under certain conditions.

‎src/main/kotlin/com/coder/gateway/CoderGatewayConstants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ package com.coder.gateway
33
object CoderGatewayConstants {
44
const val GATEWAY_CONNECTOR_ID = "Coder.Gateway.Connector"
55
const val GATEWAY_RECENT_CONNECTIONS_ID = "Coder.Gateway.Recent.Connections"
6+
const val GATEWAY_SETUP_COMMAND_ERROR = "CODER_SETUP_ERROR"
67
}

‎src/main/kotlin/com/coder/gateway/CoderRemoteConnectionHandle.kt

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
package com.coder.gateway
44

5+
import com.coder.gateway.CoderGatewayConstants.GATEWAY_SETUP_COMMAND_ERROR
56
import com.coder.gateway.cli.CoderCLIManager
67
import com.coder.gateway.models.WorkspaceProjectIDE
78
import com.coder.gateway.models.toIdeWithStatus
@@ -160,25 +161,38 @@ class CoderRemoteConnectionHandle {
160161
)
161162
logger.info("Adding ${parameters.ideName} for ${parameters.hostname}:${parameters.projectPath} to recent connections")
162163
recentConnectionsService.addRecentConnection(parameters.toRecentWorkspaceConnection())
164+
} catch (e: CoderSetupCommandException) {
165+
logger.error("Failed to run setup command", e)
166+
showConnectionErrorMessage(
167+
e.message ?: "Unknown error",
168+
"gateway.connector.coder.setup-command.failed",
169+
)
163170
} catch (e: Exception) {
164171
if (isCancellation(e)) {
165172
logger.info("Connection canceled due to ${e.javaClass.simpleName}")
166173
} else {
167174
logger.error("Failed to connect (will not retry)", e)
168-
// The dialog will close once we return so write the error
169-
// out into a new dialog.
170-
ApplicationManager.getApplication().invokeAndWait {
171-
Messages.showMessageDialog(
172-
e.message ?: e.javaClass.simpleName ?: "Aborted",
173-
CoderGatewayBundle.message("gateway.connector.coder.connection.failed"),
174-
Messages.getErrorIcon(),
175-
)
176-
}
175+
showConnectionErrorMessage(
176+
e.message ?: e.javaClass.simpleName ?: "Aborted",
177+
"gateway.connector.coder.connection.failed"
178+
)
177179
}
178180
}
179181
}
180182
}
181183

184+
// The dialog will close once we return so write the error
185+
// out into a new dialog.
186+
private fun showConnectionErrorMessage(message: String, titleKey: String) {
187+
ApplicationManager.getApplication().invokeAndWait {
188+
Messages.showMessageDialog(
189+
message,
190+
CoderGatewayBundle.message(titleKey),
191+
Messages.getErrorIcon(),
192+
)
193+
}
194+
}
195+
182196
/**
183197
* Return a new (non-EAP) IDE if we should update.
184198
*/
@@ -412,18 +426,15 @@ class CoderRemoteConnectionHandle {
412426
) {
413427
if (setupCommand.isNotBlank()) {
414428
indicator.text = "Running setup command..."
415-
try {
429+
processSetupCommand(ignoreSetupFailure) {
416430
exec(workspace, setupCommand)
417-
} catch (ex: Exception) {
418-
if (!ignoreSetupFailure) {
419-
throw ex
420-
}
421431
}
422432
} else {
423433
logger.info("No setup command to run on ${workspace.hostname}")
424434
}
425435
}
426436

437+
427438
/**
428439
* Execute a command in the IDE's bin directory.
429440
* This exists since the accessor does not provide a generic exec.
@@ -523,5 +534,26 @@ class CoderRemoteConnectionHandle {
523534

524535
companion object {
525536
val logger = Logger.getInstance(CoderRemoteConnectionHandle::class.java.simpleName)
537+
@Throws(CoderSetupCommandException::class)
538+
fun processSetupCommand(
539+
ignoreSetupFailure: Boolean,
540+
execCommand: () -> String
541+
) {
542+
try {
543+
val errorText = execCommand
544+
.invoke()
545+
.lines()
546+
.firstOrNull { it.contains(GATEWAY_SETUP_COMMAND_ERROR) }
547+
?.let { it.substring(it.indexOf(GATEWAY_SETUP_COMMAND_ERROR) + GATEWAY_SETUP_COMMAND_ERROR.length).trim() }
548+
549+
if (!errorText.isNullOrBlank()) {
550+
throw CoderSetupCommandException(errorText)
551+
}
552+
} catch (ex: Exception) {
553+
if (!ignoreSetupFailure) {
554+
throw CoderSetupCommandException(ex.message ?: "Unknown error", ex)
555+
}
556+
}
557+
}
526558
}
527559
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.coder.gateway
2+
3+
class CoderSetupCommandException : Exception {
4+
5+
constructor(message: String) : super(message)
6+
constructor(message: String, cause: Throwable) : super(message, cause)
7+
}

‎src/main/resources/messages/CoderGatewayBundle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ gateway.connector.coder.connection.provider.title=Connecting to Coder workspace.
4949
gateway.connector.coder.connecting=Connecting...
5050
gateway.connector.coder.connecting.retry=Connecting (attempt {0})...
5151
gateway.connector.coder.connection.failed=Failed to connect
52+
gateway.connector.coder.setup-command.failed=Failed to set up backend IDE
5253
gateway.connector.coder.connecting.failed.retry=Failed to connect...retrying {0}
5354
gateway.connector.settings.data-directory.title=Data directory
5455
gateway.connector.settings.data-directory.comment=Directories are created \
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.coder.gateway.util
2+
3+
import com.coder.gateway.CoderRemoteConnectionHandle.Companion.processSetupCommand
4+
import com.coder.gateway.CoderSetupCommandException
5+
import org.junit.jupiter.api.Test
6+
import org.junit.jupiter.api.assertThrows
7+
import kotlin.test.assertEquals
8+
9+
internal class SetupCommandTest {
10+
11+
@Test
12+
fun executionErrors() {
13+
assertEquals(
14+
"Execution error",
15+
assertThrows<CoderSetupCommandException> {
16+
processSetupCommand(false) { throw Exception("Execution error") }
17+
}.message
18+
)
19+
processSetupCommand(true) { throw Exception("Execution error") }
20+
}
21+
22+
@Test
23+
fun setupScriptError() {
24+
assertEquals(
25+
"Your IDE is expired, please update",
26+
assertThrows<CoderSetupCommandException> {
27+
processSetupCommand(false) {
28+
"""
29+
execution line 1
30+
execution line 2
31+
CODER_SETUP_ERRORYour IDE is expired, please update
32+
execution line 3
33+
"""
34+
}
35+
}.message
36+
)
37+
38+
processSetupCommand(true) {
39+
"""
40+
execution line 1
41+
execution line 2
42+
CODER_SETUP_ERRORYour IDE is expired, please update
43+
execution line 3
44+
"""
45+
}
46+
47+
}
48+
}

0 commit comments

Comments
 (0)
Please sign in to comment.