Skip to content

[rebuild] support desktop IDEs #16818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions components/gitpod-cli/cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,15 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
Target string
Source string
Permission os.FileMode
Optional bool
}

prepareFS := []mnte{
{Source: "/workspace"},
{Source: "/.supervisor"},
{Source: "/ide"},
{Source: "/ide-desktop", Optional: true},
{Source: "/ide-desktop-plugins", Optional: true},
{Source: "/workspace/.gitpod-debug/.docker-root", Target: "/workspace/.docker-root", Permission: 0710},
{Source: "/workspace/.gitpod-debug/.gitpod", Target: "/workspace/.gitpod", Permission: 0751},
{Source: "/workspace/.gitpod-debug/.vscode-remote", Target: "/workspace/.vscode-remote", Permission: 0751},
Expand Down Expand Up @@ -291,6 +294,9 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
for _, mnt := range prepareFS {
fd, err := os.Stat(mnt.Source)
if err != nil {
if (os.IsPermission(err) || os.IsNotExist(err)) && mnt.Optional {
continue
}
if !os.IsNotExist(err) {
return err
}
Expand All @@ -311,6 +317,25 @@ func runRebuild(ctx context.Context, supervisorClient *supervisor.SupervisorClie
}
if mnt.Target == "" {
mnt.Target = mnt.Source
} else if !mnt.IsFile {
// if target is not same with source and it not a file, ensure target is created by gitpod user
_, err = os.Stat(mnt.Target)
if err != nil {
if (os.IsPermission(err) || os.IsNotExist(err)) && mnt.Optional {
continue
}
if !os.IsNotExist(err) {
return err
}
err = os.MkdirAll(mnt.Target, mnt.Permission)
if err != nil {
return err
}
_, err = os.Stat(mnt.Target)
if err != nil {
return err
}
}
}
dockerArgs = append(dockerArgs, "-v", fmt.Sprintf("%s:%s", mnt.Source, mnt.Target))
}
Expand Down
4 changes: 4 additions & 0 deletions components/ide/jetbrains/gateway-plugin/BUILD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ packages:
- "src/main/resources-stable/*"
- "*.kts"
- "*.md"
argdeps:
- publishToJBMarketplace
env:
- DO_PUBLISH=${publishToJBMarketplace}
config:
Expand All @@ -32,6 +34,8 @@ packages:
- "src/main/resources-latest/*"
- "*.kts"
- "*.md"
argdeps:
- publishToJBMarketplace
env:
- DO_PUBLISH=${publishToJBMarketplace}
config:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
val connectParams = ConnectParams(
parameters["gitpodHost"]!!,
parameters["workspaceId"]!!,
parameters["backendPort"]
parameters["backendPort"],
parameters["debugWorkspace"] == "true"
)

val connectionKeyId = "${connectParams.gitpodHost}-${connectParams.workspaceId}-${connectParams.backendPort}"
var connectionKeyId = "${connectParams.gitpodHost}-${connectParams.resolvedWorkspaceId}-${connectParams.backendPort}"

var found = true
val connectionLifetime = activeConnections.computeIfAbsent(connectionKeyId) {
Expand All @@ -88,7 +89,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
if (found) {
val message =
"You are trying to connect to a workspace that has a client already open. Check for opened JetBrains clients on your machine"
val title = "${connectParams.workspaceId} (${connectParams.gitpodHost})"
val title = connectParams.title
val okButton = Messages.getOkButton()
val options = arrayOf(okButton)
val defaultIndex = 0
Expand All @@ -104,8 +105,8 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
}

val client = gitpod.obtainClient(connectParams.gitpodHost)
val updates = client.listenToWorkspace(connectionLifetime, connectParams.workspaceId)
val workspace = client.syncWorkspace(connectParams.workspaceId).workspace
val updates = client.listenToWorkspace(connectionLifetime, connectParams.actualWorkspaceId)
val workspace = client.syncWorkspace(connectParams.actualWorkspaceId).workspace

val phaseMessage = JLabel()
val statusMessage = JLabel()
Expand All @@ -120,7 +121,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
background = phaseMessage.background
columns = 30
}
var ideUrl = ""
var resolvedIdeUrl = ""
val connectionPanel = panel {
indent {
row {
Expand All @@ -144,9 +145,9 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
}
panel {
row {
link(connectParams.workspaceId) {
if (ideUrl.isNotBlank()) {
BrowserUtil.browse(ideUrl)
link(connectParams.resolvedWorkspaceId) {
if (resolvedIdeUrl.isNotBlank()) {
BrowserUtil.browse(resolvedIdeUrl)
}
}
}
Expand Down Expand Up @@ -183,7 +184,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
if (WorkspaceInstance.isUpToDate(lastUpdate, update)) {
continue
}
ideUrl = update.ideUrl
resolvedIdeUrl = update.ideUrl.replace(connectParams.actualWorkspaceId, connectParams.resolvedWorkspaceId)
lastUpdate = update
if (!update.status.conditions.failed.isNullOrBlank()) {
setErrorMessage(update.status.conditions.failed)
Expand Down Expand Up @@ -243,18 +244,17 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
if (thinClientJob == null && update.status.phase == "running") {
thinClientJob = launch {
try {
val updatedIdeUrl = URL(update.ideUrl)
val sshHostUrl =
URL(update.ideUrl.replace(update.workspaceId, "${update.workspaceId}.ssh"))
val hostKeys = resolveHostKeys(updatedIdeUrl, connectParams)
val hostKeys = resolveHostKeys(URL(update.ideUrl), connectParams)
if (hostKeys.isNullOrEmpty()) {
setErrorMessage("${connectParams.gitpodHost} installation does not allow SSH access, public keys cannot be found")
return@launch
}
val ownerToken = client.server.getOwnerToken(update.workspaceId).await()
val sshHostUrl =
URL(resolvedIdeUrl.replace(connectParams.resolvedWorkspaceId, "${connectParams.resolvedWorkspaceId}.ssh"))
val credentials =
resolveCredentials(sshHostUrl, update.workspaceId, ownerToken, hostKeys)
val joinLink = resolveJoinLink(updatedIdeUrl, ownerToken, connectParams)
resolveCredentials(sshHostUrl, connectParams.resolvedWorkspaceId, ownerToken, hostKeys)
val joinLink = resolveJoinLink(URL(resolvedIdeUrl), ownerToken, connectParams)
if (joinLink.isNullOrEmpty()) {
setErrorMessage("failed to fetch JetBrains Gateway Join Link.")
return@launch
Expand Down Expand Up @@ -283,7 +283,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
throw t
}
thisLogger().error(
"${connectParams.gitpodHost}: ${connectParams.workspaceId}: failed to connect:",
"${connectParams.gitpodHost}: ${connectParams.resolvedWorkspaceId}: failed to connect:",
t
)
setErrorMessage("" + t.message)
Expand All @@ -292,15 +292,15 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
}
} catch (e: Throwable) {
thisLogger().error(
"${connectParams.gitpodHost}: ${connectParams.workspaceId}: failed to process workspace update:",
"${connectParams.gitpodHost}: ${connectParams.resolvedWorkspaceId}: failed to process workspace update:",
e
)
}
}
connectionLifetime.terminate()
} catch (t: Throwable) {
thisLogger().error(
"${connectParams.gitpodHost}: ${connectParams.workspaceId}: failed to process workspace updates:",
"${connectParams.gitpodHost}: ${connectParams.resolvedWorkspaceId}: failed to process workspace updates:",
t
)
setErrorMessage("failed to process workspace updates ${t.message}")
Expand Down Expand Up @@ -451,16 +451,16 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
return response.body()
}
if (response.statusCode() < 500) {
thisLogger().error("${connectParams.gitpodHost}: ${connectParams.workspaceId}: failed to fetch '$endpointUrl': ${response.statusCode()}")
thisLogger().error("${connectParams.gitpodHost}: ${connectParams.resolvedWorkspaceId}: failed to fetch '$endpointUrl': ${response.statusCode()}")
return null
}
thisLogger().warn("${connectParams.gitpodHost}: ${connectParams.workspaceId}: failed to fetch '$endpointUrl', trying again...: ${response.statusCode()}")
thisLogger().warn("${connectParams.gitpodHost}: ${connectParams.resolvedWorkspaceId}: failed to fetch '$endpointUrl', trying again...: ${response.statusCode()}")
} catch (t: Throwable) {
if (t is CancellationException) {
throw t
}
thisLogger().warn(
"${connectParams.gitpodHost}: ${connectParams.workspaceId}: failed to fetch '$endpointUrl', trying again...:",
"${connectParams.gitpodHost}: ${connectParams.resolvedWorkspaceId}: failed to fetch '$endpointUrl', trying again...:",
t
)
}
Expand All @@ -476,9 +476,13 @@ class GitpodConnectionProvider : GatewayConnectionProvider {

private data class ConnectParams(
val gitpodHost: String,
val workspaceId: String,
val backendPort: String?
)
val actualWorkspaceId: String,
val backendPort: String?,
val debugWorkspace: Boolean,
) {
val resolvedWorkspaceId = "${if (debugWorkspace) "debug-" else ""}$actualWorkspaceId"
val title = "$resolvedWorkspaceId ($gitpodHost)"
}

private class GitpodConnectionHandle(
lifetime: Lifetime,
Expand All @@ -491,7 +495,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
}

override fun getTitle(): String {
return "${params.workspaceId} (${params.gitpodHost})"
return params.title
}

override fun hideToTrayOnStart(): Boolean {
Expand Down