@backstage/plugin-catalog-backend-module-bitbucket-server 0.5.12-next.0 → 0.5.13-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/config.schema.json +406 -0
- package/dist/alpha.cjs.js +12 -0
- package/dist/alpha.cjs.js.map +1 -0
- package/dist/alpha.d.ts +51 -0
- package/dist/events/BitbucketServerScmEventsBridge.cjs.js +83 -0
- package/dist/events/BitbucketServerScmEventsBridge.cjs.js.map +1 -0
- package/dist/events/analyzeBitbucketServerWebhookEvent.cjs.js +80 -0
- package/dist/events/analyzeBitbucketServerWebhookEvent.cjs.js.map +1 -0
- package/dist/module/catalogModuleBitbucketServerEntityProvider.cjs.js +19 -2
- package/dist/module/catalogModuleBitbucketServerEntityProvider.cjs.js.map +1 -1
- package/package.json +21 -11
- package/config.d.ts +0 -104
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend-module-bitbucket-server
|
|
2
2
|
|
|
3
|
+
## 0.5.13-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-plugin-api@1.9.3-next.0
|
|
9
|
+
- @backstage/plugin-catalog-node@2.2.3-next.0
|
|
10
|
+
- @backstage/plugin-events-node@0.4.24-next.0
|
|
11
|
+
|
|
12
|
+
## 0.5.12
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 9e2ff8c: Added a Bitbucket Server SCM event translation layer to the catalog backend module. The module now subscribes to Bitbucket Server webhook events and translates them into generic catalog SCM events, enabling instant catalog reprocessing when repositories are pushed to or renamed. The `analyzeBitbucketServerWebhookEvent` function is exported from the alpha entry point for custom integrations.
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @backstage/integration@2.0.3
|
|
19
|
+
- @backstage/backend-plugin-api@1.9.2
|
|
20
|
+
- @backstage/plugin-catalog-node@2.2.2
|
|
21
|
+
- @backstage/plugin-events-node@0.4.23
|
|
22
|
+
|
|
3
23
|
## 0.5.12-next.0
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"catalog": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"providers": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"bitbucketServer": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"catalogPath": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "(Optional) Path to the catalog file. Default to \"/catalog-info.yaml\".",
|
|
19
|
+
"visibility": "frontend"
|
|
20
|
+
},
|
|
21
|
+
"filters": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"repoSlug": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "(Optional) Regular expression filter for the repository slug.",
|
|
27
|
+
"visibility": "frontend"
|
|
28
|
+
},
|
|
29
|
+
"projectKey": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "(Optional) Regular expression filter for the project key.",
|
|
32
|
+
"visibility": "frontend"
|
|
33
|
+
},
|
|
34
|
+
"skipArchivedRepos": {
|
|
35
|
+
"type": "boolean",
|
|
36
|
+
"description": "(Optional) Skip archived repositories"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"description": "(Optional) Filters applied to discovered catalog files in repositories.",
|
|
40
|
+
"visibility": "frontend"
|
|
41
|
+
},
|
|
42
|
+
"validateLocationsExist": {
|
|
43
|
+
"type": "boolean",
|
|
44
|
+
"description": "(Optional) Whether to validate locations that exist before emitting them. Default: `false`."
|
|
45
|
+
},
|
|
46
|
+
"schedule": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": {
|
|
49
|
+
"frequency": {
|
|
50
|
+
"anyOf": [
|
|
51
|
+
{
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"cron": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"description": "A crontab style string."
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"required": [
|
|
60
|
+
"cron"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"type": "string"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"type": "object",
|
|
68
|
+
"properties": {
|
|
69
|
+
"years": {
|
|
70
|
+
"type": "number"
|
|
71
|
+
},
|
|
72
|
+
"months": {
|
|
73
|
+
"type": "number"
|
|
74
|
+
},
|
|
75
|
+
"weeks": {
|
|
76
|
+
"type": "number"
|
|
77
|
+
},
|
|
78
|
+
"days": {
|
|
79
|
+
"type": "number"
|
|
80
|
+
},
|
|
81
|
+
"hours": {
|
|
82
|
+
"type": "number"
|
|
83
|
+
},
|
|
84
|
+
"minutes": {
|
|
85
|
+
"type": "number"
|
|
86
|
+
},
|
|
87
|
+
"seconds": {
|
|
88
|
+
"type": "number"
|
|
89
|
+
},
|
|
90
|
+
"milliseconds": {
|
|
91
|
+
"type": "number"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"description": "Human friendly durations object."
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {
|
|
99
|
+
"trigger": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"const": "manual"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"required": [
|
|
105
|
+
"trigger"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"description": "How often you want the task to run. The system does its best to avoid overlapping invocations."
|
|
110
|
+
},
|
|
111
|
+
"timeout": {
|
|
112
|
+
"anyOf": [
|
|
113
|
+
{
|
|
114
|
+
"type": "string"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"type": "object",
|
|
118
|
+
"properties": {
|
|
119
|
+
"years": {
|
|
120
|
+
"type": "number"
|
|
121
|
+
},
|
|
122
|
+
"months": {
|
|
123
|
+
"type": "number"
|
|
124
|
+
},
|
|
125
|
+
"weeks": {
|
|
126
|
+
"type": "number"
|
|
127
|
+
},
|
|
128
|
+
"days": {
|
|
129
|
+
"type": "number"
|
|
130
|
+
},
|
|
131
|
+
"hours": {
|
|
132
|
+
"type": "number"
|
|
133
|
+
},
|
|
134
|
+
"minutes": {
|
|
135
|
+
"type": "number"
|
|
136
|
+
},
|
|
137
|
+
"seconds": {
|
|
138
|
+
"type": "number"
|
|
139
|
+
},
|
|
140
|
+
"milliseconds": {
|
|
141
|
+
"type": "number"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"description": "Human friendly durations object."
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"description": "The maximum amount of time that a single task invocation can take, before it's considered timed out and gets \"released\" such that a new invocation is permitted to take place (possibly, then, on a different worker)."
|
|
148
|
+
},
|
|
149
|
+
"initialDelay": {
|
|
150
|
+
"anyOf": [
|
|
151
|
+
{
|
|
152
|
+
"type": "string"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": {
|
|
157
|
+
"years": {
|
|
158
|
+
"type": "number"
|
|
159
|
+
},
|
|
160
|
+
"months": {
|
|
161
|
+
"type": "number"
|
|
162
|
+
},
|
|
163
|
+
"weeks": {
|
|
164
|
+
"type": "number"
|
|
165
|
+
},
|
|
166
|
+
"days": {
|
|
167
|
+
"type": "number"
|
|
168
|
+
},
|
|
169
|
+
"hours": {
|
|
170
|
+
"type": "number"
|
|
171
|
+
},
|
|
172
|
+
"minutes": {
|
|
173
|
+
"type": "number"
|
|
174
|
+
},
|
|
175
|
+
"seconds": {
|
|
176
|
+
"type": "number"
|
|
177
|
+
},
|
|
178
|
+
"milliseconds": {
|
|
179
|
+
"type": "number"
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"description": "Human friendly durations object."
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"description": "The amount of time that should pass before the first invocation happens."
|
|
186
|
+
},
|
|
187
|
+
"scope": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"enum": [
|
|
190
|
+
"global",
|
|
191
|
+
"local"
|
|
192
|
+
],
|
|
193
|
+
"description": "Sets the scope of concurrency control / locking to apply for invocations of this task."
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"required": [
|
|
197
|
+
"frequency",
|
|
198
|
+
"timeout"
|
|
199
|
+
],
|
|
200
|
+
"description": "(Optional) TaskScheduleDefinition for the refresh."
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"type": "object",
|
|
206
|
+
"additionalProperties": {
|
|
207
|
+
"type": "object",
|
|
208
|
+
"properties": {
|
|
209
|
+
"catalogPath": {
|
|
210
|
+
"type": "string",
|
|
211
|
+
"description": "(Optional) Path to the catalog file. Default to \"/catalog-info.yaml\".",
|
|
212
|
+
"visibility": "frontend"
|
|
213
|
+
},
|
|
214
|
+
"filters": {
|
|
215
|
+
"type": "object",
|
|
216
|
+
"properties": {
|
|
217
|
+
"repoSlug": {
|
|
218
|
+
"type": "string",
|
|
219
|
+
"description": "(Optional) Regular expression filter for the repository slug.",
|
|
220
|
+
"visibility": "frontend"
|
|
221
|
+
},
|
|
222
|
+
"projectKey": {
|
|
223
|
+
"type": "string",
|
|
224
|
+
"description": "(Optional) Regular expression filter for the project key.",
|
|
225
|
+
"visibility": "frontend"
|
|
226
|
+
},
|
|
227
|
+
"skipArchivedRepos": {
|
|
228
|
+
"type": "boolean",
|
|
229
|
+
"description": "(Optional) Skip archived repositories"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"description": "(Optional) Filters applied to discovered catalog files in repositories.",
|
|
233
|
+
"visibility": "frontend"
|
|
234
|
+
},
|
|
235
|
+
"validateLocationsExist": {
|
|
236
|
+
"type": "boolean",
|
|
237
|
+
"description": "(Optional) Whether to validate locations that exist before emitting them. Default: `false`."
|
|
238
|
+
},
|
|
239
|
+
"schedule": {
|
|
240
|
+
"type": "object",
|
|
241
|
+
"properties": {
|
|
242
|
+
"frequency": {
|
|
243
|
+
"anyOf": [
|
|
244
|
+
{
|
|
245
|
+
"type": "object",
|
|
246
|
+
"properties": {
|
|
247
|
+
"cron": {
|
|
248
|
+
"type": "string",
|
|
249
|
+
"description": "A crontab style string."
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"required": [
|
|
253
|
+
"cron"
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"type": "string"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"type": "object",
|
|
261
|
+
"properties": {
|
|
262
|
+
"years": {
|
|
263
|
+
"type": "number"
|
|
264
|
+
},
|
|
265
|
+
"months": {
|
|
266
|
+
"type": "number"
|
|
267
|
+
},
|
|
268
|
+
"weeks": {
|
|
269
|
+
"type": "number"
|
|
270
|
+
},
|
|
271
|
+
"days": {
|
|
272
|
+
"type": "number"
|
|
273
|
+
},
|
|
274
|
+
"hours": {
|
|
275
|
+
"type": "number"
|
|
276
|
+
},
|
|
277
|
+
"minutes": {
|
|
278
|
+
"type": "number"
|
|
279
|
+
},
|
|
280
|
+
"seconds": {
|
|
281
|
+
"type": "number"
|
|
282
|
+
},
|
|
283
|
+
"milliseconds": {
|
|
284
|
+
"type": "number"
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
"description": "Human friendly durations object."
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"type": "object",
|
|
291
|
+
"properties": {
|
|
292
|
+
"trigger": {
|
|
293
|
+
"type": "string",
|
|
294
|
+
"const": "manual"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"required": [
|
|
298
|
+
"trigger"
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
],
|
|
302
|
+
"description": "How often you want the task to run. The system does its best to avoid overlapping invocations."
|
|
303
|
+
},
|
|
304
|
+
"timeout": {
|
|
305
|
+
"anyOf": [
|
|
306
|
+
{
|
|
307
|
+
"type": "string"
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"type": "object",
|
|
311
|
+
"properties": {
|
|
312
|
+
"years": {
|
|
313
|
+
"type": "number"
|
|
314
|
+
},
|
|
315
|
+
"months": {
|
|
316
|
+
"type": "number"
|
|
317
|
+
},
|
|
318
|
+
"weeks": {
|
|
319
|
+
"type": "number"
|
|
320
|
+
},
|
|
321
|
+
"days": {
|
|
322
|
+
"type": "number"
|
|
323
|
+
},
|
|
324
|
+
"hours": {
|
|
325
|
+
"type": "number"
|
|
326
|
+
},
|
|
327
|
+
"minutes": {
|
|
328
|
+
"type": "number"
|
|
329
|
+
},
|
|
330
|
+
"seconds": {
|
|
331
|
+
"type": "number"
|
|
332
|
+
},
|
|
333
|
+
"milliseconds": {
|
|
334
|
+
"type": "number"
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
"description": "Human friendly durations object."
|
|
338
|
+
}
|
|
339
|
+
],
|
|
340
|
+
"description": "The maximum amount of time that a single task invocation can take, before it's considered timed out and gets \"released\" such that a new invocation is permitted to take place (possibly, then, on a different worker)."
|
|
341
|
+
},
|
|
342
|
+
"initialDelay": {
|
|
343
|
+
"anyOf": [
|
|
344
|
+
{
|
|
345
|
+
"type": "string"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"type": "object",
|
|
349
|
+
"properties": {
|
|
350
|
+
"years": {
|
|
351
|
+
"type": "number"
|
|
352
|
+
},
|
|
353
|
+
"months": {
|
|
354
|
+
"type": "number"
|
|
355
|
+
},
|
|
356
|
+
"weeks": {
|
|
357
|
+
"type": "number"
|
|
358
|
+
},
|
|
359
|
+
"days": {
|
|
360
|
+
"type": "number"
|
|
361
|
+
},
|
|
362
|
+
"hours": {
|
|
363
|
+
"type": "number"
|
|
364
|
+
},
|
|
365
|
+
"minutes": {
|
|
366
|
+
"type": "number"
|
|
367
|
+
},
|
|
368
|
+
"seconds": {
|
|
369
|
+
"type": "number"
|
|
370
|
+
},
|
|
371
|
+
"milliseconds": {
|
|
372
|
+
"type": "number"
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
"description": "Human friendly durations object."
|
|
376
|
+
}
|
|
377
|
+
],
|
|
378
|
+
"description": "The amount of time that should pass before the first invocation happens."
|
|
379
|
+
},
|
|
380
|
+
"scope": {
|
|
381
|
+
"type": "string",
|
|
382
|
+
"enum": [
|
|
383
|
+
"global",
|
|
384
|
+
"local"
|
|
385
|
+
],
|
|
386
|
+
"description": "Sets the scope of concurrency control / locking to apply for invocations of this task."
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
"required": [
|
|
390
|
+
"frequency",
|
|
391
|
+
"timeout"
|
|
392
|
+
],
|
|
393
|
+
"description": "(Optional) TaskScheduleDefinition for the refresh."
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
"description": "BitbucketServerEntityProvider configuration\n\nUses \"default\" as default id for the single config variant."
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var catalogModuleBitbucketServerEntityProvider = require('./module/catalogModuleBitbucketServerEntityProvider.cjs.js');
|
|
6
|
+
var analyzeBitbucketServerWebhookEvent = require('./events/analyzeBitbucketServerWebhookEvent.cjs.js');
|
|
7
|
+
|
|
8
|
+
const _feature = catalogModuleBitbucketServerEntityProvider.catalogModuleBitbucketServerEntityProvider;
|
|
9
|
+
|
|
10
|
+
exports.analyzeBitbucketServerWebhookEvent = analyzeBitbucketServerWebhookEvent.analyzeBitbucketServerWebhookEvent;
|
|
11
|
+
exports.default = _feature;
|
|
12
|
+
//# sourceMappingURL=alpha.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":["../src/alpha.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { default as feature } from './module';\n\n/** @alpha */\nconst _feature = feature;\nexport default _feature;\n\nexport {\n analyzeBitbucketServerWebhookEvent,\n type AnalyzeBitbucketServerWebhookEventResult,\n} from './events/analyzeBitbucketServerWebhookEvent';\n"],"names":["feature"],"mappings":";;;;;;;AAmBA,MAAM,QAAA,GAAWA;;;;;"}
|
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
import { CatalogScmEvent } from '@backstage/plugin-catalog-node/alpha';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The result of analyzing a Bitbucket Server webhook event.
|
|
6
|
+
*
|
|
7
|
+
* - `ok` — one or more catalog SCM events were produced.
|
|
8
|
+
* - `ignored` — the event was valid but not relevant.
|
|
9
|
+
* - `aborted` — the event could not be fully processed due to missing data.
|
|
10
|
+
* - `unsupported-event` — the event type is not handled by this analyzer.
|
|
11
|
+
*
|
|
12
|
+
* @alpha
|
|
13
|
+
*/
|
|
14
|
+
type AnalyzeBitbucketServerWebhookEventResult = {
|
|
15
|
+
result: 'unsupported-event';
|
|
16
|
+
event: string;
|
|
17
|
+
} | {
|
|
18
|
+
result: 'ignored';
|
|
19
|
+
reason: string;
|
|
20
|
+
} | {
|
|
21
|
+
result: 'aborted';
|
|
22
|
+
reason: string;
|
|
23
|
+
} | {
|
|
24
|
+
result: 'ok';
|
|
25
|
+
events: CatalogScmEvent[];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Analyzes a Bitbucket Server webhook event and translates it into zero or more
|
|
29
|
+
* catalog SCM events that entity providers can act on.
|
|
30
|
+
*
|
|
31
|
+
* Bitbucket Server push payloads do not include file-level change data, so only
|
|
32
|
+
* repository-level events are produced (unlike the GitLab and Azure DevOps
|
|
33
|
+
* analyzers which can emit fine-grained `location.*` events). Bitbucket Server
|
|
34
|
+
* does not emit a repository deletion webhook, so no `repository.deleted` event
|
|
35
|
+
* is produced.
|
|
36
|
+
*
|
|
37
|
+
* Supported event types:
|
|
38
|
+
* - `repo:refs_changed` — emits a `repository.updated` event to trigger catalog
|
|
39
|
+
* refresh for the repository.
|
|
40
|
+
* - `repo:modified` — translates repository renames into `repository.moved`
|
|
41
|
+
* events, or emits `repository.updated` for other metadata changes.
|
|
42
|
+
*
|
|
43
|
+
* @alpha
|
|
44
|
+
*/
|
|
45
|
+
declare function analyzeBitbucketServerWebhookEvent(eventType: string, eventPayload: unknown): Promise<AnalyzeBitbucketServerWebhookEventResult>;
|
|
46
|
+
|
|
47
|
+
/** @alpha */
|
|
48
|
+
declare const _feature: _backstage_backend_plugin_api.BackendFeature;
|
|
49
|
+
|
|
50
|
+
export { analyzeBitbucketServerWebhookEvent, _feature as default };
|
|
51
|
+
export type { AnalyzeBitbucketServerWebhookEventResult };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var analyzeBitbucketServerWebhookEvent = require('./analyzeBitbucketServerWebhookEvent.cjs.js');
|
|
4
|
+
|
|
5
|
+
class BitbucketServerScmEventsBridge {
|
|
6
|
+
#logger;
|
|
7
|
+
#events;
|
|
8
|
+
#catalogScmEvents;
|
|
9
|
+
#shuttingDown;
|
|
10
|
+
#pendingPublish;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.#logger = options.logger;
|
|
13
|
+
this.#events = options.events;
|
|
14
|
+
this.#catalogScmEvents = options.catalogScmEvents;
|
|
15
|
+
this.#shuttingDown = false;
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
await this.#events.subscribe({
|
|
19
|
+
id: "catalog-bitbucket-server-scm-events-bridge",
|
|
20
|
+
topics: ["bitbucketServer"],
|
|
21
|
+
onEvent: this.#onEvent.bind(this)
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async stop() {
|
|
25
|
+
this.#shuttingDown = true;
|
|
26
|
+
await this.#pendingPublish;
|
|
27
|
+
}
|
|
28
|
+
async #onEvent(params) {
|
|
29
|
+
const eventType = params.metadata?.["x-event-key"] ?? this.#extractEventTypeFromTopic(params.topic);
|
|
30
|
+
if (!eventType || !params.eventPayload) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
while (this.#pendingPublish) {
|
|
34
|
+
await this.#pendingPublish;
|
|
35
|
+
}
|
|
36
|
+
if (this.#shuttingDown) {
|
|
37
|
+
this.#logger.warn(
|
|
38
|
+
`Skipping Bitbucket Server webhook event of type "${eventType}" on topic "${params.topic}" because the bridge is shutting down`
|
|
39
|
+
);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.#pendingPublish = Promise.resolve().then(async () => {
|
|
43
|
+
try {
|
|
44
|
+
const output = await analyzeBitbucketServerWebhookEvent.analyzeBitbucketServerWebhookEvent(
|
|
45
|
+
eventType,
|
|
46
|
+
params.eventPayload
|
|
47
|
+
);
|
|
48
|
+
if (output.result === "ok") {
|
|
49
|
+
await this.#catalogScmEvents.publish(output.events);
|
|
50
|
+
} else if (output.result === "ignored") {
|
|
51
|
+
this.#logger.debug(
|
|
52
|
+
`Skipping Bitbucket Server webhook event of type "${eventType}" on topic "${params.topic}" because it is ignored: ${output.reason}`
|
|
53
|
+
);
|
|
54
|
+
} else if (output.result === "aborted") {
|
|
55
|
+
this.#logger.warn(
|
|
56
|
+
`Skipping Bitbucket Server webhook event of type "${eventType}" on topic "${params.topic}" because it is aborted: ${output.reason}`
|
|
57
|
+
);
|
|
58
|
+
} else if (output.result === "unsupported-event") {
|
|
59
|
+
this.#logger.debug(
|
|
60
|
+
`Skipping Bitbucket Server webhook event of type "${eventType}" on topic "${params.topic}" because it is unsupported: ${output.event}`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
this.#logger.warn(
|
|
65
|
+
`Failed to handle Bitbucket Server webhook event of type "${eventType}"`,
|
|
66
|
+
error
|
|
67
|
+
);
|
|
68
|
+
} finally {
|
|
69
|
+
this.#pendingPublish = void 0;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
await this.#pendingPublish;
|
|
73
|
+
}
|
|
74
|
+
#extractEventTypeFromTopic(topic) {
|
|
75
|
+
if (topic.startsWith("bitbucketServer.")) {
|
|
76
|
+
return topic.slice("bitbucketServer.".length);
|
|
77
|
+
}
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
exports.BitbucketServerScmEventsBridge = BitbucketServerScmEventsBridge;
|
|
83
|
+
//# sourceMappingURL=BitbucketServerScmEventsBridge.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitbucketServerScmEventsBridge.cjs.js","sources":["../../src/events/BitbucketServerScmEventsBridge.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { CatalogScmEventsService } from '@backstage/plugin-catalog-node/alpha';\nimport { EventParams, EventsService } from '@backstage/plugin-events-node';\nimport { analyzeBitbucketServerWebhookEvent } from './analyzeBitbucketServerWebhookEvent';\n\n/**\n * Takes Bitbucket Server webhook events, analyzes them, and publishes them as\n * catalog SCM events that entity providers and others can subscribe to.\n */\nexport class BitbucketServerScmEventsBridge {\n readonly #logger: LoggerService;\n readonly #events: EventsService;\n readonly #catalogScmEvents: CatalogScmEventsService;\n #shuttingDown: boolean;\n #pendingPublish: Promise<void> | undefined;\n\n constructor(options: {\n logger: LoggerService;\n events: EventsService;\n catalogScmEvents: CatalogScmEventsService;\n }) {\n this.#logger = options.logger;\n this.#events = options.events;\n this.#catalogScmEvents = options.catalogScmEvents;\n this.#shuttingDown = false;\n }\n\n async start() {\n await this.#events.subscribe({\n id: 'catalog-bitbucket-server-scm-events-bridge',\n topics: ['bitbucketServer'],\n onEvent: this.#onEvent.bind(this),\n });\n }\n\n async stop() {\n this.#shuttingDown = true;\n await this.#pendingPublish;\n }\n\n async #onEvent(params: EventParams): Promise<void> {\n const eventType =\n (params.metadata?.['x-event-key'] as string | undefined) ??\n this.#extractEventTypeFromTopic(params.topic);\n if (!eventType || !params.eventPayload) {\n return;\n }\n\n while (this.#pendingPublish) {\n await this.#pendingPublish;\n }\n\n if (this.#shuttingDown) {\n this.#logger.warn(\n `Skipping Bitbucket Server webhook event of type \"${eventType}\" on topic \"${params.topic}\" because the bridge is shutting down`,\n );\n return;\n }\n\n this.#pendingPublish = Promise.resolve().then(async () => {\n try {\n const output = await analyzeBitbucketServerWebhookEvent(\n eventType,\n params.eventPayload,\n );\n\n if (output.result === 'ok') {\n await this.#catalogScmEvents.publish(output.events);\n } else if (output.result === 'ignored') {\n this.#logger.debug(\n `Skipping Bitbucket Server webhook event of type \"${eventType}\" on topic \"${params.topic}\" because it is ignored: ${output.reason}`,\n );\n } else if (output.result === 'aborted') {\n this.#logger.warn(\n `Skipping Bitbucket Server webhook event of type \"${eventType}\" on topic \"${params.topic}\" because it is aborted: ${output.reason}`,\n );\n } else if (output.result === 'unsupported-event') {\n this.#logger.debug(\n `Skipping Bitbucket Server webhook event of type \"${eventType}\" on topic \"${params.topic}\" because it is unsupported: ${output.event}`,\n );\n }\n } catch (error) {\n this.#logger.warn(\n `Failed to handle Bitbucket Server webhook event of type \"${eventType}\"`,\n error,\n );\n } finally {\n this.#pendingPublish = undefined;\n }\n });\n\n await this.#pendingPublish;\n }\n\n #extractEventTypeFromTopic(topic: string): string | undefined {\n if (topic.startsWith('bitbucketServer.')) {\n return topic.slice('bitbucketServer.'.length);\n }\n return undefined;\n }\n}\n"],"names":["analyzeBitbucketServerWebhookEvent"],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
|
|
5
|
+
function asObject(value) {
|
|
6
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function asArray(value) {
|
|
12
|
+
return Array.isArray(value) ? value : void 0;
|
|
13
|
+
}
|
|
14
|
+
function asString(value) {
|
|
15
|
+
return typeof value === "string" ? value : void 0;
|
|
16
|
+
}
|
|
17
|
+
function getRepositoryUrl(repository) {
|
|
18
|
+
const links = asObject(repository?.links);
|
|
19
|
+
const self = asArray(links?.self);
|
|
20
|
+
const first = asObject(self?.[0]);
|
|
21
|
+
return asString(first?.href);
|
|
22
|
+
}
|
|
23
|
+
async function onRefsChangedEvent(payload) {
|
|
24
|
+
const repositoryUrl = getRepositoryUrl(asObject(payload.repository));
|
|
25
|
+
if (!repositoryUrl) {
|
|
26
|
+
return {
|
|
27
|
+
result: "aborted",
|
|
28
|
+
reason: "Bitbucket Server repo:refs_changed event did not include repository.links.self[0].href"
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
result: "ok",
|
|
33
|
+
events: [{ type: "repository.updated", url: repositoryUrl }]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function onModifiedEvent(payload) {
|
|
37
|
+
const repositoryUrl = getRepositoryUrl(asObject(payload.new));
|
|
38
|
+
const oldRepositoryUrl = getRepositoryUrl(asObject(payload.old));
|
|
39
|
+
if (!repositoryUrl) {
|
|
40
|
+
return {
|
|
41
|
+
result: "aborted",
|
|
42
|
+
reason: "Bitbucket Server repo:modified event did not include new.links.self[0].href"
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (oldRepositoryUrl && oldRepositoryUrl !== repositoryUrl) {
|
|
46
|
+
return {
|
|
47
|
+
result: "ok",
|
|
48
|
+
events: [
|
|
49
|
+
{
|
|
50
|
+
type: "repository.moved",
|
|
51
|
+
fromUrl: oldRepositoryUrl,
|
|
52
|
+
toUrl: repositoryUrl
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
result: "ok",
|
|
59
|
+
events: [{ type: "repository.updated", url: repositoryUrl }]
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function analyzeBitbucketServerWebhookEvent(eventType, eventPayload) {
|
|
63
|
+
const payload = asObject(eventPayload);
|
|
64
|
+
if (!payload) {
|
|
65
|
+
throw new errors.InputError(
|
|
66
|
+
"Bitbucket Server webhook event payload is not an object"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
switch (eventType) {
|
|
70
|
+
case "repo:refs_changed":
|
|
71
|
+
return onRefsChangedEvent(payload);
|
|
72
|
+
case "repo:modified":
|
|
73
|
+
return onModifiedEvent(payload);
|
|
74
|
+
default:
|
|
75
|
+
return { result: "unsupported-event", event: eventType };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
exports.analyzeBitbucketServerWebhookEvent = analyzeBitbucketServerWebhookEvent;
|
|
80
|
+
//# sourceMappingURL=analyzeBitbucketServerWebhookEvent.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeBitbucketServerWebhookEvent.cjs.js","sources":["../../src/events/analyzeBitbucketServerWebhookEvent.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { CatalogScmEvent } from '@backstage/plugin-catalog-node/alpha';\n\n/**\n * The result of analyzing a Bitbucket Server webhook event.\n *\n * - `ok` — one or more catalog SCM events were produced.\n * - `ignored` — the event was valid but not relevant.\n * - `aborted` — the event could not be fully processed due to missing data.\n * - `unsupported-event` — the event type is not handled by this analyzer.\n *\n * @alpha\n */\nexport type AnalyzeBitbucketServerWebhookEventResult =\n | {\n result: 'unsupported-event';\n event: string;\n }\n | {\n result: 'ignored';\n reason: string;\n }\n | {\n result: 'aborted';\n reason: string;\n }\n | {\n result: 'ok';\n events: CatalogScmEvent[];\n };\n\ntype JsonObject = Record<string, unknown>;\n\nfunction asObject(value: unknown): JsonObject | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n return value as JsonObject;\n}\n\nfunction asArray(value: unknown): unknown[] | undefined {\n return Array.isArray(value) ? value : undefined;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction getRepositoryUrl(\n repository: JsonObject | undefined,\n): string | undefined {\n const links = asObject(repository?.links);\n const self = asArray(links?.self);\n const first = asObject(self?.[0]);\n return asString(first?.href);\n}\n\nasync function onRefsChangedEvent(\n payload: JsonObject,\n): Promise<AnalyzeBitbucketServerWebhookEventResult> {\n const repositoryUrl = getRepositoryUrl(asObject(payload.repository));\n\n if (!repositoryUrl) {\n return {\n result: 'aborted',\n reason:\n 'Bitbucket Server repo:refs_changed event did not include repository.links.self[0].href',\n };\n }\n\n return {\n result: 'ok',\n events: [{ type: 'repository.updated', url: repositoryUrl }],\n };\n}\n\nasync function onModifiedEvent(\n payload: JsonObject,\n): Promise<AnalyzeBitbucketServerWebhookEventResult> {\n const repositoryUrl = getRepositoryUrl(asObject(payload.new));\n const oldRepositoryUrl = getRepositoryUrl(asObject(payload.old));\n\n if (!repositoryUrl) {\n return {\n result: 'aborted',\n reason:\n 'Bitbucket Server repo:modified event did not include new.links.self[0].href',\n };\n }\n\n if (oldRepositoryUrl && oldRepositoryUrl !== repositoryUrl) {\n return {\n result: 'ok',\n events: [\n {\n type: 'repository.moved',\n fromUrl: oldRepositoryUrl,\n toUrl: repositoryUrl,\n },\n ],\n };\n }\n\n return {\n result: 'ok',\n events: [{ type: 'repository.updated', url: repositoryUrl }],\n };\n}\n\n/**\n * Analyzes a Bitbucket Server webhook event and translates it into zero or more\n * catalog SCM events that entity providers can act on.\n *\n * Bitbucket Server push payloads do not include file-level change data, so only\n * repository-level events are produced (unlike the GitLab and Azure DevOps\n * analyzers which can emit fine-grained `location.*` events). Bitbucket Server\n * does not emit a repository deletion webhook, so no `repository.deleted` event\n * is produced.\n *\n * Supported event types:\n * - `repo:refs_changed` — emits a `repository.updated` event to trigger catalog\n * refresh for the repository.\n * - `repo:modified` — translates repository renames into `repository.moved`\n * events, or emits `repository.updated` for other metadata changes.\n *\n * @alpha\n */\nexport async function analyzeBitbucketServerWebhookEvent(\n eventType: string,\n eventPayload: unknown,\n): Promise<AnalyzeBitbucketServerWebhookEventResult> {\n const payload = asObject(eventPayload);\n if (!payload) {\n throw new InputError(\n 'Bitbucket Server webhook event payload is not an object',\n );\n }\n\n switch (eventType) {\n case 'repo:refs_changed':\n return onRefsChangedEvent(payload);\n case 'repo:modified':\n return onModifiedEvent(payload);\n default:\n return { result: 'unsupported-event', event: eventType };\n }\n}\n"],"names":["InputError"],"mappings":";;;;AAiDA,SAAS,SAAS,KAAA,EAAwC;AACxD,EAAA,IAAI,CAAC,SAAS,OAAO,KAAA,KAAU,YAAY,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,QAAQ,KAAA,EAAuC;AACtD,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,MAAA;AACxC;AAEA,SAAS,SAAS,KAAA,EAAoC;AACpD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,MAAA;AAC7C;AAEA,SAAS,iBACP,UAAA,EACoB;AACpB,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,UAAA,EAAY,KAAK,CAAA;AACxC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,GAAO,CAAC,CAAC,CAAA;AAChC,EAAA,OAAO,QAAA,CAAS,OAAO,IAAI,CAAA;AAC7B;AAEA,eAAe,mBACb,OAAA,EACmD;AACnD,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAC,CAAA;AAEnE,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EACE;AAAA,KACJ;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,IAAA;AAAA,IACR,QAAQ,CAAC,EAAE,MAAM,oBAAA,EAAsB,GAAA,EAAK,eAAe;AAAA,GAC7D;AACF;AAEA,eAAe,gBACb,OAAA,EACmD;AACnD,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,QAAA,CAAS,OAAA,CAAQ,GAAG,CAAC,CAAA;AAC5D,EAAA,MAAM,gBAAA,GAAmB,gBAAA,CAAiB,QAAA,CAAS,OAAA,CAAQ,GAAG,CAAC,CAAA;AAE/D,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EACE;AAAA,KACJ;AAAA,EACF;AAEA,EAAA,IAAI,gBAAA,IAAoB,qBAAqB,aAAA,EAAe;AAC1D,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,IAAA;AAAA,MACR,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,IAAA,EAAM,kBAAA;AAAA,UACN,OAAA,EAAS,gBAAA;AAAA,UACT,KAAA,EAAO;AAAA;AACT;AACF,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,IAAA;AAAA,IACR,QAAQ,CAAC,EAAE,MAAM,oBAAA,EAAsB,GAAA,EAAK,eAAe;AAAA,GAC7D;AACF;AAoBA,eAAsB,kCAAA,CACpB,WACA,YAAA,EACmD;AACnD,EAAA,MAAM,OAAA,GAAU,SAAS,YAAY,CAAA;AACrC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAIA,iBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,QAAQ,SAAA;AAAW,IACjB,KAAK,mBAAA;AACH,MAAA,OAAO,mBAAmB,OAAO,CAAA;AAAA,IACnC,KAAK,eAAA;AACH,MAAA,OAAO,gBAAgB,OAAO,CAAA;AAAA,IAChC;AACE,MAAA,OAAO,EAAE,MAAA,EAAQ,mBAAA,EAAqB,KAAA,EAAO,SAAA,EAAU;AAAA;AAE7D;;;;"}
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
4
|
var pluginCatalogNode = require('@backstage/plugin-catalog-node');
|
|
5
|
+
var alpha = require('@backstage/plugin-catalog-node/alpha');
|
|
5
6
|
var pluginEventsNode = require('@backstage/plugin-events-node');
|
|
6
7
|
var BitbucketServerEntityProvider = require('../providers/BitbucketServerEntityProvider.cjs.js');
|
|
8
|
+
var BitbucketServerScmEventsBridge = require('../events/BitbucketServerScmEventsBridge.cjs.js');
|
|
7
9
|
|
|
8
10
|
const catalogModuleBitbucketServerEntityProvider = backendPluginApi.createBackendModule({
|
|
9
11
|
pluginId: "catalog",
|
|
@@ -17,7 +19,9 @@ const catalogModuleBitbucketServerEntityProvider = backendPluginApi.createBacken
|
|
|
17
19
|
events: pluginEventsNode.eventsServiceRef,
|
|
18
20
|
logger: backendPluginApi.coreServices.logger,
|
|
19
21
|
scheduler: backendPluginApi.coreServices.scheduler,
|
|
20
|
-
auth: backendPluginApi.coreServices.auth
|
|
22
|
+
auth: backendPluginApi.coreServices.auth,
|
|
23
|
+
catalogScmEvents: alpha.catalogScmEventsServiceRef,
|
|
24
|
+
lifecycle: backendPluginApi.coreServices.lifecycle
|
|
21
25
|
},
|
|
22
26
|
async init({
|
|
23
27
|
catalog,
|
|
@@ -26,7 +30,9 @@ const catalogModuleBitbucketServerEntityProvider = backendPluginApi.createBacken
|
|
|
26
30
|
events,
|
|
27
31
|
logger,
|
|
28
32
|
scheduler,
|
|
29
|
-
auth
|
|
33
|
+
auth,
|
|
34
|
+
catalogScmEvents,
|
|
35
|
+
lifecycle
|
|
30
36
|
}) {
|
|
31
37
|
const providers = BitbucketServerEntityProvider.BitbucketServerEntityProvider.fromConfig(config, {
|
|
32
38
|
catalogApi,
|
|
@@ -36,6 +42,17 @@ const catalogModuleBitbucketServerEntityProvider = backendPluginApi.createBacken
|
|
|
36
42
|
auth
|
|
37
43
|
});
|
|
38
44
|
catalog.addEntityProvider(providers);
|
|
45
|
+
const bridge = new BitbucketServerScmEventsBridge.BitbucketServerScmEventsBridge({
|
|
46
|
+
logger,
|
|
47
|
+
events,
|
|
48
|
+
catalogScmEvents
|
|
49
|
+
});
|
|
50
|
+
lifecycle.addStartupHook(async () => {
|
|
51
|
+
await bridge.start();
|
|
52
|
+
});
|
|
53
|
+
lifecycle.addShutdownHook(async () => {
|
|
54
|
+
await bridge.stop();
|
|
55
|
+
});
|
|
39
56
|
}
|
|
40
57
|
});
|
|
41
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalogModuleBitbucketServerEntityProvider.cjs.js","sources":["../../src/module/catalogModuleBitbucketServerEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { BitbucketServerEntityProvider } from '../providers/BitbucketServerEntityProvider';\n\n/**\n * @public\n */\nexport const catalogModuleBitbucketServerEntityProvider = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'bitbucket-server-entity-provider',\n register(env) {\n env.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint,\n catalogApi: catalogServiceRef,\n config: coreServices.rootConfig,\n events: eventsServiceRef,\n logger: coreServices.logger,\n scheduler: coreServices.scheduler,\n auth: coreServices.auth,\n },\n async init({\n catalog,\n catalogApi,\n config,\n events,\n logger,\n scheduler,\n auth,\n }) {\n const providers = BitbucketServerEntityProvider.fromConfig(config, {\n catalogApi,\n events,\n logger,\n scheduler,\n auth,\n });\n\n catalog.addEntityProvider(providers);\n },\n });\n },\n});\n"],"names":["createBackendModule","catalogProcessingExtensionPoint","catalogServiceRef","coreServices","eventsServiceRef","BitbucketServerEntityProvider"],"mappings":"
|
|
1
|
+
{"version":3,"file":"catalogModuleBitbucketServerEntityProvider.cjs.js","sources":["../../src/module/catalogModuleBitbucketServerEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';\nimport { catalogScmEventsServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { BitbucketServerEntityProvider } from '../providers/BitbucketServerEntityProvider';\nimport { BitbucketServerScmEventsBridge } from '../events/BitbucketServerScmEventsBridge';\n\n/**\n * @public\n */\nexport const catalogModuleBitbucketServerEntityProvider = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'bitbucket-server-entity-provider',\n register(env) {\n env.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint,\n catalogApi: catalogServiceRef,\n config: coreServices.rootConfig,\n events: eventsServiceRef,\n logger: coreServices.logger,\n scheduler: coreServices.scheduler,\n auth: coreServices.auth,\n catalogScmEvents: catalogScmEventsServiceRef,\n lifecycle: coreServices.lifecycle,\n },\n async init({\n catalog,\n catalogApi,\n config,\n events,\n logger,\n scheduler,\n auth,\n catalogScmEvents,\n lifecycle,\n }) {\n const providers = BitbucketServerEntityProvider.fromConfig(config, {\n catalogApi,\n events,\n logger,\n scheduler,\n auth,\n });\n\n catalog.addEntityProvider(providers);\n\n const bridge = new BitbucketServerScmEventsBridge({\n logger,\n events,\n catalogScmEvents,\n });\n lifecycle.addStartupHook(async () => {\n await bridge.start();\n });\n lifecycle.addShutdownHook(async () => {\n await bridge.stop();\n });\n },\n });\n },\n});\n"],"names":["createBackendModule","catalogProcessingExtensionPoint","catalogServiceRef","coreServices","eventsServiceRef","catalogScmEventsServiceRef","BitbucketServerEntityProvider","BitbucketServerScmEventsBridge"],"mappings":";;;;;;;;;AA8BO,MAAM,6CAA6CA,oCAAA,CAAoB;AAAA,EAC5E,QAAA,EAAU,SAAA;AAAA,EACV,QAAA,EAAU,kCAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,OAAA,EAASC,iDAAA;AAAA,QACT,UAAA,EAAYC,mCAAA;AAAA,QACZ,QAAQC,6BAAA,CAAa,UAAA;AAAA,QACrB,MAAA,EAAQC,iCAAA;AAAA,QACR,QAAQD,6BAAA,CAAa,MAAA;AAAA,QACrB,WAAWA,6BAAA,CAAa,SAAA;AAAA,QACxB,MAAMA,6BAAA,CAAa,IAAA;AAAA,QACnB,gBAAA,EAAkBE,gCAAA;AAAA,QAClB,WAAWF,6BAAA,CAAa;AAAA,OAC1B;AAAA,MACA,MAAM,IAAA,CAAK;AAAA,QACT,OAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,IAAA;AAAA,QACA,gBAAA;AAAA,QACA;AAAA,OACF,EAAG;AACD,QAAA,MAAM,SAAA,GAAYG,2DAAA,CAA8B,UAAA,CAAW,MAAA,EAAQ;AAAA,UACjE,UAAA;AAAA,UACA,MAAA;AAAA,UACA,MAAA;AAAA,UACA,SAAA;AAAA,UACA;AAAA,SACD,CAAA;AAED,QAAA,OAAA,CAAQ,kBAAkB,SAAS,CAAA;AAEnC,QAAA,MAAM,MAAA,GAAS,IAAIC,6DAAA,CAA+B;AAAA,UAChD,MAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,SAAA,CAAU,eAAe,YAAY;AACnC,UAAA,MAAM,OAAO,KAAA,EAAM;AAAA,QACrB,CAAC,CAAA;AACD,QAAA,SAAA,CAAU,gBAAgB,YAAY;AACpC,UAAA,MAAM,OAAO,IAAA,EAAK;AAAA,QACpB,CAAC,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-catalog-backend-module-bitbucket-server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.13-next.0",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "backend-plugin-module",
|
|
6
6
|
"pluginId": "catalog",
|
|
7
7
|
"pluginPackage": "@backstage/plugin-catalog-backend",
|
|
8
8
|
"features": {
|
|
9
|
-
".": "@backstage/BackendFeature"
|
|
9
|
+
".": "@backstage/BackendFeature",
|
|
10
|
+
"./alpha": "@backstage/BackendFeature"
|
|
10
11
|
}
|
|
11
12
|
},
|
|
12
13
|
"publishConfig": {
|
|
@@ -29,19 +30,28 @@
|
|
|
29
30
|
"types": "./dist/index.d.ts",
|
|
30
31
|
"default": "./dist/index.cjs.js"
|
|
31
32
|
},
|
|
33
|
+
"./alpha": {
|
|
34
|
+
"backstage": "@backstage/BackendFeature",
|
|
35
|
+
"require": "./dist/alpha.cjs.js",
|
|
36
|
+
"types": "./dist/alpha.d.ts",
|
|
37
|
+
"default": "./dist/alpha.cjs.js"
|
|
38
|
+
},
|
|
32
39
|
"./package.json": "./package.json"
|
|
33
40
|
},
|
|
34
41
|
"main": "./dist/index.cjs.js",
|
|
35
42
|
"types": "./dist/index.d.ts",
|
|
36
43
|
"typesVersions": {
|
|
37
44
|
"*": {
|
|
45
|
+
"alpha": [
|
|
46
|
+
"dist/alpha.d.ts"
|
|
47
|
+
],
|
|
38
48
|
"package.json": [
|
|
39
49
|
"package.json"
|
|
40
50
|
]
|
|
41
51
|
}
|
|
42
52
|
},
|
|
43
53
|
"files": [
|
|
44
|
-
"config.
|
|
54
|
+
"config.schema.json",
|
|
45
55
|
"dist"
|
|
46
56
|
],
|
|
47
57
|
"scripts": {
|
|
@@ -54,20 +64,20 @@
|
|
|
54
64
|
"test": "backstage-cli package test"
|
|
55
65
|
},
|
|
56
66
|
"dependencies": {
|
|
57
|
-
"@backstage/backend-plugin-api": "1.9.
|
|
67
|
+
"@backstage/backend-plugin-api": "1.9.3-next.0",
|
|
58
68
|
"@backstage/catalog-model": "1.9.0",
|
|
59
69
|
"@backstage/config": "1.3.8",
|
|
60
70
|
"@backstage/errors": "1.3.1",
|
|
61
|
-
"@backstage/integration": "2.0.3
|
|
71
|
+
"@backstage/integration": "2.0.3",
|
|
62
72
|
"@backstage/plugin-catalog-common": "1.1.10",
|
|
63
|
-
"@backstage/plugin-catalog-node": "2.2.
|
|
64
|
-
"@backstage/plugin-events-node": "0.4.
|
|
73
|
+
"@backstage/plugin-catalog-node": "2.2.3-next.0",
|
|
74
|
+
"@backstage/plugin-events-node": "0.4.24-next.0"
|
|
65
75
|
},
|
|
66
76
|
"devDependencies": {
|
|
67
|
-
"@backstage/backend-test-utils": "1.11.
|
|
68
|
-
"@backstage/cli": "0.36.
|
|
69
|
-
"@backstage/plugin-events-backend-test-utils": "0.1.
|
|
77
|
+
"@backstage/backend-test-utils": "1.11.5-next.0",
|
|
78
|
+
"@backstage/cli": "0.36.4-next.0",
|
|
79
|
+
"@backstage/plugin-events-backend-test-utils": "0.1.57-next.0",
|
|
70
80
|
"msw": "^1.0.0"
|
|
71
81
|
},
|
|
72
|
-
"configSchema": "config.
|
|
82
|
+
"configSchema": "config.schema.json"
|
|
73
83
|
}
|
package/config.d.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 The Backstage Authors
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { SchedulerServiceTaskScheduleDefinitionConfig } from '@backstage/backend-plugin-api';
|
|
18
|
-
|
|
19
|
-
export interface Config {
|
|
20
|
-
catalog?: {
|
|
21
|
-
providers?: {
|
|
22
|
-
/**
|
|
23
|
-
* BitbucketServerEntityProvider configuration
|
|
24
|
-
*
|
|
25
|
-
* Uses "default" as default id for the single config variant.
|
|
26
|
-
*/
|
|
27
|
-
bitbucketServer?:
|
|
28
|
-
| {
|
|
29
|
-
/**
|
|
30
|
-
* (Optional) Path to the catalog file. Default to "/catalog-info.yaml".
|
|
31
|
-
* @visibility frontend
|
|
32
|
-
*/
|
|
33
|
-
catalogPath?: string;
|
|
34
|
-
/**
|
|
35
|
-
* (Optional) Filters applied to discovered catalog files in repositories.
|
|
36
|
-
* @visibility frontend
|
|
37
|
-
*/
|
|
38
|
-
filters?: {
|
|
39
|
-
/**
|
|
40
|
-
* (Optional) Regular expression filter for the repository slug.
|
|
41
|
-
* @visibility frontend
|
|
42
|
-
*/
|
|
43
|
-
repoSlug?: string;
|
|
44
|
-
/**
|
|
45
|
-
* (Optional) Regular expression filter for the project key.
|
|
46
|
-
* @visibility frontend
|
|
47
|
-
*/
|
|
48
|
-
projectKey?: string;
|
|
49
|
-
/**
|
|
50
|
-
* (Optional) Skip archived repositories
|
|
51
|
-
*/
|
|
52
|
-
skipArchivedRepos?: boolean;
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* (Optional) Whether to validate locations that exist before emitting them.
|
|
56
|
-
* Default: `false`.
|
|
57
|
-
*/
|
|
58
|
-
validateLocationsExist?: boolean;
|
|
59
|
-
/**
|
|
60
|
-
* (Optional) TaskScheduleDefinition for the refresh.
|
|
61
|
-
*/
|
|
62
|
-
schedule?: SchedulerServiceTaskScheduleDefinitionConfig;
|
|
63
|
-
}
|
|
64
|
-
| {
|
|
65
|
-
[name: string]: {
|
|
66
|
-
/**
|
|
67
|
-
* (Optional) Path to the catalog file. Default to "/catalog-info.yaml".
|
|
68
|
-
* @visibility frontend
|
|
69
|
-
*/
|
|
70
|
-
catalogPath?: string;
|
|
71
|
-
/**
|
|
72
|
-
* (Optional) Filters applied to discovered catalog files in repositories.
|
|
73
|
-
* @visibility frontend
|
|
74
|
-
*/
|
|
75
|
-
filters?: {
|
|
76
|
-
/**
|
|
77
|
-
* (Optional) Regular expression filter for the repository slug.
|
|
78
|
-
* @visibility frontend
|
|
79
|
-
*/
|
|
80
|
-
repoSlug?: string;
|
|
81
|
-
/**
|
|
82
|
-
* (Optional) Regular expression filter for the project key.
|
|
83
|
-
* @visibility frontend
|
|
84
|
-
*/
|
|
85
|
-
projectKey?: string;
|
|
86
|
-
/**
|
|
87
|
-
* (Optional) Skip archived repositories
|
|
88
|
-
*/
|
|
89
|
-
skipArchivedRepos?: boolean;
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* (Optional) Whether to validate locations that exist before emitting them.
|
|
93
|
-
* Default: `false`.
|
|
94
|
-
*/
|
|
95
|
-
validateLocationsExist?: boolean;
|
|
96
|
-
/**
|
|
97
|
-
* (Optional) TaskScheduleDefinition for the refresh.
|
|
98
|
-
*/
|
|
99
|
-
schedule?: SchedulerServiceTaskScheduleDefinitionConfig;
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
|
-
}
|