Skip to content

Commit 699b636

Browse files
Fix broken scaffolder events parser (#1678)
* fix(bulk-import): replace @microsoft/fetch-event-source(working only with frontend) to eventsource Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com> * feat(bulk-import): use newer moder eventsource-client Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com> * feat(bulk-import): cleanup log Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com> * fix(bulk-import): remove non-existent template refs and add scaffolder configuration Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com> * fix(bulk-import): fix format Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com> --------- Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>
1 parent f379b0d commit 699b636

4 files changed

Lines changed: 40 additions & 78 deletions

File tree

workspaces/bulk-import/app-config.yaml

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,11 @@ catalog:
9696
target: ../../examples/entities.yaml
9797

9898
# Local example templates
99-
- type: file
100-
target: ../../examples/template/get-default-branch.yaml
101-
rules:
102-
- allow: [Template]
103-
104-
- type: file
105-
target: ../../examples/template/create-repo-with-catalog-info.yaml
106-
rules:
107-
- allow: [Template]
108-
10999
- type: file
110100
target: ../../examples/template/create-pr-with-catalog-info.yaml
111101
rules:
112102
- allow: [Template]
113103

114-
- type: file
115-
target: ../../examples/template/import-components-from-existing-repo.yaml
116-
rules:
117-
- allow: [Template]
118-
119104
# Local example organizational data
120105
- type: file
121106
target: ../../examples/org.yaml
@@ -136,3 +121,7 @@ catalog:
136121
permission:
137122
# setting this to `false` will disable permissions
138123
enabled: true
124+
# scaffolder template execution configuration. Disabled by default.
125+
# bulkImport:
126+
# importTemplate: template:default/create-pr-with-catalog-info
127+
# importAPI: scaffolder

workspaces/bulk-import/plugins/bulk-import-backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@
5353
"@backstage/plugin-permission-common": "^0.9.1",
5454
"@backstage/plugin-permission-node": "^0.10.3",
5555
"@gitbeaker/rest": "^43.4.0",
56-
"@microsoft/fetch-event-source": "^2.0.1",
5756
"@octokit/auth-app": "^6.0.3",
5857
"@octokit/rest": "^20.0.2",
5958
"@red-hat-developer-hub/backstage-plugin-bulk-import-common": "workspace:^",
6059
"ajv-formats": "^3.0.1",
60+
"eventsource-client": "^1.2.0",
6161
"express": "^4.17.1",
6262
"git-url-parse": "^14.0.0",
6363
"js-yaml": "^4.1.0",

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/import/execute-template.ts

Lines changed: 18 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
} from '@backstage/backend-plugin-api';
2222
import { Config } from '@backstage/config';
2323

24-
import { fetchEventSource } from '@microsoft/fetch-event-source';
24+
import { createEventSource } from 'eventsource-client';
2525
import gitUrlParse from 'git-url-parse';
2626

2727
import { getCatalogFilename } from '../../../catalog/catalogUtils';
@@ -54,78 +54,35 @@ async function* getEvents(
5454
scaffolderUrl: string,
5555
token: string,
5656
logger: LoggerService,
57-
) {
57+
): AsyncGenerator<ScaffolderEvent> {
5858
const url = `${scaffolderUrl}/v2/tasks/${taskId}/eventstream`;
5959

60-
const queue: ScaffolderEvent[] = [];
61-
let resolver: ((event: ScaffolderEvent) => void) | undefined;
62-
63-
const handleEvent = (data: any) => {
64-
logger.info('Received event:', data);
65-
if (resolver) {
66-
resolver(data);
67-
resolver = undefined;
68-
} else {
69-
queue.push(data);
70-
}
71-
};
72-
73-
const controller = new AbortController();
74-
75-
fetchEventSource(url, {
76-
method: 'GET',
60+
const eventSource = createEventSource({
61+
url,
7762
headers: {
7863
Authorization: `Bearer ${token}`,
7964
},
80-
signal: controller.signal,
81-
onopen: async response => {
82-
logger.info('SSE connection opened', { status: response.status });
83-
},
84-
onmessage: event => {
65+
});
66+
try {
67+
for await (const event of eventSource) {
8568
try {
8669
const data: ScaffolderEvent = JSON.parse(event.data);
87-
handleEvent(data);
70+
yield data;
71+
if (data.type === 'completion' || data.type === 'error') {
72+
break;
73+
}
8874
} catch (err) {
89-
logger.error('==== Failed to parse SSE event', err);
75+
logger.error('Failed to parse SSE event', err);
9076
}
91-
},
92-
onclose: () => {
93-
logger.info('SSE connection closed');
94-
},
95-
onerror: err => {
96-
logger.error('==== SSE error', err);
97-
handleEvent({
98-
type: 'error',
99-
error: err,
100-
id: -1,
101-
isTaskRecoverable: false,
102-
taskId,
103-
body: { message: err?.message ?? '' },
104-
createdAt: new Date().toISOString(),
105-
});
106-
controller.abort();
107-
},
108-
}).catch(err => logger.error('==== fetchEventSource failed', err));
109-
110-
const nextEvent = (): Promise<ScaffolderEvent> =>
111-
new Promise(resolve => {
112-
resolver = resolve;
113-
});
114-
115-
while (true) {
116-
const event: ScaffolderEvent =
117-
queue.length > 0 ? queue.shift()! : await nextEvent();
118-
119-
yield event;
120-
121-
if (event.type === 'completion' || event.type === 'error') {
122-
controller.abort();
123-
break;
12477
}
78+
} catch (err) {
79+
logger.error('SSE error', err);
80+
} finally {
81+
eventSource.close();
12582
}
12683
}
12784

128-
async function processTaskEvents(
85+
export async function processTaskEvents(
12986
taskId: string,
13087
scaffolderUrl: string,
13188
token: string,
@@ -143,7 +100,7 @@ async function processTaskEvents(
143100
}
144101
}
145102
} catch (e) {
146-
logger.error(`==== Failed to process events for task ${taskId}`, e);
103+
logger.error(`Failed to process events for task ${taskId}`, e);
147104
}
148105
}
149106

workspaces/bulk-import/yarn.lock

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9071,7 +9071,6 @@ __metadata:
90719071
"@backstage/plugin-permission-node": ^0.10.3
90729072
"@backstage/types": ^1.2.1
90739073
"@gitbeaker/rest": ^43.4.0
9074-
"@microsoft/fetch-event-source": ^2.0.1
90759074
"@octokit/auth-app": ^6.0.3
90769075
"@octokit/rest": ^20.0.2
90779076
"@openapitools/openapi-generator-cli": 2.20.2
@@ -9083,6 +9082,7 @@ __metadata:
90839082
"@types/node-fetch": ^2.5.12
90849083
"@types/supertest": 2.0.16
90859084
ajv-formats: ^3.0.1
9085+
eventsource-client: ^1.2.0
90869086
express: ^4.17.1
90879087
git-url-parse: ^14.0.0
90889088
js-yaml: ^4.1.0
@@ -18320,6 +18320,22 @@ __metadata:
1832018320
languageName: node
1832118321
linkType: hard
1832218322

18323+
"eventsource-client@npm:^1.2.0":
18324+
version: 1.2.0
18325+
resolution: "eventsource-client@npm:1.2.0"
18326+
dependencies:
18327+
eventsource-parser: ^3.0.0
18328+
checksum: 744b772176d09feab761244575cbf74b57d6fb6746e0863ece3549bfe606d38fc86d7d704e5ffa69bfb7b586929c29e29ce0059f194de20c2630b148c346d9bc
18329+
languageName: node
18330+
linkType: hard
18331+
18332+
"eventsource-parser@npm:^3.0.0":
18333+
version: 3.0.6
18334+
resolution: "eventsource-parser@npm:3.0.6"
18335+
checksum: b90ec27f8d992afa7df171db202faaedb1782214f64e50690cbf78bc2629f7751575aa27a72d8ae447e5a7094938406b1a3ea1d89e5f0f2d6916cc8a694b6587
18336+
languageName: node
18337+
linkType: hard
18338+
1832318339
"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3":
1832418340
version: 1.0.3
1832518341
resolution: "evp_bytestokey@npm:1.0.3"

0 commit comments

Comments
 (0)