fix: wrap child group transformer in try/catch to keep burst resilient
A throwing custom groupTransformer on a child group member would fail the entire groups-phase burst. Apply the same try/catch + debug/warn logging pattern already used for user member transformation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: pillaris <pillaris@adobe.com>
This commit is contained in:
+64
@@ -728,6 +728,70 @@ describe('MicrosoftGraphIncrementalEntityProvider', () => {
|
||||
expect(parentEntity!.entity.spec?.children).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('logs a warning and skips a child group member when the transformer throws', async () => {
|
||||
const throwingGroupTransformer = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
// first call: parent group transform succeeds
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Group',
|
||||
metadata: {
|
||||
name: 'parent-group',
|
||||
annotations: { 'graph.microsoft.com/group-id': 'grp-parent' },
|
||||
},
|
||||
spec: { type: 'team', children: [], members: [] },
|
||||
})
|
||||
.mockRejectedValueOnce(new Error('Transformer error'));
|
||||
|
||||
(mockClient.getOrganization as jest.Mock).mockResolvedValue({
|
||||
id: 'org-id',
|
||||
displayName: 'My Org',
|
||||
});
|
||||
mockRequestOnePage.mockResolvedValueOnce({
|
||||
items: [
|
||||
{
|
||||
id: 'grp-parent',
|
||||
displayName: 'Parent',
|
||||
mail: 'parent@example.com',
|
||||
},
|
||||
],
|
||||
nextLink: undefined,
|
||||
});
|
||||
(mockClient.getGroupMembers as jest.Mock).mockReturnValue(
|
||||
asyncYield({
|
||||
'@odata.type': '#microsoft.graph.group',
|
||||
id: 'grp-child',
|
||||
displayName: 'Child Group',
|
||||
mail: 'child@example.com',
|
||||
}),
|
||||
);
|
||||
|
||||
const provider = new MicrosoftGraphIncrementalEntityProvider({
|
||||
id: 'default',
|
||||
provider: baseProviderConfig as any,
|
||||
logger,
|
||||
groupTransformer: throwingGroupTransformer,
|
||||
});
|
||||
|
||||
const result = await provider.next(makeContext(), groupsCursor);
|
||||
|
||||
// Parent group still emitted despite child transformer throwing
|
||||
const parentEntity = result.entities!.find(
|
||||
e =>
|
||||
e.entity.metadata.annotations?.[
|
||||
MICROSOFT_GRAPH_GROUP_ID_ANNOTATION
|
||||
] === 'grp-parent',
|
||||
);
|
||||
expect(parentEntity).toBeDefined();
|
||||
expect(parentEntity!.entity.spec?.children).toHaveLength(0);
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'group member child group grp-child failed to transform, skipping',
|
||||
),
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns done:false with groups cursor when nextLink is present', async () => {
|
||||
const nextLink =
|
||||
'https://graph.microsoft.com/v1.0/groups?$skiptoken=page2';
|
||||
|
||||
+22
-7
@@ -481,14 +481,29 @@ export class MicrosoftGraphIncrementalEntityProvider
|
||||
// With a filter, child groups may not be ingested themselves,
|
||||
// which would produce dangling spec.children references.
|
||||
if (!provider.groupFilter && !provider.groupSearch) {
|
||||
const childEntity = await groupTransformer(
|
||||
member as MicrosoftGraph.Group,
|
||||
);
|
||||
if (childEntity) {
|
||||
childEntity.metadata.name = capEntityName(
|
||||
childEntity.metadata.name,
|
||||
try {
|
||||
const childEntity = await groupTransformer(
|
||||
member as MicrosoftGraph.Group,
|
||||
);
|
||||
if (childEntity) {
|
||||
childEntity.metadata.name = capEntityName(
|
||||
childEntity.metadata.name,
|
||||
);
|
||||
childRefs.push(stringifyEntityRef(childEntity));
|
||||
} else {
|
||||
this.options.logger.debug(
|
||||
`${this.getProviderName()}: group member child group ${
|
||||
member.id
|
||||
} could not be transformed (sparse object?), skipping`,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
this.options.logger.warn(
|
||||
`${this.getProviderName()}: group member child group ${
|
||||
member.id
|
||||
} failed to transform, skipping`,
|
||||
{ error: e },
|
||||
);
|
||||
childRefs.push(stringifyEntityRef(childEntity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user