Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(jb): observe ports status and send notification
Browse files Browse the repository at this point in the history
Andrea Falzetti committed May 25, 2022
1 parent 6972cd5 commit 57e3dee
Showing 2 changed files with 115 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -30,7 +30,21 @@ ports:
onOpen: ignore
# Dev Theia
- port: 13444
- port: 8080
onOpen: open-browser
visibility: public
- port: 8081
onOpen: notify
visibility: public
- port: 8082
onOpen: ignore
- port: 8083
onOpen: notify
tasks:
- command: npx --yes live-server .
- command: npx --yes live-server --port 8081 .
- command: npx --yes live-server --port 8082 .
- command: npx --yes live-server --port 8083 .
- name: Add Harvester kubeconfig
command: |
./dev/preview/util/download-and-merge-harvester-kubeconfig.sh
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

package io.gitpod.jetbrains.remote

import com.intellij.ide.BrowserUtil
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.notification.NotificationAction
import com.intellij.notification.NotificationGroupManager
@@ -23,6 +24,10 @@ import io.gitpod.jetbrains.remote.utils.Retrier.retry
import io.gitpod.supervisor.api.*
import io.gitpod.supervisor.api.Info.WorkspaceInfoResponse
import io.gitpod.supervisor.api.Notification.*
import io.gitpod.supervisor.api.Status.OnPortExposedAction
import io.gitpod.supervisor.api.Status.PortsStatus
import io.gitpod.supervisor.api.Status.PortsStatusRequest
import io.gitpod.supervisor.api.Status.PortsStatusResponse
import io.grpc.ManagedChannel
import io.grpc.ManagedChannelBuilder
import io.grpc.stub.ClientCallStreamObserver
@@ -46,6 +51,7 @@ import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
import javax.websocket.DeploymentException


@Service
class GitpodManager : Disposable {

@@ -199,6 +205,101 @@ class GitpodManager : Disposable {
}
}

private val portsObserveJob = GlobalScope.launch {
if (application.isHeadlessEnvironment) {
return@launch
}

// Ignore JetBrains default ports
val ignorePorts = listOf(5990, 5991, 6679, 6942, 6943)
val portsStatus = hashMapOf<Int, PortsStatus>()

val status = StatusServiceGrpc.newStub(supervisorChannel)
while (isActive) {
try {
val f = CompletableFuture<Void>()
status.portsStatus(
PortsStatusRequest.newBuilder().setObserve(true).build(),
object : ClientResponseObserver<PortsStatusRequest, PortsStatusResponse> {
override fun beforeStart(requestStream: ClientCallStreamObserver<PortsStatusRequest>) {
lifetime.onTerminationOrNow {
requestStream.cancel(null, null)
}
}

override fun onNext(ps: PortsStatusResponse) {
for (port in ps.portsList) {
if (ignorePorts.contains(port.localPort)) {
continue
}

val isNew = !portsStatus.containsKey(port.localPort)

if (isNew) {
portsStatus[port.localPort] = port
//continue
}

//println("DEBUG[${port.localPort}] -> before hasExposed(${portsStatus[port.localPort]?.hasExposed().toString()}) -> now hasExposed(${port.hasExposed()})")

val wasAlreadyExposed = !portsStatus[port.localPort]?.hasExposed()!!
if ((isNew || wasAlreadyExposed) && port.hasExposed()) {
if (port.exposed.onExposed.number == OnPortExposedAction.ignore_VALUE) {
continue
}

if (port.exposed.onExposed.number == OnPortExposedAction.open_browser_VALUE) {
BrowserUtil.browse(port.exposed.url)
continue
}

if (port.exposed.onExposed.number == OnPortExposedAction.open_preview_VALUE) {
BrowserUtil.browse(port.exposed.url)
continue
}

if (port.served && !port.exposed.url.isNullOrEmpty()) {
println("Show port notification‼️‼️ ${port.localPort}")
val message =
"Your application running on port " + port.localPort + " is available."
println(message)
val notification =
notificationGroup.createNotification(message, NotificationType.INFORMATION)
// TODO(andreafalzetti): add analytics event
val lambda = { BrowserUtil.browse(port.exposed.url) }
val action = NotificationAction.createSimpleExpiring("Open in browser", lambda)
notification.addAction(action)
notification.notify(null)
}
}
}

}

override fun onError(t: Throwable) {
f.completeExceptionally(t)
}

override fun onCompleted() {
f.complete(null)
}
})
f.await()
} catch (t: Throwable) {
if (t is CancellationException) {
throw t
}
thisLogger().error("gitpod: failed to stream ports status: ", t)
}
delay(1000)
}
}
init {
lifetime.onTerminationOrNow {
portsObserveJob.cancel()
}
}

val pendingInfo = CompletableFuture<WorkspaceInfoResponse>()
private val infoJob = GlobalScope.launch {
if (application.isHeadlessEnvironment) {

0 comments on commit 57e3dee

Please sign in to comment.