Skip to content

Conversation

@HimavarshaVS
Copy link
Collaborator

@HimavarshaVS HimavarshaVS commented Oct 3, 2025

Description

Issue was raised that, despite setting LANGFLOW_DATABASE_URL in .env file, it is defaulting to sqlite.

Root cause

Pydantic settings inside lfx/settings/base.py was instantiated even before env variables are loaded when starting langflow

Fix

Make sure env variables are loaded when calling settingservice if doesn't exist already.

Testing

Before : #9795
After :
image
image

Summary by CodeRabbit

  • New Features

    • Automatically loads configuration from a .env file (if present) without overriding existing environment variables.
    • Enables async MySQL connectivity via a new runtime dependency.
  • Tests

    • Added a unit test to validate environment-driven settings loading.
  • Chores

    • Included aiomysql as a runtime dependency.
  • Style

    • Minor formatting cleanup with no impact on behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 3, 2025

Walkthrough

Introduces dotenv-based environment loading in SettingsService initialization, adds new SettingsService methods, adds aiomysql dependency, and creates a unit test validating environment-driven settings. Also performs a minor formatting cleanup in a CLI entrypoint.

Changes

Cohort / File(s) Summary of changes
CLI formatting
src/backend/base/langflow/__main__.py
Removed an extra blank line; no logic changes.
Tests: settings env
src/backend/tests/unit/services/database/test_vertex_builds.py
Added test_settings_from_env to validate settings populated from environment variables, including database URL and vertex build limits.
Dependencies
src/lfx/pyproject.toml
Added runtime dependency: aiomysql >=0.2.0,<1.0.0.
SettingsService init and dotenv
src/lfx/src/lfx/services/settings/service.py
Added one-time .env auto-loading using python-dotenv if .env exists in CWD. Introduced/updated SettingsService with __init__, initialize (classmethod), set, and async teardown.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App
  participant SettingsService
  participant Env as OS Env
  participant DotEnv as .env Loader

  App->>SettingsService: initialize()
  activate SettingsService
  alt First import and .env present
    SettingsService->>DotEnv: load(.env, override=false)
    Note right of DotEnv: Loads variables if not already set
  else Already loaded or .env missing
    Note right of SettingsService: Skip dotenv load
  end
  SettingsService->>Env: read existing env vars
  SettingsService-->>App: SettingsService(settings, auth_settings)
  deactivate SettingsService
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement, size:L, lgtm

Suggested reviewers

  • jordanrfrazier
  • rjordanfrazier

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Test File Naming And Structure ⚠️ Warning The backend test file is correctly named test_vertex_builds.py and uses pytest-style functions, yet the new test test_settings_from_env only verifies a happy path and lacks negative or edge-case coverage such as unset environment variables or invalid values, and there is no additional structure (fixtures or teardown) to manage test-specific environment mutations which could leak state. Consequently, the current test additions do not satisfy the comprehensive scenario coverage required by the custom check. Please extend the test suite to include negative and edge-case scenarios (e.g., missing or malformed environment variables) and ensure any environment changes are properly isolated or cleaned up so that the tests align with the required structure and coverage expectations.
✅ Passed checks (6 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Test Coverage For New Implementations ✅ Passed I reviewed the bug fix ensuring .env variables load before settings initialization and verified that the PR adds test_settings_from_env in src/backend/tests/unit/services/database/test_vertex_builds.py, which patches the relevant environment variables and asserts the updated settings values, thereby covering the regression. No other new functionality was introduced, so no additional tests are required. The new test follows the project’s naming convention and directly exercises the new environment-loading behavior rather than serving as a placeholder.
Test Quality And Coverage ✅ Passed The PR adds new logic to load environment variables before initializing settings and introduces a new unit test test_settings_from_env in src/backend/tests/unit/services/database/test_vertex_builds.py that explicitly validates the primary behavior of this change by asserting that configuration values sourced from the environment are correctly reflected in the settings. The test uses pytest’s monkeypatch fixture for environment manipulation, structurally aligns with the project’s backend testing patterns, and verifies substantive behavior rather than acting as a smoke test; it also exercises the asynchronous service initialization by awaiting SettingsService.initialize(), which is appropriate for the async context even though no API endpoints are touched, so error-handling coverage is not directly relevant.
Excessive Mock Usage Warning ✅ Passed I inspected the modified unit test test_settings_from_env in src/backend/tests/unit/services/database/test_vertex_builds.py and found that it relies solely on monkeypatch to set environment variables without introducing any mock objects. No other mocks were added or present in the surrounding context, so the test exercises real behavior of the settings loader without obscuring interactions.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the core change, namely fixing the inability to load the database URL from environment variables, and directly reflects the main issue addressed by the pull request.
✨ 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 bug-9795

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.

@HimavarshaVS HimavarshaVS force-pushed the bug-9795 branch 2 times, most recently from 8e5db2d to 25eabd3 Compare October 3, 2025 15:23
@HimavarshaVS HimavarshaVS marked this pull request as ready for review October 3, 2025 15:26
@HimavarshaVS HimavarshaVS changed the title Fix : Unable to load DB url Fix : Unable to load DB url from .env Oct 3, 2025
Copy link
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.

Actionable comments posted: 3

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/settings/service.py (1)

44-46: Risk of bypassing Pydantic validators with setattr.

Using setattr(self.settings, key, value) on a Pydantic Settings instance may not reliably trigger field validators and could bypass validation logic, even with validate_assignment=True.

Consider using direct attribute assignment or Pydantic's model_copy(update={...}) to ensure validators run:

     def set(self, key, value):
-        setattr(self.settings, key, value)
-        return self.settings
+        # Trigger Pydantic validation by direct assignment
+        if hasattr(self.settings, key):
+            setattr(self.settings, key, value)
+        else:
+            msg = f"Invalid settings key: {key}"
+            raise AttributeError(msg)
+        return self.settings

Alternatively, validate the input before assignment or document this behavior if intentional.

🧹 Nitpick comments (3)
src/lfx/src/lfx/services/settings/service.py (2)

13-19: LGTM with minor suggestions for clarity and consistency.

The dotenv loading logic correctly prevents duplicate loads and respects existing environment variables (override=False). However, consider these improvements:

  1. Guard logging placement: The debug log "Loading .env file inside lfx settings service" is emitted even if no .env exists. Move it inside the if env_file.exists(): block to avoid misleading logs.

  2. Guard value consistency: The guard is checked with os.environ.get("_LANGFLOW_DOTENV_LOADED") (returns string or None) and set to "1". While functional, using a consistent sentinel (e.g., "true" or checking in os.environ) improves readability.

Apply this diff to improve logging clarity:

 # Load .env file if it exists
 if not os.environ.get("_LANGFLOW_DOTENV_LOADED"):
-    logger.debug("Loading .env file inside lfx settings service")
     env_file = Path.cwd() / ".env"
     if env_file.exists():
+        logger.debug("Loading .env file inside lfx settings service")
         load_dotenv(env_file, override=False)
         os.environ["_LANGFLOW_DOTENV_LOADED"] = "1"

30-42: Remove orphaned comment and verify config_dir check necessity.

  1. Orphaned comment (Line 32): The comment "Check if a string is a valid path or a file name" is not followed by any related logic. Either remove it or complete the intended check.

  2. config_dir validation (Lines 35-37): According to the Settings class in base.py, the set_langflow_dir validator sets a default config_dir using platformdirs.user_cache_dir. This check may be redundant unless the validator can fail or be bypassed.

Apply this diff to remove the orphaned comment:

     @classmethod
     def initialize(cls) -> SettingsService:
-        # Check if a string is a valid path or a file name
-
         settings = Settings()
         if not settings.config_dir:

If the config_dir check is truly defensive, add a comment explaining when it might be None despite the validator.

src/backend/tests/unit/services/database/test_vertex_builds.py (1)

319-336: Test scope does not verify .env file loading.

The test sets environment variables directly via monkeypatch.setenv, which bypasses the .env file loading mechanism introduced in service.py (Lines 13-19). This verifies Pydantic's environment-driven settings but not the dotenv integration.

To comprehensively test the PR's stated objective (loading from .env), add a test that:

  1. Creates a temporary .env file with test variables.
  2. Invokes SettingsService.initialize() (which triggers dotenv loading).
  3. Asserts settings are loaded from the file.

Example:

def test_settings_from_dotenv_file(tmp_path, monkeypatch):
    """Test that settings are loaded from .env file."""
    # Create temp .env file
    env_file = tmp_path / ".env"
    env_file.write_text(
        "LANGFLOW_MAX_VERTEX_BUILDS_TO_KEEP=10\n"
        "LANGFLOW_DATABASE_URL=sqlite:///test.db\n"
    )
    
    # Change working directory to temp path
    monkeypatch.chdir(tmp_path)
    
    # Reset guard to allow loading
    monkeypatch.delenv("_LANGFLOW_DOTENV_LOADED", raising=False)
    
    # Reload module to trigger dotenv loading
    import importlib
    import lfx.services.settings.service
    importlib.reload(lfx.services.settings.service)
    
    from lfx.services.settings.service import SettingsService
    
    settings_service = SettingsService.initialize()
    assert settings_service.settings.max_vertex_builds_to_keep == 10
    assert settings_service.settings.database_url == "sqlite:///test.db"

This would validate the entire .env loading path introduced in this PR.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f07ade6 and fe686b7.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • src/backend/base/langflow/__main__.py (0 hunks)
  • src/backend/tests/unit/services/database/test_vertex_builds.py (1 hunks)
  • src/lfx/pyproject.toml (1 hunks)
  • src/lfx/src/lfx/services/settings/service.py (1 hunks)
💤 Files with no reviewable changes (1)
  • src/backend/base/langflow/main.py
🧰 Additional context used
📓 Path-based instructions (5)
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/tests/unit/services/database/test_vertex_builds.py
src/backend/tests/unit/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Files:

  • src/backend/tests/unit/services/database/test_vertex_builds.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Unit tests for backend code must be located in the 'src/backend/tests/' directory, with component tests organized by component subdirectory under 'src/backend/tests/unit/components/'.
Test files should use the same filename as the component under test, with an appropriate test prefix or suffix (e.g., 'my_component.py' → 'test_my_component.py').
Use the 'client' fixture (an async httpx.AsyncClient) for API tests in backend Python tests, as defined in 'src/backend/tests/conftest.py'.
When writing component tests, inherit from the appropriate base class in 'src/backend/tests/base.py' (ComponentTestBase, ComponentTestBaseWithClient, or ComponentTestBaseWithoutClient) and provide the required fixtures: 'component_class', 'default_kwargs', and 'file_names_mapping'.
Each test in backend Python test files should have a clear docstring explaining its purpose, and complex setups or mocks should be well-commented.
Test both sync and async code paths in backend Python tests, using '@pytest.mark.asyncio' for async tests.
Mock external dependencies appropriately in backend Python tests to isolate unit tests from external services.
Test error handling and edge cases in backend Python tests, including using 'pytest.raises' and asserting error messages.
Validate input/output behavior and test component initialization and configuration in backend Python tests.
Use the 'no_blockbuster' pytest marker to skip the blockbuster plugin in tests when necessary.
Be aware of ContextVar propagation in async tests; test both direct event loop execution and 'asyncio.to_thread' scenarios to ensure proper context isolation.
Test error handling by mocking internal functions using monkeypatch in backend Python tests.
Test resource cleanup in backend Python tests by using fixtures that ensure proper initialization and cleanup of resources.
Test timeout and performance constraints in backend Python tests using 'asyncio.wait_for' and timing assertions.
Test Langflow's Messag...

Files:

  • src/backend/tests/unit/services/database/test_vertex_builds.py
{**/test_*.py,**/*.test.{ts,tsx}}

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

{**/test_*.py,**/*.test.{ts,tsx}}: Warn when mocks replace testing real behavior/interactions in test files
Suggest using real objects or simpler test doubles when mocks become excessive
Ensure mocks are reserved for external dependencies, not core application logic, in tests
Test files should have descriptive test names that explain what is being validated
Organize tests logically with proper setup and teardown
Include edge cases and error conditions for comprehensive test coverage
Cover both positive and negative scenarios where appropriate
Tests must cover the main functionality being implemented
Avoid smoke-only tests; assert meaningful behavior and outcomes
Follow project testing frameworks (pytest for backend, Playwright for frontend)
For API endpoints, verify both success and error responses in tests

Files:

  • src/backend/tests/unit/services/database/test_vertex_builds.py
**/test_*.py

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/test_*.py: Backend test files must follow naming convention test_*.py
Backend tests should use proper pytest structure
For async Python code, use proper pytest async testing patterns (e.g., pytest-asyncio)

Files:

  • src/backend/tests/unit/services/database/test_vertex_builds.py
🧬 Code graph analysis (2)
src/backend/tests/unit/services/database/test_vertex_builds.py (1)
src/lfx/src/lfx/services/settings/service.py (2)
  • SettingsService (22-49)
  • initialize (31-42)
src/lfx/src/lfx/services/settings/service.py (1)
src/lfx/src/lfx/services/settings/base.py (1)
  • Settings (60-555)
🪛 GitHub Actions: Ruff Style Check
src/backend/tests/unit/services/database/test_vertex_builds.py

[error] 336-336: ruff check failed: W292 No newline at end of file.

🪛 GitHub Check: Ruff Style Check (3.13)
src/backend/tests/unit/services/database/test_vertex_builds.py

[failure] 336-336: Ruff (W292)
src/backend/tests/unit/services/database/test_vertex_builds.py:336:56: W292 No newline at end of file

⏰ 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). (2)
  • GitHub Check: Update Starter Projects
  • GitHub Check: Optimize new Python code in this PR
🔇 Additional comments (2)
src/lfx/src/lfx/services/settings/service.py (2)

25-28: LGTM!

The constructor correctly initializes the service with settings and auth settings.


48-49: LGTM!

The teardown stub is appropriate for a service class and allows future cleanup logic.

@codecov
Copy link

codecov bot commented Oct 3, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 24.17%. Comparing base (662f069) to head (3e3c3f9).
⚠️ Report is 138 commits behind head on main.

❌ Your project status has failed because the head coverage (47.08%) is below the target coverage (55.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main   #10100   +/-   ##
=======================================
  Coverage   24.17%   24.17%           
=======================================
  Files        1086     1086           
  Lines       40044    40043    -1     
  Branches     5541     5541           
=======================================
  Hits         9679     9679           
+ Misses      30194    30193    -1     
  Partials      171      171           
Flag Coverage Δ
backend 47.08% <ø> (ø)

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

Files with missing lines Coverage Δ
src/backend/base/langflow/__main__.py 56.00% <ø> (ø)
🚀 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.

@HimavarshaVS HimavarshaVS changed the title Fix : Unable to load DB url from .env fix : Unable to load DB url from .env Oct 3, 2025
@HimavarshaVS HimavarshaVS changed the title fix : Unable to load DB url from .env fix : Unable to load DB url from env Oct 3, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Oct 6, 2025

@HimavarshaVS HimavarshaVS changed the title fix : Unable to load DB url from env fix : unable to load db url from env Oct 6, 2025
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