From bf45dacc7f2e1a184795229be43135a740119ce5 Mon Sep 17 00:00:00 2001 From: RepoRover Date: Wed, 27 Aug 2025 12:38:09 +0300 Subject: [PATCH 1/9] fix: enforce required environment variables in configuration & pass them into generated schemas dynamically --- README.md | 2 +- database_schema_spec/cli/generator.py | 7 +++++++ database_schema_spec/core/config.py | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a7addd9..b33c00c 100644 --- a/README.md +++ b/README.md @@ -150,5 +150,5 @@ output/ ├── vmap.json └── postgresql/ └── 15.0/ - └── unified_schema.json + └── spec.json ``` diff --git a/database_schema_spec/cli/generator.py b/database_schema_spec/cli/generator.py index f152943..bff32e8 100644 --- a/database_schema_spec/cli/generator.py +++ b/database_schema_spec/cli/generator.py @@ -130,6 +130,13 @@ def generate_variant(self, variant: DatabaseVariantSpec) -> Path: base_schema, variant ) + # Inject dynamic $id derived from BASE_URL for the final output + id_field = config.json_schema_fields.id_field + spec_url = self.output_manager._get_spec_url( + variant.engine, variant.version, config.base_url + ) + unified_schema[id_field] = spec_url + # Validate the resulting schema validation_result = self.validator.validate_schema(unified_schema) if not validation_result.is_valid: diff --git a/database_schema_spec/core/config.py b/database_schema_spec/core/config.py index 3978fff..9ba57ff 100644 --- a/database_schema_spec/core/config.py +++ b/database_schema_spec/core/config.py @@ -1,7 +1,9 @@ """Configuration constants for the database schema spec generator.""" +import os from pathlib import Path +from dotenv import load_dotenv from pydantic import BaseModel, Field, ValidationError from pydantic_settings import BaseSettings @@ -65,6 +67,12 @@ class Config(BaseSettings): def __init__(self, **data): """Initialize config with custom error handling for missing required fields.""" try: + # Enforce presence of required env variables in the process environment + # before delegating to BaseSettings. This ensures tests that clear os.environ + # see the expected ConfigurationError. + if "base_url" not in data and "BASE_URL" not in os.environ: + raise ConfigurationError(variable_name="BASE_URL") + super().__init__(**data) except ValidationError as e: # Only handle missing field errors, let other validation errors bubble up @@ -80,4 +88,6 @@ def __init__(self, **data): raise +# At application import time, populate os.environ from .env (if present), then enforce presence. +load_dotenv() config = Config() From 3400ccb6e85044823dc23be24aa5736332c130ae Mon Sep 17 00:00:00 2001 From: RepoRover Date: Wed, 27 Aug 2025 12:51:54 +0300 Subject: [PATCH 2/9] fix: reorder top-level keys in generated schemas to prioritize $id and $schema fields --- database_schema_spec/cli/generator.py | 21 +++++++++++++++++++ .../engines/postgresql/v15.0/spec.json | 1 - docs/specs.json | 1 - 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/database_schema_spec/cli/generator.py b/database_schema_spec/cli/generator.py index bff32e8..60d8057 100644 --- a/database_schema_spec/cli/generator.py +++ b/database_schema_spec/cli/generator.py @@ -132,11 +132,32 @@ def generate_variant(self, variant: DatabaseVariantSpec) -> Path: # Inject dynamic $id derived from BASE_URL for the final output id_field = config.json_schema_fields.id_field + schema_field = config.json_schema_fields.schema_field spec_url = self.output_manager._get_spec_url( variant.engine, variant.version, config.base_url ) + # Set/override $id unified_schema[id_field] = spec_url + # Reorder top-level keys to ensure `$id` appears immediately after `$schema` when present + if isinstance(unified_schema, dict): + reordered: dict[str, object] = {} + # If $schema exists, place it first + if schema_field in unified_schema: + reordered[schema_field] = unified_schema[schema_field] + reordered[id_field] = unified_schema[id_field] + for k, v in unified_schema.items(): + if k not in (schema_field, id_field): + reordered[k] = v + unified_schema = reordered # type: ignore[assignment] + else: + # If no $schema, put $id first then the rest in original order + reordered[id_field] = unified_schema[id_field] + for k, v in unified_schema.items(): + if k != id_field: + reordered[k] = v + unified_schema = reordered # type: ignore[assignment] + # Validate the resulting schema validation_result = self.validator.validate_schema(unified_schema) if not validation_result.is_valid: diff --git a/docs/schemas/engines/postgresql/v15.0/spec.json b/docs/schemas/engines/postgresql/v15.0/spec.json index f93cf53..e9afd1c 100644 --- a/docs/schemas/engines/postgresql/v15.0/spec.json +++ b/docs/schemas/engines/postgresql/v15.0/spec.json @@ -1,6 +1,5 @@ { "title": "PostgreSQL 15.0 Schema Rules", - "$id": "https://schemas.bfloo.com/postgresql/15.0/spec.json", "properties": { "schema": { "properties": { diff --git a/docs/specs.json b/docs/specs.json index 438f1de..be553fa 100644 --- a/docs/specs.json +++ b/docs/specs.json @@ -1,6 +1,5 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://schemas.bfloo.com/database-schema-spec/v1/specs.json", "title": "Database Schema Specification", "description": "Standardized JSON schema specification for database structure definition and validation. Provides a consistent format for representing database schemas across applications with built-in validation rules", "type": "object", From baa420c9603ff02ba886f7e61a113288a3c18bf6 Mon Sep 17 00:00:00 2001 From: RepoRover Date: Wed, 27 Aug 2025 12:53:17 +0300 Subject: [PATCH 3/9] fix: moved description field from snapshot to schema definition --- docs/examples/example_1.json | 2 +- docs/examples/example_2.json | 2 +- docs/examples/example_3.json | 2 +- docs/schemas/base/schema.json | 22 +++++++++++----------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/examples/example_1.json b/docs/examples/example_1.json index 9331ea6..b4d84e6 100644 --- a/docs/examples/example_1.json +++ b/docs/examples/example_1.json @@ -6,10 +6,10 @@ "schema": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "E-commerce Platform", + "description": null, "snapshot": { "id": "123e4567-e89b-12d3-a456-426614174000", "label": "v1.0.0", - "description": null, "parent_id": null, "created_at": "2024-01-15T10:30:00" }, diff --git a/docs/examples/example_2.json b/docs/examples/example_2.json index c222546..91a40ae 100644 --- a/docs/examples/example_2.json +++ b/docs/examples/example_2.json @@ -6,10 +6,10 @@ "schema": { "id": "8a2e8f50-b29c-42d4-a817-556644330001", "name": "Inventory Management System", + "description": null, "snapshot": { "id": "987fcdeb-51d2-43a1-b123-456789abcdef", "label": "v2.1.0", - "description": null, "parent_id": "550e8400-e29b-41d4-a716-446655440000", "created_at": "2024-03-20T14:45:00" }, diff --git a/docs/examples/example_3.json b/docs/examples/example_3.json index 70e85fe..88f9ccf 100644 --- a/docs/examples/example_3.json +++ b/docs/examples/example_3.json @@ -6,10 +6,10 @@ "schema": { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "name": "Healthcare Management System", + "description": "Comprehensive healthcare management with patient records and appointments", "snapshot": { "id": "456def78-9abc-45e6-f789-012345678901", "label": "v3.2.1", - "description": "Comprehensive healthcare management with patient records and appointments", "parent_id": "8a2e8f50-b29c-42d4-a817-556644330001", "created_at": "2024-05-15T09:20:00" }, diff --git a/docs/schemas/base/schema.json b/docs/schemas/base/schema.json index 8c8e534..a7ff2ff 100644 --- a/docs/schemas/base/schema.json +++ b/docs/schemas/base/schema.json @@ -20,6 +20,15 @@ "Human Resources Portal" ] }, + "description": { + "type": ["string", "null"], + "description": "Description of the snapshot", + "examples": [ + "Initial schema for the e-commerce platform", + "Schema update to add new tables for inventory tracking", + null + ] + }, "snapshot": { "type": "object", "properties": { @@ -39,15 +48,6 @@ "maxLength": 64, "examples": ["v1.0.0", "v1.1.0", "v2.0.0"] }, - "description": { - "type": ["string", "null"], - "description": "Description of the snapshot", - "examples": [ - "Initial schema setup", - "Added new tables", - "Updated column types" - ] - }, "parent_id": { "type": ["string", "null"], "format": "uuid", @@ -61,7 +61,7 @@ "examples": ["2023-10-01T12:00:00", "2023-10-02T15:30:00"] } }, - "required": ["id", "label", "description", "parent_id", "created_at"], + "required": ["id", "label", "parent_id", "created_at"], "additionalProperties": false }, "tables": { @@ -69,6 +69,6 @@ "description": "List of tables in the schema" } }, - "required": ["id", "name", "snapshot", "tables"], + "required": ["id", "name", "description", "snapshot", "tables"], "additionalProperties": false } From 26e75b96434d58aed814f8bb83d11733e1120041 Mon Sep 17 00:00:00 2001 From: RepoRover Date: Wed, 27 Aug 2025 14:42:30 +0300 Subject: [PATCH 4/9] fix: enable overriding of environment variables when loading .env file --- database_schema_spec/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database_schema_spec/core/config.py b/database_schema_spec/core/config.py index 9ba57ff..b131f4d 100644 --- a/database_schema_spec/core/config.py +++ b/database_schema_spec/core/config.py @@ -89,5 +89,5 @@ def __init__(self, **data): # At application import time, populate os.environ from .env (if present), then enforce presence. -load_dotenv() +load_dotenv(override=True) config = Config() From 1d2232d200230c78da5c5075db8e0441e69fed1d Mon Sep 17 00:00:00 2001 From: RepoRover Date: Wed, 27 Aug 2025 22:09:14 +0300 Subject: [PATCH 5/9] feat: add Dockerfile, .dockerignore for schema generation and workflow to create images --- .dockerignore | 77 +++++++++++++ .github/workflows/create-staging-image.yaml | 116 ++++++++++++++++++++ Dockerfile | 39 +++++++ 3 files changed, 232 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/create-staging-image.yaml create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2975329 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,77 @@ +# Version control +.git +.gitignore +.gitattributes + +# Python artifacts +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +.venv +.venv/ +.python-version +pip-log.txt +pip-delete-this-directory.txt + +# Development and testing +tests/ +.pytest_cache/ +.coverage +.coverage.* +coverage.xml +htmlcov/ +.tox/ +.nox/ +.cache +.mypy_cache/ +.ruff_cache/ +.pyright/ +.pre-commit-config.yaml +.env.example + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Documentation (optional, remove if needed in image) +README.md +docs/README.md + +# CI/CD +.github/ + +# Build artifacts +build/ +dist/ +*.egg-info/ + +# Logs +*.log +logs/ + +# Temporary files +.tmp/ +temp/ +*.tmp + +# Node modules (if any) +node_modules/ + +# Docker +Dockerfile* +docker-compose*.yml +.dockerignore \ No newline at end of file diff --git a/.github/workflows/create-staging-image.yaml b/.github/workflows/create-staging-image.yaml new file mode 100644 index 0000000..e399910 --- /dev/null +++ b/.github/workflows/create-staging-image.yaml @@ -0,0 +1,116 @@ +name: "Staging CI/CD - Create Release Candidate Image" + +on: + push: + tags: + - "v*.*.*-rc.*" # Run on every tag matching this pattern (e.g. v1.4.0-rc.1) + +permissions: + contents: read + +jobs: + quality_checks: + uses: ./.github/workflows/ci.yaml + + prepare_metadata: + runs-on: ubuntu-latest + needs: quality_checks + outputs: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + steps: + - name: Checkout code + uses: actions/checkout@v5.0.0 + with: + ref: ${{ github.ref }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5.8.0 + with: + images: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} + tags: | + type=ref,event=tag,enable=true # Tag is the version tag, i.e. reference that triggered the workflow + type=raw,value=staging-latest # Tag for the latest staging image, hardcoded to 'staging-latest' + + flavor: | + latest=false # Disable latest tag for this workflow + + labels: | + org.opencontainers.image.title=${{ github.event.repository.name }} + org.opencontainers.image.description=${{ github.event.repository.description }} + org.opencontainers.image.url=${{ github.event.repository.html_url }} + org.opencontainers.image.source=${{ github.event.repository.clone_url }} + org.opencontainers.image.version=${{ github.ref_name }} + org.opencontainers.image.revision=${{ github.sha }} + + build_image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + needs: [quality_checks, prepare_metadata] + outputs: + image-url: ghcr.io/${{ github.repository_owner}}/${{ github.repository }}:${{ github.ref_name }} + image-id: ${{ steps.build.outputs.imageid }} + digest: ${{ steps.build.outputs.digest }} + + steps: + - name: Checkout code + uses: actions/checkout@v5.0.0 + with: + ref: ${{ github.ref }} + + - name: Generate env file + run: | + echo "BASE_URL=${{ vars.STAGING_BASE_URL }}" >> .env + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3.11.1 + with: + platforms: linux/amd64 + + - name: Restore Docker cache + uses: actions/cache@v4.2.4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to GHCR + uses: docker/login-action@v3.5.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build and push Docker image + - name: Build and push Docker image + id: build + uses: docker/build-push-action@v6.18.0 + with: + context: . + push: true + tags: ${{ needs.prepare_metadata.outputs.tags }} + labels: ${{ needs.prepare_metadata.outputs.labels }} + platforms: linux/amd64 + provenance: false + sbom: false + cache-from: | + type=gha + type=local,src=/tmp/.buildx-cache + + cache-to: | + type=gha,mode=max + type=local,dest=/tmp/.buildx-cache-updated,mode=max + + build-args: | + BUILDKIT_INLINE_CACHE=1 + + - name: Update cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-updated /tmp/.buildx-cache diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8112059 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +# Multi-stage build for database schema spec generator +# Stage 1: Build the schemas +FROM alpine:3.22.1 AS builder + +# Install Python, uv, and git (needed for some dependencies) +RUN apk add --no-cache python3 py3-pip git + +# Install uv package manager +RUN pip3 install --break-system-packages uv + +# Set working directory +WORKDIR /app + +# Copy dependency files first for better caching +COPY pyproject.toml uv.lock ./ + +# Install dependencies +RUN uv sync --frozen --no-install-project --no-dev + +# Copy source code and input files +COPY main.py ./ +COPY database_schema_spec/ ./database_schema_spec/ +COPY docs/ ./docs/ +COPY .env ./ + +# Generate the schemas +RUN uv run python main.py + +# Stage 2: Final lightweight image with only the output +FROM alpine:3.22.1 + +# Create output directory +RUN mkdir -p /output + +# Copy generated schemas from builder stage +COPY --from=builder /app/output/ /output/ + +# Optional: Set a default command to list contents (for debugging) +CMD ["ls", "-la", "/output"] From dc1ab3484dc111008d85f430959885b787634a4a Mon Sep 17 00:00:00 2001 From: RepoRover Date: Wed, 27 Aug 2025 23:36:34 +0300 Subject: [PATCH 6/9] feat: added workflow to create production images & cleaned workflow to create staging images --- .github/workflows/create-prod-image.yaml | 117 ++++++++++++++++++++ .github/workflows/create-staging-image.yaml | 13 ++- 2 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/create-prod-image.yaml diff --git a/.github/workflows/create-prod-image.yaml b/.github/workflows/create-prod-image.yaml new file mode 100644 index 0000000..8c56c90 --- /dev/null +++ b/.github/workflows/create-prod-image.yaml @@ -0,0 +1,117 @@ +name: "Production CI/CD - Create Release Image" + +on: + push: + tags: + # Run on every tag matching this pattern (e.g. v1.4.0) + - v[0-9]*.[0-9]*.[0-9]* + - "!v[0-9]*.[0-9]*.[0-9]*-rc.[0-9]*" + +permissions: + contents: read + +jobs: + quality_checks: + uses: ./.github/workflows/ci.yaml + + prepare_metadata: + runs-on: ubuntu-latest + needs: quality_checks + outputs: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + steps: + - name: Checkout code + uses: actions/checkout@v5.0.0 + with: + ref: ${{ github.ref }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5.8.0 + with: + images: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} + tags: | + type=ref,event=tag,enable=true + + flavor: | + latest=true + + labels: | + org.opencontainers.image.title=${{ github.event.repository.name }} + org.opencontainers.image.description=${{ github.event.repository.description }} + org.opencontainers.image.url=${{ github.event.repository.html_url }} + org.opencontainers.image.source=${{ github.event.repository.clone_url }} + org.opencontainers.image.version=${{ github.ref_name }} + org.opencontainers.image.revision=${{ github.sha }} + + build_image: + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + + environment: production + needs: [quality_checks, prepare_metadata] + outputs: + image-url: ghcr.io/${{ github.repository_owner}}/${{ github.repository }}:${{ github.ref_name }} + image-id: ${{ steps.build.outputs.imageid }} + digest: ${{ steps.build.outputs.digest }} + + steps: + - name: Checkout code + uses: actions/checkout@v5.0.0 + with: + ref: ${{ github.ref }} + + - name: Generate env file + run: | + echo "BASE_URL=${{ vars.BASE_URL }}" >> .env + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3.11.1 + with: + platforms: linux/amd64 + + - name: Restore Docker cache + uses: actions/cache@v4.2.4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to GHCR + uses: docker/login-action@v3.5.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + id: build + uses: docker/build-push-action@v6.18.0 + with: + context: . + push: true + tags: ${{ needs.prepare_metadata.outputs.tags }} + labels: ${{ needs.prepare_metadata.outputs.labels }} + platforms: linux/amd64 + provenance: false + sbom: false + cache-from: | + type=gha + type=local,src=/tmp/.buildx-cache + + cache-to: | + type=gha,mode=max + type=local,dest=/tmp/.buildx-cache-updated,mode=max + + build-args: | + BUILDKIT_INLINE_CACHE=1 + + - name: Update cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-updated /tmp/.buildx-cache diff --git a/.github/workflows/create-staging-image.yaml b/.github/workflows/create-staging-image.yaml index e399910..7f9be0e 100644 --- a/.github/workflows/create-staging-image.yaml +++ b/.github/workflows/create-staging-image.yaml @@ -3,7 +3,8 @@ name: "Staging CI/CD - Create Release Candidate Image" on: push: tags: - - "v*.*.*-rc.*" # Run on every tag matching this pattern (e.g. v1.4.0-rc.1) + # Run on every tag matching this pattern (e.g. v1.4.0-rc.1) + - "v[0-9]*.[0-9]*.[0-9]*-rc.[0-9]*" permissions: contents: read @@ -31,11 +32,11 @@ jobs: with: images: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} tags: | - type=ref,event=tag,enable=true # Tag is the version tag, i.e. reference that triggered the workflow - type=raw,value=staging-latest # Tag for the latest staging image, hardcoded to 'staging-latest' + type=ref,event=tag,enable=true + type=raw,value=staging-latest flavor: | - latest=false # Disable latest tag for this workflow + latest=false labels: | org.opencontainers.image.title=${{ github.event.repository.name }} @@ -51,6 +52,7 @@ jobs: contents: read packages: write + environment: staging needs: [quality_checks, prepare_metadata] outputs: image-url: ghcr.io/${{ github.repository_owner}}/${{ github.repository }}:${{ github.ref_name }} @@ -65,7 +67,7 @@ jobs: - name: Generate env file run: | - echo "BASE_URL=${{ vars.STAGING_BASE_URL }}" >> .env + echo "BASE_URL=${{ vars.BASE_URL }}" >> .env - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.11.1 @@ -87,7 +89,6 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # Build and push Docker image - name: Build and push Docker image id: build uses: docker/build-push-action@v6.18.0 From d1349c5f456b934527e8866e4a9526ab176b2a3c Mon Sep 17 00:00:00 2001 From: Matheus-OAMK Date: Thu, 28 Aug 2025 23:06:57 +0300 Subject: [PATCH 7/9] refactor(config): Remove unecessary python-dotenv dependency - Removed python-dotenv dependency and lines utilizing it. The pydantic_settings managed the environment and should fail on missing dependencies. --- database_schema_spec/core/config.py | 6 ------ pyproject.toml | 1 - uv.lock | 4 +--- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/database_schema_spec/core/config.py b/database_schema_spec/core/config.py index b131f4d..552bc62 100644 --- a/database_schema_spec/core/config.py +++ b/database_schema_spec/core/config.py @@ -1,9 +1,7 @@ """Configuration constants for the database schema spec generator.""" -import os from pathlib import Path -from dotenv import load_dotenv from pydantic import BaseModel, Field, ValidationError from pydantic_settings import BaseSettings @@ -70,8 +68,6 @@ def __init__(self, **data): # Enforce presence of required env variables in the process environment # before delegating to BaseSettings. This ensures tests that clear os.environ # see the expected ConfigurationError. - if "base_url" not in data and "BASE_URL" not in os.environ: - raise ConfigurationError(variable_name="BASE_URL") super().__init__(**data) except ValidationError as e: @@ -88,6 +84,4 @@ def __init__(self, **data): raise -# At application import time, populate os.environ from .env (if present), then enforce presence. -load_dotenv(override=True) config = Config() diff --git a/pyproject.toml b/pyproject.toml index 04268c8..ecdcacf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,6 @@ dependencies = [ "jsonschema>=4.25.0", "pydantic>=2.11.7", "pydantic-settings>=2.10.1", - "python-dotenv>=1.1.1", ] [dependency-groups] diff --git a/uv.lock b/uv.lock index 0b2c531..4110c67 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.13" [[package]] @@ -99,7 +99,6 @@ dependencies = [ { name = "jsonschema" }, { name = "pydantic" }, { name = "pydantic-settings" }, - { name = "python-dotenv" }, ] [package.dev-dependencies] @@ -117,7 +116,6 @@ requires-dist = [ { name = "jsonschema", specifier = ">=4.25.0" }, { name = "pydantic", specifier = ">=2.11.7" }, { name = "pydantic-settings", specifier = ">=2.10.1" }, - { name = "python-dotenv", specifier = ">=1.1.1" }, ] [package.metadata.requires-dev] From 8da6dffbc2bf4d7a0139065b85383a2f1bbab22d Mon Sep 17 00:00:00 2001 From: Matheus-OAMK Date: Thu, 28 Aug 2025 23:11:22 +0300 Subject: [PATCH 8/9] refactor(Dockerfile): Pin UV version and simplify building stage - Refactiored the dockerfile to have a pinned version of UV for consistent builds. - Simplified dockerfile by utilizing UV's prebuilt image --- Dockerfile | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8112059..85cab20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,6 @@ # Multi-stage build for database schema spec generator # Stage 1: Build the schemas -FROM alpine:3.22.1 AS builder - -# Install Python, uv, and git (needed for some dependencies) -RUN apk add --no-cache python3 py3-pip git - -# Install uv package manager -RUN pip3 install --break-system-packages uv +FROM ghcr.io/astral-sh/uv:0.8.13-alpine3.22 AS builder # Set working directory WORKDIR /app @@ -27,7 +21,7 @@ COPY .env ./ RUN uv run python main.py # Stage 2: Final lightweight image with only the output -FROM alpine:3.22.1 +FROM alpine:3.22 AS final # Create output directory RUN mkdir -p /output From 4acb74364bcf95a292aef1b456415a0a3c5c72ca Mon Sep 17 00:00:00 2001 From: Matheus-OAMK Date: Thu, 28 Aug 2025 23:25:02 +0300 Subject: [PATCH 9/9] refactor(config): Remove leftover comments --- database_schema_spec/core/config.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/database_schema_spec/core/config.py b/database_schema_spec/core/config.py index 552bc62..3978fff 100644 --- a/database_schema_spec/core/config.py +++ b/database_schema_spec/core/config.py @@ -65,10 +65,6 @@ class Config(BaseSettings): def __init__(self, **data): """Initialize config with custom error handling for missing required fields.""" try: - # Enforce presence of required env variables in the process environment - # before delegating to BaseSettings. This ensures tests that clear os.environ - # see the expected ConfigurationError. - super().__init__(**data) except ValidationError as e: # Only handle missing field errors, let other validation errors bubble up