diff --git a/.github/workflows/run-regression-tests.yml b/.github/workflows/run-regression-tests.yml
index 7676f714..44d48940 100644
--- a/.github/workflows/run-regression-tests.yml
+++ b/.github/workflows/run-regression-tests.yml
@@ -29,8 +29,39 @@ jobs:
- name: 'Setup: Checkout plugin'
uses: actions/checkout@v2
+ # Restore Maven and Tycho dependencies cache
+ - name: 'Cache: Maven and Tycho repository (restore)'
+ uses: actions/cache/restore@v4
+ with:
+ path: |
+ ~/.m2/repository
+ !~/.m2/repository/io/openliberty/tools/eclipse
+ key: ${{ runner.os }}-maven-tycho-${{ hashFiles('pom.xml', '.mvn/**', 'releng/**') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-tycho-
+
+ # Restore Gradle dependencies cache
+ - name: 'Cache: Gradle (restore)'
+ uses: actions/cache/restore@v4
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: |
+ ${{ runner.os }}-gradle-
+
+ # Restore downloaded tools cache (JDK, Maven, Gradle)
+ - name: 'Cache: Downloaded tools (restore)'
+ uses: actions/cache/restore@v4
+ with:
+ path: test-tools/liberty-dev-tools
+ key: ${{ runner.os }}-tools-jdk21.0.3-maven3.9.6-gradle8.8
+ restore-keys: |
+ ${{ runner.os }}-tools-
+
# Install the required software.
- - name: 'Setup: Install required software'
+ - name: 'Setup: Install required software'
run: bash ./tests/resources/ci/scripts/setup.sh
# Build the plugin.
@@ -50,3 +81,31 @@ jobs:
with:
name: test-app-logs
path: logs
+
+ # Save Maven and Tycho dependencies cache (even on failure)
+ - name: 'Cache: Maven and Tycho repository (save)'
+ uses: actions/cache/save@v4
+ if: always()
+ with:
+ path: |
+ ~/.m2/repository
+ !~/.m2/repository/io/openliberty/tools/eclipse
+ key: ${{ runner.os }}-maven-tycho-${{ hashFiles('pom.xml', '.mvn/**', 'releng/**') }}
+
+ # Save Gradle dependencies cache (even on failure)
+ - name: 'Cache: Gradle (save)'
+ uses: actions/cache/save@v4
+ if: always()
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+
+ # Save downloaded tools cache (even on failure)
+ - name: 'Cache: Downloaded tools (save)'
+ uses: actions/cache/save@v4
+ if: always()
+ with:
+ path: test-tools/liberty-dev-tools
+ key: ${{ runner.os }}-tools-jdk21.0.3-maven3.9.6-gradle8.8
diff --git a/bundles/io.openliberty.tools.eclipse.lsp4e/META-INF/MANIFEST.MF b/bundles/io.openliberty.tools.eclipse.lsp4e/META-INF/MANIFEST.MF
index b49798f3..feba70e0 100644
--- a/bundles/io.openliberty.tools.eclipse.lsp4e/META-INF/MANIFEST.MF
+++ b/bundles/io.openliberty.tools.eclipse.lsp4e/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Liberty Tools Support for Language Servers
Bundle-Vendor: Open Liberty
Bundle-SymbolicName: io.openliberty.tools.eclipse.lsp4e;singleton:=true
-Bundle-Version: 25.0.8.qualifier
+Bundle-Version: 25.0.12.qualifier
Bundle-Activator: io.openliberty.tools.eclipse.ls.plugin.LibertyToolsLSPlugin
Bundle-ActivationPolicy: lazy
Automatic-Module-Name: io.openliberty.tools.eclipse.lsp4e
diff --git a/bundles/io.openliberty.tools.eclipse.lsp4e/pom.xml b/bundles/io.openliberty.tools.eclipse.lsp4e/pom.xml
index 0e381f5a..f7eff829 100644
--- a/bundles/io.openliberty.tools.eclipse.lsp4e/pom.xml
+++ b/bundles/io.openliberty.tools.eclipse.lsp4e/pom.xml
@@ -20,7 +20,7 @@
io.openliberty.tools.eclipse
parent
- 25.0.8-SNAPSHOT
+ 25.0.12-SNAPSHOT
../../pom.xml
diff --git a/bundles/io.openliberty.tools.eclipse.product/META-INF/MANIFEST.MF b/bundles/io.openliberty.tools.eclipse.product/META-INF/MANIFEST.MF
index accbaf63..8849879f 100644
--- a/bundles/io.openliberty.tools.eclipse.product/META-INF/MANIFEST.MF
+++ b/bundles/io.openliberty.tools.eclipse.product/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Liberty Tools
Bundle-Vendor: Open Liberty
Bundle-SymbolicName: io.openliberty.tools.eclipse.product;singleton:=true
-Bundle-Version: 25.0.8.qualifier
+Bundle-Version: 25.0.12.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: io.openliberty.tools.eclipse
Bundle-ActivationPolicy: lazy
diff --git a/bundles/io.openliberty.tools.eclipse.ui/META-INF/MANIFEST.MF b/bundles/io.openliberty.tools.eclipse.ui/META-INF/MANIFEST.MF
index 2c2a989a..2df81a4d 100644
--- a/bundles/io.openliberty.tools.eclipse.ui/META-INF/MANIFEST.MF
+++ b/bundles/io.openliberty.tools.eclipse.ui/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Liberty Tools UI
Bundle-Vendor: Open Liberty
Bundle-SymbolicName: io.openliberty.tools.eclipse.ui;singleton:=true
-Bundle-Version: 25.0.8.qualifier
+Bundle-Version: 25.0.12.qualifier
Bundle-Activator: io.openliberty.tools.eclipse.LibertyDevPlugin
Export-Package: io.openliberty.tools.eclipse;x-friends:="io.openliberty.tools.eclipse.tests",
io.openliberty.tools.eclipse.debug;x-friends:="io.openliberty.tools.eclipse.tests",
diff --git a/features/io.openliberty.tools.eclipse.feature/feature.xml b/features/io.openliberty.tools.eclipse.feature/feature.xml
index b9e939f0..c79341a8 100644
--- a/features/io.openliberty.tools.eclipse.feature/feature.xml
+++ b/features/io.openliberty.tools.eclipse.feature/feature.xml
@@ -14,7 +14,7 @@
@@ -28,21 +28,21 @@
id="io.openliberty.tools.eclipse.ui"
download-size="0"
install-size="0"
- version="25.0.8.qualifier"
+ version="25.0.12.qualifier"
unpack="false"/>
diff --git a/pom.xml b/pom.xml
index e3e9afa5..b4017f92 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
4.0.0
io.openliberty.tools.eclipse
parent
- 25.0.8-SNAPSHOT
+ 25.0.12-SNAPSHOT
pom
@@ -196,7 +196,7 @@
io.openliberty.tools.eclipse
target-platform-${eclipse.target}
- 25.0.8-SNAPSHOT
+ 25.0.12-SNAPSHOT
target-platform-${eclipse.target}
diff --git a/releng/io.openliberty.tools.update/category.xml b/releng/io.openliberty.tools.update/category.xml
index 1d32e25f..e01c58c0 100644
--- a/releng/io.openliberty.tools.update/category.xml
+++ b/releng/io.openliberty.tools.update/category.xml
@@ -12,7 +12,7 @@
IBM Corporation - initial implementation
-->
-
+
diff --git a/tests/META-INF/MANIFEST.MF b/tests/META-INF/MANIFEST.MF
index 5cdc4d09..2ae3bd85 100644
--- a/tests/META-INF/MANIFEST.MF
+++ b/tests/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-Copyright: Copyright (c) 2022, 2025 IBM Corporation and others.
Bundle-ManifestVersion: 2
Bundle-Name: Tests Plug-in
Bundle-SymbolicName: io.openliberty.tools.eclipse.tests
-Bundle-Version: 25.0.8.qualifier
+Bundle-Version: 25.0.12.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-21
Require-Bundle: junit-jupiter-api,
org.eclipse.ui,
diff --git a/tests/pom.xml b/tests/pom.xml
index dbb3a409..3afb2c10 100755
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -17,7 +17,7 @@
io.openliberty.tools.eclipse
parent
- 25.0.8-SNAPSHOT
+ 25.0.12-SNAPSHOT
io.openliberty.tools.eclipse.tests
@@ -39,6 +39,7 @@
junit5
false
alphabetical
+ 7200
20000
${mvnLogFile}
diff --git a/tests/resources/ci/scripts/setup.sh b/tests/resources/ci/scripts/setup.sh
index 87717a39..3744c98b 100755
--- a/tests/resources/ci/scripts/setup.sh
+++ b/tests/resources/ci/scripts/setup.sh
@@ -95,6 +95,17 @@ installCustomSoftware() {
installJDK() {
local javaHome="${SOFTWARE_INSTALL_DIR}/jdk-${SEMERU_OPEN_JDK_VERSION}+${SEMERU_OPEN_JDK_BUILD}"
+ # Skip installation if JDK is already installed (from cache)
+ if [[ -d "${javaHome}" ]] || [[ -d "${javaHome}/Contents/Home" ]]; then
+ echo "JDK ${SEMERU_OPEN_JDK_VERSION}+${SEMERU_OPEN_JDK_BUILD} already installed, skipping download"
+ if [[ $OS == "Darwin" ]]; then
+ javaHome="${javaHome}/Contents/Home"
+ fi
+ echo "JAVA_HOME=${javaHome}" >> $GITHUB_ENV
+ echo "${javaHome}/bin" >> $GITHUB_PATH
+ return 0
+ fi
+
# Download, validate, and expand the JDK archive.
if [[ $OS == "Linux" ]]; then
local url="https://github.com/ibmruntimes/semeru${SEMERU_OPEN_JDK_MAJOR}-binaries/releases/download/jdk-${SEMERU_OPEN_JDK_VERSION}%2B${SEMERU_OPEN_JDK_BUILD}_openj9-${SEMERU_OPENJ9_VERSION}/ibm-semeru-open-jdk_x64_linux_${SEMERU_OPEN_JDK_VERSION}_${SEMERU_OPEN_JDK_BUILD}_openj9-${SEMERU_OPENJ9_VERSION}.tar.gz"
@@ -142,6 +153,13 @@ installMaven() {
local mavenHome="${SOFTWARE_INSTALL_DIR}/apache-maven-${MAVEN_VERSION}"
local url="https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.zip"
+ # Skip installation if Maven is already installed (from cache)
+ if [[ -d "${mavenHome}" ]]; then
+ echo "Maven ${MAVEN_VERSION} already installed at ${mavenHome}, skipping download"
+ echo "${mavenHome}/bin" >> $GITHUB_PATH
+ return 0
+ fi
+
# Download the Maven archive.
curl -fsSL -o /tmp/liberty-dev-tool-apache-maven.zip "$url"
@@ -171,6 +189,13 @@ installGradle() {
local gradleHome="${SOFTWARE_INSTALL_DIR}/gradle-${GRADLE_VERSION}"
local url="https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip"
+ # Skip installation if Gradle is already installed (from cache)
+ if [[ -d "${gradleHome}" ]]; then
+ echo "Gradle ${GRADLE_VERSION} already installed at ${gradleHome}, skipping download"
+ echo "${gradleHome}/bin" >> $GITHUB_PATH
+ return 0
+ fi
+
# Download the Gradle archive.
curl -fsSL -o /tmp/liberty-dev-tool-gradle.zip "$url"
diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java
index 4a22a085..5803ab9a 100644
--- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java
+++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java
@@ -72,10 +72,12 @@
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
import io.openliberty.tools.eclipse.CommandBuilder;
import io.openliberty.tools.eclipse.CommandBuilder.CommandNotFoundException;
@@ -87,6 +89,9 @@
import io.openliberty.tools.eclipse.ui.dashboard.DashboardView;
import io.openliberty.tools.eclipse.ui.launch.LaunchConfigurationDelegateLauncher;
+import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getObjectInDebugView;
+import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.terminateLaunch;
+
/**
* Tests Open Liberty Eclipse plugin functions.
*/
@@ -199,6 +204,17 @@ public static void setup() throws Exception {
}
+ @AfterEach
+ public void afterEach(TestInfo info) {
+ terminateLaunch();
+
+ // Validate that launch has been removed
+ Object launch = getObjectInDebugView("[Liberty]");
+ Assertions.assertNull(launch);
+
+ super.afterEach(info);
+ }
+
@AfterAll
public static void cleanup() {
for (File p : projectsToInstall) {
diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java
index 855a9d8a..5980a99c 100644
--- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java
+++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java
@@ -71,10 +71,12 @@
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
import io.openliberty.tools.eclipse.CommandBuilder;
import io.openliberty.tools.eclipse.CommandBuilder.CommandNotFoundException;
@@ -84,6 +86,9 @@
import io.openliberty.tools.eclipse.ui.dashboard.DashboardView;
import io.openliberty.tools.eclipse.ui.launch.LaunchConfigurationDelegateLauncher;
+import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getObjectInDebugView;
+import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.terminateLaunch;
+
/**
* Tests Open Liberty Eclipse plugin functions.
*/
@@ -201,6 +206,17 @@ public static void setup() throws Exception {
validateBeforeTestRun();
}
+ @AfterEach
+ public void afterEach(TestInfo info) {
+ terminateLaunch();
+
+ // Validate that launch has been removed
+ Object launch = getObjectInDebugView("[Liberty]");
+ Assertions.assertNull(launch);
+
+ super.afterEach(info);
+ }
+
@AfterAll
public static void cleanup() {
for (String p : projectPaths) {
diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenWithSpaceTest.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenWithSpaceTest.java
index d5cc45f3..25405875 100644
--- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenWithSpaceTest.java
+++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenWithSpaceTest.java
@@ -92,7 +92,7 @@ public void afterEach(TestInfo info) {
Assertions.assertNull(launch);
super.afterEach(info);
- }
+ }
@AfterAll
public static void cleanup() throws IOException {
diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java
index 7dbc1689..8186a259 100644
--- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java
+++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java
@@ -27,7 +27,6 @@
import java.util.Iterator;
import java.util.List;
-import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
@@ -60,6 +59,7 @@
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.part.ViewPart;
@@ -135,10 +135,17 @@ public void run() {
*/
public static SWTBotMenu getDebuggerConnectMenuForDebugObject(Object debugObject) {
openDebugPerspective();
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Show View", "Debug");
+ // Open Debug view using Eclipse API instead of menu navigation
+ // This is more reliable in headless CI environments
+ showDebugView();
SWTBotTreeItem obj = new SWTBotTreeItem((TreeItem) debugObject);
+
+ // Ensure the tree item is properly selected and focused before accessing context menu
+ // This is critical for headless CI environments where context menus can hang
+ obj.select();
+ obj.setFocus();
+ MagicWidgetFinder.pause(500);
return obj.contextMenu("Connect Liberty Debugger");
}
@@ -152,8 +159,15 @@ public static SWTBotMenu getDebuggerConnectMenuForDebugObject(Object debugObject
*/
public static void disconnectDebugTarget(Object debugTarget) {
openDebugPerspective();
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Show View", "Debug");
+ // Open Debug view using Eclipse API instead of menu navigation
+ // This is more reliable in headless CI environments
+ showDebugView();
+
+ // Ensure proper selection before accessing context menu
+ SWTBotTreeItem obj = new SWTBotTreeItem((TreeItem) debugTarget);
+ obj.select();
+ obj.setFocus();
+ MagicWidgetFinder.pause(500);
MagicWidgetFinder.context(debugTarget, "Disconnect");
@@ -164,46 +178,93 @@ public static void disconnectDebugTarget(Object debugTarget) {
* Terminate the launch
*/
public static void terminateLaunch() {
- openDebugPerspective();
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Show View", "Debug");
+ // Use getObjectInDebugView to find the Liberty launch with retry logic
+ Object launch = getObjectInDebugView("[Liberty]");
- Object debugView = MagicWidgetFinder.findGlobal("Debug");
+ // Only attempt to terminate if launch exists
+ if (launch != null) {
+ System.out.println("Found Liberty launch, attempting to terminate");
+ MagicWidgetFinder.context(launch, "Terminate and Remove");
- Object launch = MagicWidgetFinder.find("[Liberty]", debugView,
- Option.factory().useContains(true).setThrowExceptionOnNotFound(false).build());
-
- MagicWidgetFinder.context(launch, "Terminate and Remove");
-
- try {
- Shell confirm = (Shell) findGlobal("Terminate and Remove", Option.factory().widgetClass(Shell.class).build());
+ try {
+ Shell confirm = (Shell) findGlobal("Terminate and Remove", Option.factory().widgetClass(Shell.class).build());
- MagicWidgetFinder.go("Yes", confirm);
- MagicWidgetFinder.pause(3000);
- } catch (Exception e) {
- // The configrmation pop up window only shows if the launch has not yet been terminated.
- // If it has been terminated (or stopped), there is no confirmation.
+ MagicWidgetFinder.go("Yes", confirm);
+ MagicWidgetFinder.pause(3000);
+ } catch (Exception e) {
+ // The confirmation pop up window only shows if the launch has not yet been terminated.
+ // If it has been terminated (or stopped), there is no confirmation.
+ }
+ } else {
+ System.out.println("No Liberty launch found in Debug view to terminate");
}
-
}
/**
* Returns the debug object item in the Debug View with the given name.
* The debug object can either be a launch, a debug target, or a process in the Debug View.
- *
+ *
* @param objectName - The name of the object in the Debug View.
- *
+ *
* @return
*/
- public static Object getObjectInDebugView(String objectName) {
+ public static Object getObjectInDebugView(final String objectName) {
+ // Don't wrap in syncExec - MagicWidgetFinder methods already handle thread synchronization
+ // Nested syncExec calls can cause deadlocks in headless CI environments
openDebugPerspective();
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Show View", "Debug");
+ showDebugView();
- Object debugView = MagicWidgetFinder.findGlobal("Debug");
+ // Get the Debug view directly using Eclipse API instead of text search
+ // This is more reliable than findGlobal("Debug") which could find the wrong view
+ final Object[] debugViewHolder = new Object[1];
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IWorkbench wb = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
+ if (window != null && window.getActivePage() != null) {
+ // Get the Debug view by its ID
+ ViewPart debugView = (ViewPart) window.getActivePage().findView("org.eclipse.debug.ui.DebugView");
+ if (debugView != null) {
+ // Activate it to ensure widgets are rendered
+ window.getActivePage().activate(debugView);
+ debugViewHolder[0] = debugView;
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Failed to get Debug view: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ });
+
+ // Give the view time to activate and render
+ MagicWidgetFinder.pause(500);
+
+ Object debugView = debugViewHolder[0];
+ if (debugView == null) {
+ System.err.println("Debug view not found, cannot find object: " + objectName);
+ return null;
+ }
+
+ // Try multiple times to find the object, as it may take time to appear in headless CI
+ Object result = null;
+ for (int attempt = 0; attempt < 3 && result == null; attempt++) {
+ if (attempt > 0) {
+ System.out.println("Retry attempt " + attempt + " to find object: " + objectName);
+ MagicWidgetFinder.pause(1000);
+ }
+
+ result = MagicWidgetFinder.find(objectName, debugView,
+ Option.factory().useContains(true).setThrowExceptionOnNotFound(false).widgetClass(TreeItem.class).build());
+ }
+
+ if (result == null) {
+ System.out.println("Object not found in Debug view after 3 attempts: " + objectName);
+ }
- return MagicWidgetFinder.find(objectName, debugView,
- Option.factory().useContains(true).setThrowExceptionOnNotFound(false).widgetClass(TreeItem.class).build());
+ return result;
}
/**
@@ -226,6 +287,31 @@ public void run() {
Display.getDefault().syncExec(runnable);
}
+ /**
+ * Opens the Debug view using Eclipse API directly.
+ * This is more reliable than menu navigation in headless CI environments.
+ */
+ private static void showDebugView() {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IWorkbench wb = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
+ if (window != null && window.getActivePage() != null) {
+ // Show the Debug view using its ID
+ window.getActivePage().showView("org.eclipse.debug.ui.DebugView");
+ }
+ } catch (Exception e) {
+ System.err.println("Failed to open Debug view: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ });
+ // Give the view time to open
+ MagicWidgetFinder.pause(500);
+ }
+
public static void openJavaPerspectiveViaMenu() {
Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
@@ -239,7 +325,33 @@ public static void openJavaPerspectiveViaMenu() {
public static SWTBotTable getDashboardTable() {
openDashboardUsingToolbar();
+
+ // Ensure the dashboard view is actually shown and has focus
+ // This prevents finding the wrong view (like ConsoleView) when the console takes focus after server start
Object dashboardView = findGlobal(DASHBOARD_VIEW_TITLE, Option.factory().widgetClass(ViewPart.class).build());
+
+ // Explicitly show and activate the dashboard view to ensure it has focus
+ if (dashboardView instanceof ViewPart) {
+ final ViewPart vp = (ViewPart) dashboardView;
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IWorkbench wb = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
+ if (window != null && window.getActivePage() != null) {
+ window.getActivePage().activate(vp);
+ }
+ } catch (Exception e) {
+ System.err.println("Failed to activate dashboard view: " + e.getMessage());
+ }
+ }
+ });
+
+ // Give the UI a moment to update after activation
+ MagicWidgetFinder.pause(500);
+ }
+
Table table = ((DashboardView) dashboardView).getTable();
return new SWTBotTable(table);
}
@@ -389,56 +501,59 @@ public static SWTBotMenu getAppDebugAsMenu(SWTWorkbenchBot bot, String item) {
* @param buildTool the build tool to be used (Maven or Gradle)
*/
public static void setBuildCmdPathInPreferences(SWTWorkbenchBot bot, String buildTool) {
+ // Use Eclipse preference store API directly instead of UI navigation
+ // This avoids issues with menu accessibility in headless CI environments
- /* Preferences are accessed from a different menu on macOS than on Windows and Linux */
- /* Currently not possible to access the Preferences dialog panel on macOS so we */
- /* will return and just use an app configured with a wrapper */
- if (Platform.getOS().equals(Platform.OS_MACOSX)) {
- return;
- }
+ String finalMvnExecutableLoc = AbstractLibertyPluginSWTBotTest.getMvnCmdPath();
+ String finalGradleExecutableLoc = AbstractLibertyPluginSWTBotTest.getGradleCmdPath();
- String finalMvnExecutableLoc = null;
- String finalGradleExecutableLoc = null;
- Object locationLabel = null;
- Object locationText = null;
+ // Get the preference store for the Liberty Tools plugin
+ org.eclipse.jface.preference.IPreferenceStore prefStore = new org.eclipse.ui.preferences.ScopedPreferenceStore(
+ org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE,
+ "io.openliberty.tools.eclipse.ui");
- finalMvnExecutableLoc = AbstractLibertyPluginSWTBotTest.getMvnCmdPath();
- finalGradleExecutableLoc = AbstractLibertyPluginSWTBotTest.getGradleCmdPath();
-
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Preferences");
-
- TreeItem liberty = (TreeItem) findGlobal("Liberty", Option.factory().widgetClass(TreeItem.class).build());
- go(liberty);
- if (buildTool == "Maven") {
- locationLabel = findGlobal("Maven Install Location:", Option.factory().widgetClass(Label.class).build());
- locationText = ControlFinder.findControlInRange(locationLabel, Text.class, Direction.EAST);
- set(locationText, finalMvnExecutableLoc);
- } else if (buildTool == "Gradle") {
- locationLabel = findGlobal("Gradle Install Location:", Option.factory().widgetClass(Label.class).build());
- locationText = ControlFinder.findControlInRange(locationLabel, Text.class, Direction.EAST);
- set(locationText, finalGradleExecutableLoc);
+ if ("Maven".equals(buildTool)) {
+ prefStore.setValue("MVNPATH", finalMvnExecutableLoc);
+ } else if ("Gradle".equals(buildTool)) {
+ prefStore.setValue("GRADLEPATH", finalGradleExecutableLoc);
}
- goGlobal("Apply and Close");
+ // Save the preference store
+ if (prefStore instanceof org.eclipse.ui.preferences.ScopedPreferenceStore) {
+ try {
+ ((org.eclipse.ui.preferences.ScopedPreferenceStore) prefStore).save();
+ } catch (java.io.IOException e) {
+ System.err.println("Failed to save preferences: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
}
public static void unsetBuildCmdPathInPreferences(SWTWorkbenchBot bot, String buildTool) {
-
- /* Preferences are accessed from a different menu on macOS than on Windows and Linux */
- /* Currently not possible to access the Preferences dialog panel on macOS so we */
- /* will return and just use an app configured with a wrapper */
- if (Platform.getOS().equals(Platform.OS_MACOSX)) {
- return;
+ // Use Eclipse preference store API directly instead of UI navigation
+ // This avoids issues with menu accessibility in headless CI environments
+
+ // Get the preference store for the Liberty Tools plugin
+ org.eclipse.jface.preference.IPreferenceStore prefStore = new org.eclipse.ui.preferences.ScopedPreferenceStore(
+ org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE,
+ "io.openliberty.tools.eclipse.ui");
+
+ // Reset to default values (empty strings)
+ if ("Maven".equals(buildTool)) {
+ prefStore.setToDefault("MVNPATH");
+ } else if ("Gradle".equals(buildTool)) {
+ prefStore.setToDefault("GRADLEPATH");
}
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Preferences");
-
- findGlobal("Liberty", Option.factory().widgetClass(TreeItem.class).build());
-
- goGlobal("Restore Defaults");
- goGlobal("Apply and Close");
+ // Save the preference store
+ if (prefStore instanceof org.eclipse.ui.preferences.ScopedPreferenceStore) {
+ try {
+ ((org.eclipse.ui.preferences.ScopedPreferenceStore) prefStore).save();
+ } catch (java.io.IOException e) {
+ System.err.println("Failed to save preferences: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
}
/**
@@ -680,8 +795,9 @@ public static void checkRunCleanProjectCheckBox(Shell shell, String runDebugConf
public static Object getAppInPackageExplorerTree(String appName) {
openJavaPerspectiveViaMenu();
- Object windowMenu = findGlobal("Window", Option.factory().widgetClass(MenuItem.class).build());
- goMenuItem(windowMenu, "Show View", "Package Explorer");
+ // Open Package Explorer view using Eclipse API instead of menu navigation
+ // This is more reliable in headless CI environments
+ showPackageExplorerView();
Object peView = MagicWidgetFinder.findGlobal("Package Explorer");
Object project = MagicWidgetFinder.find(appName, peView, Option.factory().useContains(true).widgetClass(TreeItem.class).build());
@@ -945,6 +1061,31 @@ public static void closeDashboardView(SWTWorkbenchBot bot) {
}
}
+ /**
+ * Opens the Package Explorer view using Eclipse API directly.
+ * This is more reliable than menu navigation in headless CI environments.
+ */
+ private static void showPackageExplorerView() {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IWorkbench wb = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
+ if (window != null && window.getActivePage() != null) {
+ // Show the Package Explorer view using its ID
+ window.getActivePage().showView("org.eclipse.jdt.ui.PackageExplorer");
+ }
+ } catch (Exception e) {
+ System.err.println("Failed to open Package Explorer view: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ });
+ // Give the view time to open
+ MagicWidgetFinder.pause(500);
+ }
+
/**
* Switches the Liberty run configuration main tab to the JRE Tab. A Liberty configuration must be opened prior to calling this
* method.