Skip to content

fix(ci): pin code-server to v4.113.1 for Selenium tests#2752

Closed
anusshukla wants to merge 1 commit into
mainfrom
fix/pin-code-server-version
Closed

fix(ci): pin code-server to v4.113.1 for Selenium tests#2752
anusshukla wants to merge 1 commit into
mainfrom
fix/pin-code-server-version

Conversation

@anusshukla
Copy link
Copy Markdown
Contributor

Summary

  • Pin code-server to v4.113.1 in Selenium test container to fix extension activation failures
  • Re-enable all 15 previously skipped Selenium UI tests
  • Build custom container image locally instead of using upstream selenium-adt:main directly

Background

code-server v4.114.0 (released April 4, 2026) has a bug preventing VS Code extensions from loading properly in the selenium-adt container. This caused all Selenium UI tests to fail with TimeoutException while waiting for the Ansible extension to activate.

Changes

  1. New test/ui/Containerfile.selenium: Extends ghcr.io/ansible/selenium-adt:main and pins code-server to v4.113.1
  2. Updated docker-compose.yml: Builds from the local Containerfile instead of using the upstream image directly
  3. Removed skip markers: All 15 Selenium tests that were previously skipped due to flakiness are now enabled

Test plan

  • CI passes with all Selenium UI tests running
  • Container builds successfully with pinned code-server version
  • Extension activates properly in the test environment

Fixes: #2580
Related: ansible/ansible-dev-tools#677

Made with Cursor

code-server v4.114.0 (released April 4, 2026) has a bug preventing
extensions from loading properly in the selenium-adt container, causing
all Selenium UI tests to fail with TimeoutException waiting for the
Ansible extension to activate.

This change:
- Adds a local Containerfile that extends selenium-adt:main and pins
  code-server to v4.113.1 (last known working version)
- Updates docker-compose.yml to build from this local Containerfile
- Removes the @pytest.mark.skip decorators from all 15 previously
  flaky Selenium tests

Fixes: #2580
Related: ansible/ansible-dev-tools#677
Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

The changes pin the selenium-adt Docker image locally to ensure consistent test environments and enable 14 previously skipped UI tests across five test files. A new Containerfile builds the selenium image with pinned code-server and extensions, while skip decorators are removed from tests to allow execution in CI.

Changes

Cohort / File(s) Summary
Docker & Container Setup
docker-compose.yml, test/ui/Containerfile.selenium
Switches selenium-vscode service from pulling remote image to building locally from new Containerfile with pinned code-server 4.113.1 and specific VS Code extensions.
UI Test Unskipping
test/ui/test_00_commands.py, test/ui/test_01_dev_webviews.py, test/ui/test_02_welcome_webviews.py, test/ui/test_03_llm_provider_webview.py, test/ui/test_50_mcp_server.py
Removes @pytest.mark.skip(...) decorators from 14 tests total, enabling previously skipped UI tests to run in CI instead of being conditionally skipped due to flakiness concerns.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A local image pinned so tight,
No more remote pulls in the night,
Fourteen tests emerge from their sleep,
Stable selenium, promises to keep!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: pinning code-server to v4.113.1 to fix Selenium test failures in CI.
Linked Issues check ✅ Passed The PR addresses the primary objective from #2580 by fixing Selenium UI test failures (33/51 failed runs) through code-server version pinning and test re-enablement.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing Selenium UI tests: containerfile for pinned code-server, docker-compose configuration, and re-enabling previously skipped tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pin-code-server-version

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
test/ui/Containerfile.selenium (2)

11-11: Consider asserting the installed version.

Since the whole point of this file is version pinning, a follow-up RUN code-server --version | grep -q '^4\.113\.1' would fail the build early if install.sh silently ignored the --version flag or resolved to something else.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/ui/Containerfile.selenium` at line 11, Add a verification step after the
installer RUN that asserts the installed code-server matches the pinned version:
after the existing RUN that pipes to install.sh with --version 4.113.1, run a
command that invokes code-server --version and greps/validates it starts with
"4.113.1" so the build fails early if install.sh ignored or resolved the version
incorrectly; update the Docker instruction sequence that calls the installer to
include this verification and ensure it runs in the same layer or follows
immediately so failures stop the build.

5-5: Base image uses the mutable :main tag — undermines the pin.

Pinning code-server only helps if the base layer is also stable. ghcr.io/ansible/selenium-adt:main can be re-tagged at any time, which means a rebuild may pull a newer base that bundles code-server 4.114.0 (or later) and your RUN curl … install.sh only layers over whatever is already there. Consider pinning to an immutable digest (@sha256:…) or a released tag so this workaround is reproducible.

-FROM ghcr.io/ansible/selenium-adt:main
+FROM ghcr.io/ansible/selenium-adt@sha256:<digest>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/ui/Containerfile.selenium` at line 5, The Dockerfile’s base image
currently uses a mutable tag "ghcr.io/ansible/selenium-adt:main" which defeats
your code-server pin; change the FROM line to reference an immutable image
(either a released tag like "ghcr.io/ansible/selenium-adt:<release-tag>" or
preferably a digest "ghcr.io/ansible/selenium-adt@sha256:<digest>") so the base
layer is reproducible, and ensure the chosen tag/digest corresponds to the
expected code-server version that your RUN curl … install.sh step assumes.
docker-compose.yml (1)

7-10: LGTM on the compose change.

Switching to a local build with a stable selenium-adt-pinned:local tag is the right shape. One minor consideration: with build: present, docker compose up will rebuild/cache based on the Containerfile, but CI that previously relied on pull_policy: missing to skip network work will now always evaluate the build. If build time becomes a concern, enabling BuildKit cache or pushing the pinned image to a registry would help.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose.yml` around lines 7 - 10, The compose change switches the
service to a local build (build.context / build.dockerfile) with image
"selenium-adt-pinned:local", which will force builds where CI previously relied
on pull_policy: missing; to avoid unnecessary rebuilds add build cache support
or use a pushed pinned image: enable BuildKit in CI (set DOCKER_BUILDKIT=1), add
a cache source by configuring build.cache_from to reference the pinned image
(e.g., cache_from: ["selenium-adt-pinned:local"] or a registry-tagged image) or
push "selenium-adt-pinned:local" to your registry and reference that image in
cache_from so CI can reuse layers instead of rebuilding each run.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/ui/Containerfile.selenium`:
- Around line 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.

---

Nitpick comments:
In `@docker-compose.yml`:
- Around line 7-10: The compose change switches the service to a local build
(build.context / build.dockerfile) with image "selenium-adt-pinned:local", which
will force builds where CI previously relied on pull_policy: missing; to avoid
unnecessary rebuilds add build cache support or use a pushed pinned image:
enable BuildKit in CI (set DOCKER_BUILDKIT=1), add a cache source by configuring
build.cache_from to reference the pinned image (e.g., cache_from:
["selenium-adt-pinned:local"] or a registry-tagged image) or push
"selenium-adt-pinned:local" to your registry and reference that image in
cache_from so CI can reuse layers instead of rebuilding each run.

In `@test/ui/Containerfile.selenium`:
- Line 11: Add a verification step after the installer RUN that asserts the
installed code-server matches the pinned version: after the existing RUN that
pipes to install.sh with --version 4.113.1, run a command that invokes
code-server --version and greps/validates it starts with "4.113.1" so the build
fails early if install.sh ignored or resolved the version incorrectly; update
the Docker instruction sequence that calls the installer to include this
verification and ensure it runs in the same layer or follows immediately so
failures stop the build.
- Line 5: The Dockerfile’s base image currently uses a mutable tag
"ghcr.io/ansible/selenium-adt:main" which defeats your code-server pin; change
the FROM line to reference an immutable image (either a released tag like
"ghcr.io/ansible/selenium-adt:<release-tag>" or preferably a digest
"ghcr.io/ansible/selenium-adt@sha256:<digest>") so the base layer is
reproducible, and ensure the chosen tag/digest corresponds to the expected
code-server version that your RUN curl … install.sh step assumes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cfe87dae-cc72-4c05-a712-09575816bb67

📥 Commits

Reviewing files that changed from the base of the PR and between 039cb98 and 0cff577.

📒 Files selected for processing (7)
  • docker-compose.yml
  • test/ui/Containerfile.selenium
  • test/ui/test_00_commands.py
  • test/ui/test_01_dev_webviews.py
  • test/ui/test_02_welcome_webviews.py
  • test/ui/test_03_llm_provider_webview.py
  • test/ui/test_50_mcp_server.py
💤 Files with no reviewable changes (5)
  • test/ui/test_00_commands.py
  • test/ui/test_02_welcome_webviews.py
  • test/ui/test_01_dev_webviews.py
  • test/ui/test_50_mcp_server.py
  • test/ui/test_03_llm_provider_webview.py

Comment on lines +13 to +17
# 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
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

CI Status Dashboard ❌

1 participant