Skip to content

Commit 95fc3d7

Browse files
committed
[jb]: customize remote indicator
1 parent 7ccac75 commit 95fc3d7

File tree

10 files changed

+115
-67
lines changed

10 files changed

+115
-67
lines changed

components/ide/jetbrains/backend-plugin/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pluginUntilBuild=213.*
1212
pluginVerifierIdeVersions=2021.3.1
1313
# IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties
1414
platformType=IU
15-
platformVersion=213-EAP-SNAPSHOT
15+
platformVersion=213.6777.52
1616
platformDownloadSources=true
1717
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1818
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22

components/ide/jetbrains/backend-plugin/launch-dev-server.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# Licensed under the GNU Affero General Public License (AGPL).
44
# See License-AGPL.txt in the project root for license information.
55

6+
set -e
7+
set -o pipefail
8+
69
TEST_BACKEND_DIR=/workspace/ide-backend
710
if [ ! -d "$TEST_BACKEND_DIR" ]; then
811
mkdir -p $TEST_BACKEND_DIR
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License-AGPL.txt in the project root for license information.
4+
5+
package io.gitpod.jetbrains.remote
6+
7+
import com.intellij.openapi.components.service
8+
import com.intellij.remoteDev.customization.GatewayBranding
9+
import io.gitpod.jetbrains.remote.icons.GitpodIcons
10+
import kotlinx.coroutines.GlobalScope
11+
import kotlinx.coroutines.future.await
12+
import kotlinx.coroutines.launch
13+
import javax.swing.Icon
14+
15+
class GitpodBranding : GatewayBranding {
16+
17+
val manager = service<GitpodManager>()
18+
19+
/*
20+
TODO(ak) GITPOD_WORSPACE_ID is a subject to change
21+
ideally we should not rely on it, but here `getName` is sync
22+
alternatively we could precompute another env var based on supervisor info endpoint
23+
before starting backend
24+
*/
25+
private var name = System.getenv("GITPOD_WORKSPACE_ID") ?: "Gitpod"
26+
init {
27+
GlobalScope.launch {
28+
val info = manager.pendingInfo.await()
29+
name = info.workspaceId
30+
}
31+
}
32+
33+
override fun getIcon(): Icon {
34+
return GitpodIcons.Logo
35+
}
36+
37+
override fun getName(): String {
38+
return name
39+
}
40+
41+
}

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodClientProjectSessionTracker.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ class GitpodClientProjectSessionTracker(
2525
event = "jb_session"
2626
properties = mapOf(
2727
"sessionId" to session.clientId.value,
28-
"instanceId" to info.infoResponse.instanceId,
29-
"workspaceId" to info.infoResponse.workspaceId,
28+
"instanceId" to info.instanceId,
29+
"workspaceId" to info.workspaceId,
3030
"appName" to ApplicationInfo.getInstance().versionName,
3131
"appVersion" to ApplicationInfo.getInstance().fullVersion,
3232
"timestamp" to System.currentTimeMillis()

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodManager.kt

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ import git4idea.config.GitVcsApplicationSettings
1818
import io.gitpod.gitpodprotocol.api.GitpodClient
1919
import io.gitpod.gitpodprotocol.api.GitpodServerLauncher
2020
import io.gitpod.jetbrains.remote.services.HeartbeatService
21-
import io.gitpod.jetbrains.remote.services.SupervisorInfoService
21+
import io.gitpod.supervisor.api.*
22+
import io.gitpod.supervisor.api.Info.WorkspaceInfoResponse
2223
import io.gitpod.supervisor.api.Notification.*
23-
import io.gitpod.supervisor.api.NotificationServiceGrpc
24+
import io.grpc.ManagedChannel
25+
import io.grpc.ManagedChannelBuilder
2426
import io.grpc.stub.ClientCallStreamObserver
2527
import io.grpc.stub.ClientResponseObserver
2628
import kotlinx.coroutines.GlobalScope
2729
import kotlinx.coroutines.delay
2830
import kotlinx.coroutines.future.await
31+
import kotlinx.coroutines.guava.asDeferred
2932
import kotlinx.coroutines.isActive
3033
import kotlinx.coroutines.launch
3134
import org.jetbrains.ide.BuiltInServerManager
@@ -37,10 +40,16 @@ import java.time.Duration
3740
import java.util.concurrent.CancellationException
3841
import java.util.concurrent.CompletableFuture
3942
import javax.websocket.DeploymentException
43+
import io.gitpod.jetbrains.remote.utils.Retrier.retry
4044

4145
@Service
4246
class GitpodManager : Disposable {
4347

48+
companion object {
49+
// there should be only one channel per an application to avoid memory leak
50+
val supervisorChannel: ManagedChannel = ManagedChannelBuilder.forTarget("localhost:22999").usePlaintext().build()
51+
}
52+
4453
val devMode = System.getenv("JB_DEV").toBoolean()
4554

4655
private val lifetime = Lifetime.Eternal.createNested()
@@ -84,8 +93,8 @@ class GitpodManager : Disposable {
8493

8594
private val notificationGroup = NotificationGroupManager.getInstance().getNotificationGroup("Gitpod Notifications")
8695
private val notificationsJob = GlobalScope.launch {
87-
val notifications = NotificationServiceGrpc.newStub(SupervisorInfoService.channel)
88-
val futureNotifications = NotificationServiceGrpc.newFutureStub(SupervisorInfoService.channel)
96+
val notifications = NotificationServiceGrpc.newStub(supervisorChannel)
97+
val futureNotifications = NotificationServiceGrpc.newFutureStub(supervisorChannel)
8998
while (isActive) {
9099
try {
91100
val f = CompletableFuture<Void>()
@@ -145,11 +154,18 @@ class GitpodManager : Disposable {
145154
}
146155
}
147156

148-
val pendingInfo = CompletableFuture<SupervisorInfoService.Result>()
157+
val pendingInfo = CompletableFuture<WorkspaceInfoResponse>()
149158
private val infoJob = GlobalScope.launch {
150159
try {
151-
// TOO(ak) inline SupervisorInfoService
152-
pendingInfo.complete(SupervisorInfoService.fetch())
160+
// TODO(ak) replace retry with proper handling of grpc errors
161+
val infoResponse = retry(3) {
162+
InfoServiceGrpc
163+
.newFutureStub(supervisorChannel)
164+
.workspaceInfo(Info.WorkspaceInfoRequest.newBuilder().build())
165+
.asDeferred()
166+
.await()
167+
}
168+
pendingInfo.complete(infoResponse)
153169
} catch (t: Throwable) {
154170
pendingInfo.completeExceptionally(t)
155171
}
@@ -163,6 +179,23 @@ class GitpodManager : Disposable {
163179
val client = GitpodClient()
164180
private val serverJob = GlobalScope.launch {
165181
val info = pendingInfo.await()
182+
183+
// TODO(ak) replace retry with proper handling of grpc errors
184+
val tokenResponse = retry(3) {
185+
val request = Token.GetTokenRequest.newBuilder()
186+
.setHost(info.gitpodApi.host)
187+
.addScope("function:sendHeartBeat")
188+
.addScope("function:trackEvent")
189+
.setKind("gitpod")
190+
.build()
191+
192+
TokenServiceGrpc
193+
.newFutureStub(supervisorChannel)
194+
.getToken(request)
195+
.asDeferred()
196+
.await()
197+
}
198+
166199
val launcher = GitpodServerLauncher.create(client)
167200
val plugin = PluginManagerCore.getPlugin(PluginId.getId("io.gitpod.jetbrains.remote"))!!
168201
val connect = {
@@ -171,11 +204,11 @@ class GitpodManager : Disposable {
171204
// see https://intellij-support.jetbrains.com/hc/en-us/community/posts/360003146180/comments/360000376240
172205
Thread.currentThread().contextClassLoader = HeartbeatService::class.java.classLoader
173206
launcher.listen(
174-
info.infoResponse.gitpodApi.endpoint,
175-
info.infoResponse.gitpodHost,
207+
info.gitpodApi.endpoint,
208+
info.gitpodHost,
176209
plugin.pluginId.idString,
177210
plugin.version,
178-
info.tokenResponse.token
211+
tokenResponse.token
179212
)
180213
} finally {
181214
Thread.currentThread().contextClassLoader = originalClassLoader;
@@ -186,7 +219,7 @@ class GitpodManager : Disposable {
186219
val maxReconnectionDelay = 30 * 1000L
187220
val reconnectionDelayGrowFactor = 1.5;
188221
var reconnectionDelay = minReconnectionDelay;
189-
val gitpodHost = info.infoResponse.gitpodApi.host
222+
val gitpodHost = info.gitpodApi.host
190223
var closeReason: Any = "cancelled"
191224
try {
192225
while (kotlin.coroutines.coroutineContext.isActive) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License-AGPL.txt in the project root for license information.
4+
package io.gitpod.jetbrains.remote.icons
5+
6+
import com.intellij.openapi.util.IconLoader
7+
8+
object GitpodIcons {
9+
@JvmField
10+
val Logo = IconLoader.getIcon("/icons/logo.svg", javaClass)
11+
}

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/services/HeartbeatService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class HeartbeatService : Disposable {
4040
}
4141

4242
if (wasClosed != null) {
43-
manager.client.server.sendHeartBeat(SendHeartBeatOptions(info.infoResponse.instanceId, wasClosed)).await()
43+
manager.client.server.sendHeartBeat(SendHeartBeatOptions(info.instanceId, wasClosed)).await()
4444
}
4545
} catch (t: Throwable) {
4646
thisLogger().error("gitpod: failed to check activity:", t)

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/services/SupervisorInfoService.kt

Lines changed: 0 additions & 52 deletions
This file was deleted.

components/ide/jetbrains/backend-plugin/src/main/resources/META-INF/plugin.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
<notificationGroup id="Gitpod Notifications" displayType="BALLOON" isLogByDefault="false" />
2323
<httpRequestHandler implementation="io.gitpod.jetbrains.remote.GitpodCLIService"/>
2424
<projectService serviceImplementation="io.gitpod.jetbrains.remote.GitpodClientProjectSessionTracker" client="guest" preload="true"/>
25+
<applicationService serviceImplementation="io.gitpod.jetbrains.remote.GitpodBranding"
26+
serviceInterface="com.intellij.remoteDev.customization.GatewayBranding"
27+
overrides="true" />
2528
</extensions>
2629

2730
</idea-plugin>
Lines changed: 9 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)