Fix env_to_branch migration

This commit is contained in:
Konstantin Wohlwend 2026-01-23 17:17:43 -08:00
parent 70ead41121
commit 3bb31badcd
2 changed files with 74 additions and 18 deletions

View File

@ -1,4 +1,4 @@
name: DB migrations are backwards-compatible with main branch
name: DB migrations are backwards-compatible
on:
push:
@ -16,6 +16,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
migrations_changed: ${{ steps.check-diff.outputs.migrations_changed }}
base_branch: ${{ steps.check-diff.outputs.base_branch }}
steps:
- name: Checkout current branch
uses: actions/checkout@v6
@ -25,9 +26,17 @@ jobs:
- name: Check for migration changes
id: check-diff
run: |
# Get the merge base with main
git fetch origin main
MERGE_BASE=$(git merge-base HEAD origin/main)
# Determine base branch: dev compares to main, all others compare to dev
if [ "${{ github.ref }}" = "refs/heads/dev" ]; then
BASE_BRANCH="main"
else
BASE_BRANCH="dev"
fi
echo "base_branch=$BASE_BRANCH" >> $GITHUB_OUTPUT
# Get the merge base with the base branch
git fetch origin $BASE_BRANCH
MERGE_BASE=$(git merge-base HEAD origin/$BASE_BRANCH)
# Check if there are any changes in the migrations folder
if git diff --quiet "$MERGE_BASE" HEAD -- apps/backend/prisma/migrations/; then
@ -39,7 +48,7 @@ jobs:
fi
backwards-compatibility:
name: Test migrations with main branch code
name: Test migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code
needs: check-migrations-changed
if: needs.check-migrations-changed.outputs.migrations_changed == 'true'
runs-on: ubicloud-standard-8
@ -61,19 +70,19 @@ jobs:
mkdir -p saved-migrations
cp -r current-branch/apps/backend/prisma/migrations/* saved-migrations/
# Now checkout main branch
- name: Checkout main branch
# Now checkout base branch (main for dev, dev for all others)
- name: Checkout base branch
uses: actions/checkout@v6
with:
ref: main
path: main-branch
ref: ${{ needs.check-migrations-changed.outputs.base_branch }}
path: base-branch
# Move main-branch to the root for the rest of the workflow (keep main's migrations for now)
# Move base-branch to the root for the rest of the workflow (keep base's migrations for now)
- name: Setup working directory
run: |
shopt -s dotglob
mv main-branch/* .
rm -rf main-branch current-branch
mv base-branch/* .
rm -rf base-branch current-branch
- name: Setup Node.js
uses: actions/setup-node@v6
@ -187,8 +196,8 @@ jobs:
- name: Wait 10 seconds
run: sleep 10
# First test run: main branch with main's migrations
- name: Run tests (main branch with original migrations)
# First test run: base branch with base's migrations
- name: Run tests (base branch with original migrations)
run: pnpm test
# Now copy over current branch's migrations and run migrate
@ -201,8 +210,8 @@ jobs:
- name: Run database migrations
run: pnpm run db:migrate
# Second test run: main branch code with new migrations applied
- name: Run tests (main branch with new migrations)
# Second test run: base branch code with new migrations applied
- name: Run tests (base branch with new migrations)
run: pnpm test
- name: Verify data integrity

View File

@ -178,6 +178,52 @@ END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- SPLIT_STATEMENT_SENTINEL
-- Create function to flatten nested JSONB into dot-notation
-- e.g., {"auth": {"oauth": {"providers": {"github": {"isShared": true}}}}}
-- becomes {"auth.oauth.providers.github.isShared": true}
-- SPLIT_STATEMENT_SENTINEL
-- SINGLE_STATEMENT_SENTINEL
CREATE OR REPLACE FUNCTION temp_flatten_config(config JSONB, path_prefix TEXT DEFAULT '')
RETURNS JSONB AS $$
DECLARE
result JSONB := '{}'::jsonb;
key TEXT;
value JSONB;
full_path TEXT;
flattened_child JSONB;
child_key TEXT;
child_value JSONB;
BEGIN
IF config IS NULL THEN
RETURN '{}'::jsonb;
END IF;
FOR key, value IN SELECT * FROM jsonb_each(config) LOOP
-- Build the full path for this key
IF path_prefix = '' THEN
full_path := key;
ELSE
full_path := path_prefix || '.' || key;
END IF;
-- If value is an object, recurse and flatten
IF jsonb_typeof(value) = 'object' THEN
flattened_child := temp_flatten_config(value, full_path);
-- Merge all flattened child keys into result
FOR child_key, child_value IN SELECT * FROM jsonb_each(flattened_child) LOOP
result := result || jsonb_build_object(child_key, child_value);
END LOOP;
ELSE
-- Non-object values: add with full dot-notation path
result := result || jsonb_build_object(full_path, value);
END IF;
END LOOP;
RETURN result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- SPLIT_STATEMENT_SENTINEL
-- Create temporary index to speed up the migration
-- SPLIT_STATEMENT_SENTINEL
-- SINGLE_STATEMENT_SENTINEL
@ -216,7 +262,7 @@ inserted AS (
),
updated AS (
UPDATE "EnvironmentConfigOverride" eco
SET "config" = temp_filter_env_only_config(eco."config"),
SET "config" = temp_flatten_config(temp_filter_env_only_config(eco."config")),
"updatedAt" = CURRENT_TIMESTAMP
FROM inserted i
WHERE eco."projectId" = i."projectId"
@ -259,7 +305,7 @@ upserted_branch AS (
RETURNING "projectId", "branchId"
)
UPDATE "EnvironmentConfigOverride" eco
SET "config" = temp_filter_env_only_config(eco."config"),
SET "config" = temp_flatten_config(temp_filter_env_only_config(eco."config")),
"updatedAt" = CURRENT_TIMESTAMP
FROM leftover_configs lc
WHERE eco."projectId" = lc."projectId"
@ -267,6 +313,7 @@ WHERE eco."projectId" = lc."projectId"
-- SPLIT_STATEMENT_SENTINEL
-- Clean up temporary functions
DROP FUNCTION IF EXISTS temp_flatten_config(JSONB, TEXT);
DROP FUNCTION IF EXISTS temp_filter_env_only_config(JSONB);
DROP FUNCTION IF EXISTS temp_filter_branch_config(JSONB);
DROP FUNCTION IF EXISTS temp_filter_config(JSONB, BOOLEAN, TEXT);