Skip to content

Add V2 UI packaging and Docker integration#137

Open
tomerqodo wants to merge 2 commits into
qodo_combined_20260121_demo_10_base_add_v2_ui_packaging_and_docker_integration_pr541from
qodo_combined_20260121_demo_10_head_add_v2_ui_packaging_and_docker_integration_pr541
Open

Add V2 UI packaging and Docker integration#137
tomerqodo wants to merge 2 commits into
qodo_combined_20260121_demo_10_base_add_v2_ui_packaging_and_docker_integration_pr541from
qodo_combined_20260121_demo_10_head_add_v2_ui_packaging_and_docker_integration_pr541

Conversation

@tomerqodo

Copy link
Copy Markdown

Benchmark PR from qodo-benchmark#541

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (3) 📎 Requirement gaps (0)

Grey Divider


Action required

1. ui_logger uses logging.getLogger() 📘 Rule violation ✧ Quality
Description
• The new code instantiates ui_logger via logging.getLogger("ui_server") without the
  standardized get_logger(...) pattern and without a logger type annotation.
• This breaks consistency in logging configuration/type-safety expectations and can lead to uneven
  formatting/handlers compared to other loggers created via get_logger.
Code

src/prefect/server/api/server.py[R531-532]

+            ui_logger = logging.getLogger("ui_server")
+            ui_logger.info("Serving experimental V2 UI")
Evidence
PR Compliance ID 9 requires logger instances to be created with `logger: "logging.Logger" =
get_logger("module_name"). The added lines create a logger using logging.getLogger(...)` instead,
violating the required initialization pattern and omitting the required annotation.

AGENTS.md
src/prefect/server/api/server.py[531-532]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A new logger is created with `logging.getLogger("ui_server")`, which violates the required standardized logger initialization pattern (`logger: "logging.Logger" = get_logger("...")`).

## Issue Context
This code path runs when serving the UI, so consistent logger configuration matters for downstream handlers/formatters and type safety.

## Fix Focus Areas
- src/prefect/server/api/server.py[529-533]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. prefect.__init__ missing future annotations 📘 Rule violation ⛯ Reliability
Description
src/prefect/__init__.py contains type annotations (including newly added annotated constants)
  but does not include from __future__ import annotations as the first import statement.
• This violates the required typing standard and can reduce forward-reference robustness and
  type-checking performance.
Code

src/prefect/init.py[R67-72]

+# The absolute path to the built V2 UI within the Python module, used by
+# `prefect server start` to serve a dynamic build of the V2 UI
+__ui_v2_static_subpath__: pathlib.Path = __module_path__ / "server" / "ui_v2_build"
+
+# The absolute path to the built V2 UI within the Python module
+__ui_v2_static_path__: pathlib.Path = __module_path__ / "server" / "ui_v2"
Evidence
PR Compliance ID 7 requires every src/ Python file with type annotations to include `from
__future__ import annotations as the first import. src/prefect/__init__.py` uses type annotations
(including the new __ui_v2_* annotated paths) but its first import is import sys and there is no
future-annotations import.

AGENTS.md
src/prefect/init.py[5-10]
src/prefect/init.py[67-72]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`src/prefect/__init__.py` uses type annotations but is missing `from __future__ import annotations` as the first import statement.

## Issue Context
Compliance requires future-annotations in any `src/` file containing type hints to improve forward-reference behavior and type-checking performance.

## Fix Focus Areas
- src/prefect/__init__.py[1-10]
- src/prefect/__init__.py[55-74]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. ServerUISettings missing future annotations 📘 Rule violation ⛯ Reliability
Description
src/prefect/settings/models/server/ui.py contains type annotations (including the newly added
  v2_enabled: bool) but does not include from __future__ import annotations as the first import
  statement.
• This violates the typing standard and may cause avoidable runtime import coupling for annotations
  in more complex cases.
Code

src/prefect/settings/models/server/ui.py[R22-25]

+    v2_enabled: bool = Field(
+        default=True,
+        description="Whether to serve the experimental V2 UI instead of the default V1 UI.",
+    )
Evidence
PR Compliance ID 7 requires from __future__ import annotations as the first import in any src/
Python file using type annotations. This file begins with from typing ... and adds/contains
annotated fields like v2_enabled: bool, but has no future-annotations import.

AGENTS.md
src/prefect/settings/models/server/ui.py[1-6]
src/prefect/settings/models/server/ui.py[22-26]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`src/prefect/settings/models/server/ui.py` contains type annotations but lacks the required `from __future__ import annotations` import as the first import statement.

## Issue Context
Compliance requires future-annotations for all `src/` Python files that use type hints.

## Fix Focus Areas
- src/prefect/settings/models/server/ui.py[1-10]
- src/prefect/settings/models/server/ui.py[20-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. V2 UI path mismatch 🐞 Bug ✓ Correctness
Description
• Prefect’s runtime constant for the V2 UI directory points to server/ui_v2, but CI/Docker
  packaging writes the built assets to server/ui-v2.
• When v2_enabled is true, the UI server checks os.path.exists(source_static_path) and will skip
  mounting the UI if the path does not exist.
• This will likely ship an install where the V2 UI is never served (and since v2_enabled defaults
  true, it can effectively disable the UI by default).
Code

src/prefect/init.py[R67-72]

+# The absolute path to the built V2 UI within the Python module, used by
+# `prefect server start` to serve a dynamic build of the V2 UI
+__ui_v2_static_subpath__: pathlib.Path = __module_path__ / "server" / "ui_v2_build"
+
+# The absolute path to the built V2 UI within the Python module
+__ui_v2_static_path__: pathlib.Path = __module_path__ / "server" / "ui_v2"
Evidence
The server uses prefect.__ui_v2_static_path__ as the source directory when V2 is enabled, then
only mounts the UI if that directory exists. However, all build/packaging steps added in this PR
place the V2 build output under src/prefect/server/ui-v2 (hyphen), while the runtime constant
points at server/ui_v2 (underscore). That mismatch makes the existence check fail and prevents the
UI mount.

src/prefect/init.py[67-72]
src/prefect/server/api/server.py[462-465]
src/prefect/server/api/server.py[524-527]
Dockerfile[102-107]
.github/workflows/python-package.yaml[46-52]
pyproject.toml[231-233]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Runtime V2 UI path constants (`prefect.__ui_v2_static_path__`) point to `server/ui_v2` (underscore), but Docker/CI/Hatch package the V2 UI into `server/ui-v2` (hyphen). When V2 is enabled, the server checks `os.path.exists(source_static_path)` and will not mount the UI if the directory is missing.

### Issue Context
This can cause Prefect Server to ship with `v2_enabled=True` but no UI being served, because the server is looking in a different directory than the one containing the packaged artifacts.

### Fix Focus Areas
- src/prefect/__init__.py[67-72]
- Dockerfile[102-107]
- .github/workflows/python-package.yaml[46-52]
- pyproject.toml[231-233]
- src/prefect/server/api/server.py[462-466]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Wrong V2 cache subpath 🐞 Bug ⛯ Reliability
Description
• When v2_enabled is true, the code sets static_subpath to the V1 __ui_static_subpath__
  instead of the V2 __ui_v2_static_subpath__.
• This means V2 assets would be copied into the V1 build/cache directory, potentially overwriting V1
  assets and causing confusing behavior when toggling V1/V2.
• The dedicated V2 subpath constant is currently unused, indicating this is likely an oversight.
Code

src/prefect/server/api/server.py[R462-465]

+    if v2_enabled:
+        source_static_path = prefect.__ui_v2_static_path__
+        static_subpath = prefect.__ui_static_subpath__
+        cache_key = f"v2:{prefect.__version__}:{base_url}"
Evidence
The repository defines a separate V2 cache/build subpath (__ui_v2_static_subpath__), but the new
V2 serving branch uses the V1 subpath (__ui_static_subpath__). Since static_dir defaults to
static_subpath and copy_directory copies the chosen UI’s files into static_dir, V2 builds
would be written into the V1 cache location.

src/prefect/init.py[60-72]
src/prefect/server/api/server.py[462-469]
src/prefect/server/api/server.py[471-474]
src/prefect/server/api/server.py[505-510]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
In `create_ui_app`, the V2 code path sets `static_subpath` to the V1 value (`prefect.__ui_static_subpath__`). As a result, V2 UI assets would be copied into the V1 UI cache/build directory, potentially overwriting V1 assets.

### Issue Context
`src/prefect/__init__.py` defines `__ui_v2_static_subpath__` explicitly, suggesting the design intends separate cache/build directories.

### Fix Focus Areas
- src/prefect/server/api/server.py[462-474]
- src/prefect/__init__.py[60-72]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Experimental enabled by default 🐞 Bug ⛯ Reliability
Description
• The new server.ui.v2_enabled flag defaults to True while explicitly described as
  “experimental”.
• If V2 assets are missing/mismatched (as in the path issues above), this default can cause the
  server to start without mounting any UI.
• Even if assets are present, enabling an experimental UI by default may be an unintended breaking
  UX change for existing users.
Code

src/prefect/settings/models/server/ui.py[R22-25]

+    v2_enabled: bool = Field(
+        default=True,
+        description="Whether to serve the experimental V2 UI instead of the default V1 UI.",
+    )
Evidence
The setting is explicitly labeled experimental yet defaults to enabled. This amplifies the impact of
any V2 UI packaging/serving mismatch, and changes default behavior for all installations/upgrades
unless explicitly configured otherwise.

src/prefect/settings/models/server/ui.py[22-25]
src/prefect/server/api/server.py[459-465]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`server.ui.v2_enabled` is described as experimental but defaults to `True`, which can unintentionally switch users to the experimental UI (or result in no UI being served if assets are missing).

### Issue Context
There is already logic that only mounts the UI if `os.path.exists(source_static_path)`. With the current path mismatch, the default `True` setting can disable UI serving entirely.

### Fix Focus Areas
- src/prefect/settings/models/server/ui.py[22-25]
- src/prefect/server/api/server.py[459-469]
- src/prefect/server/api/server.py[524-528]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment on lines +531 to +532
ui_logger = logging.getLogger("ui_server")
ui_logger.info("Serving experimental V2 UI")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. ui_logger uses logging.getlogger() 📘 Rule violation ✧ Quality

• The new code instantiates ui_logger via logging.getLogger("ui_server") without the
  standardized get_logger(...) pattern and without a logger type annotation.
• This breaks consistency in logging configuration/type-safety expectations and can lead to uneven
  formatting/handlers compared to other loggers created via get_logger.
Agent prompt
## Issue description
A new logger is created with `logging.getLogger("ui_server")`, which violates the required standardized logger initialization pattern (`logger: "logging.Logger" = get_logger("...")`).

## Issue Context
This code path runs when serving the UI, so consistent logger configuration matters for downstream handlers/formatters and type safety.

## Fix Focus Areas
- src/prefect/server/api/server.py[529-533]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/prefect/__init__.py
Comment on lines +67 to +72
# The absolute path to the built V2 UI within the Python module, used by
# `prefect server start` to serve a dynamic build of the V2 UI
__ui_v2_static_subpath__: pathlib.Path = __module_path__ / "server" / "ui_v2_build"

# The absolute path to the built V2 UI within the Python module
__ui_v2_static_path__: pathlib.Path = __module_path__ / "server" / "ui_v2"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. prefect.init missing future annotations 📘 Rule violation ⛯ Reliability

src/prefect/__init__.py contains type annotations (including newly added annotated constants)
  but does not include from __future__ import annotations as the first import statement.
• This violates the required typing standard and can reduce forward-reference robustness and
  type-checking performance.
Agent prompt
## Issue description
`src/prefect/__init__.py` uses type annotations but is missing `from __future__ import annotations` as the first import statement.

## Issue Context
Compliance requires future-annotations in any `src/` file containing type hints to improve forward-reference behavior and type-checking performance.

## Fix Focus Areas
- src/prefect/__init__.py[1-10]
- src/prefect/__init__.py[55-74]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +22 to +25
v2_enabled: bool = Field(
default=True,
description="Whether to serve the experimental V2 UI instead of the default V1 UI.",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. serveruisettings missing future annotations 📘 Rule violation ⛯ Reliability

src/prefect/settings/models/server/ui.py contains type annotations (including the newly added
  v2_enabled: bool) but does not include from __future__ import annotations as the first import
  statement.
• This violates the typing standard and may cause avoidable runtime import coupling for annotations
  in more complex cases.
Agent prompt
## Issue description
`src/prefect/settings/models/server/ui.py` contains type annotations but lacks the required `from __future__ import annotations` import as the first import statement.

## Issue Context
Compliance requires future-annotations for all `src/` Python files that use type hints.

## Fix Focus Areas
- src/prefect/settings/models/server/ui.py[1-10]
- src/prefect/settings/models/server/ui.py[20-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/prefect/__init__.py
Comment on lines +67 to +72
# The absolute path to the built V2 UI within the Python module, used by
# `prefect server start` to serve a dynamic build of the V2 UI
__ui_v2_static_subpath__: pathlib.Path = __module_path__ / "server" / "ui_v2_build"

# The absolute path to the built V2 UI within the Python module
__ui_v2_static_path__: pathlib.Path = __module_path__ / "server" / "ui_v2"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

4. V2 ui path mismatch 🐞 Bug ✓ Correctness

• Prefect’s runtime constant for the V2 UI directory points to server/ui_v2, but CI/Docker
  packaging writes the built assets to server/ui-v2.
• When v2_enabled is true, the UI server checks os.path.exists(source_static_path) and will skip
  mounting the UI if the path does not exist.
• This will likely ship an install where the V2 UI is never served (and since v2_enabled defaults
  true, it can effectively disable the UI by default).
Agent prompt
### Issue description
Runtime V2 UI path constants (`prefect.__ui_v2_static_path__`) point to `server/ui_v2` (underscore), but Docker/CI/Hatch package the V2 UI into `server/ui-v2` (hyphen). When V2 is enabled, the server checks `os.path.exists(source_static_path)` and will not mount the UI if the directory is missing.

### Issue Context
This can cause Prefect Server to ship with `v2_enabled=True` but no UI being served, because the server is looking in a different directory than the one containing the packaged artifacts.

### Fix Focus Areas
- src/prefect/__init__.py[67-72]
- Dockerfile[102-107]
- .github/workflows/python-package.yaml[46-52]
- pyproject.toml[231-233]
- src/prefect/server/api/server.py[462-466]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +462 to +465
if v2_enabled:
source_static_path = prefect.__ui_v2_static_path__
static_subpath = prefect.__ui_static_subpath__
cache_key = f"v2:{prefect.__version__}:{base_url}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

5. Wrong v2 cache subpath 🐞 Bug ⛯ Reliability

• When v2_enabled is true, the code sets static_subpath to the V1 __ui_static_subpath__
  instead of the V2 __ui_v2_static_subpath__.
• This means V2 assets would be copied into the V1 build/cache directory, potentially overwriting V1
  assets and causing confusing behavior when toggling V1/V2.
• The dedicated V2 subpath constant is currently unused, indicating this is likely an oversight.
Agent prompt
### Issue description
In `create_ui_app`, the V2 code path sets `static_subpath` to the V1 value (`prefect.__ui_static_subpath__`). As a result, V2 UI assets would be copied into the V1 UI cache/build directory, potentially overwriting V1 assets.

### Issue Context
`src/prefect/__init__.py` defines `__ui_v2_static_subpath__` explicitly, suggesting the design intends separate cache/build directories.

### Fix Focus Areas
- src/prefect/server/api/server.py[462-474]
- src/prefect/__init__.py[60-72]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +22 to +25
v2_enabled: bool = Field(
default=True,
description="Whether to serve the experimental V2 UI instead of the default V1 UI.",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

6. Experimental enabled by default 🐞 Bug ⛯ Reliability

• The new server.ui.v2_enabled flag defaults to True while explicitly described as
  “experimental”.
• If V2 assets are missing/mismatched (as in the path issues above), this default can cause the
  server to start without mounting any UI.
• Even if assets are present, enabling an experimental UI by default may be an unintended breaking
  UX change for existing users.
Agent prompt
### Issue description
`server.ui.v2_enabled` is described as experimental but defaults to `True`, which can unintentionally switch users to the experimental UI (or result in no UI being served if assets are missing).

### Issue Context
There is already logic that only mounts the UI if `os.path.exists(source_static_path)`. With the current path mismatch, the default `True` setting can disable UI serving entirely.

### Fix Focus Areas
- src/prefect/settings/models/server/ui.py[22-25]
- src/prefect/server/api/server.py[459-469]
- src/prefect/server/api/server.py[524-528]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant