Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/validate-python-types.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Validate Python Type Generation

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
validate-python-types:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build project
run: npm run build

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install Python dependencies
run: |
pip install pydantic mypy

- name: Start test database
working-directory: test/db
run: |
docker compose up -d --wait

- name: Wait for database to be ready
run: |
# Install PostgreSQL client for health check
sudo apt-get update && sudo apt-get install -y postgresql-client
until pg_isready -h localhost -p 5432 -U postgres; do
echo "Waiting for database..."
sleep 1
done
echo "Database is ready!"

- name: Generate Python types
id: generate-types
run: |
node --loader ts-node/esm scripts/generate-python-types-test.ts > generated_types.py
echo "Generated Python types (first 30 lines):"
head -30 generated_types.py

- name: Validate Python types runtime
run: |
python -c "import generated_types; print('✓ Generated Python types are valid and can be imported')"

- name: Validate Python types with mypy
run: |
mypy generated_types.py --strict

- name: Cleanup
if: always()
working-directory: test/db
run: docker compose down
44 changes: 44 additions & 0 deletions scripts/generate-python-types-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env node

/**
* Script to generate Python types for CI validation
* This script uses the test database setup to generate Python types
*/

import { build } from '../src/server/app.js'

const TEST_CONNECTION_STRING = 'postgresql://postgres:postgres@localhost:5432'

async function generatePythonTypes() {
const app = build()

try {
const response = await app.inject({
method: 'GET',
url: '/generators/python',
headers: {
pg: TEST_CONNECTION_STRING,
},
query: {
access_control: 'public',
},
})

if (response.statusCode !== 200) {
console.error(`Failed to generate types: ${response.statusCode}`)
console.error(response.body)
process.exit(1)
}

// Write to stdout so it can be captured
process.stdout.write(response.body)
} catch (error) {
console.error('Error generating Python types:', error)
process.exit(1)
} finally {
await app.close()
}
}

generatePythonTypes()

3 changes: 2 additions & 1 deletion test/db/00-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ CREATE TABLE public.users (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name text,
status user_status DEFAULT 'ACTIVE',
decimal numeric
decimal numeric,
user_uuid uuid DEFAULT gen_random_uuid()
);
INSERT INTO
public.users (name)
Expand Down
20 changes: 10 additions & 10 deletions test/lib/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ test('list set-returning function with single object limit', async () => {
"definition": "
SELECT * FROM public.users_audit WHERE user_id = user_row.id;
",
"id": 16506,
"id": 16507,
"identity_argument_types": "user_row users",
"is_set_returning_function": true,
"language": "sql",
"name": "get_user_audit_setof_single_row",
"prorows": 1,
"return_type": "SETOF users_audit",
"return_type_id": 16418,
"return_type_relation_id": 16416,
"return_type_id": 16419,
"return_type_relation_id": 16417,
"schema": "public",
"security_definer": false,
},
Expand Down Expand Up @@ -118,15 +118,15 @@ test('list set-returning function with multiples definitions', async () => {
"definition": "
SELECT * FROM public.todos WHERE "user-id" = user_row.id;
",
"id": 16509,
"id": 16510,
"identity_argument_types": "user_row users",
"is_set_returning_function": true,
"language": "sql",
"name": "get_todos_setof_rows",
"prorows": 1000,
"return_type": "SETOF todos",
"return_type_id": 16404,
"return_type_relation_id": 16402,
"return_type_id": 16405,
"return_type_relation_id": 16403,
"schema": "public",
"security_definer": false,
},
Expand All @@ -136,7 +136,7 @@ test('list set-returning function with multiples definitions', async () => {
"has_default": false,
"mode": "in",
"name": "todo_row",
"type_id": 16404,
"type_id": 16405,
},
],
"argument_types": "todo_row todos",
Expand All @@ -153,15 +153,15 @@ test('list set-returning function with multiples definitions', async () => {
"definition": "
SELECT * FROM public.todos WHERE "user-id" = todo_row."user-id";
",
"id": 16510,
"id": 16511,
"identity_argument_types": "todo_row todos",
"is_set_returning_function": true,
"language": "sql",
"name": "get_todos_setof_rows",
"prorows": 1000,
"return_type": "SETOF todos",
"return_type_id": 16404,
"return_type_relation_id": 16402,
"return_type_id": 16405,
"return_type_relation_id": 16403,
"schema": "public",
"security_definer": false,
},
Expand Down
18 changes: 18 additions & 0 deletions test/lib/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,24 @@ test('list', async () => {
"schema": "public",
"table": "users",
},
{
"check": null,
"comment": null,
"data_type": "uuid",
"default_value": "gen_random_uuid()",
"enums": [],
"format": "uuid",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
"is_nullable": true,
"is_unique": false,
"is_updatable": true,
"name": "user_uuid",
"ordinal_position": 5,
"schema": "public",
"table": "users",
},
],
"comment": null,
"dead_rows_estimate": Any<Number>,
Expand Down
2 changes: 1 addition & 1 deletion test/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ test('list types with include Table Types', async () => {
"id": Any<Number>,
"name": "todos",
"schema": "public",
"type_relation_id": 16402,
"type_relation_id": 16403,
}
`
)
Expand Down
24 changes: 12 additions & 12 deletions test/lib/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test('list', async () => {
"default_value": null,
"enums": [],
"format": "int8",
"id": "16423.1",
"id": "16424.1",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
Expand All @@ -26,7 +26,7 @@ test('list', async () => {
"ordinal_position": 1,
"schema": "public",
"table": "todos_view",
"table_id": 16423,
"table_id": 16424,
},
{
"check": null,
Expand All @@ -35,7 +35,7 @@ test('list', async () => {
"default_value": null,
"enums": [],
"format": "text",
"id": "16423.2",
"id": "16424.2",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
Expand All @@ -46,7 +46,7 @@ test('list', async () => {
"ordinal_position": 2,
"schema": "public",
"table": "todos_view",
"table_id": 16423,
"table_id": 16424,
},
{
"check": null,
Expand All @@ -55,7 +55,7 @@ test('list', async () => {
"default_value": null,
"enums": [],
"format": "int8",
"id": "16423.3",
"id": "16424.3",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
Expand All @@ -66,7 +66,7 @@ test('list', async () => {
"ordinal_position": 3,
"schema": "public",
"table": "todos_view",
"table_id": 16423,
"table_id": 16424,
},
],
"comment": null,
Expand Down Expand Up @@ -112,7 +112,7 @@ test('retrieve', async () => {
"default_value": null,
"enums": [],
"format": "int8",
"id": "16423.1",
"id": "16424.1",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
Expand All @@ -123,7 +123,7 @@ test('retrieve', async () => {
"ordinal_position": 1,
"schema": "public",
"table": "todos_view",
"table_id": 16423,
"table_id": 16424,
},
{
"check": null,
Expand All @@ -132,7 +132,7 @@ test('retrieve', async () => {
"default_value": null,
"enums": [],
"format": "text",
"id": "16423.2",
"id": "16424.2",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
Expand All @@ -143,7 +143,7 @@ test('retrieve', async () => {
"ordinal_position": 2,
"schema": "public",
"table": "todos_view",
"table_id": 16423,
"table_id": 16424,
},
{
"check": null,
Expand All @@ -152,7 +152,7 @@ test('retrieve', async () => {
"default_value": null,
"enums": [],
"format": "int8",
"id": "16423.3",
"id": "16424.3",
"identity_generation": null,
"is_generated": false,
"is_identity": false,
Expand All @@ -163,7 +163,7 @@ test('retrieve', async () => {
"ordinal_position": 3,
"schema": "public",
"table": "todos_view",
"table_id": 16423,
"table_id": 16424,
},
],
"comment": null,
Expand Down
6 changes: 3 additions & 3 deletions test/server/indexes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test('list indexes', async () => {
0,
],
"comment": null,
"id": 16399,
"id": 16400,
"index_attributes": [
{
"attribute_name": "id",
Expand Down Expand Up @@ -57,7 +57,7 @@ test('list indexes', async () => {
})

test('retrieve index', async () => {
const res = await app.inject({ method: 'GET', path: '/indexes/16399' })
const res = await app.inject({ method: 'GET', path: '/indexes/16400' })
const index = res.json<PostgresIndex>()
expect(index).toMatchInlineSnapshot(
`
Expand All @@ -71,7 +71,7 @@ test('retrieve index', async () => {
0,
],
"comment": null,
"id": 16399,
"id": 16400,
"index_attributes": [
{
"attribute_name": "id",
Expand Down
Loading