registry/scripts/mirror_data
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Tadas Antanavicius 2d49e5b68c
fix: prevent NULL status values during migration 008 (#587)
## Summary
- Fixes migration 008 failing with "column contains null values" error
- Adds COALESCE protection to handle 126 servers without status fields
- Includes test utilities to reproduce and verify fixes with production
data

## Problem

Migration 008 was failing in production because:
- 126 out of 781 servers have no `status` field in their JSON
- When extracting `rec.value->>'status'`, these became NULL values
- The `ALTER TABLE servers ALTER COLUMN status SET NOT NULL` constraint
then failed

## Solution

1. **Prevent NULLs during migration**: Use COALESCE to provide 'active'
default when status is NULL/empty
2. **Enhanced debugging**: Added RAISE NOTICE statements to log
problematic values
3. **Safety check**: Double-check that throws exception if any NULLs
remain
4. **Test utilities**: Created mirror_data tools to test migrations with
real production data

## Testing

Created and used `scripts/mirror_data/` tools to:
- Fetch all 781 servers from production API
- Load them into a test database
- Verify the migration fix works correctly

### Results:
- **Before fix**: 126 NULL status values created during migration
- **After fix**: 0 NULL status values, all servers have valid status
- Migration completes successfully with NOT NULL constraint

## Test plan
- [x] Tested locally with production data using mirror_data tools
- [x] Verified 0 NULL values after migration (vs 126 before)
- [x] Confirmed NOT NULL constraint adds successfully
- [ ] Deploy to staging and verify migration succeeds
- [ ] Monitor production deployment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-30 06:43:26 -07:00
..
.gitignore fix: prevent NULL status values during migration 008 (#587) 2025-09-30 06:43:26 -07:00
fetch_production_data.go fix: prevent NULL status values during migration 008 (#587) 2025-09-30 06:43:26 -07:00
load_production_data.go fix: prevent NULL status values during migration 008 (#587) 2025-09-30 06:43:26 -07:00
README.md fix: prevent NULL status values during migration 008 (#587) 2025-09-30 06:43:26 -07:00

Mirror Production Data

Note: These tools were created by Claude Code as a simple way to kick the tires on data migrations. They are not intended for production use.

Tools to fetch and load production registry data for local testing and migration debugging.

Overview

These scripts help you:

  1. Fetch all server data from the production registry API
  2. Load it into a local PostgreSQL database
  3. Test migrations against real production data

Prerequisites

  • Go 1.24.x
  • PostgreSQL (via Docker or local installation)
  • Required Go packages:
    go get github.com/google/uuid github.com/lib/pq
    

Usage

1. Fetch Production Data

# From the project root directory
go run scripts/mirror_data/fetch_production_data.go

This will:

Output: production_servers.json containing all server records

2. Set Up Test Database

Start a PostgreSQL container for testing:

docker run -d --name test-postgres \
  -p 5433:5432 \
  -e POSTGRES_PASSWORD=testpass \
  -e POSTGRES_DB=registry_test \
  postgres:16

Or reset an existing database:

docker exec test-postgres psql -U postgres postgres -c "DROP DATABASE IF EXISTS registry_test;"
docker exec test-postgres psql -U postgres postgres -c "CREATE DATABASE registry_test;"

3. Load Production Data

# From the project root directory
go run scripts/mirror_data/load_production_data.go

This will:

  1. Connect to PostgreSQL at localhost:5433
  2. Apply migrations up to a configurable point (default: migration 007)
  3. Load all production server data
  4. Analyze the data and report statistics
  5. Show sample servers with NULL status values

To test a different migration, edit maxMigration in the script (line 24)

4. Test Migrations

After loading the data, you can test migrations against real production data.

Testing a Single Migration

# Test migration 008
cat internal/database/migrations/008_separate_official_metadata.sql | \
  docker exec -i test-postgres psql -U postgres -d registry_test

Debugging Failed Migrations

  1. Check the error output:
# Run migration and capture all output
cat internal/database/migrations/008_separate_official_metadata.sql | \
  docker exec -i test-postgres psql -U postgres -d registry_test 2>&1 | \
  grep -E "(ERROR|NOTICE|WARNING)"
  1. Inspect data before migration:
# Check for NULL values that might cause issues
docker exec test-postgres psql -U postgres -d registry_test -c \
  "SELECT COUNT(*) FROM servers WHERE value->>'status' IS NULL;"

# Find sample problematic records
docker exec test-postgres psql -U postgres -d registry_test -c \
  "SELECT value->>'name', value->>'version' FROM servers \
   WHERE value->>'status' IS NULL LIMIT 5;"
  1. Test partial migrations:
# Extract and run only part of a migration to isolate issues
# For example, run only up to the NOT NULL constraint:
docker exec test-postgres psql -U postgres -d registry_test <<EOF
BEGIN;
-- Paste migration SQL up to the problematic line
-- Check intermediate state
SELECT COUNT(*) FROM servers WHERE status IS NULL;
ROLLBACK;  -- or COMMIT if testing further
EOF

Testing Migration Rollback

# Start a transaction to test and rollback
docker exec test-postgres psql -U postgres -d registry_test <<EOF
BEGIN;
\i /dev/stdin < internal/database/migrations/008_separate_official_metadata.sql
-- Inspect the results
\d servers
SELECT COUNT(*) FROM servers;
ROLLBACK;  -- Undo all changes
EOF

Iterative Testing Workflow

  1. Reset database to clean state:
docker exec test-postgres psql -U postgres postgres -c "DROP DATABASE IF EXISTS registry_test;"
docker exec test-postgres psql -U postgres postgres -c "CREATE DATABASE registry_test;"
go run scripts/mirror_data/load_production_data.go
  1. Test your migration changes:
cat internal/database/migrations/008_separate_official_metadata.sql | \
  docker exec -i test-postgres psql -U postgres -d registry_test
  1. Verify the results:
# Check final table structure
docker exec test-postgres psql -U postgres -d registry_test -c "\d servers"

# Verify data integrity
docker exec test-postgres psql -U postgres -d registry_test -c \
  "SELECT COUNT(*), COUNT(DISTINCT server_name) FROM servers;"

Common Migration Issues to Check

  • NULL values: Check columns before adding NOT NULL constraints
  • Unique constraints: Verify no duplicates exist before adding
  • Check constraints: Validate all existing data matches the constraint
  • Data type changes: Ensure all values can be cast to new type
  • Foreign keys: Verify referential integrity before adding

5. Clean Up

docker stop test-postgres
docker rm test-postgres

Configuration

The load_production_data.go script connects to:

  • Host: localhost
  • Port: 5433
  • Database: registry_test
  • User: postgres
  • Password: testpass

Modify line 17 in the script if you need different connection parameters.

Example Output

When running load_production_data.go:

Running migrations 001-007...
  Applying migration 1: 001_initial_schema.sql
  Applying migration 2: 002_add_server_extensions.sql
  ...

Loading production data...
Loading 779 servers...
Data loaded successfully!

Total servers in database: 779

Analyzing status field in JSON data...
  Total servers: 779
  NULL status: 126
  Empty status: 0
  'null' string status: 0
  'active' status: 652
  'deprecated' status: 0
  'deleted' status: 0
  Other/Invalid: 1

Sample servers with NULL status:
  - com.biodnd/agent-ip@0.1.2
  - io.github.jkakar/cookwith-mcp@1.0.0
  ...

Database is ready for testing migration 008!

Troubleshooting

Port already in use

If port 5433 is already in use, either:

  • Stop the existing service using that port
  • Use a different port in both the Docker command and the Go script

Connection refused

Ensure the PostgreSQL container is running and healthy:

docker ps | grep test-postgres
docker logs test-postgres

Migration failures

The script stops at migration 007 intentionally. To test migration 008, run it manually after the data is loaded.