Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 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
59 changes: 59 additions & 0 deletions components/gitpod-cli/cmd/jetbrains-gradle-pause.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package cmd

import (
"os"

"github.com/spf13/cobra"
)

const gradleSyncLockFile = "/tmp/gitpod-gradle.lock"

var jetbrainsGradlePauseCmd = &cobra.Command{
Use: "pause",
Short: "Pause Gradle Sync in JetBrains IDEs",
Long: `Pause JetBrains IDE gradle sync to prevent performance issues on Gitpod workspace startup when there's no Prebuilds ready.

This command is typically used to prevent concurrent Gradle syncs between:
- Manual gradle initialization in Gitpod init tasks
- JetBrains Gateway/IDEA's automatic Gradle sync on project open

Typical usage in your .gitpod.yml:

tasks:
- init: |
ide jetbrains gradle pause # Prevent IDEA's gradle sync
...
./gradlew <init_service> # Run your initialization tasks
ide jetbrains gradle resume # Enable
command: ./gradlew <dev_service>

If you have two init tasks want to pause Gradle Sync:

tasks:
- name: Task 1
init: |
ide jetbrains gradle pause # Prevent IDEA's gradle sync
./gradlew <init_service>
gp sync-await gradle-init-1
ide jetbrains gradle resume # Enable
- name: Task 2
init: |
./gradlew <init_service>
gp sync-done gradle-init-1
`,
RunE: func(cmd *cobra.Command, args []string) error {
err := os.WriteFile(gradleSyncLockFile, []byte{}, 0644)
if err != nil && os.IsExist(err) {
return nil
}
return err
},
}

func init() {
jetbrainsGradleCmd.AddCommand(jetbrainsGradlePauseCmd)
}
27 changes: 27 additions & 0 deletions components/gitpod-cli/cmd/jetbrains-gradle-resume.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package cmd

import (
"os"

"github.com/spf13/cobra"
)

var jetbrainsGradleResumeCmd = &cobra.Command{
Use: "resume",
Short: "Resume paused Gradle Sync in JetBrains IDEs",
RunE: func(cmd *cobra.Command, args []string) error {
err := os.Remove(gradleSyncLockFile)
if err != nil && os.IsNotExist(err) {
return nil
}
return err
},
}

func init() {
jetbrainsGradleCmd.AddCommand(jetbrainsGradleResumeCmd)
}
18 changes: 18 additions & 0 deletions components/gitpod-cli/cmd/jetbrains-gradle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package cmd

import (
"github.com/spf13/cobra"
)

var jetbrainsGradleCmd = &cobra.Command{
Use: "gradle",
Short: "Interact with JetBrains Gradle services.",
}

func init() {
jetbrainsCmd.AddCommand(jetbrainsGradleCmd)
}
19 changes: 19 additions & 0 deletions components/gitpod-cli/cmd/jetbrains.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package cmd

import (
"github.com/spf13/cobra"
)

var jetbrainsCmd = &cobra.Command{
Use: "jetbrains",
Aliases: []string{"jb"},
Short: "Interact with JetBrains editor.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Short: "Interact with JetBrains editor.",
Short: "Interact with JetBrains IDEs",

}

func init() {
rootCmd.AddCommand(jetbrainsCmd)
}
2 changes: 2 additions & 0 deletions components/ide/jetbrains/backend-plugin/BUILD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ packages:
- NO_VERIFY_JB_PLUGIN=true
config:
commands:
- ["rm", "-rf", "src/main/kotlin/io/gitpod/jetbrains/remote/listeners/GradleSyncListener.kt"]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need this line because the file exclude in build.gradle.kt somehow not working well. (And I don't want to investigate why)

- ["mv", "build.gradle-stable.kts", "build.gradle.kts"]
- ["./build.sh", "${__git_commit}"]
- name: plugin-latest-rider
Expand Down Expand Up @@ -182,6 +183,7 @@ packages:
- SDKMAN_DIR=/home/gitpod/.sdkman
config:
commands:
- ["rm", "-rf", "src/main/kotlin/io/gitpod/jetbrains/remote/listeners/GradleSyncListener.kt"]
# TODO(hw): remove after 2024.2.* is stable
- ["mv", "build.gradle-latest.kts", "build.gradle.kts"]
- - "bash"
Expand Down
1 change: 1 addition & 0 deletions components/ide/jetbrains/backend-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ project(":") {
if (properties("platformType") == "RD") {
print("Rider: exclude unnecessary files")
sourceSets["main"].kotlin.exclude("**/GitpodForceUpdateMavenProjectsActivity.kt")
sourceSets["main"].kotlin.exclude("**/GradleSyncListener.kt")
sourceSets["main"].kotlin.exclude("**/maven.xml")
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package io.gitpod.jetbrains.remote.listeners

import com.intellij.notification.Notification
import com.intellij.notification.NotificationAction
import com.intellij.notification.NotificationType
import com.intellij.notification.Notifications
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
import java.io.File

class GradleSyncListener : ExternalSystemTaskNotificationListener {
override fun onStart(id: ExternalSystemTaskId, workingDir: String?) {
if (id.projectSystemId.toString() != "GRADLE" || id.type != ExternalSystemTaskType.RESOLVE_PROJECT) {
return
}
val lockFile = File("/tmp/gitpod-gradle.lock")
if (!lockFile.exists()) {
return
}

val notification = Notification(
"gitpod",
"Gitpod: Pause gradle sync",
"Pausing Gradle Sync, execute <code style='color: orange;'>gp jetbrains gradle resume</code> to unblock all builtin Gradle Sync <br><br>Current Task ID: ${id.id}",
NotificationType.INFORMATION
)
var isCancelled = false
notification.addAction(object : NotificationAction("Cancel") {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
isCancelled = true
notification.expire()
}
})
Comment on lines +38 to +43
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually cancel the sync? It looks more like it just dismisses the notification. If so, let's rename it to Dismiss. I definitely could be missing something though.

Notifications.Bus.notify(notification)

while (lockFile.exists()) {
if (isCancelled) {
thisLogger().warn("gitpod: gradle sync pausing is cancelled")
break
}
Thread.sleep(1000)
}
thisLogger().warn("gitpod: gradle sync pausing finished")
ApplicationManager.getApplication().invokeLater {
notification.expire()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
<applicationService serviceInterface="io.gitpod.jetbrains.remote.GitpodIgnoredPortsForNotificationService"
serviceImplementation="io.gitpod.jetbrains.remote.internal.GitpodIgnoredPortsForNotificationServiceImpl"
preload="true"/>

<externalSystemTaskNotificationListener
implementation="io.gitpod.jetbrains.remote.listeners.GradleSyncListener"/>
</extensions>

<actions>
Expand Down
Loading