Skip to content

Return YAML contents inline from deploy API, remove /yaml endpoint#118

Open
amito wants to merge 3 commits intollm-d-incubation:mainfrom
amito:refactor/deploy-api-response-format
Open

Return YAML contents inline from deploy API, remove /yaml endpoint#118
amito wants to merge 3 commits intollm-d-incubation:mainfrom
amito:refactor/deploy-api-response-format

Conversation

@amito
Copy link
Copy Markdown
Collaborator

@amito amito commented Mar 23, 2026

Description

The deploy endpoints previously returned internal file paths in the response, requiring a second GET /deployments/{id}/yaml round-trip to fetch the actual YAML contents. This leaked backend implementation details and added unnecessary latency for API consumers (including the MCP integration).

generate_all() now captures rendered YAML strings at template render time and returns them in a contents key. All three endpoints that call it (/deploy, /deploy-to-cluster, /recommend) return YAML content directly. The GET /deployments/{id}/yaml endpoint has been removed.

Main changes:

  • generator.py: generate_all() returns a contents dict alongside files
  • configuration.py: /deploy and /deploy-to-cluster return contents; GET /deployments/{id}/yaml removed
  • recommendation.py: /recommend returns contents instead of file paths; error path returns {} instead of [] for type consistency
  • api_client.py: Remove second GET round-trip
  • deployment.py: Remove second GET round-trip; zip download entries use proper filenames ({deployment_id}-{type}.yaml)

How has this been tested?

  • test_yaml_generation.py updated to assert contents key exists, its keys match files, and each value is a non-empty YAML string
  • Full non-DB test suite passes (uv run pytest -q)
  • mypy and ruff clean on all changed files across all commits

Summary by CodeRabbit

  • Improvements
    • Deployment responses now include generated YAML contents directly, removing the need for a follow-up fetch and reducing API round-trips.
    • UI now obtains YAML from the initial deploy response and packages downloads with filenames that include the deployment ID and config type.
  • Bug Fixes
    • Existing HTTP errors during deploy now propagate unchanged.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

Generator now returns rendered YAML contents inline; the API removed the GET /api/v1/deployments/{deployment_id}/yaml endpoint and returns YAML contents in deploy responses; recommendation route, UI client, and tests updated to consume the inline contents mapping instead of reading files from disk.

Changes

Cohort / File(s) Summary
API Route Updates
src/neuralnav/api/routes/configuration.py
Removed GET /api/v1/deployments/{deployment_id}/yaml. deploy_model and deploy_to_cluster now populate response "files" from result["contents"]; added except HTTPException: raise; removed unused glob import.
Recommendation Route
src/neuralnav/api/routes/recommendation.py
simple_recommend now reads auto-generated YAML from yaml_result["contents"] (logging, fallbacks, and response field updated to use yaml_contents).
Generator output shape
src/neuralnav/configuration/generator.py
generate_all() return shape changed to include contents (map: config_type → rendered YAML string) alongside files, deployment_id, and namespace (previous metadata removed).
Client/UI changes
ui/api_client.py, ui/components/deployment.py
Removed follow-up GET /api/v1/deployments/{deployment_id}/yaml; both now consume files/contents directly from the POST /api/v1/deploy response. ZIP download filenames changed to "{deployment_id}-{config_type}.yaml".
Tests
tests/test_yaml_generation.py
Test extended to assert presence of contents, that contents keys match files keys, and each contents[config_type] is a non-empty string; YAML validation still uses files.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant UI as UI Client
participant API as Server API
participant Gen as DeploymentGenerator
participant K8s as Cluster
UI->>API: POST /api/v1/deploy (recommendation)
API->>Gen: generate_all(recommendation, namespace)
Gen-->>API: {deployment_id, files, contents}
API->>API: validate files/contents
API->>K8s: deploy_to_cluster(... contents ...)
K8s-->>API: deployment result
API-->>UI: POST response {success, deployment_id, files: contents, ...}

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main change: returning YAML contents inline from the deploy API and removing the separate /yaml endpoint.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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.

@amito
Copy link
Copy Markdown
Collaborator Author

amito commented Mar 23, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 2

Caution

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

⚠️ Outside diff range comments (1)
src/neuralnav/configuration/generator.py (1)

232-244: ⚠️ Potential issue | 🟡 Minor

Docstring is outdated.

The docstring still mentions metadata in the return description, but the actual return now includes contents instead.

Suggested fix
     def generate_all(
         self, recommendation: DeploymentRecommendation, namespace: str = "default"
     ) -> dict[str, Any]:
         """
         Generate all deployment YAML files.

         Args:
             recommendation: Deployment recommendation
             namespace: Kubernetes namespace

         Returns:
-            Dictionary with deployment_id, namespace, files, and metadata
+            Dictionary with deployment_id, namespace, files (paths), and contents (rendered YAML)
         """
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/neuralnav/configuration/generator.py` around lines 232 - 244, The
generate_all function's docstring return section is stale: it mentions returning
`metadata` but the function now returns `contents`; update the docstring in
generate_all to accurately describe the returned dict (keys like
`deployment_id`, `namespace`, `files`, and `contents`) and adjust the "Returns:"
text to match the current return structure and types; reference the generate_all
method to locate and edit the docstring so callers/readers get correct
documentation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/neuralnav/api/routes/recommendation.py`:
- Line 114: The assignments to result["yaml_files"] are inconsistent: in the
success path (where yaml_contents is used) result["yaml_files"] is a dict, but
in the no-viable-configs error path it’s set to an empty list; update the error
path to assign an empty dict instead of a list so the type remains consistent.
Locate the handlers in recommendation.py (the function handling the
recommendation response flow that sets result["yaml_files"]) and replace the
empty list assignment with an empty dict (or otherwise ensure both paths produce
the same dict-shaped structure).

In `@ui/components/deployment.py`:
- Around line 86-87: The deployment response handler stores inline YAML into
st.session_state.deployment_yaml_files using result.get("files") but the keys
are bare config type names (e.g., "inferenceservice") instead of proper
filenames, which makes downloaded ZIP entries unclear; update the assignment so
keys are normalized to filenames (e.g.,
f"{st.session_state.deployment_id}-inferenceservice.yaml" or append ".yaml" to
each key) before storing in st.session_state.deployment_yaml_files and ensure
the mapping transformation occurs where result.get("files") is processed
(reference st.session_state.deployment_id and the deployment_yaml_files
assignment).

---

Outside diff comments:
In `@src/neuralnav/configuration/generator.py`:
- Around line 232-244: The generate_all function's docstring return section is
stale: it mentions returning `metadata` but the function now returns `contents`;
update the docstring in generate_all to accurately describe the returned dict
(keys like `deployment_id`, `namespace`, `files`, and `contents`) and adjust the
"Returns:" text to match the current return structure and types; reference the
generate_all method to locate and edit the docstring so callers/readers get
correct documentation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c2ef299d-c54d-4bc7-afed-c91b018001ba

📥 Commits

Reviewing files that changed from the base of the PR and between 3bff2da and 2f916a6.

📒 Files selected for processing (6)
  • src/neuralnav/api/routes/configuration.py
  • src/neuralnav/api/routes/recommendation.py
  • src/neuralnav/configuration/generator.py
  • tests/test_yaml_generation.py
  • ui/api_client.py
  • ui/components/deployment.py

Comment thread src/neuralnav/api/routes/recommendation.py
Comment thread ui/components/deployment.py
@amito amito force-pushed the refactor/deploy-api-response-format branch from 2f916a6 to b597049 Compare March 23, 2026 08:57
@amito
Copy link
Copy Markdown
Collaborator Author

amito commented Mar 23, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@amito amito marked this pull request as ready for review March 23, 2026 19:31
@amito amito force-pushed the refactor/deploy-api-response-format branch from b597049 to 4828da7 Compare March 23, 2026 20:13
@amito amito force-pushed the refactor/deploy-api-response-format branch from 4828da7 to 8787fc7 Compare March 26, 2026 16:30
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.

🧹 Nitpick comments (1)
src/neuralnav/api/routes/configuration.py (1)

83-104: Match the typed API contract to the new inline-YAML payload.

Switching these handlers to result["contents"] is the right runtime change, but the declared contract still lags behind it: DeploymentResponse.files is still dict[str, Any], and /deploy-to-cluster still returns an untyped dict. Tightening those to dict[str, str] and adding a response model for the cluster path would keep OpenAPI/docs/generated clients aligned with the new behavior.

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

Also applies to: 265-270

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

In `@src/neuralnav/api/routes/configuration.py` around lines 83 - 104, The API
contract still declares DeploymentResponse.files as dict[str, Any] while the
handlers now return inline YAML in result["contents"] (dict[str, str]); update
the DeploymentResponse model to files: dict[str, str] and adjust any other
response types that return the raw dict (e.g., the /deploy-to-cluster route
handler) to use a concrete response model matching the new payload; ensure the
route decorator/return annotation references the updated model so OpenAPI/docs
and generated clients reflect dict[str, str].
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/neuralnav/api/routes/configuration.py`:
- Around line 83-104: The API contract still declares DeploymentResponse.files
as dict[str, Any] while the handlers now return inline YAML in
result["contents"] (dict[str, str]); update the DeploymentResponse model to
files: dict[str, str] and adjust any other response types that return the raw
dict (e.g., the /deploy-to-cluster route handler) to use a concrete response
model matching the new payload; ensure the route decorator/return annotation
references the updated model so OpenAPI/docs and generated clients reflect
dict[str, str].

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8099020c-dbe1-48e1-a182-2d18dfd6b9ec

📥 Commits

Reviewing files that changed from the base of the PR and between 4828da7 and 8787fc7.

📒 Files selected for processing (6)
  • src/neuralnav/api/routes/configuration.py
  • src/neuralnav/api/routes/recommendation.py
  • src/neuralnav/configuration/generator.py
  • tests/test_yaml_generation.py
  • ui/api_client.py
  • ui/components/deployment.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/test_yaml_generation.py
  • src/neuralnav/api/routes/recommendation.py
  • ui/components/deployment.py
  • ui/api_client.py
  • src/neuralnav/configuration/generator.py

namasl pushed a commit that referenced this pull request Mar 26, 2026
Signed-off-by: rudeigerc <rudeigerc@gmail.com>
@amito amito force-pushed the refactor/deploy-api-response-format branch 2 times, most recently from c3b3c30 to cc570eb Compare March 30, 2026 13:12
amito added 3 commits April 14, 2026 22:55
generate_all() now returns rendered YAML strings in a 'contents' key
alongside file paths. The /deploy, /deploy-to-cluster, and /recommend
endpoints return YAML contents instead of internal file paths,
eliminating the need for a separate GET call. Removes GET
/deployments/{id}/yaml endpoint.

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Amit Oren <amoren@redhat.com>
Assert that the 'contents' key exists, its keys match 'files', and
values are non-empty strings.

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Amit Oren <amoren@redhat.com>
Remove second GET /deployments/{id}/yaml round-trip from both
api_client.deploy_and_generate_yaml() and the deployment component.
YAML contents are now read directly from the deploy response. Zip
download entries use proper filenames ({deployment_id}-{type}.yaml).

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Amit Oren <amoren@redhat.com>
@amito amito force-pushed the refactor/deploy-api-response-format branch from cc570eb to c3d3d31 Compare April 14, 2026 19:56
@amito amito requested a review from anfredette April 16, 2026 12:51
Copy link
Copy Markdown
Collaborator

@anfredette anfredette left a comment

Choose a reason for hiding this comment

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

Just a couple of nits for readability since this changed from files to YAML content. Otherwise, LGTM.

"deployment_id": deployment_id,
"namespace": request.namespace,
"files": files,
"files": result["contents"],
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
"files": result["contents"],
"yaml_contents": result["contents"],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we change "files" to "yaml_contents" here and on lines 38 and 104 above?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also, another nit for readability, for files = result["files"] at line 238, renaming the files variable to file_paths would be a little more clear.

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.

2 participants