Skip to content

feat: schemas for pluggable deployment service#11979

Merged
jordanrfrazier merged 12 commits into
mainfrom
deployment-schemas-lfx
Mar 2, 2026
Merged

feat: schemas for pluggable deployment service#11979
jordanrfrazier merged 12 commits into
mainfrom
deployment-schemas-lfx

Conversation

@HzaRashid
Copy link
Copy Markdown
Collaborator

@HzaRashid HzaRashid commented Mar 2, 2026

Introduces the schemas and interface for the pluggable deployment service. Does not register the service. Includes tests for schema validation.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced deployment service infrastructure to support create, update, delete, and manage deployment operations.
    • Added execution tracking capabilities for deployments.
    • Enhanced error handling with specialized exceptions for deployment-related failures.
  • Tests

    • Added comprehensive unit tests for deployment schema validation and operations.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 2, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR introduces a comprehensive deployment service framework for LFX, establishing base abstractions, provider-agnostic protocols, custom exception hierarchy, and extensive Pydantic-based schema definitions for deployments, executions, configurations, and snapshots. Comprehensive unit tests validate schema behaviors and constraints.

Changes

Cohort / File(s) Summary
Core Service Abstractions
src/lfx/src/lfx/services/deployment/__init__.py, src/lfx/src/lfx/services/deployment/base.py, src/lfx/src/lfx/services/deployment/service.py
Introduces BaseDeploymentService abstract base class defining provider-agnostic interface for deployment operations (CRUD, lifecycle, execution management) and DeploymentService implementation. Package initializer re-exports DeploymentService.
Protocol Interfaces
src/lfx/src/lfx/services/interfaces.py
Adds DeploymentServiceProtocol defining async adapter interface with methods for deployment and execution management; extends TYPE_CHECKING imports for deployment schema types.
Error Handling
src/lfx/src/lfx/services/deployment/exceptions.py
Establishes deployment-specific exception hierarchy with DeploymentError base class and specialized exceptions (AuthenticationError, CredentialResolutionError, DeploymentConflictError, InvalidContentError, etc.) with custom error codes.
Data Schemas
src/lfx/src/lfx/services/deployment/schema.py
Comprehensive Pydantic models covering deployment lifecycle (DeploymentCreate, DeploymentUpdate, DeploymentListParams), execution management (ExecutionCreate), configuration (Config, ConfigItem, ConfigDeploymentBindingUpdate), snapshots (SnapshotItems, SnapshotDeploymentBindingUpdate), environment variables, and result types. Includes validators for ID normalization, deduplication, mutual exclusivity constraints, and conflict detection.
Testing
src/lfx/tests/unit/services/deployment/__init__.py, src/lfx/tests/unit/services/deployment/test_deployment_schema.py
Unit tests validating schema behavior including field validation, ID normalization, deduplication, overlap detection, and consistency across result types; package docstring added.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error PR adds 1,033 lines of implementation but only tests schema models (202/442 lines), leaving 591 lines untested across base.py, exceptions.py, service.py, and interfaces.py. Add tests for BaseDeploymentService abstract methods, all 10 exception classes, DeploymentService implementation, DeploymentServiceProtocol interface, and integration tests to achieve at least 80% code coverage.
Docstring Coverage ⚠️ Warning Docstring coverage is 53.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Quality And Coverage ⚠️ Warning Test coverage is incomplete: only schema validation tested; async methods, exceptions, base classes, and service logic untested. Add async tests with pytest-asyncio, exception handling tests for all 9+ custom exceptions, BaseDeploymentService behavioral tests, and both success/failure paths for all operations.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing schemas and infrastructure for a pluggable deployment service across multiple new files.
Test File Naming And Structure ✅ Passed test_deployment_schema.py follows correct patterns with descriptive test names and comprehensive coverage of positive and negative scenarios including edge cases.
Excessive Mock Usage Warning ✅ Passed Test file test_deployment_schema.py (202 lines) focuses on real schema validation behavior using actual Pydantic models rather than excessive mocking.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch deployment-schemas-lfx

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 2, 2026

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 23%
22.87% (7981/34889) 15.45% (4224/27334) 15.6% (1147/7348)

Unit Test Results

Tests Skipped Failures Errors Time
2611 0 💤 0 ❌ 0 🔥 42.749s ⏱️

@github-actions github-actions Bot added the enhancement New feature or request label Mar 2, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
Copy link
Copy Markdown
Contributor

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lfx/src/lfx/services/interfaces.py (1)

34-39: ⚠️ Potential issue | 🟡 Minor

Typo in docstring: "Auhtenticated" should be "Authenticated".

📝 Proposed fix
 class AuthUserProtocol(Protocol):
-    """Auhtenticated user object (id, username, is_active, is_superuser).
+    """Authenticated user object (id, username, is_active, is_superuser).
 
     Implementations may use User or UserRead from the database layer; this protocol
     describes the surface needed by consumers of the auth service.
     """
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lfx/src/lfx/services/interfaces.py` around lines 34 - 39, Fix the typo in
the docstring of AuthUserProtocol: change "Auhtenticated" to "Authenticated" in
the class AuthUserProtocol's docstring so it reads "Authenticated user object
(id, username, is_active, is_superuser)."; update only the docstring text in the
AuthUserProtocol declaration.
🧹 Nitpick comments (5)
src/lfx/src/lfx/services/deployment/base.py (2)

44-52: Abstract property with default return value is unreachable code.

The name property is marked @abstractmethod so subclasses must override it, making return "deployment_service" unreachable. Consider removing the return statement or using ... for consistency.

♻️ Proposed fix
     `@property`
     `@abstractmethod`
     def name(self) -> str:
         """Service name identifier.
 
         Returns:
             str: The service name.
         """
-        return "deployment_service"
+        ...
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lfx/src/lfx/services/deployment/base.py` around lines 44 - 52, The
abstract property name() in the deployment base (the `@property` `@abstractmethod`
def name(self) -> str) includes an unreachable return "deployment_service";
remove the concrete return and make the method abstract-only (replace the body
with "..."/pass or raise NotImplementedError) so subclasses must implement it,
ensuring the `@abstractmethod` contract is honored; update any docstring as needed
but do not provide a default return value in the abstract def name.

64-72: Inconsistent abstract method body style.

list_types uses ... as the body (Line 72) while other abstract methods rely on implicit pass after the docstring. Consider using a consistent style across all abstract methods for readability.

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

In `@src/lfx/src/lfx/services/deployment/base.py` around lines 64 - 72, The
abstract method list_types currently uses an explicit ellipsis as its body; make
it consistent with the other abstract methods by removing the ellipsis and
leaving the method with just the docstring (i.e., implicit pass after the
docstring) in the abstract class where list_types is defined so that the method
signature and `@abstractmethod` decorator remain but the body style matches the
others.
src/lfx/tests/unit/services/deployment/test_deployment_schema.py (1)

140-142: Consider adding a test for SnapshotItems(raw_payloads=None).

The schema allows raw_payloads to be None, but the current tests only cover the required field case and empty list rejection. Adding a test confirming SnapshotItems(raw_payloads=None) is valid would improve coverage.

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

In `@src/lfx/tests/unit/services/deployment/test_deployment_schema.py` around
lines 140 - 142, Add a unit test that verifies SnapshotItems accepts
raw_payloads=None: create a new test (e.g.,
test_snapshot_items_accepts_none_raw_payload) that constructs
SnapshotItems(raw_payloads=None) and asserts no ValidationError is raised
(optionally assert the instance.raw_payloads is None). This complements the
existing tests that cover required field and empty list rejection and references
the SnapshotItems class and raw_payloads field.
src/lfx/src/lfx/services/deployment/service.py (1)

46-49: Concrete __init__ with abstract methods creates an unusual pattern.

The class can be instantiated (since __init__ is not abstract), but all other methods will raise NotImplementedError. This is a valid "template" pattern, but it differs from typical ABC usage where instantiation would fail. If this is intentional (e.g., to allow partial implementations or testing), consider adding a clarifying comment.

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

In `@src/lfx/src/lfx/services/deployment/service.py` around lines 46 - 49, The
concrete __init__ calls super().__init__() and self.set_ready() while other
methods in this class raise NotImplementedError, creating a template pattern
that allows instantiation; either make the initializer abstract to prevent
instantiation or keep it concrete but add a clarifying comment that this class
is intentionally instantiable for partial implementations/tests. Update the
class around __init__ and set_ready to reflect the chosen approach: if
preventing instantiation, mark __init__ as abstract (or the class as abstract)
so instantiation fails; if allowing it, add a clear docstring/comment on
__init__ stating that concrete __init__ + abstract methods is intentional and
why.
src/lfx/src/lfx/services/deployment/schema.py (1)

27-42: Note: TODO comment at Line 42.

The TODO to validate presence of nodes and edges in data is tracked. Consider creating an issue to implement this validation if it's required for data integrity.

Would you like me to open an issue to track implementing the nodes/edges validation in BaseFlowArtifact.data?

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

In `@src/lfx/src/lfx/services/deployment/schema.py` around lines 27 - 42, Add a
Pydantic validator on BaseFlowArtifact to enforce that the data field contains
required keys "nodes" and "edges" (and that they are lists) so malformed flow
payloads are rejected; implement this by adding a `@field_validator`("data")
method (or `@model_validator` if you prefer whole-model validation) on the
BaseFlowArtifact class that checks data is a dict, verifies "nodes" and "edges"
exist and are list-like, and raises a ValueError with a clear message when the
check fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/lfx/src/lfx/services/interfaces.py`:
- Around line 34-39: Fix the typo in the docstring of AuthUserProtocol: change
"Auhtenticated" to "Authenticated" in the class AuthUserProtocol's docstring so
it reads "Authenticated user object (id, username, is_active, is_superuser).";
update only the docstring text in the AuthUserProtocol declaration.

---

Nitpick comments:
In `@src/lfx/src/lfx/services/deployment/base.py`:
- Around line 44-52: The abstract property name() in the deployment base (the
`@property` `@abstractmethod` def name(self) -> str) includes an unreachable return
"deployment_service"; remove the concrete return and make the method
abstract-only (replace the body with "..."/pass or raise NotImplementedError) so
subclasses must implement it, ensuring the `@abstractmethod` contract is honored;
update any docstring as needed but do not provide a default return value in the
abstract def name.
- Around line 64-72: The abstract method list_types currently uses an explicit
ellipsis as its body; make it consistent with the other abstract methods by
removing the ellipsis and leaving the method with just the docstring (i.e.,
implicit pass after the docstring) in the abstract class where list_types is
defined so that the method signature and `@abstractmethod` decorator remain but
the body style matches the others.

In `@src/lfx/src/lfx/services/deployment/schema.py`:
- Around line 27-42: Add a Pydantic validator on BaseFlowArtifact to enforce
that the data field contains required keys "nodes" and "edges" (and that they
are lists) so malformed flow payloads are rejected; implement this by adding a
`@field_validator`("data") method (or `@model_validator` if you prefer whole-model
validation) on the BaseFlowArtifact class that checks data is a dict, verifies
"nodes" and "edges" exist and are list-like, and raises a ValueError with a
clear message when the check fails.

In `@src/lfx/src/lfx/services/deployment/service.py`:
- Around line 46-49: The concrete __init__ calls super().__init__() and
self.set_ready() while other methods in this class raise NotImplementedError,
creating a template pattern that allows instantiation; either make the
initializer abstract to prevent instantiation or keep it concrete but add a
clarifying comment that this class is intentionally instantiable for partial
implementations/tests. Update the class around __init__ and set_ready to reflect
the chosen approach: if preventing instantiation, mark __init__ as abstract (or
the class as abstract) so instantiation fails; if allowing it, add a clear
docstring/comment on __init__ stating that concrete __init__ + abstract methods
is intentional and why.

In `@src/lfx/tests/unit/services/deployment/test_deployment_schema.py`:
- Around line 140-142: Add a unit test that verifies SnapshotItems accepts
raw_payloads=None: create a new test (e.g.,
test_snapshot_items_accepts_none_raw_payload) that constructs
SnapshotItems(raw_payloads=None) and asserts no ValidationError is raised
(optionally assert the instance.raw_payloads is None). This complements the
existing tests that cover required field and empty list rejection and references
the SnapshotItems class and raw_payloads field.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 355c589 and ce42da0.

📒 Files selected for processing (8)
  • src/lfx/src/lfx/services/deployment/__init__.py
  • src/lfx/src/lfx/services/deployment/base.py
  • src/lfx/src/lfx/services/deployment/exceptions.py
  • src/lfx/src/lfx/services/deployment/schema.py
  • src/lfx/src/lfx/services/deployment/service.py
  • src/lfx/src/lfx/services/interfaces.py
  • src/lfx/tests/unit/services/deployment/__init__.py
  • src/lfx/tests/unit/services/deployment/test_deployment_schema.py

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 2, 2026

Codecov Report

❌ Patch coverage is 95.72368% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.27%. Comparing base (d602738) to head (6c349e4).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/lfx/src/lfx/services/deployment/schema.py 94.11% 7 Missing and 6 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #11979      +/-   ##
==========================================
+ Coverage   36.40%   37.27%   +0.86%     
==========================================
  Files        1570     1592      +22     
  Lines       76655    78263    +1608     
  Branches    11629    11821     +192     
==========================================
+ Hits        27910    29176    +1266     
- Misses      47169    47462     +293     
- Partials     1576     1625      +49     
Flag Coverage Δ
backend 57.31% <ø> (+0.90%) ⬆️
frontend 20.49% <ø> (+0.69%) ⬆️
lfx 42.18% <95.72%> (+0.72%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/lfx/src/lfx/services/deployment/base.py 100.00% <100.00%> (ø)
src/lfx/src/lfx/services/deployment/exceptions.py 100.00% <100.00%> (ø)
src/lfx/src/lfx/services/deployment/service.py 100.00% <100.00%> (ø)
src/lfx/src/lfx/services/interfaces.py 100.00% <100.00%> (ø)
src/lfx/src/lfx/services/deployment/schema.py 94.11% <94.11%> (ø)

... and 47 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
… exceptions

  - Add redeploy, duplicate, create_execution, get_execution to DeploymentServiceProtocol so it matches BaseDeploymentService
  - Add @runtime_checkable to DeploymentServiceProtocol
  - Use IdLike alias in base.py, service.py, and interfaces.py instead of
    raw UUID | str
  - Make DeploymentError.error_code required (all subclasses already provide one)
  - Store deployment_id on DeploymentNotFoundError regardless of custom message
  - Add isinstance checks for nodes/edges in BaseFlowArtifact.validate_data
  - Add min_length=1 to BaseFlowArtifact.name
  - Remove redundant provider_data re-declaration from DeploymentStatusResult
  - Add descriptive messages to all NotImplementedError raises in stub service
  - Remove misleading set_ready() from stub DeploymentService
  - Export BaseDeploymentService and DeploymentError from package __init__
  - Fix "Auhtenticated" typo in AuthUserProtocol docstring
  - Parametrize stub method tests to cover all 11 methods
  - Add tests for protocol conformance, get_deployment_create_schema,
    DeploymentNotFoundError.deployment_id, flow name validation, nodes/edges
    type validation, ConfigItem/DeploymentUpdate happy paths
Copy link
Copy Markdown
Collaborator

@jordanrfrazier jordanrfrazier left a comment

Choose a reason for hiding this comment

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

lgtm

@jordanrfrazier jordanrfrazier enabled auto-merge March 2, 2026 23:16
@github-actions github-actions Bot added lgtm This PR has been approved by a maintainer enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 2, 2026
@jordanrfrazier jordanrfrazier added this pull request to the merge queue Mar 2, 2026
Merged via the queue into main with commit 91c016a Mar 2, 2026
87 of 88 checks passed
@jordanrfrazier jordanrfrazier deleted the deployment-schemas-lfx branch March 2, 2026 23:42
HimavarshaVS pushed a commit that referenced this pull request Mar 10, 2026
* checkout deployment serice schemas

* simplify schemas

* internal facing schema improvements and structuring

* add tests

* use string for name property

* address coderabbit suggestions for implementing todos and adding tests

* address claude maximus comments

* remove teardown from base.add tests for uncovered exception classes

* stub db as AsyncSession

* address review findings: align protocol with ABC, tighten schemas and exceptions

  - Add redeploy, duplicate, create_execution, get_execution to DeploymentServiceProtocol so it matches BaseDeploymentService
  - Add @runtime_checkable to DeploymentServiceProtocol
  - Use IdLike alias in base.py, service.py, and interfaces.py instead of
    raw UUID | str
  - Make DeploymentError.error_code required (all subclasses already provide one)
  - Store deployment_id on DeploymentNotFoundError regardless of custom message
  - Add isinstance checks for nodes/edges in BaseFlowArtifact.validate_data
  - Add min_length=1 to BaseFlowArtifact.name
  - Remove redundant provider_data re-declaration from DeploymentStatusResult
  - Add descriptive messages to all NotImplementedError raises in stub service
  - Remove misleading set_ready() from stub DeploymentService
  - Export BaseDeploymentService and DeploymentError from package __init__
  - Fix "Auhtenticated" typo in AuthUserProtocol docstring
  - Parametrize stub method tests to cover all 11 methods
  - Add tests for protocol conformance, get_deployment_create_schema,
    DeploymentNotFoundError.deployment_id, flow name validation, nodes/edges
    type validation, ConfigItem/DeploymentUpdate happy paths

* Add domain-specific exception type

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants