feat(kb): Knowledge Bases — Infrastructure Overhaul #1018
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Database Migration Validation | |
| on: | |
| pull_request: | |
| paths: | |
| - 'src/backend/base/langflow/alembic/**' | |
| - 'src/backend/base/langflow/services/database/models/**' | |
| - 'src/backend/base/langflow/services/database/service.py' | |
| - 'src/backend/tests/unit/alembic/**' | |
| - '.github/workflows/migration-validation.yml' | |
| jobs: | |
| model-migration-consistency: | |
| name: Model/Migration Consistency | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:16 | |
| env: | |
| POSTGRES_USER: langflow | |
| POSTGRES_PASSWORD: langflow | |
| POSTGRES_DB: langflow | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd="pg_isready -U langflow" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| - name: Setup Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Install dependencies | |
| run: | | |
| uv sync --extra postgresql | |
| - name: Check model/migration consistency | |
| env: | |
| MIGRATION_VALIDATION_CI: "true" | |
| LANGFLOW_TEST_DATABASE_URI: "postgresql://langflow:langflow@localhost:5432/langflow" | |
| run: | | |
| uv run pytest src/backend/tests/unit/alembic/test_migration_execution.py -x -v | |
| validate-migration: | |
| name: Migration Pattern Validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Get changed migration files | |
| id: changed-files | |
| run: | | |
| set -euo pipefail | |
| CHANGED_FILES=$(git diff --name-only origin/main...HEAD | grep -E 'src/backend/base/langflow/alembic/versions/.*\.py$' | grep -v 'test_migrations/' || echo "") | |
| if [ -z "$CHANGED_FILES" ]; then | |
| echo "No migration files changed" | |
| echo "files=" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Changed migration files:" | |
| echo "$CHANGED_FILES" | |
| echo "files=$(printf '%s' "$CHANGED_FILES" | tr '\n' ' ')" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Validate migration patterns | |
| if: steps.changed-files.outputs.files != '' | |
| env: | |
| MIGRATION_FILES: ${{ steps.changed-files.outputs.files }} | |
| run: | | |
| python src/backend/base/langflow/alembic/migration_validator.py $MIGRATION_FILES | |
| - name: Generate validation report | |
| if: always() && steps.changed-files.outputs.files != '' | |
| env: | |
| MIGRATION_FILES: ${{ steps.changed-files.outputs.files }} | |
| run: | | |
| python src/backend/base/langflow/alembic/migration_validator.py \ | |
| --json $MIGRATION_FILES > validation-report.json 2> validation-stderr.txt || true | |
| if [ ! -s validation-report.json ]; then | |
| echo "::error::Validator produced no output. Stderr:" | |
| cat validation-stderr.txt | |
| fi | |
| - name: Post PR comment with results | |
| if: always() && steps.changed-files.outputs.files != '' | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| let message = ''; | |
| let validationPassed = true; | |
| try { | |
| const report = JSON.parse(fs.readFileSync('validation-report.json', 'utf8')); | |
| for (const result of report) { | |
| if (!result.valid) { | |
| validationPassed = false; | |
| } | |
| } | |
| if (validationPassed) { | |
| message = `✅ **Migration Validation Passed**\n\n`; | |
| message += `All migrations follow the Expand-Contract pattern correctly.\n\n`; | |
| } else { | |
| message = `❌ **Migration Validation Failed**\n\n`; | |
| message += `Your migrations don't follow the Expand-Contract pattern.\n\n`; | |
| for (const result of report) { | |
| if (!result.valid || result.warnings.length > 0) { | |
| message += `### File: \`${result.file.split('/').pop()}\`\n`; | |
| message += `**Phase:** ${result.phase}\n\n`; | |
| if (result.violations && result.violations.length > 0) { | |
| message += `**Violations:**\n`; | |
| for (const v of result.violations) { | |
| message += `- Line ${v.line}: ${v.message}\n`; | |
| } | |
| message += `\n`; | |
| } | |
| if (result.warnings && result.warnings.length > 0) { | |
| message += `**Warnings:**\n`; | |
| for (const w of result.warnings) { | |
| message += `- Line ${w.line}: ${w.message}\n`; | |
| } | |
| message += `\n`; | |
| } | |
| } | |
| } | |
| message += `### Resources\n`; | |
| message += `- Review the [DB Migration Guide](./src/backend/base/langflow/alembic/DB-MIGRATION-GUIDE.MD)\n`; | |
| message += `- Use \`python scripts/generate_migration.py --help\` to generate compliant migrations\n\n`; | |
| message += `### Common Issues & Solutions\n`; | |
| message += `- **New columns must be nullable:** Add \`nullable=True\` or \`server_default\`\n`; | |
| message += `- **Missing phase marker:** Add \`Phase: EXPAND/MIGRATE/CONTRACT\` to docstring\n`; | |
| message += `- **Column drops:** Only allowed in CONTRACT phase\n`; | |
| message += `- **Direct renames:** Use expand-contract pattern instead\n`; | |
| } | |
| } catch (error) { | |
| message = `⚠️ **Migration validation check failed to run properly**\n`; | |
| message += `Error: ${error.message}\n`; | |
| validationPassed = false; | |
| } | |
| // Post or update comment (non-critical — don't let API errors mask validation results) | |
| try { | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const botComment = comments.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('Migration Validation') | |
| ); | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: message | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: message | |
| }); | |
| } | |
| } catch (apiError) { | |
| core.warning(`Failed to post PR comment: ${apiError.message}`); | |
| } | |
| // Fail the workflow if validation didn't pass | |
| if (!validationPassed) { | |
| core.setFailed('Migration validation failed'); | |
| } |