fix(import,migrate): prevent destructive blueprint relation and scorecard updates#77
Merged
EricFernandezPort merged 4 commits intoJun 11, 2026
Conversation
Use fetch-and-merge on the 409 update path in both import and migrate so that a Phase 1 PUT (which strips relations for dependency ordering) never removes existing relation definitions from the target. Phase 2a then restores the import file's relations as the final state. This is a single structural safeguard that covers all scenarios: --skip-entities, --include blueprints, circular deps, and normal imports. Co-authored-by: Cursor <cursoragent@cursor.com>
…ng deletion The scorecard conflict/update path used UpdateScorecards (bulk PUT to /blueprints/:id/scorecards) which replaces the entire scorecard collection. When only a subset of scorecards were sent, all other scorecards on that blueprint were deleted. Switch both import and migrate to use UpdateScorecard (singular PATCH to /blueprints/:id/scorecards/:id) for updates, consistent with the additive semantics used by teams, users, pages, and integrations. Co-authored-by: Cursor <cursoragent@cursor.com>
The Port API has no PATCH endpoint for individual scorecards, causing 404 errors on update. Instead, fetch the existing scorecard set, merge in the updates (preserving sibling scorecards), and bulk PUT the result. Applies to both import and migrate modules. Co-authored-by: Cursor <cursoragent@cursor.com>
76b84d8 to
298d581
Compare
GetBlueprint returns audit fields (createdAt, updatedAt, createdBy, updatedBy, id) that were being forwarded to UpdateBlueprint unchanged. Strip these before every blueprint PUT in both import and migrate to prevent breakage if the API tightens validation. Also removes accidentally committed port-cli binary. Co-authored-by: Cursor <cursoragent@cursor.com>
298d581 to
4f438d6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes two safety issues in
port importandport migratethat could silently destroy production data:1. Blueprint relation stripping destroys entity relation data
When importing blueprints, Phase 1 strips relation fields to handle circular dependencies. The subsequent PUT replaces the entire blueprint, permanently removing all relation definitions — and with them, every entity-level relation value.
Fix:
createOrUpdateBlueprintnow fetches the existing blueprint before updating and merges incoming fields on top, preserving any fields not present in the import payload (including stripped relations).2. Scorecard updates via non-existent PATCH endpoint (404)
On conflict during scorecard creation, the CLI attempted
PATCH /blueprints/{bp}/scorecards/{id}which does not exist in the Port API, producing 404 errors.Fix: On conflict, the CLI now fetches the full scorecard set for the blueprint, merges in the updated scorecards (preserving sibling scorecards), and performs a single bulk
PUT /blueprints/{bp}/scorecards. This is additive — existing scorecards not in the import payload are preserved.Test plan
TestImportScorecards_ConflictUsesFetchMergePUT— verifies fetch-merge-bulk-PUT flow on conflictTestImportScorecards_BulkPutFailureRecordsError— verifies error recording on bulk PUT failurego test ./...passes