Skip to content

Commit 0224df0

Browse files
EMaherCopilotCopilot
authored
fix: strip schemaId/typeName from operation PATCH during reconciliation (#111)
* fix: strip schemaId/typeName from operation PATCH during reconciliation After spec import, APIM assigns its own auto-generated schema IDs to operation request/response representations. The reconciliation PATCH was sending the source instance's schema IDs, which don't exist on the target. APIM silently drops schemaId/typeName when the referenced schema doesn't exist, causing the compare phase to report missing fields. By stripping these fields from the PATCH body, APIM retains the schema references it assigned during its own spec import. The compare script already normalizes auto-generated hex IDs, so both sides match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: make reconciliation comments terse * docs: tighten reconciliation comments * docs(squad): record schema-ref reconciliation decision * updating cmd to create log file * updating squad files * skipping schema ids, doing semantic compare --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 0942ffa commit 0224df0

5 files changed

Lines changed: 567 additions & 226 deletions

File tree

.squad/decisions.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
## Active Decisions
44

5+
### 2026-06-08T18:52:23Z: Long-Term Maintainability Over Quick Fixes
6+
**By:** User directive (anonymized)
7+
**Status:** Active directive
8+
**What:** When fixing code in tests or product logic, avoid quick/easy fixes and prefer solutions optimized for long-term maintainability.
9+
**Why:** Establishes a durable engineering quality standard and reduces short-lived patchwork changes.
10+
11+
### 2026-06-08T18:50:20Z: Round-Trip Test Default Execution Standard
12+
**By:** User directive (anonymized)
13+
**Status:** Active directive
14+
**What:** When the user asks to run the round-trip test, follow the workflow documented in `tests/integration/all-resource-types/README.md` Quick Commands, default to StandardV2 SKU, and always save the log. Use Premium SKU only when branch-specific changes require Premium-only coverage.
15+
**Why:** Enforces consistent execution defaults and reliable log capture for repeatable integration test runs.
16+
17+
### 2026-06-05T23:40:00Z: Operation reconciliation PATCH strips schema refs
18+
**By:** ApimExpert + TypeScriptDev
19+
**Status:** Implemented
20+
**What:** `reconcileOperationsAfterSpecImport` removes `schemaId` and `typeName` from operation `request.representations` and `responses[].representations` before PATCH.
21+
**Why:** Those IDs are source-instance specific. After target spec import, APIM assigns its own schema IDs; sending stale source IDs causes APIM to drop schema refs.
522
### 2026-07-15: PR #102 Metadata Correction
623
**By:** GitHubExpert
724
**Status:** Applied (partial)

src/services/api-publisher.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,9 @@ async function reconcileOperationsAfterSpecImport(
437437
}
438438
}
439439

440+
// Strip source schema refs; APIM rebinds on import and drops stale IDs.
441+
stripRepresentationSchemaRefs(patchProps);
442+
440443
if (Object.keys(patchProps).length === 0) return;
441444

442445
const patchBody: Record<string, unknown> = { properties: patchProps };
@@ -459,6 +462,39 @@ async function reconcileOperationsAfterSpecImport(
459462
}
460463
}
461464

465+
/** Strip source schema refs from request/response representations before PATCH. */
466+
function stripRepresentationSchemaRefs(patchProps: Record<string, unknown>): void {
467+
const SCHEMA_REF_FIELDS = ['schemaId', 'typeName'];
468+
469+
function stripFromRepresentations(representations: unknown): void {
470+
if (!Array.isArray(representations)) return;
471+
for (const rep of representations) {
472+
if (rep && typeof rep === 'object') {
473+
for (const field of SCHEMA_REF_FIELDS) {
474+
delete (rep as Record<string, unknown>)[field];
475+
}
476+
}
477+
}
478+
}
479+
480+
// Strip schema refs from request.representations.
481+
const request = patchProps.request;
482+
if (request && typeof request === 'object') {
483+
const req = request as Record<string, unknown>;
484+
stripFromRepresentations(req.representations);
485+
}
486+
487+
// Strip schema refs from responses[].representations.
488+
const responses = patchProps.responses;
489+
if (Array.isArray(responses)) {
490+
for (const response of responses) {
491+
if (response && typeof response === 'object') {
492+
stripFromRepresentations((response as Record<string, unknown>).representations);
493+
}
494+
}
495+
}
496+
}
497+
462498
/**
463499
* Extract revision number from API name (e.g., "my-api;rev=2" -> 2)
464500
*/

0 commit comments

Comments
 (0)