<!-- Provide a brief summary of your changes --> ## Motivation and Context <!-- Why is this change needed? What problem does it solve? --> The following PR fixes an issue we introduced on September, 30th that caused some of the migrations to not apply. This PR fixes it. After merging we'll have to reset staging as this would not work there (this is expected). ## 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: --> - [x] 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>
204 lines
No EOL
5.7 KiB
PL/PgSQL
204 lines
No EOL
5.7 KiB
PL/PgSQL
-- Migrate package references to canonical format
|
|
-- This migration:
|
|
-- - Converts OCI packages to use canonical single-line references (registry/namespace/image:tag)
|
|
-- - Removes redundant version and registryBaseUrl fields from MCPB packages
|
|
-- - Removes package-type-specific forbidden fields (e.g., fileSha256 from non-MCPB packages)
|
|
-- - Ensures all packages have required transport field
|
|
|
|
BEGIN;
|
|
|
|
-- Helper function to convert OCI package to canonical reference format
|
|
CREATE OR REPLACE FUNCTION convert_oci_package_to_canonical(pkg jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
result jsonb;
|
|
registry_url text;
|
|
registry_host text;
|
|
identifier text;
|
|
version_str text;
|
|
canonical_ref text;
|
|
BEGIN
|
|
-- Start with the original package
|
|
result := pkg;
|
|
|
|
-- Only process OCI packages
|
|
IF pkg->>'registryType' != 'oci' THEN
|
|
RETURN result;
|
|
END IF;
|
|
|
|
-- Get current values
|
|
registry_url := pkg->>'registryBaseUrl';
|
|
identifier := pkg->>'identifier';
|
|
version_str := pkg->>'version';
|
|
|
|
-- Skip if already in canonical format (no registryBaseUrl and no separate version)
|
|
-- Canonical format has registry in identifier like "ghcr.io/owner/repo:tag"
|
|
IF registry_url IS NULL AND (identifier LIKE '%:%' OR identifier LIKE '%@sha256:%') THEN
|
|
RETURN result;
|
|
END IF;
|
|
|
|
-- Extract registry host from registryBaseUrl
|
|
IF registry_url IS NOT NULL THEN
|
|
registry_host := regexp_replace(registry_url, '^https?://', '');
|
|
ELSE
|
|
-- Default to docker.io if no registry specified
|
|
registry_host := 'docker.io';
|
|
END IF;
|
|
|
|
-- Build canonical reference
|
|
-- Format: registry/namespace/image:tag
|
|
IF version_str IS NOT NULL AND version_str != '' THEN
|
|
canonical_ref := registry_host || '/' || identifier || ':' || version_str;
|
|
ELSE
|
|
-- Default to 'latest' tag if no version specified
|
|
canonical_ref := registry_host || '/' || identifier || ':latest';
|
|
END IF;
|
|
|
|
-- Update identifier to canonical reference
|
|
result := jsonb_set(result, '{identifier}', to_jsonb(canonical_ref));
|
|
|
|
-- Remove registryBaseUrl field (no longer needed for OCI)
|
|
result := result - 'registryBaseUrl';
|
|
|
|
-- Remove version field (now part of identifier for OCI)
|
|
result := result - 'version';
|
|
|
|
RETURN result;
|
|
END;
|
|
$$;
|
|
|
|
-- Helper function to convert MCPB package to canonical reference format
|
|
CREATE OR REPLACE FUNCTION convert_mcpb_package_to_canonical(pkg jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
result jsonb;
|
|
BEGIN
|
|
-- Start with the original package
|
|
result := pkg;
|
|
|
|
-- Only process MCPB packages
|
|
IF pkg->>'registryType' != 'mcpb' THEN
|
|
RETURN result;
|
|
END IF;
|
|
|
|
-- Remove version field if it exists (version is embedded in the download URL)
|
|
result := result - 'version';
|
|
|
|
-- Remove registryBaseUrl field if it exists (not needed for MCPB)
|
|
result := result - 'registryBaseUrl';
|
|
|
|
RETURN result;
|
|
END;
|
|
$$;
|
|
|
|
-- Helper function to remove package-type-specific forbidden fields
|
|
CREATE OR REPLACE FUNCTION remove_forbidden_fields(pkg jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
result jsonb;
|
|
registry_type text;
|
|
BEGIN
|
|
result := pkg;
|
|
registry_type := pkg->>'registryType';
|
|
|
|
-- Remove fileSha256 from non-MCPB packages (it's MCPB-only)
|
|
IF registry_type != 'mcpb' AND result ? 'fileSha256' THEN
|
|
result := result - 'fileSha256';
|
|
END IF;
|
|
|
|
RETURN result;
|
|
END;
|
|
$$;
|
|
|
|
-- Helper function to ensure transport field exists
|
|
CREATE OR REPLACE FUNCTION ensure_transport_field(pkg jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
result jsonb;
|
|
registry_type text;
|
|
runtime_hint text;
|
|
BEGIN
|
|
result := pkg;
|
|
|
|
-- If transport already exists, return as-is
|
|
IF result ? 'transport' THEN
|
|
RETURN result;
|
|
END IF;
|
|
|
|
-- Get registry type and runtime hint
|
|
registry_type := pkg->>'registryType';
|
|
runtime_hint := pkg->>'runtimeHint';
|
|
|
|
-- Add default transport based on package type
|
|
-- Most packages use stdio transport
|
|
result := jsonb_set(result, '{transport}', '{"type": "stdio"}'::jsonb);
|
|
|
|
RETURN result;
|
|
END;
|
|
$$;
|
|
|
|
-- Helper function to convert all packages in a packages array
|
|
CREATE OR REPLACE FUNCTION convert_packages_array(packages jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
result jsonb := '[]'::jsonb;
|
|
pkg jsonb;
|
|
BEGIN
|
|
-- Handle null or empty arrays
|
|
IF packages IS NULL OR jsonb_array_length(packages) = 0 THEN
|
|
RETURN packages;
|
|
END IF;
|
|
|
|
-- Process each package
|
|
FOR pkg IN SELECT * FROM jsonb_array_elements(packages)
|
|
LOOP
|
|
-- First convert OCI packages to canonical format
|
|
pkg := convert_oci_package_to_canonical(pkg);
|
|
|
|
-- Then convert MCPB packages to canonical format
|
|
pkg := convert_mcpb_package_to_canonical(pkg);
|
|
|
|
-- Remove package-type-specific forbidden fields
|
|
pkg := remove_forbidden_fields(pkg);
|
|
|
|
-- Finally ensure transport field exists
|
|
pkg := ensure_transport_field(pkg);
|
|
|
|
-- Add to result array
|
|
result := result || jsonb_build_array(pkg);
|
|
END LOOP;
|
|
|
|
RETURN result;
|
|
END;
|
|
$$;
|
|
|
|
-- Migrate all server packages to canonical format
|
|
-- After migration 003, all data is stored in the 'value' JSONB column
|
|
UPDATE servers
|
|
SET value = jsonb_set(
|
|
value,
|
|
'{packages}',
|
|
convert_packages_array(value->'packages')
|
|
)
|
|
WHERE value ? 'packages'
|
|
AND value->'packages' IS NOT NULL
|
|
AND jsonb_array_length(value->'packages') > 0;
|
|
|
|
-- Clean up helper functions
|
|
DROP FUNCTION IF EXISTS convert_oci_package_to_canonical(jsonb);
|
|
DROP FUNCTION IF EXISTS convert_mcpb_package_to_canonical(jsonb);
|
|
DROP FUNCTION IF EXISTS remove_forbidden_fields(jsonb);
|
|
DROP FUNCTION IF EXISTS ensure_transport_field(jsonb);
|
|
DROP FUNCTION IF EXISTS convert_packages_array(jsonb);
|
|
|
|
COMMIT; |