Skip to content
Closed
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
6 changes: 4 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
# cspell: ignore healthcheck
services:
selenium-vscode:
image: ghcr.io/ansible/selenium-adt:main
pull_policy: missing
build:
context: .
dockerfile: test/ui/Containerfile.selenium
image: selenium-adt-pinned:local
container_name: selenium-vscode
shm_size: "10g"
security_opt:
Expand Down
19 changes: 19 additions & 0 deletions test/ui/Containerfile.selenium
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Extends ghcr.io/ansible/selenium-adt:main with pinned code-server version
# This is a workaround for https://github.com/coder/code-server/issues/7890
# code-server v4.114.0 has a bug preventing extensions from loading properly.
# Pin to v4.113.1 until the upstream fix is available.
FROM ghcr.io/ansible/selenium-adt:main

USER root

# Reinstall code-server with pinned version to avoid extension loading bug
# in v4.114.0 (released April 4, 2026)
RUN curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.113.1

# Reinstall extensions that may have been affected
RUN code-server --install-extension ms-python.vscode-python-envs \
--install-extension ms-python.python \
--install-extension redhat.vscode-yaml \
--install-extension redhat.vscode-redhat-account
Comment on lines +13 to +17
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the base image to confirm selenium user home and existing extension location.
podman run --rm --entrypoint sh ghcr.io/ansible/selenium-adt:main -c '
  id
  getent passwd 1001
  ls -la /home/selenium/.local/share/code-server/extensions 2>/dev/null || echo "no selenium extensions dir"
  ls -la /root/.local/share/code-server/extensions 2>/dev/null || echo "no root extensions dir"
  which code-server && code-server --version
'

Repository: ansible/vscode-ansible

Length of output: 112


🏁 Script executed:

find . -name "Containerfile*" -o -name "docker-compose*" | head -20

Repository: ansible/vscode-ansible

Length of output: 159


🏁 Script executed:

cat -n test/ui/Containerfile.selenium

Repository: ansible/vscode-ansible

Length of output: 998


🏁 Script executed:

find . -name "docker-compose*" -type f

Repository: ansible/vscode-ansible

Length of output: 86


🏁 Script executed:

cat -n docker-compose.yml

Repository: ansible/vscode-ansible

Length of output: 1449


🏁 Script executed:

grep -A 20 "selenium-adt" docker-compose.yml

Repository: ansible/vscode-ansible

Length of output: 787


🏁 Script executed:

grep -r "selenium\|USER 1001" --include="*.md" --include="*.txt" .

Repository: ansible/vscode-ansible

Length of output: 149


🏁 Script executed:

cat -n Containerfile

Repository: ansible/vscode-ansible

Length of output: 2539


🏁 Script executed:

rg "selenium|user.*1001|1001.*home" -i

Repository: ansible/vscode-ansible

Length of output: 4847


🏁 Script executed:

find . -name "README*" -o -name "*.md" | xargs grep -l "selenium\|user.*1001" 2>/dev/null | head -10

Repository: ansible/vscode-ansible

Length of output: 97


🏁 Script executed:

rg "home.*selenium|selenium.*home|UID|GID" --include="*.md" --include="*.txt" --include="*.yml" -i

Repository: ansible/vscode-ansible

Length of output: 507


🏁 Script executed:

# Check if there are any other references to the base image or its setup
rg "ghcr.io/ansible/selenium-adt" -A 5 -B 5

Repository: ansible/vscode-ansible

Length of output: 825


🏁 Script executed:

cat -n docs/development/test_code.md

Repository: ansible/vscode-ansible

Length of output: 3674


Installing extensions as root places them in the wrong user's home directory.

The extensions are installed at lines 14–17 while the container is in USER root context. The code-server --install-extension command writes to the invoking user's $HOME — in this case, /root/.local/share/code-server/extensions. However, the container switches to USER 1001 at line 19, and the docker-compose.yml mounts code-server data directories under /home/selenium/.local/share/code-server/... (the home directory of user 1001). The runtime process will look for extensions under /home/selenium/.local/share/code-server/extensions and will not find the ones installed under /root, silently reproducing the very extension-loading failure this PR aims to fix.

Move the extension installation after switching to the runtime user:

🛠️ Suggested fix
-# Reinstall extensions that may have been affected
-RUN code-server --install-extension ms-python.vscode-python-envs \
-    --install-extension ms-python.python \
-    --install-extension redhat.vscode-yaml \
-    --install-extension redhat.vscode-redhat-account
-
-USER 1001
+USER 1001
+
+# Reinstall extensions under the runtime user's data dir
+RUN code-server --install-extension ms-python.vscode-python-envs \
+    --install-extension ms-python.python \
+    --install-extension redhat.vscode-yaml \
+    --install-extension redhat.vscode-redhat-account
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/ui/Containerfile.selenium` around lines 13 - 17, The extension install
commands run as root so they land in /root/.local/share/code-server/extensions
and won't be visible to the runtime user; move the three code-server
--install-extension invocations out of the root section and run them after the
Dockerfile switches to USER 1001 (or run them as UID 1001) so the extensions are
installed into /home/selenium/.local/share/code-server/extensions used at
runtime; remove or avoid the root-level install to prevent duplicate/misplaced
extension files.


USER 1001
2 changes: 0 additions & 2 deletions test/ui/test_00_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
]


@pytest.mark.skip(reason="Flaky on CI - tests container image, not extension code")
def test_terminal(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down Expand Up @@ -72,7 +71,6 @@ def check_output() -> bool:
assert not missing, f"Missing packages in 'adt --version' output: {missing}"


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_create_empty_playbook(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down
2 changes: 0 additions & 2 deletions test/ui/test_01_dev_webviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_devfile_webview(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down Expand Up @@ -58,7 +57,6 @@ def test_devfile_webview(
vscode_button_click(driver, "reset-button")


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_devcontainer_webview(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down
3 changes: 0 additions & 3 deletions test/ui/test_02_welcome_webviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
@pytest.mark.modify_settings({"ansible.lightspeed.enabled": False})
def test_sidebar_nav(
browser_setup: Any,
Expand Down Expand Up @@ -44,7 +43,6 @@ def test_sidebar_nav(
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_header_and_subtitle(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down Expand Up @@ -78,7 +76,6 @@ def test_header_and_subtitle(
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_mcp_section(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down
4 changes: 0 additions & 4 deletions test/ui/test_03_llm_provider_webview.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_llm_provider_webview_opens(
browser_setup: Any,
screenshot_on_fail: Any,
Expand All @@ -32,7 +31,6 @@ def test_llm_provider_webview_opens(
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_llm_provider_webview_lists_providers(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down Expand Up @@ -73,7 +71,6 @@ def test_llm_provider_webview_lists_providers(
assert rhcustom_provider is not None, "Red Hat AI provider should be listed"


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_llm_provider_webview_edit_button(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down Expand Up @@ -106,7 +103,6 @@ def test_llm_provider_webview_edit_button(
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_rhcustom_provider_config_fields(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down
4 changes: 0 additions & 4 deletions test/ui/test_50_mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ def _assert_disable_notification(driver: Any) -> None:
)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_mcp_server_enable_via_command(
browser_setup: Any,
screenshot_on_fail: Any,
Expand All @@ -72,7 +71,6 @@ def test_mcp_server_enable_via_command(
_assert_enable_notification(driver)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_mcp_server_disable(
browser_setup: Any,
screenshot_on_fail: Any,
Expand All @@ -86,7 +84,6 @@ def test_mcp_server_disable(
_assert_disable_notification(driver)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
@pytest.mark.modify_settings({"ansible.mcpServer.enabled": True})
def test_mcp_server_enabled_via_settings(
browser_setup: Any,
Expand All @@ -102,7 +99,6 @@ def test_mcp_server_enabled_via_settings(
_assert_enable_notification(driver)


@pytest.mark.skip(reason="Flaky on CI - extension activation timing issues")
def test_mcp_server_usable(
browser_setup: Any,
screenshot_on_fail: Any,
Expand Down
Loading