Skip to content

test(oracle): add E2E tests for Flyway-managed Oracle schema - #576

Merged
slin1237 merged 5 commits into
mainfrom
keyang/db-migration-test
Mar 3, 2026
Merged

slin1237 merged 5 commits into
mainfrom
keyang/db-migration-test

Conversation

@key4ng

@key4ng key4ng commented Mar 3, 2026 •

Copy link
Copy Markdown
Member

Description

Problem

SMG supports --schema-config for working with externally-managed Oracle tables (e.g. Flyway), but there are no automated tests verifying this works end-to-end.

Solution

Add CI infrastructure to create an Oracle user with Flyway-like DDL tables, and run the existing state management tests against it using --schema-config.

Changes

  • scripts/ci_agentic_svc_deps.sh: Add create-oracle-flyway-user and cleanup-oracle-flyway-user commands that create a second Oracle test user, execute V1+V2 DDL via oracledb Python, and export ATP_FLYWAY_* env vars
  • scripts/oracle_flyway/: Add CI-only Flyway SQL files (tables + indexes, no sweep procedures) and schema-config.yaml
  • e2e_test/infra/gateway.py: Handle oracle-custom history backend — maps to --history-backend oracle with ATP_FLYWAY_* credentials and --schema-config
  • e2e_test/fixtures/hooks.py: Register oracle-custom in storage marker help text
  • e2e_test/responses/test_state_management.py: Add TestStateManagementOracleCustom inheriting from TestStateManagementCloud (OpenAI-only)
  • .github/workflows/pr-test-rust.yml: Add Flyway user setup/cleanup to Oracle steps
  • bindings/python/src/lib.rs: Add schema_config field to Router, load YAML and apply to storage backend configs
  • bindings/python/src/smg/router_args.py: Add --schema-config CLI argument
  • bindings/python/Cargo.toml: Add serde_yaml dependency for schema config parsing

Summary by CodeRabbit

Release Notes

  • New Features

    • Added schema configuration support to enable custom table and column remapping for storage backends.
    • Introduced Oracle Flyway user management for dedicated schema testing and migration support.
    • Extended test infrastructure to support oracle-custom backend option.
  • Tests

    • Added new test classes for XAI backend and oracle-custom storage configurations.
  • Chores

    • Added database migration scripts defining conversation and response table structures for Oracle.

…r management scripts

- Added support for Flyway-managed Oracle schema configuration, including a new YAML schema config file.
- Implemented creation and cleanup scripts for an Oracle Flyway user in the CI workflow.
- Updated the Router and Gateway classes to handle the new schema configuration.
- Enhanced the Python bindings to include schema configuration as an argument.
- Added tests for state management with the new oracle-custom backend.

This change improves the flexibility of schema management in Oracle environments.

Signed-off-by: key4ng <rukeyang@gmail.com>
@coderabbitai

coderabbitai Bot commented Mar 3, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces schema configuration support across the codebase to enable Oracle Flyway-managed table and column remapping. It adds CLI arguments, configuration loading infrastructure, and new Flyway SQL migration scripts that define conversation and response storage tables for Oracle backends.

Changes

Cohort / File(s) Summary
CI Workflow & Oracle Setup
.github/workflows/pr-test-rust.yml, scripts/ci_agentic_svc_deps.sh
Extends Oracle test infrastructure to create and manage dedicated Flyway user with environment variables; adds commands for Flyway user creation/cleanup and updates cleanup workflow step to handle multiple users.
Configuration Types & Re-exports
model_gateway/src/config/types.rs
Re-exports SchemaConfig from smg_data_connector to make it available as a public type for configuration building.
Rust Core Configuration
model_gateway/src/main.rs
Adds schema_config CLI field and load_schema_config method; threads loaded schema through build_oracle_config, build_postgres_config, and build_redis_config builder methods to propagate schema into backend configurations.
Python Bindings & Dependencies
bindings/python/Cargo.toml, bindings/python/src/lib.rs, bindings/python/src/smg/router_args.py
Adds serde_yaml dependency; introduces schema_config field to Router struct with YAML loading and propagation to history backends; adds --schema-config CLI argument to RouterArgs dataclass.
E2E Testing Infrastructure
e2e_test/fixtures/hooks.py, e2e_test/infra/gateway.py, e2e_test/responses/test_state_management.py
Expands test marker to include "oracle-custom" storage backend; updates gateway cloud mode to recognize oracle-custom backend and configure Flyway environment variables with schema-config argument; refactors state management tests with shared base class and separate backend-specific test classes.
Oracle Flyway Migrations
scripts/oracle_flyway/schema-config.yaml, scripts/oracle_flyway/sql/V1__Create_responses_table.sql, scripts/oracle_flyway/sql/V2__Create_v2_conversations_and_alter_responses.sql
Adds schema configuration YAML mapping SMG tables to Flyway-managed Oracle tables with column remappings; introduces two Flyway migration scripts creating RESPONSES, CONVERSATIONS_V2, CONVERSATION_ITEMS, and CONVERSATION_ITEM_LINKS tables with primary keys and optimized indexes.

Sequence Diagram

sequenceDiagram
    participant User as User/CLI
    participant Config as Config Loader
    participant Router as Router/Gateway
    participant Backend as Backend Config<br/>(Oracle/Postgres/Redis)
    
    User->>Config: Provide schema_config path & other args
    Config->>Config: Load YAML schema from path
    Config->>Config: Parse into SchemaConfig object
    Config->>Router: Initialize Router with SchemaConfig
    Router->>Router: Call to_router_config()
    Router->>Backend: Pass SchemaConfig to Oracle builder
    Router->>Backend: Pass SchemaConfig to Postgres builder
    Router->>Backend: Pass SchemaConfig to Redis builder
    Backend->>Backend: Augment config with schema<br/>(table/column remapping)
    Router->>Router: Construct RouterConfig with<br/>schema-aware backends
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • CatherineSue
  • slin1237
  • XinyueZhang369

Poem

🐰 Flyway hops through Oracle's domain,
With schemas dancing, columns rearrange,
Tables spring to life—V1, V2 refrain,
Config threads spin through every range,
A tidy tale of migrations made plain! 🌊✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main objective: adding end-to-end tests for a Flyway-managed Oracle schema. It is concise, specific, and directly aligns with the substantial infrastructure and test additions across CI, Python bindings, and E2E test files.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch keyang/db-migration-test

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added python-bindings Python bindings changes dependencies Dependency updates ci CI/CD configuration changes tests Test changes model-gateway Model gateway crate changes labels Mar 3, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the flexibility and management of Oracle database schemas within the system. By introducing Flyway-managed schema support, it allows for dynamic configuration of table and column mappings through a YAML file, which is crucial for environments requiring custom schema layouts. The changes also include robust CI tooling for managing dedicated Flyway users and comprehensive test coverage for the new 'oracle-custom' backend, ensuring reliable operation and easier integration with diverse Oracle setups.

Highlights

  • Flyway-managed Oracle Schema Support: Introduced support for Flyway-managed Oracle schema configurations, allowing for flexible table and column remapping via a YAML config file.
  • CI Scripting for Oracle Flyway Users: Implemented new CI scripts to create and clean up dedicated Oracle Flyway users, ensuring proper isolation and setup for testing environments.
  • Router and Gateway Integration: Updated the Router and Gateway components to integrate and utilize the new schema configuration, enabling dynamic schema adjustments.
  • Python Bindings Enhancement: Enhanced Python bindings to accept schema configuration as an argument, improving configurability for Python users.
  • New End-to-End Tests: Added end-to-end tests for state management using the new 'oracle-custom' backend, validating the Flyway-managed schema functionality.
Changelog
  • bindings/python/Cargo.toml
    • Added serde_yaml dependency for YAML parsing.
  • bindings/python/src/lib.rs
    • Added schema_config field to the Router struct.
    • Implemented logic to load schema configuration from a YAML file if schema_config is provided.
    • Modified to_config_oracle, to_config_postgres, and to_config_redis methods to accept and apply the loaded schema configuration.
  • bindings/python/src/smg/router_args.py
    • Added schema_config as an optional string argument to RouterArgs.
    • Included --schema-config as a new CLI argument for specifying the schema configuration file path.
  • e2e_test/fixtures/hooks.py
    • Updated the storage pytest marker to include oracle-custom as a valid backend option.
  • e2e_test/infra/gateway.py
    • Extended history_backend parameter to include oracle-custom.
    • Added logic to detect oracle-custom backend, override Oracle environment variables with Flyway user credentials, and pass the schema-config argument to the gateway.
  • e2e_test/responses/test_state_management.py
    • Introduced TestStateManagementOracleCustom class to run state management tests against the new oracle-custom backend.
  • model_gateway/src/config/types.rs
    • Exported SchemaConfig from smg_data_connector to make it available in the model_gateway configuration.
  • model_gateway/src/main.rs
    • Imported SchemaConfig for use in the main application.
    • Added a schema_config optional string argument to CliArgs.
    • Implemented load_schema_config function to parse a YAML schema file into a SchemaConfig object.
    • Modified build_oracle_config, build_postgres_config, and build_redis_config functions to accept and integrate the SchemaConfig.
    • Updated the main configuration building logic to load and pass the schema configuration to the appropriate backend builders.
  • scripts/ci_agentic_svc_deps.sh
    • Added create-oracle-flyway-user command to create a dedicated Oracle user for Flyway migrations, including granting necessary privileges and executing initial SQL scripts.
    • Added cleanup-oracle-flyway-user command to drop the created Flyway test user.
  • scripts/oracle_flyway/schema-config.yaml
    • Added a new YAML configuration file defining table and column remappings for Flyway-managed Oracle schemas, specifically for CONVERSATIONS_V2, RESPONSES, CONVERSATION_ITEMS, and CONVERSATION_ITEM_LINKS.
  • scripts/oracle_flyway/sql/V1__Create_responses_table.sql
    • Added a new SQL script to create the RESPONSES table with its columns and primary key, along with relevant indexes.
  • scripts/oracle_flyway/sql/V2__Create_v2_conversations_and_alter_responses.sql
    • Added a new SQL script to create CONVERSATIONS_V2, CONVERSATION_ITEMS, and CONVERSATION_ITEM_LINKS tables with their respective columns, primary keys, and indexes.
    • Included an ALTER TABLE statement to add a SAFETY_IDENTIFIER column to the RESPONSES table.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/pr-test-rust.yml
Activity
  • No human activity has occurred on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for Flyway-managed Oracle schemas, allowing for more flexible schema management. The changes include updates to the Router and Gateway to handle schema configuration from a YAML file, new CI scripts for managing a Flyway user in Oracle, and corresponding updates to Python bindings and tests.

My review focuses on improving code structure and maintainability. I've identified some code duplication for loading schema configurations and an opportunity to make the schema application logic more efficient by avoiding unnecessary cloning. These suggestions aim to make the codebase cleaner and more robust.

Comment on lines +592 to +607
let schema = if let Some(ref path) = self.schema_config {
let content = std::fs::read_to_string(path).map_err(|e| {
config::ConfigError::ValidationFailed {
reason: format!("Failed to read schema config file '{}': {}", path, e),
}
})?;
let schema: config::SchemaConfig =
serde_yaml::from_str(&content).map_err(|e| {
config::ConfigError::ValidationFailed {
reason: format!("Failed to parse schema config file '{}': {}", path, e),
}
})?;
Some(schema)
} else {
None
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This schema loading logic is duplicated in model_gateway/src/main.rs (inside load_schema_config). To improve maintainability and avoid code duplication, consider extracting this logic into a shared function. A good place for this would be within the smg::config module, for example, as pub fn load_schema_from_path(path: &str) -> ConfigResult<SchemaConfig>.

References
  1. Extract duplicated logic into a shared helper function to improve maintainability and reduce redundancy.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Appreciate the suggestion, but these two callers live in separate entry-point crates (CLI binary vs Python bindings). The logic is ~6 lines of straightforward read-file-then-parse glue — extracting it would add public API surface to the config module for something only used at initialization. Keeping it inline in each caller is fine here.

Comment thread model_gateway/src/main.rs
Comment on lines 1039 to 1053
let oracle = if history_backend == HistoryBackend::Oracle {
Some(self.build_oracle_config()?)
Some(self.build_oracle_config(schema.clone())?)
} else {
None
};
let postgres = if history_backend == HistoryBackend::Postgres {
Some(self.build_postgres_config()?)
Some(self.build_postgres_config(schema.clone())?)
} else {
None
};
let redis = if history_backend == HistoryBackend::Redis {
Some(self.build_redis_config()?)
Some(self.build_redis_config(schema)?)
} else {
None
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current logic for applying the schema configuration involves cloning the schema for both Oracle and Postgres backends. Since only one history backend can be active at a time, these clones are unnecessary. You can refactor this to avoid cloning by using a match statement to construct a tuple of the backend configs, moving the schema into the correct one. This will make the code more efficient and cleaner.

        let (oracle, postgres, redis) = match history_backend {
            HistoryBackend::Oracle => (Some(self.build_oracle_config(schema)?), None, None),
            HistoryBackend::Postgres => (None, Some(self.build_postgres_config(schema)?), None),
            HistoryBackend::Redis => (None, None, Some(self.build_redis_config(schema)?)),
            _ => (None, None, None),
        };
References
  1. Refactor match statements to avoid duplication. When arms have common logic, use the match to return the differing value and perform the common logic once.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — since only one history backend is active at a time, the clones are unnecessary. Refactored to a single match statement. 👍

@key4ng key4ng changed the title feat(oracle): introduce Flyway-managed schema support and related use… ci(oracle): add E2E tests for Flyway-managed Oracle schema Mar 3, 2026
@key4ng key4ng changed the title ci(oracle): add E2E tests for Flyway-managed Oracle schema test(oracle): add E2E tests for Flyway-managed Oracle schema Mar 3, 2026
key4ng added 4 commits March 3, 2026 00:47
- Modified the test suite to focus on OpenAI only for the base class.
- Introduced a new test class for xAI cloud API, inheriting from the OpenAI tests.
- Updated documentation strings to reflect the changes in backend focus.

This refactor enhances clarity and organization of the state management tests for different cloud backends.

Signed-off-by: key4ng <rukeyang@gmail.com>
…g file handling

- Updated error messages in the Router and CLI argument handling to use more concise formatting with Rust's string interpolation.
- Changed schema assignment in Oracle and Postgres configurations to use `clone_from` for better performance.

These changes enhance code readability and maintainability while improving error reporting for schema configuration issues.

Signed-off-by: key4ng <rukeyang@gmail.com>
- Refactored the state management test classes to introduce a base class for shared functionality.
- Updated the OpenAI and xAI test classes to inherit from the new base class, improving code reuse.
- Enhanced documentation strings to clarify the purpose of each test class.

This restructuring improves the organization and maintainability of the test suite for cloud backends.

Signed-off-by: key4ng <rukeyang@gmail.com>
…reading

- Simplified error handling in the Router and CLI argument loading functions by reducing nested structures.
- Improved readability of error messages related to schema configuration file parsing.

These changes enhance code clarity and maintainability in schema configuration handling.

Signed-off-by: key4ng <rukeyang@gmail.com>
@key4ng
key4ng marked this pull request as ready for review March 3, 2026 02:59
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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)
bindings/python/Cargo.toml (1)

30-35: ⚠️ Potential issue | 🟡 Minor

Profile section has no effect in non-root package.

The pipeline warning indicates this [profile.ci] section will be ignored. Cargo only reads profile configurations from the workspace root Cargo.toml. Consider moving this to the workspace root or removing it from this file.

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

In `@bindings/python/Cargo.toml` around lines 30 - 35, The [profile.ci] section in
this Cargo.toml has no effect because Cargo only reads profile settings from the
workspace root; either remove the [profile.ci] block here or move its exact
contents (inherits = "release", opt-level = 2, lto = "thin", codegen-units = 16,
strip = true) into the workspace root Cargo.toml so Cargo will apply the
profile; update or delete the local [profile.ci] block accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e_test/infra/gateway.py`:
- Around line 307-313: The code appends a relative schema-config path
("scripts/oracle_flyway/schema-config.yaml") to mode_args when history_backend
== "oracle-custom", which makes startup CWD-dependent; change this to compute
and pass an absolute path (e.g. resolve the repo-root-relative path using the
current module's location or a known repo root) before extending mode_args so
schema-config is always an absolute filesystem path; update the branch handling
in gateway.py where history_backend and mode_args are used to perform the
resolution and append the absolute path for the "schema-config" argument.

In `@scripts/ci_agentic_svc_deps.sh`:
- Around line 211-213: Multiple consecutive appends to "$GITHUB_ENV" (the three
echo lines writing ATP_FLYWAY_USER, ATP_FLYWAY_PASSWORD, ATP_FLYWAY_DSN) should
be grouped into a single append to avoid repeated redirects; replace the three
echo statements that write to "$GITHUB_ENV" with a single multiline append that
writes all three environment entries at once (e.g., a here-doc or combined
printf) so the writes for ATP_FLYWAY_USER, ATP_FLYWAY_PASSWORD and
ATP_FLYWAY_DSN are performed in one redirected block.

---

Outside diff comments:
In `@bindings/python/Cargo.toml`:
- Around line 30-35: The [profile.ci] section in this Cargo.toml has no effect
because Cargo only reads profile settings from the workspace root; either remove
the [profile.ci] block here or move its exact contents (inherits = "release",
opt-level = 2, lto = "thin", codegen-units = 16, strip = true) into the
workspace root Cargo.toml so Cargo will apply the profile; update or delete the
local [profile.ci] block accordingly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0dc691 and a2e0002.

📒 Files selected for processing (13)
  • .github/workflows/pr-test-rust.yml
  • bindings/python/Cargo.toml
  • bindings/python/src/lib.rs
  • bindings/python/src/smg/router_args.py
  • e2e_test/fixtures/hooks.py
  • e2e_test/infra/gateway.py
  • e2e_test/responses/test_state_management.py
  • model_gateway/src/config/types.rs
  • model_gateway/src/main.rs
  • scripts/ci_agentic_svc_deps.sh
  • scripts/oracle_flyway/schema-config.yaml
  • scripts/oracle_flyway/sql/V1__Create_responses_table.sql
  • scripts/oracle_flyway/sql/V2__Create_v2_conversations_and_alter_responses.sql

Comment thread e2e_test/infra/gateway.py
Comment thread scripts/ci_agentic_svc_deps.sh
@slin1237
slin1237 merged commit fd31582 into main Mar 3, 2026
24 checks passed
@slin1237
slin1237 deleted the keyang/db-migration-test branch March 3, 2026 03:30
key4ng added a commit that referenced this pull request Mar 3, 2026
…feedback (#591)

Signed-off-by: Keyang Ru <rukeyang@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci CI/CD configuration changes dependencies Dependency updates model-gateway Model gateway crate changes python-bindings Python bindings changes tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants