Skip to content

Commit 076317f

Browse files
committed
fix: handle NULL status values in migration 008
Fixes production deployment crash where migration 008 fails with: "column status of relation servers contains null values" Problem: - 9 servers in production have explicit "status": null in their JSON - Migration didn't handle NULL values properly when extracting to column - When adding NOT NULL constraint, it failed Solution: - Add COALESCE to official metadata path (handles NULL in official meta) - Use NULLIF to convert string 'null' to SQL NULL, then COALESCE to 'active' - Ensures all status values are non-NULL before constraint is added Affected servers: - 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
1 parent a0bc09d commit 076317f

28 files changed

+109
-112
lines changed

cmd/publisher/commands/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ func createServerJSON(
308308
URL: repoURL,
309309
Source: repoSource,
310310
},
311-
Version: version,
311+
Version: version,
312312
Packages: []model.Package{pkg},
313313
}
314314
}

cmd/publisher/commands/logout.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func LogoutCommand() error {
1313
}
1414

1515
tokenPath := filepath.Join(homeDir, TokenFileName)
16-
16+
1717
// Check if token file exists
1818
if _, err := os.Stat(tokenPath); os.IsNotExist(err) {
1919
_, _ = fmt.Fprintln(os.Stdout, "Not logged in")
@@ -30,7 +30,7 @@ func LogoutCommand() error {
3030
".mcpregistry_github_token",
3131
".mcpregistry_registry_token",
3232
}
33-
33+
3434
for _, file := range legacyFiles {
3535
path := filepath.Join(homeDir, file)
3636
if _, err := os.Stat(path); err == nil {
@@ -40,4 +40,4 @@ func LogoutCommand() error {
4040

4141
_, _ = fmt.Fprintln(os.Stdout, "✓ Successfully logged out")
4242
return nil
43-
}
43+
}

cmd/publisher/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,4 @@ func printUsage() {
6767
_, _ = fmt.Fprintln(os.Stdout, " publish Publish server.json to the registry")
6868
_, _ = fmt.Fprintln(os.Stdout)
6969
_, _ = fmt.Fprintln(os.Stdout, "Use 'mcp-publisher <command> --help' for more information about a command.")
70-
}
70+
}

deploy/pkg/k8s/ingress.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func SetupIngressController(ctx *pulumi.Context, cluster *providers.ProviderInfo
5151
Values: pulumi.Map{
5252
"controller": pulumi.Map{
5353
"service": pulumi.Map{
54-
"type": serviceType,
54+
"type": serviceType,
5555
"annotations": pulumi.Map{},
5656
},
5757
"config": pulumi.Map{

deploy/pkg/providers/gcp/provider.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ type Provider struct{}
2222
// createGCPProvider creates a GCP provider with explicit credentials if configured
2323
func createGCPProvider(ctx *pulumi.Context, name string) (*gcp.Provider, error) {
2424
gcpConf := config.New(ctx, "gcp")
25-
25+
2626
// Get project ID from config
2727
projectID := gcpConf.Get("project")
2828
if projectID == "" {
2929
return nil, fmt.Errorf("GCP project ID not configured. Set gcp:project")
3030
}
31-
31+
3232
// Get region from config or use default
3333
region := gcpConf.Get("region")
3434
if region == "" {
3535
region = "us-central1"
3636
}
37-
37+
3838
// Get credentials from config (base64 encoded service account JSON)
3939
credentials := gcpConf.Get("credentials")
4040
if credentials != "" {
@@ -45,7 +45,7 @@ func createGCPProvider(ctx *pulumi.Context, name string) (*gcp.Provider, error)
4545
}
4646
credentials = string(decodedCreds)
4747
}
48-
48+
4949
// Create a GCP provider with explicit credentials if provided
5050
if credentials != "" {
5151
return gcp.NewProvider(ctx, name, &gcp.ProviderArgs{
@@ -54,7 +54,7 @@ func createGCPProvider(ctx *pulumi.Context, name string) (*gcp.Provider, error)
5454
Credentials: pulumi.String(credentials),
5555
})
5656
}
57-
57+
5858
return nil, nil
5959
}
6060

internal/api/handlers/v0/auth/http_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,6 @@ func TestDefaultHTTPKeyFetcher(t *testing.T) {
387387
}
388388
}
389389

390-
391390
func TestHTTPAuthHandler_Permissions(t *testing.T) {
392391
cfg := &config.Config{
393392
JWTPrivateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
@@ -738,4 +737,3 @@ func TestHTTPvsDNS_PermissionDifferences(t *testing.T) {
738737
})
739738
}
740739
}
741-

internal/api/handlers/v0/edit.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ func RegisterEditEndpoints(api huma.API, registry service.RegistryService, cfg *
9797

9898
// Prevent undeleting servers - once deleted, they stay deleted
9999
if currentServer.Meta.Official != nil &&
100-
currentServer.Meta.Official.Status == model.StatusDeleted &&
101-
newStatus != model.StatusDeleted {
100+
currentServer.Meta.Official.Status == model.StatusDeleted &&
101+
newStatus != model.StatusDeleted {
102102
return nil, huma.Error400BadRequest("Cannot change status of deleted server. Deleted servers cannot be undeleted.")
103103
}
104104

internal/api/handlers/v0/edit_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,4 +639,4 @@ func TestEditServerEndpointEdgeCases(t *testing.T) {
639639
// Helper function
640640
func stringPtr(s string) *string {
641641
return &s
642-
}
642+
}

internal/api/handlers/v0/publish.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ func buildPermissionErrorMessage(attemptedResource string, permissions []auth.Pe
7575
permissionStrs = append(permissionStrs, perm.ResourcePattern)
7676
}
7777
}
78-
78+
7979
errorMsg := "You do not have permission to publish this server"
8080
if len(permissionStrs) > 0 {
8181
errorMsg += ". You have permission to publish: " + strings.Join(permissionStrs, ", ")
8282
} else {
8383
errorMsg += ". You do not have any publish permissions"
8484
}
8585
errorMsg += ". Attempting to publish: " + attemptedResource
86-
86+
8787
return errorMsg
8888
}

internal/api/handlers/v0/publish_integration_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ func TestPublishIntegration(t *testing.T) {
162162

163163
t.Run("publish fails with invalid token", func(t *testing.T) {
164164
publishReq := apiv0.ServerJSON{
165-
Name: "io.github.domdomegg/test-server",
166-
Description: "Test server",
167-
Version: "1.0.0",
165+
Name: "io.github.domdomegg/test-server",
166+
Description: "Test server",
167+
Version: "1.0.0",
168168
}
169169

170170
body, err := json.Marshal(publishReq)
@@ -185,7 +185,7 @@ func TestPublishIntegration(t *testing.T) {
185185
publishReq := apiv0.ServerJSON{
186186
Name: "io.github.other/test-server",
187187
Description: "A test server",
188-
Version: "1.0.0",
188+
Version: "1.0.0",
189189
Repository: model.Repository{
190190
URL: "https://github.com/example/test-server",
191191
Source: "github",
@@ -221,7 +221,7 @@ func TestPublishIntegration(t *testing.T) {
221221
publishReq := apiv0.ServerJSON{
222222
Name: "io.github.domdomegg/airtable-mcp-server",
223223
Description: "A test server with MCPB package",
224-
Version: "1.7.2",
224+
Version: "1.7.2",
225225
Packages: []model.Package{
226226
{
227227
RegistryType: model.RegistryTypeMCPB,

0 commit comments

Comments
 (0)