Skip to content

Conversation

@albertsola
Copy link
Contributor

@albertsola albertsola commented Dec 11, 2025

Summary by CodeRabbit

  • New Features

    • Products created during seeding are now automatically published, with enforced state transitions and validation to ensure final published status.
  • Chores

    • Added a log entry indicating successful completion of the seeding process.
  • Tests

    • Added test coverage for the publish workflow to validate status transitions and publish behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 11, 2025

Walkthrough

Adds an async product publication step: publish_product(context, mpt_vendor, mpt_operations) fetches a product, advances Draft to Review, requests publish for Pending/Unpublished via operations client, validates final Published state, and is invoked from seed_product after creation.

Changes

Cohort / File(s) Summary
Product publication workflow
seed/catalog/product.py
Added async def publish_product(context, mpt_vendor, mpt_operations) to fetch product by ID, call vendor review for Draft, call operations publish for Pending/Unpublished, and raise if final status is not Published. seed_product now calls publish_product after creating a product.
Seeding completion logging
seed/seed_api.py
Added logger.info("Seeding completed successfully.") after awaiting seed_accounts() and seed_catalog() within the try block.
Publication workflow tests
tests/seed/catalog/test_product.py
Added test_publish_product that creates Draft/Pending/Published product instances, mocks vendor_client.catalog.products.get, .review, and operations_client.catalog.products.publish, invokes publish_product(...), and asserts the expected get→review→publish call sequence for product id prod-123.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller
    participant publish_product
    participant VendorClient
    participant OpsClient

    Caller->>publish_product: publish_product(context, vendor, ops)
    publish_product->>VendorClient: get(product_id)
    VendorClient-->>publish_product: product (status)

    alt status == Draft
        publish_product->>VendorClient: review(product_id)
        VendorClient-->>publish_product: reviewed (status -> Pending)
        publish_product->>OpsClient: publish(product_id)
        OpsClient-->>publish_product: published (status -> Published)
    else status == Pending or Unpublished
        publish_product->>OpsClient: publish(product_id)
        OpsClient-->>publish_product: published (status -> Published)
    else status == Published
        note right of publish_product: no action required
    end

    publish_product->>publish_product: validate final status == Published
    alt final == Published
        publish_product-->>Caller: return success
    else
        publish_product-->>Caller: raise error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect state-transition logic in seed/catalog/product.py (Draft → Review → Published) and error paths.
  • Verify correct use and mocking of mpt_vendor vs mpt_operations client methods.
  • Confirm seed_product integration point and that new logging in seed/seed_api.py is correctly placed.
  • Review the new test tests/seed/catalog/test_product.py for adequate coverage and correct assertions of call order.

Poem

🐰 I nudged a draft and gave it a shove,
Reviewed with care, then pushed with love.
From quiet Draft to Published light,
I danced a hop into the night. ✨📦

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'MPT-16325 Publish product during the seeding process' clearly and concisely describes the main change: adding a product publication step to the seeding workflow.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch MPT-16325-Product-listing-seeding-fail-due-to-product-not-being-published

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

github-actions bot commented Dec 11, 2025

✅ Found Jira issue key in the title: MPT-16325

Generated by 🚫 dangerJS against ef9fe59

@albertsola albertsola force-pushed the MPT-16325-Product-listing-seeding-fail-due-to-product-not-being-published branch from ed72157 to d8cd2ac Compare December 11, 2025 10:26
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/seed/catalog/test_product.py (1)

32-46: Test design consideration: using the same client for both vendor and operations.

The test passes vendor_client for both the mpt_vendor and mpt_operations parameters (line 41), which doesn't reflect the production scenario where different clients with different permissions are used. While this is acceptable for unit testing the workflow logic, consider whether an integration test with separate client instances would provide additional confidence that the operations client is properly configured.

seed/catalog/product.py (2)

60-67: Consider adding logging for state transitions.

The function performs important state transitions (Draft → Review → Pending → Published) but doesn't log these operations. For a seeding process, logging state transitions would help with debugging and monitoring progress.

For example:

logger.debug(f"Publishing product {product_id}, current status: {product.status}")
if product.status == "Draft":
    logger.debug(f"Submitting product {product_id} for review")
    product = await mpt_vendor.catalog.products.review(product_id)
if product.status in {"Pending", "Unpublished"}:
    logger.debug(f"Publishing product {product_id}")
    product = await mpt_operations.catalog.products.publish(product_id)
logger.debug(f"Product {product_id} published successfully")

67-67: Consider defining a custom exception class.

The static analysis tool suggests avoiding long inline exception messages. While this is a minor style issue, defining a custom exception class would improve consistency and make error handling more maintainable.

For example, you could define:

class ProductPublishError(RuntimeError):
    """Raised when product publication fails."""
    def __init__(self, product_id: str, status: str):
        super().__init__(f"Product {product_id} is not published (status: {status})")
        self.product_id = product_id
        self.status = status

Then use: raise ProductPublishError(product_id, product.status)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5665533 and ed72157.

📒 Files selected for processing (3)
  • seed/catalog/product.py (2 hunks)
  • seed/seed_api.py (1 hunks)
  • tests/seed/catalog/test_product.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
seed/catalog/product.py (4)
seed/context.py (1)
  • Context (12-33)
seed/container.py (1)
  • Container (7-30)
seed/helper.py (1)
  • require_context_id (23-40)
mpt_api_client/resources/catalog/mixins.py (2)
  • publish (25-34)
  • publish (62-71)
seed/seed_api.py (1)
tests/e2e/conftest.py (1)
  • logger (63-64)
🪛 Ruff (0.14.8)
seed/catalog/product.py

67-67: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
seed/seed_api.py (1)

23-23: LGTM!

The completion log message appropriately indicates successful seeding and is correctly placed after both seeding operations complete.

Copy link

@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: 0

♻️ Duplicate comments (2)
seed/catalog/product.py (2)

41-41: This call will fail due to missing @inject decorator on publish_product.

The publish_product() function is invoked without arguments, expecting dependency injection to provide context, mpt_vendor, and mpt_operations. However, the function definition at line 54 is missing the @inject decorator, causing a TypeError at runtime.


54-58: Critical: Missing @inject decorator causes runtime failure.

As flagged in the previous review, the function uses dependency injection with Provide[Container.*] defaults but lacks the @inject decorator. This prevents the DI framework from injecting dependencies when called at line 41, resulting in a TypeError.

Apply this diff:

+@inject
 async def publish_product(
     context: Context = Provide[Container.context],
     mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor],
     mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
 ) -> None:
🧹 Nitpick comments (1)
seed/catalog/product.py (1)

67-67: Optional: Consider extracting error message to a constant.

Static analysis suggests avoiding inline error messages in exception raises for better maintainability and consistency.

Define a constant at module level:

PRODUCT_NOT_PUBLISHED_ERROR = "Product {product_id} is not published"

Then use it:

-        raise RuntimeError(f"Product {product_id} is not published")
+        raise RuntimeError(PRODUCT_NOT_PUBLISHED_ERROR.format(product_id=product_id))

As per static analysis hints.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed72157 and d8cd2ac.

📒 Files selected for processing (3)
  • seed/catalog/product.py (2 hunks)
  • seed/seed_api.py (1 hunks)
  • tests/seed/catalog/test_product.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/seed/catalog/test_product.py
🧰 Additional context used
🧬 Code graph analysis (1)
seed/seed_api.py (1)
tests/e2e/conftest.py (1)
  • logger (63-64)
🪛 Ruff (0.14.8)
seed/catalog/product.py

67-67: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
seed/seed_api.py (1)

23-23: LGTM!

The success log provides clear feedback that the seeding process completed without errors, complementing the existing exception logging on line 25.

seed/catalog/product.py (1)

62-67: The product state transitions are well-defined in the API client. The review() method explicitly transitions to "Pending" (as documented in mpt_api_client/resources/catalog/mixins.py), and publish() transitions to "Published". The codebase only defines four product states: Draft, Pending, Published, and Unpublished. No intermediate states like "UnderReview" or "Rejected" exist, so the state flow logic in lines 62–67 correctly handles all possible product states without risk of skipped steps.

@albertsola albertsola force-pushed the MPT-16325-Product-listing-seeding-fail-due-to-product-not-being-published branch from d8cd2ac to ef9fe59 Compare December 11, 2025 10:38
Copy link

@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: 0

🧹 Nitpick comments (1)
seed/catalog/product.py (1)

54-69: LGTM: Solid publication workflow with correct dependency injection.

The @inject decorator is now present (addressing the previous critical review), and the state transition logic is sound:

  • Fetches the product and advances through Draft→Review→Pending/Unpublished→Publish as needed
  • Final status validation ensures the product reaches Published state
  • Idempotent design handles already-published products gracefully

Optional: Add debug logging for observability.

Consider adding logger.debug statements at key transitions (e.g., "Reviewing product {product_id}", "Publishing product {product_id}") to aid debugging if the seeding fails at the publication step.

 async def publish_product(
     context: Context = Provide[Container.context],
     mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor],
     mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
 ) -> None:
     """Publish product."""
     product_id = require_context_id(context, "catalog.product.id", "publish product")
+    logger.debug("Publishing product %s ...", product_id)
     product = await mpt_vendor.catalog.products.get(product_id)
     if product.status == "Draft":
+        logger.debug("Reviewing product %s (status: Draft)", product_id)
         product = await mpt_vendor.catalog.products.review(product_id)
     if product.status in {"Pending", "Unpublished"}:
+        logger.debug("Publishing product %s (status: %s)", product_id, product.status)
         product = await mpt_operations.catalog.products.publish(product_id)
     if product.status != "Published":
         raise RuntimeError(f"Product {product_id} is not published")
+    logger.debug("Product %s published successfully", product_id)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8cd2ac and ef9fe59.

📒 Files selected for processing (3)
  • seed/catalog/product.py (2 hunks)
  • seed/seed_api.py (1 hunks)
  • tests/seed/catalog/test_product.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/seed/catalog/test_product.py
🧰 Additional context used
🧬 Code graph analysis (1)
seed/seed_api.py (1)
tests/e2e/conftest.py (1)
  • logger (63-64)
🪛 Ruff (0.14.8)
seed/catalog/product.py

68-68: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
seed/seed_api.py (1)

23-23: LGTM: Useful success logging added.

The log statement correctly indicates successful completion of the seeding process and is appropriately placed within the try block after all operations succeed.

seed/catalog/product.py (1)

41-41: LGTM: Product publishing integrated into seeding flow.

The call to publish_product() correctly leverages dependency injection and appropriately sequences the publication step immediately after product creation.

@sonarqubecloud
Copy link

"""Publish product."""
product_id = require_context_id(context, "catalog.product.id", "publish product")
product = await mpt_vendor.catalog.products.get(product_id)
if product.status == "Draft":
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we use a Enum for those statuses?

mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
) -> None:
"""Publish product."""
product_id = require_context_id(context, "catalog.product.id", "publish product")
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use an ActionEnum instead of passing a str? It would avoid having different str for the same action, I can see different patterns like starting with uppercase and other with lowercase

@albertsola albertsola merged commit 2556f5f into main Dec 11, 2025
6 checks passed
@albertsola albertsola deleted the MPT-16325-Product-listing-seeding-fail-due-to-product-not-being-published branch December 11, 2025 15:28
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.

4 participants