Commit graph registry/internal/database/migrations/008_separate_official_metadata.sql
Author SHA1 Message 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
Radoslav Dimitrov
e39b008b41
Ensure we populate sane defaults for NULL values (#583)
<!-- Provide a brief summary of your changes -->

## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR tries to ensure sane defaults for entries that for one
reason or another have NULL values for some of their properties.

## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->

## Breaking Changes
<!-- Will users need to update their code or configurations? -->

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed

## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->

---------

Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
2025-09-30 15:47:18 +03:00
Tadas Antanavicius
3dc4f93370
fix: handle NULL status values in migration 008 (#578)
## Problem

Production deployment is failing with CrashLoopBackOff. Migration 008
fails with:
```
ERROR: column "status" of relation "servers" contains null values (SQLSTATE 23502)
```

## Root Cause

The migration extracts the `status` field from an unexpected location in
the data structure.

### Actual Data Structure (Before Migration)

In the current format, `status` is at the **top level** of the JSON, not
nested in official metadata:

```json
{
  "name": "com.example/server",
  "version": "1.0.0",
  "status": "active",           ← STATUS IS HERE (top level)
  "_meta": {
    "io.modelcontextprotocol.registry/official": {
      "serverId": "uuid",
      "publishedAt": "2025-09-01T00:00:00Z",
      "isLatest": true
      // NO STATUS FIELD HERE
    }
  }
}
```

For 120 out of 765 servers, the status field is **missing entirely**:
```json
{
  "name": "com.biodnd/agent-ip",
  "version": "0.1.2",
  // ← NO STATUS FIELD AT ALL
  "_meta": {
    "io.modelcontextprotocol.registry/official": {
      "serverId": "uuid",
      "publishedAt": "2025-09-23T09:47:07Z",
      "isLatest": true
      // STILL NO STATUS FIELD HERE
    }
  }
}
```

### Original Migration Logic

```sql
IF official_meta IS NOT NULL THEN
    UPDATE servers
    SET
        status = (official_meta->>'status'),  -- Extracts NULL for all servers
```

**Result:** 
- All 765 servers would have NULL status extracted
- Because `official_meta->>'status'` returns NULL (field doesn't exist
there)
- The migration tries to add `NOT NULL` constraint → fails

### Fixed Migration Logic

```sql
IF official_meta IS NOT NULL THEN
    UPDATE servers
    SET
        status = COALESCE(NULLIF(rec.value->>'status', 'null'), 'active'),
```

**Result:**
- Extracts from top-level JSON where status actually exists
- `NULLIF(rec.value->>'status', 'null')` handles edge case of literal
string "null"
- `COALESCE(..., 'active')` provides fallback when status is missing
- All servers get valid status value

### Impact Breakdown

**645 servers with `"status": "active"`:**
- Before fix: Would extract NULL → migration fails
- After fix: Extracts "active" correctly

**120 servers with missing status field:**
- Before fix: Would extract NULL → migration fails  
- After fix: Defaults to 'active' via COALESCE

## Example Servers with Missing Status

(First 9 discovered during investigation)
- com.biodnd/agent-ip
- io.github.jkakar/cookwith-mcp
- com.joelverhagen.mcp/Knapcode.SampleMcpServer
- io.github.Lyellr88/marm-mcp-server
- com.biodnd/agent-press
- io.github.timheuer/sampledotnetmcpserver
- io.github.CodeCraftersLLC/local-voice-mcp
- com.biodnd/agent-fin
- io.github.ruvnet/ruv-swarm

## Testing

Verified against production data (765 total servers):
- ✅ All servers have official metadata
- ✅ None have status in official metadata (expected)
- ✅ 645 have "status": "active" at top level
- ✅ 120 have missing status field (no field present)
- ✅ Fix extracts from correct location for all cases

## Impact

This unblocks production deployment. Once merged and released as v1.2.1,
the migration will:
1. Extract status from the correct location (top-level JSON)
2. Handle missing status fields with sensible defaults
3. Successfully add NOT NULL constraint
4. Allow pods to start normally

---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
2025-09-30 10:21:48 +03:00
Radoslav Dimitrov
b21c6f564d
Changes on the server.json format and the API (#562) 2025-09-29 23:30:35 +03:00