Skip to content
Open
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
336 changes: 336 additions & 0 deletions .github/workflows/regenerate-db-types.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
name: Generate Database Types For Schema Changes

on:
pull_request:
paths:
- apps/backend/db/db_setup.sql


permissions:
contents: write
pull-requests: write

env:
NODE_VERSION: '23'
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb

jobs:
regenerate-types:
name: Auto-regenerate DB Types
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-

- name: Install dependencies
run: |
echo "Installing project dependencies"
npm ci --legacy-peer-deps

echo "Installing kysely-codegen globally"
npm install -g kysely-codegen

echo "Verifying kysely-codegen installation"
kysely-codegen --version || {
echo "Error: kysely-codegen installation failed"
exit 1
}

- name: Setup PostgreSQL
uses: ikalnytskyi/action-setup-postgres@v6
with:
username: postgres
password: postgres
database: testdb
port: 5432
id: postgres

- name: Verify PostgreSQL connection
run: |
echo "Testing PostgreSQL connection"
psql -h localhost -U postgres -d testdb -c "SELECT version();"
env:
PGPASSWORD: postgres

- name: Initialize database schema
run: |
echo "Applying database schema"
psql -h localhost -U postgres -d testdb -f apps/backend/db/db_setup.sql

echo "Verifying schema application"
psql -h localhost -U postgres -d testdb -c "\dt"
env:
PGPASSWORD: postgres

- name: Generate types with kysely-codegen
run: |
echo "Starting type generation..."
cd apps/backend/db

# Run kysely-codegen
kysely-codegen \
--url "$DATABASE_URL" \
--out-file db-types.d.ts \
--dialect postgres || {
echo "Error: kysely-codegen failed to generate types"
exit 1
}

# Verify the output file was created
if [ ! -f "db-types.d.ts" ]; then
echo "Error: db-types.d.ts was not generated"
exit 1
fi

echo "Type generation successful"

- name: Copy generated types to lambda functions
run: |
echo "Copying generated types to lambda functions"

SOURCE_FILE="apps/backend/db/db-types.d.ts"

# verify the source file exists
if [ ! -f "$SOURCE_FILE" ]; then
echo "Error: Generated types file not found at $SOURCE_FILE"
exit 1
fi

if [ ! -s "$SOURCE_FILE" ]; then
echo "Error: Generated types file is empty"
exit 1
fi

# Define target lambda directories
LAMBDA_DIRS=()
for dir in apps/backend/lambdas/*; do
if [ -d "$dir" ]; then
LAMBDA_DIRS+=("$dir")
echo " Found: $dir"
fi
done

if [ ${#LAMBDA_DIRS[@]} -eq 0 ]; then
echo "Error: No lambda directories found in apps/backend/lambdas/"
exit 1
fi

# Track success and failures
SUCCESS_COUNT=0
FAIL_COUNT=0

for dir in "${LAMBDA_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "Copying to $dir/db-types.d.ts"
cp "$SOURCE_FILE" "$dir/db-types.d.ts"

if [ $? -eq 0 ]; then
((SUCCESS_COUNT++))
else
echo "Failed to copy to $dir"
((FAIL_COUNT++))
fi
else
echo "Warning: Directory $dir does not exist"
((FAIL_COUNT++))
fi
done

echo ""
echo "Copy summary: $SUCCESS_COUNT succeeded, $FAIL_COUNT failed"

if [ $SUCCESS_COUNT -eq 0 ]; then
echo "Error: Failed to copy types to any lambda function"
exit 1
fi

- name: Verify TypeScript compilation
run: |
echo "Verifying TypeScript compilation"

# check if tsconfig.json exists

if [ ! -f "tsconfig.json" ]; then
echo "Warning: tsconfig.json not found in root, skipping full compilation check"
echo "Performing basic syntax check on generated types..."

# Ensure the file is valid TypeScript
for file in apps/backend/lambdas/*/db-types.d.ts; do
if [ -f "$file" ]; then
npx tsc --noEmit --skipLibCheck "$file" || {
echo "Error: $file contains TypeScript errors"
exit 1
}
fi
done
else
npx tsc --noEmit --skipLibCheck || {
echo "Error: TypeScript compilation failed"
echo "The generated database types may be incompatible with the codebase."
exit 1
}
fi

echo "TypeScript compilation successful"

- name: Check for changes
id: git-check
run: |
git add -N apps/backend/lambdas/*/db-types.d.ts

if git diff --exit-code apps/backend/lambdas/*/db-types.d.ts; then
echo "changes=false" >> $GITHUB_OUTPUT
echo "No changes detected in generated types"
else
echo "changes=true" >> $GITHUB_OUTPUT
echo "Changes detected in generated types"

echo "Changed files:"
git diff --name-only apps/backend/lambdas/*/db-types.d.ts
fi

- name: Get PR author information
if: steps.git-check.outputs.changes == 'true'
id: pr-author
run: |
# username
PR_AUTHOR_NAME="${{ github.event.pull_request.user.login }}"
PR_AUTHOR_EMAIL="${{ github.event.pull_request.user.login }}@users.noreply.github.com"

REAL_EMAIL=$(gh api /users/${{ github.event.pull_request.user.login }} --jq '.email' 2>/dev/null || echo "")

if [ -n "$REAL_EMAIL" ] && [ "$REAL_EMAIL" != "null" ]; then
PR_AUTHOR_EMAIL="$REAL_EMAIL"
fi

echo "name=$PR_AUTHOR_NAME" >> $GITHUB_OUTPUT
echo "email=$PR_AUTHOR_EMAIL" >> $GITHUB_OUTPUT

echo "PR Author: $PR_AUTHOR_NAME <$PR_AUTHOR_EMAIL>"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Commit and push changes
if: steps.git-check.outputs.changes == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

git add apps/backend/lambdas/*/db-types.d.ts

COMMIT_MESSAGE="chore: auto-regenerate database types from schema changes"

if [ -n "${{ steps.pr-author.outputs.name }}" ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE}

Co-authored-by: ${{ steps.pr-author.outputs.name }} <${{ steps.pr-author.outputs.email }}>"
fi

git commit -m "$COMMIT_MESSAGE"

git push origin HEAD:${{ github.head_ref }}

echo "Changes committed + pushed successfully"

- name: Comment on PR
if: steps.git-check.outputs.changes == 'true'
uses: actions/github-script@v7
with:
script: |
const { execSync } = require('child_process');
const files = execSync('git diff --name-only apps/backend/lambdas/*/db-types.d.ts')
.toString()
.trim()
.split('\n')
.filter(f => f)
.map(f => `- \`${f}\``)
.join('\n');

const comment = `**Database Types Auto-Regenerated**

The database schema has changed and the Typescript definitions for these lambda functions were regenerated:

${files}

The updated types are now in sync with schema changes.`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});

- name: Comment on PR if no changes
if: steps.git-check.outputs.changes != 'true'
uses: actions/github-script@v7
with:
script: |
const comment = `**Database Types Check Complete**

The database schema files were modified, but the regenerated TypeScript types are identical to the existing ones.

No changes were needed and the type definitions are already up to date.`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});

- name: Workflow summary
if: always()
run: |
echo "## 🔄 Database Type Regeneration Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ steps.git-check.outputs.changes }}" == "true" ]; then
echo "### Status: Types Regenerated Successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The following files were updated and committed:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

for file in apps/backend/lambdas/*/db-types.d.ts; do
if [ -f "$file" ]; then
echo "- \`$file\`" >> $GITHUB_STEP_SUMMARY
fi
done

echo "" >> $GITHUB_STEP_SUMMARY
echo "**Next Steps:** The changes have been automatically committed to this PR. Review the updated types and merge when ready." >> $GITHUB_STEP_SUMMARY
else
echo "### Status: No Changes Needed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The regenerated types are identical to the existing ones." >> $GITHUB_STEP_SUMMARY
echo "Your type definitions are already in sync with the schema." >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Workflow Trigger:** Schema change detected in:" >> $GITHUB_STEP_SUMMARY
echo "- \`apps/backend/db/db_setup.sql\`" >> $GITHUB_STEP_SUMMARY