Skip to content

Hotfix v6.0.1 into Main#592

Merged
bedanley merged 7 commits into
mainfrom
hotfix/v6.0.1
Dec 9, 2025
Merged

Hotfix v6.0.1 into Main#592
bedanley merged 7 commits into
mainfrom
hotfix/v6.0.1

Conversation

@github-actions
Copy link
Copy Markdown

@github-actions github-actions Bot commented Dec 5, 2025

Hotfix v6.0.1 PR into Main

Summary (generated)

Summary of Changes - Hotfix v6.0.1

Overview

This hotfix v6.0.1 includes configuration updates, API behavior modifications, security enhancements, and UI adjustments across multiple components of the application.

Key Changes by Category

1. FastAPI Container & Prisma Caching

  • Files Modified: lib/api-base/fastApiContainer.ts, lib/schema/configSchema.ts, lib/serve/rest-api/Dockerfile
  • Changes: Replaced NODEENV_CACHE_DIR with PRISMA_CACHE_DIR environment variable
  • Impact: Enhanced Prisma dependency pre-caching logic with conditional fallback for offline Docker deployments
  • Documentation: Expanded deployment guide with instructions for pre-populating platform-specific Prisma binary caches (~/.cache/prisma/ and ~/.cache/prisma-python/)

2. RTK Query Refetching Behavior

  • Files Modified: Eight reducer files in lib/user-interface/react/src/shared/reducers/
    • configuration.reducer.ts
    • mcp-server.reducer.ts
    • mcp-tools.reducer.ts
    • model-management.reducer.ts
    • prompt-templates.reducer.ts
    • rag.reducer.ts
    • session.reducer.ts
    • user-preferences.reducer.ts
  • Changes: Replaced refetchOnReconnect: true with refetchOnMountOrArgChange: true
  • Impact: Alters cached data invalidation and refresh timing throughout the React application lifecycle

3. Model Management Security

  • Files Modified: lambda/models/lambda_functions.py, test/lambda/test_models_lambda.py
  • Changes:
    • Added admin permission validation to model management endpoints
    • Implemented new get_admin_status_and_groups() utility function
    • Admin-only endpoints (create, update, delete) now enforce authorization
    • Returns 403 Forbidden for unauthorized access
  • Impact: Enhanced security with role-based access control for model operations

4. Admin UI Menu

  • Files Modified: cypress/src/support/adminHelpers.ts
  • Changes: Removed 'MCP Workbench' menu item from admin menu expansion
  • Remaining Options: Model Management, RAG Management, MCP Management

External Interface Changes

  • Build configuration now recognizes PRISMA_CACHE_DIR instead of NODEENV_CACHE_DIR
  • API endpoints enforce admin authorization requirements
  • React application data refresh behavior modified for mount and argument changes

@github-actions
Copy link
Copy Markdown
Author

github-actions Bot commented Dec 5, 2025

Summary of Changes - Hotfix v6.0.1

Overview

This hotfix v6.0.1 includes configuration updates, API behavior modifications, security enhancements, and UI adjustments across multiple components of the application.

Key Changes by Category

1. FastAPI Container & Prisma Caching

  • Files Modified: lib/api-base/fastApiContainer.ts, lib/schema/configSchema.ts, lib/serve/rest-api/Dockerfile
  • Changes: Replaced NODEENV_CACHE_DIR with PRISMA_CACHE_DIR environment variable
  • Impact: Enhanced Prisma dependency pre-caching logic with conditional fallback for offline Docker deployments
  • Documentation: Expanded deployment guide with instructions for pre-populating platform-specific Prisma binary caches (~/.cache/prisma/ and ~/.cache/prisma-python/)

2. RTK Query Refetching Behavior

  • Files Modified: Eight reducer files in lib/user-interface/react/src/shared/reducers/
    • configuration.reducer.ts
    • mcp-server.reducer.ts
    • mcp-tools.reducer.ts
    • model-management.reducer.ts
    • prompt-templates.reducer.ts
    • rag.reducer.ts
    • session.reducer.ts
    • user-preferences.reducer.ts
  • Changes: Replaced refetchOnReconnect: true with refetchOnMountOrArgChange: true
  • Impact: Alters cached data invalidation and refresh timing throughout the React application lifecycle

3. Model Management Security

  • Files Modified: lambda/models/lambda_functions.py, test/lambda/test_models_lambda.py
  • Changes:
    • Added admin permission validation to model management endpoints
    • Implemented new get_admin_status_and_groups() utility function
    • Admin-only endpoints (create, update, delete) now enforce authorization
    • Returns 403 Forbidden for unauthorized access
  • Impact: Enhanced security with role-based access control for model operations

4. Admin UI Menu

  • Files Modified: cypress/src/support/adminHelpers.ts
  • Changes: Removed 'MCP Workbench' menu item from admin menu expansion
  • Remaining Options: Model Management, RAG Management, MCP Management

External Interface Changes

  • Build configuration now recognizes PRISMA_CACHE_DIR instead of NODEENV_CACHE_DIR
  • API endpoints enforce admin authorization requirements
  • React application data refresh behavior modified for mount and argument changes

Copy link
Copy Markdown
Author

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Commits Files that changed from the base of the PR and between d2711b9 and e89fe82 commits.
Files selected (6)
  • lib/api-base/fastApiContainer.ts (1)
  • lib/docs/admin/deploy.md (2)
  • lib/schema/configSchema.ts (1)
  • lib/serve/rest-api/Dockerfile (2)
  • lib/serve/rest-api/NODEENV_CACHE/.gitkeep (1)
  • lib/serve/rest-api/PRISMA_CACHE/.gitkeep (1)
Files ignored due to filter (3)
  • lib/user-interface/react/package.json
  • lisa-sdk/pyproject.toml
  • package.json
Files skipped from review due to trivial changes (2)
  • lib/serve/rest-api/NODEENV_CACHE/.gitkeep
  • lib/serve/rest-api/PRISMA_CACHE/.gitkeep
Review comments generated (4)
  • Review: 4
  • LGTM: 0

Tips

Chat with AI reviewer (/reviewbot)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging /reviewbot in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add /reviewbot: ignore anywhere in the PR description to pause further reviews from the bot.

Comment thread lib/docs/admin/deploy.md Outdated
Copy link
Copy Markdown
Author

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Commits Files that changed from the base of the PR and between e89fe82 and 143c680 commits.
Files selected (1)
  • lib/docs/admin/deploy.md (2)
Review comments generated (2)
  • Review: 2
  • LGTM: 0

Tips

Chat with AI reviewer (/reviewbot)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging /reviewbot in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add /reviewbot: ignore anywhere in the PR description to pause further reviews from the bot.

@dustins dustins changed the base branch from main to release/v6.0.0 December 5, 2025 03:59
@dustins dustins changed the base branch from release/v6.0.0 to main December 5, 2025 03:59
Copy link
Copy Markdown
Author

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Commits Files that changed from the base of the PR and between d2711b9 and 5a9ef2a commits.
Files selected (6)
  • lib/api-base/fastApiContainer.ts (1)
  • lib/docs/admin/deploy.md (2)
  • lib/schema/configSchema.ts (1)
  • lib/serve/rest-api/Dockerfile (2)
  • lib/serve/rest-api/NODEENV_CACHE/.gitkeep (1)
  • lib/serve/rest-api/PRISMA_CACHE/.gitkeep (1)
Files ignored due to filter (3)
  • lib/user-interface/react/package.json
  • lisa-sdk/pyproject.toml
  • package.json
Files skipped from review due to trivial changes (2)
  • lib/serve/rest-api/NODEENV_CACHE/.gitkeep
  • lib/serve/rest-api/PRISMA_CACHE/.gitkeep
Review comments generated (5)
  • Review: 5
  • LGTM: 0

Tips

Chat with AI reviewer (/reviewbot)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging /reviewbot in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add /reviewbot: ignore anywhere in the PR description to pause further reviews from the bot.

Comment thread lib/schema/configSchema.ts
Comment thread lib/docs/admin/deploy.md
Comment thread lib/docs/admin/deploy.md
Comment thread lib/serve/rest-api/Dockerfile
Comment thread lib/serve/rest-api/Dockerfile
bedanley
bedanley previously approved these changes Dec 5, 2025
Copy link
Copy Markdown
Author

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Commits Files that changed from the base of the PR and between 5a9ef2a and afe2355 commits.
Files selected (8)
  • lib/user-interface/react/src/shared/reducers/configuration.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/mcp-server.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/mcp-tools.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/model-management.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/prompt-templates.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/rag.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/session.reducer.ts (1)
  • lib/user-interface/react/src/shared/reducers/user-preferences.reducer.ts (1)
Review comments generated (0)
  • Review: 0
  • LGTM: 0

Tips

Chat with AI reviewer (/reviewbot)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging /reviewbot in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add /reviewbot: ignore anywhere in the PR description to pause further reviews from the bot.

Copy link
Copy Markdown
Author

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Commits Files that changed from the base of the PR and between afe2355 and 0ffe169 commits.
Files selected (2)
  • lambda/models/lambda_functions.py (6)
  • test/lambda/test_models_lambda.py (9)
Review comments generated (14)
  • Review: 14
  • LGTM: 0

Tips

Chat with AI reviewer (/reviewbot)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging /reviewbot in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add /reviewbot: ignore anywhere in the PR description to pause further reviews from the bot.

Comment on lines +64 to +76
def get_admin_status_and_groups(request: Request) -> tuple[bool, list[str]]:
admin_status = False
user_groups = []

if "aws.event" in request.scope:
event = request.scope["aws.event"]
try:
user_groups = get_groups(event)
admin_status = is_admin(event)
except Exception:
user_groups = []
admin_status = False
return admin_status, user_groups
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The get_admin_status_and_groups() function silently catches all exceptions and returns default values. This could mask legitimate errors (e.g., network issues, malformed event data). Consider logging the exception or being more specific about which exceptions to catch.

Suggested change
def get_admin_status_and_groups(request: Request) -> tuple[bool, list[str]]:
admin_status = False
user_groups = []
if "aws.event" in request.scope:
event = request.scope["aws.event"]
try:
user_groups = get_groups(event)
admin_status = is_admin(event)
except Exception:
user_groups = []
admin_status = False
return admin_status, user_groups
def get_admin_status_and_groups(request: Request) -> tuple[bool, list[str]]:
admin_status = False
user_groups = []
if "aws.event" in request.scope:
event = request.scope["aws.event"]
try:
user_groups = get_groups(event)
admin_status = is_admin(event)
except (KeyError, ValueError, TypeError):
user_groups = []
admin_status = False
return admin_status, user_groups

Comment on lines +107 to +109
admin_status, _ = get_admin_status_and_groups(request)
if not admin_status:
raise HTTPException(status_code=403, detail="User does not have permission to create models.")
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The authorization check uses a generic error message. Consider including more context about what permissions are required or suggesting next steps for the user.


import boto3
import pytest
from fastapi import HTTPException, Request
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The HTTPException import is added here but should be verified that it's used consistently throughout the test file. Ensure this import is necessary for the test cases that follow.

Comment on lines +51 to +61
from models.lambda_functions import (
app,
create_model,
delete_model,
get_admin_status_and_groups,
get_instances,
model_not_found_handler,
update_model,
user_error_handler,
validation_exception_handler,
)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The import of get_admin_status_and_groups from models.lambda_functions is added here. This is appropriate for the new authorization tests, but verify that this function is actually exported from the module and not just used internally.

Comment on lines 569 to 572
"""Test exception handlers."""
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from models.lambda_functions import model_not_found_handler, user_error_handler, validation_exception_handler

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The imports have been moved from the function signature to inside the function body. While this works, ensure this pattern is consistent with the rest of the test file. The previous version had these imports at the module level within the function, which is acceptable for test isolation.

Comment on lines +801 to +837
with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups:
mock_is_admin.return_value = True
mock_get_groups.return_value = ["admin-group"]

admin_status, user_groups = get_admin_status_and_groups(mock_request)
assert admin_status is True
assert user_groups == ["admin-group"]

# Test with non-admin event
non_admin_event = {
"requestContext": {
"authorizer": {
"username": "regular-user",
"groups": json.dumps(["user-group"]),
}
}
}

mock_request.scope = {"aws.event": non_admin_event}

with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups:
mock_is_admin.return_value = False
mock_get_groups.return_value = ["user-group"]

admin_status, user_groups = get_admin_status_and_groups(mock_request)
assert admin_status is False
assert user_groups == ["user-group"]

# Test with no event in scope
mock_request.scope = {}
admin_status, user_groups = get_admin_status_and_groups(mock_request)
assert admin_status is False
assert user_groups == []
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The test patches is_admin and get_groups functions, but these are being mocked at the module level. Verify that these functions are actually called within get_admin_status_and_groups in the implementation, otherwise the mocks won't validate the actual behavior.

Comment on lines +841 to +863
async def test_create_model_admin_required(
sample_model, model_table, mock_autoscaling_client, mock_stepfunctions_client, admin_event, non_admin_event
):
"""Test that create_model endpoint requires admin access."""

# Test non-admin cannot create
mock_request = MagicMock(spec=Request)
mock_request.scope = {"aws.event": non_admin_event}

create_request = CreateModelRequest(
modelId="test-model", modelName="test-model", modelType=ModelType.TEXTGEN, streaming=True
)

with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups:
mock_is_admin.return_value = False
mock_get_groups.return_value = []

with pytest.raises(HTTPException) as exc_info:
await create_model(create_request, mock_request)
assert exc_info.value.status_code == 403
assert "User does not have permission to create models" in str(exc_info.value.detail)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The test for test_create_model_admin_required patches is_admin and get_groups but doesn't verify that get_admin_status_and_groups is actually called. Consider adding a verification that the helper function is invoked:

Suggested change
async def test_create_model_admin_required(
sample_model, model_table, mock_autoscaling_client, mock_stepfunctions_client, admin_event, non_admin_event
):
"""Test that create_model endpoint requires admin access."""
# Test non-admin cannot create
mock_request = MagicMock(spec=Request)
mock_request.scope = {"aws.event": non_admin_event}
create_request = CreateModelRequest(
modelId="test-model", modelName="test-model", modelType=ModelType.TEXTGEN, streaming=True
)
with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups:
mock_is_admin.return_value = False
mock_get_groups.return_value = []
with pytest.raises(HTTPException) as exc_info:
await create_model(create_request, mock_request)
assert exc_info.value.status_code == 403
assert "User does not have permission to create models" in str(exc_info.value.detail)
with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups, patch(
"models.lambda_functions.get_admin_status_and_groups"
) as mock_get_admin_status:
mock_is_admin.return_value = False
mock_get_groups.return_value = []
mock_get_admin_status.return_value = (False, [])
with pytest.raises(HTTPException) as exc_info:
await create_model(create_request, mock_request)
assert exc_info.value.status_code == 403
assert "User does not have permission to create models" in str(exc_info.value.detail)
mock_get_admin_status.assert_called_once_with(mock_request)

Comment on lines +867 to +887
async def test_update_model_admin_required(
sample_model, model_table, mock_autoscaling_client, mock_stepfunctions_client, admin_event, non_admin_event
):
"""Test that update_model endpoint requires admin access."""

# Test non-admin cannot update
mock_request = MagicMock(spec=Request)
mock_request.scope = {"aws.event": non_admin_event}

update_request = UpdateModelRequest(streaming=False)

with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups:
mock_is_admin.return_value = False
mock_get_groups.return_value = []

with pytest.raises(HTTPException) as exc_info:
await update_model("test-model", update_request, mock_request)
assert exc_info.value.status_code == 403
assert "User does not have permission to update models" in str(exc_info.value.detail)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Similar to the create model test, consider mocking get_admin_status_and_groups directly and verifying it's called, rather than mocking its internal dependencies.

Comment on lines +891 to +909
async def test_delete_model_admin_required(
sample_model, model_table, mock_autoscaling_client, mock_stepfunctions_client, admin_event, non_admin_event
):
"""Test that delete_model endpoint requires admin access."""

# Test non-admin cannot delete
mock_request = MagicMock(spec=Request)
mock_request.scope = {"aws.event": non_admin_event}

with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups:
mock_is_admin.return_value = False
mock_get_groups.return_value = []

with pytest.raises(HTTPException) as exc_info:
await delete_model("test-model", mock_request)
assert exc_info.value.status_code == 403
assert "User does not have permission to delete models" in str(exc_info.value.detail)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Same pattern as above - consider mocking get_admin_status_and_groups directly for consistency and clearer test intent.

Comment on lines +913 to +994
async def test_create_update_delete_admin_allowed(
sample_model, model_table, mock_autoscaling_client, mock_stepfunctions_client, admin_event
):
"""Test that admin users can successfully create, update, and delete models."""

mock_request = MagicMock(spec=Request)
mock_request.scope = {"aws.event": admin_event}

with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups, patch("models.lambda_functions.CreateModelHandler") as mock_create_handler, patch(
"models.lambda_functions.UpdateModelHandler"
) as mock_update_handler, patch(
"models.lambda_functions.DeleteModelHandler"
) as mock_delete_handler:
mock_is_admin.return_value = True
mock_get_groups.return_value = ["admin-group"]

# Mock create handler
create_handler_instance = MagicMock()
create_model_response = CreateModelResponse(
model=LISAModel(
modelId="new-model",
modelName="new-model-name",
modelType=ModelType.TEXTGEN,
status=ModelStatus.CREATING,
streaming=True,
)
)
create_handler_instance.return_value = create_model_response
mock_create_handler.return_value = create_handler_instance

# Test admin can create
create_request = CreateModelRequest(
modelId="test-model", modelName="test-model", modelType=ModelType.TEXTGEN, streaming=True
)
response = await create_model(create_request, mock_request)
assert isinstance(response, CreateModelResponse)
assert response.model.modelId == "new-model"

# Mock update handler
model_table.put_item(Item=sample_model)
update_handler_instance = MagicMock()
update_model_response = UpdateModelResponse(
model=LISAModel(
modelId="test-model",
modelName="gpt-3.5-turbo",
modelType=ModelType.TEXTGEN,
status=ModelStatus.IN_SERVICE,
streaming=False,
features=[{"name": "test-feature", "overview": "This is a test feature"}],
)
)
update_handler_instance.return_value = update_model_response
mock_update_handler.return_value = update_handler_instance

# Test admin can update
update_request = UpdateModelRequest(streaming=False)
response = await update_model("test-model", update_request, mock_request)
assert isinstance(response, UpdateModelResponse)
assert response.model.modelId == "test-model"

# Mock delete handler
delete_handler_instance = MagicMock()
delete_model_response = DeleteModelResponse(
model=LISAModel(
modelId="test-model",
modelName="gpt-3.5-turbo",
modelType=ModelType.TEXTGEN,
status=ModelStatus.DELETING,
streaming=True,
features=[{"name": "test-feature", "overview": "This is a test feature"}],
)
)
delete_handler_instance.return_value = delete_model_response
mock_delete_handler.return_value = delete_handler_instance

# Test admin can delete
response = await delete_model("test-model", mock_request)
assert isinstance(response, DeleteModelResponse)
assert response.model.modelId == "test-model"
assert response.model.status == ModelStatus.DELETING
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The test test_create_update_delete_admin_allowed mocks is_admin and get_groups separately rather than using get_admin_status_and_groups. For consistency with the authorization tests above, consider using the helper function mock directly:

Suggested change
async def test_create_update_delete_admin_allowed(
sample_model, model_table, mock_autoscaling_client, mock_stepfunctions_client, admin_event
):
"""Test that admin users can successfully create, update, and delete models."""
mock_request = MagicMock(spec=Request)
mock_request.scope = {"aws.event": admin_event}
with patch("models.lambda_functions.is_admin") as mock_is_admin, patch(
"models.lambda_functions.get_groups"
) as mock_get_groups, patch("models.lambda_functions.CreateModelHandler") as mock_create_handler, patch(
"models.lambda_functions.UpdateModelHandler"
) as mock_update_handler, patch(
"models.lambda_functions.DeleteModelHandler"
) as mock_delete_handler:
mock_is_admin.return_value = True
mock_get_groups.return_value = ["admin-group"]
# Mock create handler
create_handler_instance = MagicMock()
create_model_response = CreateModelResponse(
model=LISAModel(
modelId="new-model",
modelName="new-model-name",
modelType=ModelType.TEXTGEN,
status=ModelStatus.CREATING,
streaming=True,
)
)
create_handler_instance.return_value = create_model_response
mock_create_handler.return_value = create_handler_instance
# Test admin can create
create_request = CreateModelRequest(
modelId="test-model", modelName="test-model", modelType=ModelType.TEXTGEN, streaming=True
)
response = await create_model(create_request, mock_request)
assert isinstance(response, CreateModelResponse)
assert response.model.modelId == "new-model"
# Mock update handler
model_table.put_item(Item=sample_model)
update_handler_instance = MagicMock()
update_model_response = UpdateModelResponse(
model=LISAModel(
modelId="test-model",
modelName="gpt-3.5-turbo",
modelType=ModelType.TEXTGEN,
status=ModelStatus.IN_SERVICE,
streaming=False,
features=[{"name": "test-feature", "overview": "This is a test feature"}],
)
)
update_handler_instance.return_value = update_model_response
mock_update_handler.return_value = update_handler_instance
# Test admin can update
update_request = UpdateModelRequest(streaming=False)
response = await update_model("test-model", update_request, mock_request)
assert isinstance(response, UpdateModelResponse)
assert response.model.modelId == "test-model"
# Mock delete handler
delete_handler_instance = MagicMock()
delete_model_response = DeleteModelResponse(
model=LISAModel(
modelId="test-model",
modelName="gpt-3.5-turbo",
modelType=ModelType.TEXTGEN,
status=ModelStatus.DELETING,
streaming=True,
features=[{"name": "test-feature", "overview": "This is a test feature"}],
)
)
delete_handler_instance.return_value = delete_model_response
mock_delete_handler.return_value = delete_handler_instance
# Test admin can delete
response = await delete_model("test-model", mock_request)
assert isinstance(response, DeleteModelResponse)
assert response.model.modelId == "test-model"
assert response.model.status == ModelStatus.DELETING
with patch("models.lambda_functions.get_admin_status_and_groups") as mock_get_admin_status, patch("models.lambda_functions.CreateModelHandler") as mock_create_handler, patch(
"models.lambda_functions.UpdateModelHandler"
) as mock_update_handler, patch(
"models.lambda_functions.DeleteModelHandler"
) as mock_delete_handler:
mock_get_admin_status.return_value = (True, ["admin-group"])

Copy link
Copy Markdown
Author

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Commits Files that changed from the base of the PR and between 0ffe169 and 7b1a9e0 commits.
Files selected (1)
  • cypress/src/support/adminHelpers.ts (1)
Review comments generated (0)
  • Review: 0
  • LGTM: 0

Tips

Chat with AI reviewer (/reviewbot)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging /reviewbot in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add /reviewbot: ignore anywhere in the PR description to pause further reviews from the bot.

@estohlmann estohlmann marked this pull request as ready for review December 5, 2025 19:17
bedanley
bedanley previously approved these changes Dec 8, 2025
@bedanley bedanley merged commit ad62c27 into main Dec 9, 2025
14 of 16 checks passed
@bedanley bedanley deleted the hotfix/v6.0.1 branch December 9, 2025 23:25
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.

3 participants