@red-hat-developer-hub/backstage-plugin-bulk-import-backend 5.0.1
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 +115 -0
- package/README.md +161 -0
- package/app-config.yaml +0 -0
- package/config.d.ts +17 -0
- package/dist/catalog/catalogHttpClient.cjs.js +284 -0
- package/dist/catalog/catalogHttpClient.cjs.js.map +1 -0
- package/dist/catalog/catalogInfoGenerator.cjs.js +60 -0
- package/dist/catalog/catalogInfoGenerator.cjs.js.map +1 -0
- package/dist/catalog/catalogUtils.cjs.js +34 -0
- package/dist/catalog/catalogUtils.cjs.js.map +1 -0
- package/dist/generated/openapidocument.cjs.js +1168 -0
- package/dist/generated/openapidocument.cjs.js.map +1 -0
- package/dist/github/GithubAppManager.cjs.js +395 -0
- package/dist/github/GithubAppManager.cjs.js.map +1 -0
- package/dist/github/githubApiService.cjs.js +659 -0
- package/dist/github/githubApiService.cjs.js.map +1 -0
- package/dist/github/types.cjs.js +8 -0
- package/dist/github/types.cjs.js.map +1 -0
- package/dist/github/utils/ghUtils.cjs.js +103 -0
- package/dist/github/utils/ghUtils.cjs.js.map +1 -0
- package/dist/github/utils/orgUtils.cjs.js +151 -0
- package/dist/github/utils/orgUtils.cjs.js.map +1 -0
- package/dist/github/utils/prUtils.cjs.js +85 -0
- package/dist/github/utils/prUtils.cjs.js.map +1 -0
- package/dist/github/utils/repoUtils.cjs.js +307 -0
- package/dist/github/utils/repoUtils.cjs.js.map +1 -0
- package/dist/github/utils/utils.cjs.js +206 -0
- package/dist/github/utils/utils.cjs.js.map +1 -0
- package/dist/helpers/auditLogUtils.cjs.js +112 -0
- package/dist/helpers/auditLogUtils.cjs.js.map +1 -0
- package/dist/helpers/auth.cjs.js +36 -0
- package/dist/helpers/auth.cjs.js.map +1 -0
- package/dist/helpers/loggingUtils.cjs.js +19 -0
- package/dist/helpers/loggingUtils.cjs.js.map +1 -0
- package/dist/helpers/pagination.cjs.js +19 -0
- package/dist/helpers/pagination.cjs.js.map +1 -0
- package/dist/index.cjs.js +12 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/plugin.cjs.js +54 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/service/handlers/handlers.cjs.js +8 -0
- package/dist/service/handlers/handlers.cjs.js.map +1 -0
- package/dist/service/handlers/import/bulkImports.cjs.js +551 -0
- package/dist/service/handlers/import/bulkImports.cjs.js.map +1 -0
- package/dist/service/handlers/import/importStatus.cjs.js +49 -0
- package/dist/service/handlers/import/importStatus.cjs.js.map +1 -0
- package/dist/service/handlers/organization/organizations.cjs.js +77 -0
- package/dist/service/handlers/organization/organizations.cjs.js.map +1 -0
- package/dist/service/handlers/ping/ping.cjs.js +12 -0
- package/dist/service/handlers/ping/ping.cjs.js.map +1 -0
- package/dist/service/handlers/repository/repositories.cjs.js +99 -0
- package/dist/service/handlers/repository/repositories.cjs.js.map +1 -0
- package/dist/service/router.cjs.js +324 -0
- package/dist/service/router.cjs.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var integration = require('@backstage/integration');
|
|
4
|
+
var gitUrlParse = require('git-url-parse');
|
|
5
|
+
var catalogUtils = require('../catalog/catalogUtils.cjs.js');
|
|
6
|
+
require('@backstage/errors');
|
|
7
|
+
require('@backstage/plugin-permission-common');
|
|
8
|
+
require('@red-hat-developer-hub/backstage-plugin-bulk-import-common');
|
|
9
|
+
var loggingUtils = require('../helpers/loggingUtils.cjs.js');
|
|
10
|
+
var handlers = require('../service/handlers/handlers.cjs.js');
|
|
11
|
+
var GithubAppManager = require('./GithubAppManager.cjs.js');
|
|
12
|
+
var types = require('./types.cjs.js');
|
|
13
|
+
var ghUtils = require('./utils/ghUtils.cjs.js');
|
|
14
|
+
var orgUtils = require('./utils/orgUtils.cjs.js');
|
|
15
|
+
var prUtils = require('./utils/prUtils.cjs.js');
|
|
16
|
+
var repoUtils = require('./utils/repoUtils.cjs.js');
|
|
17
|
+
var utils = require('./utils/utils.cjs.js');
|
|
18
|
+
|
|
19
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
20
|
+
|
|
21
|
+
var gitUrlParse__default = /*#__PURE__*/_interopDefaultCompat(gitUrlParse);
|
|
22
|
+
|
|
23
|
+
class GithubApiService {
|
|
24
|
+
logger;
|
|
25
|
+
integrations;
|
|
26
|
+
githubCredentialsProvider;
|
|
27
|
+
config;
|
|
28
|
+
// Cache for storing ETags (used for efficient caching of unchanged data returned by GitHub)
|
|
29
|
+
cache;
|
|
30
|
+
constructor(logger, config, cacheService) {
|
|
31
|
+
this.logger = logger;
|
|
32
|
+
this.config = config;
|
|
33
|
+
this.integrations = integration.ScmIntegrations.fromConfig(config);
|
|
34
|
+
this.githubCredentialsProvider = GithubAppManager.CustomGithubCredentialsProvider.fromIntegrations(this.integrations);
|
|
35
|
+
this.cache = cacheService;
|
|
36
|
+
}
|
|
37
|
+
async getRepositoryFromIntegrations(repoUrl) {
|
|
38
|
+
const gitUrl = gitUrlParse__default.default(repoUrl);
|
|
39
|
+
const ghConfig = this.integrations.github.byUrl(repoUrl)?.config;
|
|
40
|
+
if (!ghConfig) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`No GitHub integration config found for repo ${repoUrl}. Please add a configuration entry under 'integrations.github`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const credentials = await utils.getCredentialsForConfig(
|
|
46
|
+
this.githubCredentialsProvider,
|
|
47
|
+
ghConfig
|
|
48
|
+
);
|
|
49
|
+
const errors = /* @__PURE__ */ new Map();
|
|
50
|
+
let repository = void 0;
|
|
51
|
+
for (const credential of credentials) {
|
|
52
|
+
const octokit = ghUtils.buildOcto(
|
|
53
|
+
{
|
|
54
|
+
logger: this.logger,
|
|
55
|
+
cache: this.cache
|
|
56
|
+
},
|
|
57
|
+
{ credential, errors, owner: gitUrl.owner },
|
|
58
|
+
ghConfig.apiBaseUrl
|
|
59
|
+
);
|
|
60
|
+
if (!octokit) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const resp = await octokit.rest.repos.get({
|
|
64
|
+
owner: gitUrl.owner,
|
|
65
|
+
repo: gitUrl.name
|
|
66
|
+
});
|
|
67
|
+
const repo = resp?.data;
|
|
68
|
+
if (!repo) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
repository = {
|
|
72
|
+
name: repo.name,
|
|
73
|
+
full_name: repo.full_name,
|
|
74
|
+
url: repo.url,
|
|
75
|
+
html_url: repo.html_url,
|
|
76
|
+
default_branch: repo.default_branch,
|
|
77
|
+
updated_at: repo.updated_at
|
|
78
|
+
};
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
repository,
|
|
83
|
+
errors: Array.from(errors.values())
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async getOrganizationsFromIntegrations(search, pageNumber = handlers.DefaultPageNumber, pageSize = handlers.DefaultPageSize) {
|
|
87
|
+
const orgs = /* @__PURE__ */ new Map();
|
|
88
|
+
const result = await utils.fetchFromAllIntegrations(
|
|
89
|
+
{
|
|
90
|
+
logger: this.logger,
|
|
91
|
+
cache: this.cache,
|
|
92
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
93
|
+
},
|
|
94
|
+
this.integrations,
|
|
95
|
+
{
|
|
96
|
+
dataFetcher: async (octokit, credential, ghConfig) => {
|
|
97
|
+
const dataFetchErrors = /* @__PURE__ */ new Map();
|
|
98
|
+
const resp = types.isGithubAppCredential(credential) ? await orgUtils.addGithubAppOrgs(
|
|
99
|
+
{
|
|
100
|
+
logger: this.logger,
|
|
101
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
102
|
+
},
|
|
103
|
+
octokit,
|
|
104
|
+
ghConfig,
|
|
105
|
+
{
|
|
106
|
+
credentialAccountLogin: credential.accountLogin,
|
|
107
|
+
search,
|
|
108
|
+
orgs,
|
|
109
|
+
errors: dataFetchErrors
|
|
110
|
+
}
|
|
111
|
+
) : await orgUtils.addGithubTokenOrgs(
|
|
112
|
+
{
|
|
113
|
+
logger: this.logger
|
|
114
|
+
},
|
|
115
|
+
octokit,
|
|
116
|
+
credential,
|
|
117
|
+
{
|
|
118
|
+
search,
|
|
119
|
+
orgs,
|
|
120
|
+
pageNumber,
|
|
121
|
+
pageSize,
|
|
122
|
+
errors: dataFetchErrors
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
this.logger.debug(
|
|
126
|
+
`Got ${resp.totalCount} org(s) for ${ghConfig.host}`
|
|
127
|
+
);
|
|
128
|
+
return {
|
|
129
|
+
result: resp.totalCount ?? 0,
|
|
130
|
+
errors: Array.from(dataFetchErrors.values())
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
const orgList = Array.from(orgs.values());
|
|
136
|
+
const totalCount = utils.computeTotalCount(orgList, result.data, pageSize);
|
|
137
|
+
return {
|
|
138
|
+
organizations: orgList,
|
|
139
|
+
errors: Array.from(result.errors?.values() ?? []),
|
|
140
|
+
totalCount
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async getOrgRepositoriesFromIntegrations(orgName, search, pageNumber = handlers.DefaultPageNumber, pageSize = handlers.DefaultPageSize) {
|
|
144
|
+
const repositories = /* @__PURE__ */ new Map();
|
|
145
|
+
const result = await utils.fetchFromAllIntegrations(
|
|
146
|
+
{
|
|
147
|
+
logger: this.logger,
|
|
148
|
+
cache: this.cache,
|
|
149
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
150
|
+
},
|
|
151
|
+
this.integrations,
|
|
152
|
+
{
|
|
153
|
+
dataFetcher: async (octokit, credential, ghConfig) => {
|
|
154
|
+
const dataFetchErrors = /* @__PURE__ */ new Map();
|
|
155
|
+
let resp;
|
|
156
|
+
if (types.isGithubAppCredential(credential)) {
|
|
157
|
+
if (credential.accountLogin !== orgName) {
|
|
158
|
+
return {};
|
|
159
|
+
}
|
|
160
|
+
resp = await repoUtils.addGithubAppRepositories(
|
|
161
|
+
{
|
|
162
|
+
logger: this.logger,
|
|
163
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
164
|
+
},
|
|
165
|
+
octokit,
|
|
166
|
+
credential,
|
|
167
|
+
ghConfig,
|
|
168
|
+
repositories,
|
|
169
|
+
dataFetchErrors,
|
|
170
|
+
{
|
|
171
|
+
search,
|
|
172
|
+
pageNumber,
|
|
173
|
+
pageSize
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
resp = await repoUtils.addGithubTokenOrgRepositories(
|
|
178
|
+
{
|
|
179
|
+
logger: this.logger
|
|
180
|
+
},
|
|
181
|
+
octokit,
|
|
182
|
+
credential,
|
|
183
|
+
orgName,
|
|
184
|
+
repositories,
|
|
185
|
+
dataFetchErrors,
|
|
186
|
+
{
|
|
187
|
+
search,
|
|
188
|
+
pageNumber,
|
|
189
|
+
pageSize
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
this.logger.debug(
|
|
194
|
+
`Got ${resp.totalCount} org repo(s) for ${ghConfig.host}`
|
|
195
|
+
);
|
|
196
|
+
return {
|
|
197
|
+
stopFetchingData: true,
|
|
198
|
+
result: resp.totalCount ?? 0,
|
|
199
|
+
errors: Array.from(dataFetchErrors.values())
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
const repoList = Array.from(repositories.values());
|
|
205
|
+
const totalCount = utils.computeTotalCount(repoList, result.data, pageSize);
|
|
206
|
+
return {
|
|
207
|
+
repositories: repoList,
|
|
208
|
+
errors: Array.from(result.errors?.values() ?? []),
|
|
209
|
+
totalCount
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Returns GithubRepositoryResponse containing:
|
|
214
|
+
* - a list of unique repositories the github integrations have access to
|
|
215
|
+
* - a list of errors encountered by each app and/or token (if any exist)
|
|
216
|
+
*/
|
|
217
|
+
async getRepositoriesFromIntegrations(search, pageNumber = handlers.DefaultPageNumber, pageSize = handlers.DefaultPageSize) {
|
|
218
|
+
const repositories = /* @__PURE__ */ new Map();
|
|
219
|
+
const result = await utils.fetchFromAllIntegrations(
|
|
220
|
+
{
|
|
221
|
+
logger: this.logger,
|
|
222
|
+
cache: this.cache,
|
|
223
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
224
|
+
},
|
|
225
|
+
this.integrations,
|
|
226
|
+
{
|
|
227
|
+
dataFetcher: async (octokit, credential, ghConfig) => {
|
|
228
|
+
const dataFetchErrors = /* @__PURE__ */ new Map();
|
|
229
|
+
const resp = types.isGithubAppCredential(credential) ? await repoUtils.addGithubAppRepositories(
|
|
230
|
+
{
|
|
231
|
+
logger: this.logger,
|
|
232
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
233
|
+
},
|
|
234
|
+
octokit,
|
|
235
|
+
credential,
|
|
236
|
+
ghConfig,
|
|
237
|
+
repositories,
|
|
238
|
+
dataFetchErrors,
|
|
239
|
+
{
|
|
240
|
+
search,
|
|
241
|
+
pageNumber,
|
|
242
|
+
pageSize
|
|
243
|
+
}
|
|
244
|
+
) : await repoUtils.addGithubTokenRepositories(
|
|
245
|
+
{
|
|
246
|
+
logger: this.logger
|
|
247
|
+
},
|
|
248
|
+
octokit,
|
|
249
|
+
credential,
|
|
250
|
+
repositories,
|
|
251
|
+
dataFetchErrors,
|
|
252
|
+
{
|
|
253
|
+
search,
|
|
254
|
+
pageNumber,
|
|
255
|
+
pageSize
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
this.logger.debug(
|
|
259
|
+
`Got ${resp.totalCount} repo(s) for ${ghConfig.host}`
|
|
260
|
+
);
|
|
261
|
+
return {
|
|
262
|
+
result: resp.totalCount ?? 0,
|
|
263
|
+
errors: Array.from(dataFetchErrors.values())
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
const repoList = Array.from(repositories.values());
|
|
269
|
+
const totalCount = utils.computeTotalCount(repoList, result.data, pageSize);
|
|
270
|
+
return {
|
|
271
|
+
repositories: repoList,
|
|
272
|
+
errors: Array.from(result.errors?.values() ?? []),
|
|
273
|
+
totalCount
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
async filterLocationsAccessibleFromIntegrations(locationUrls) {
|
|
277
|
+
const locationGitOwnerMap = utils.extractLocationOwnerMap(locationUrls);
|
|
278
|
+
const allAccessibleAppOrgs = /* @__PURE__ */ new Set();
|
|
279
|
+
const allAccessibleTokenOrgs = /* @__PURE__ */ new Set();
|
|
280
|
+
const allAccessibleUsernames = /* @__PURE__ */ new Set();
|
|
281
|
+
await utils.fetchFromAllIntegrations(
|
|
282
|
+
{
|
|
283
|
+
logger: this.logger,
|
|
284
|
+
cache: this.cache,
|
|
285
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
286
|
+
},
|
|
287
|
+
this.integrations,
|
|
288
|
+
{
|
|
289
|
+
dataFetcher: async (octokit, credential, ghConfig) => {
|
|
290
|
+
if (types.isGithubAppCredential(credential)) {
|
|
291
|
+
const appOrgMap = await orgUtils.getAllAppOrgs(
|
|
292
|
+
this.githubCredentialsProvider,
|
|
293
|
+
ghConfig,
|
|
294
|
+
credential.accountLogin
|
|
295
|
+
);
|
|
296
|
+
for (const [_, ghOrg] of appOrgMap) {
|
|
297
|
+
allAccessibleAppOrgs.add(ghOrg.name);
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
const username = (await octokit.rest.users.getAuthenticated())?.data?.login;
|
|
301
|
+
if (username) {
|
|
302
|
+
allAccessibleUsernames.add(username);
|
|
303
|
+
}
|
|
304
|
+
(await octokit.paginate(octokit.rest.orgs.listForAuthenticatedUser))?.map((org) => org.login)?.forEach((orgName) => allAccessibleTokenOrgs.add(orgName));
|
|
305
|
+
}
|
|
306
|
+
return {};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
return locationUrls.filter((loc) => {
|
|
311
|
+
if (!locationGitOwnerMap.has(loc)) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
const owner = locationGitOwnerMap.get(loc);
|
|
315
|
+
return allAccessibleAppOrgs.has(owner) || allAccessibleTokenOrgs.has(owner) || allAccessibleUsernames.has(owner);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
async findImportOpenPr(logger, input) {
|
|
319
|
+
const ghConfig = this.integrations.github.byUrl(input.repoUrl)?.config;
|
|
320
|
+
if (!ghConfig) {
|
|
321
|
+
throw new Error(`Could not find GH integration from ${input.repoUrl}`);
|
|
322
|
+
}
|
|
323
|
+
const gitUrl = gitUrlParse__default.default(input.repoUrl);
|
|
324
|
+
const owner = gitUrl.organization;
|
|
325
|
+
const repo = gitUrl.name;
|
|
326
|
+
const credentials = await this.githubCredentialsProvider.getAllCredentials({
|
|
327
|
+
host: ghConfig.host
|
|
328
|
+
});
|
|
329
|
+
if (credentials.length === 0) {
|
|
330
|
+
throw new Error(`No credentials for GH integration`);
|
|
331
|
+
}
|
|
332
|
+
const branchName = catalogUtils.getBranchName(this.config);
|
|
333
|
+
for (const credential of credentials) {
|
|
334
|
+
const octo = ghUtils.buildOcto(
|
|
335
|
+
{
|
|
336
|
+
logger: this.logger,
|
|
337
|
+
cache: this.cache
|
|
338
|
+
},
|
|
339
|
+
{ credential, owner },
|
|
340
|
+
ghConfig.apiBaseUrl
|
|
341
|
+
);
|
|
342
|
+
if (!octo) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
return await prUtils.findOpenPRForBranch(
|
|
347
|
+
logger,
|
|
348
|
+
this.config,
|
|
349
|
+
octo,
|
|
350
|
+
owner,
|
|
351
|
+
repo,
|
|
352
|
+
branchName,
|
|
353
|
+
input.includeCatalogInfoContent
|
|
354
|
+
);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
loggingUtils.logErrorIfNeeded(this.logger, "Error fetching pull requests", error);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return {};
|
|
360
|
+
}
|
|
361
|
+
async submitPrToRepo(logger, input) {
|
|
362
|
+
const fileName = catalogUtils.getCatalogFilename(this.config);
|
|
363
|
+
const errors = [];
|
|
364
|
+
const result = await utils.executeFunctionOnFirstSuccessfulIntegration(
|
|
365
|
+
{
|
|
366
|
+
logger: this.logger,
|
|
367
|
+
cache: this.cache,
|
|
368
|
+
config: this.config,
|
|
369
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
370
|
+
},
|
|
371
|
+
this.integrations,
|
|
372
|
+
{
|
|
373
|
+
repoUrl: input.repoUrl,
|
|
374
|
+
fn: async (validatedRepo, octo) => {
|
|
375
|
+
const { owner, repo, branchName } = validatedRepo;
|
|
376
|
+
try {
|
|
377
|
+
const catalogInfoFileExists = await repoUtils.fileExistsInDefaultBranch(
|
|
378
|
+
logger,
|
|
379
|
+
octo,
|
|
380
|
+
owner,
|
|
381
|
+
repo,
|
|
382
|
+
fileName,
|
|
383
|
+
input.defaultBranch
|
|
384
|
+
);
|
|
385
|
+
if (catalogInfoFileExists) {
|
|
386
|
+
return {
|
|
387
|
+
successful: true,
|
|
388
|
+
result: {
|
|
389
|
+
hasChanges: false
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
const existingPrForBranch = await prUtils.findOpenPRForBranch(
|
|
394
|
+
logger,
|
|
395
|
+
this.config,
|
|
396
|
+
octo,
|
|
397
|
+
owner,
|
|
398
|
+
repo,
|
|
399
|
+
branchName
|
|
400
|
+
);
|
|
401
|
+
const repoData = await octo.rest.repos.get({
|
|
402
|
+
owner,
|
|
403
|
+
repo
|
|
404
|
+
});
|
|
405
|
+
const parentRef = await octo.rest.git.getRef({
|
|
406
|
+
owner,
|
|
407
|
+
repo,
|
|
408
|
+
ref: `heads/${repoData.data.default_branch}`
|
|
409
|
+
});
|
|
410
|
+
if (existingPrForBranch.prNum) {
|
|
411
|
+
await repoUtils.createOrUpdateFileInBranch(
|
|
412
|
+
octo,
|
|
413
|
+
owner,
|
|
414
|
+
repo,
|
|
415
|
+
branchName,
|
|
416
|
+
fileName,
|
|
417
|
+
input.catalogInfoContent
|
|
418
|
+
);
|
|
419
|
+
const pullRequestResponse2 = await octo.rest.pulls.update({
|
|
420
|
+
owner,
|
|
421
|
+
repo,
|
|
422
|
+
pull_number: existingPrForBranch.prNum,
|
|
423
|
+
title: input.prTitle,
|
|
424
|
+
body: input.prBody,
|
|
425
|
+
head: branchName,
|
|
426
|
+
base: repoData.data.default_branch
|
|
427
|
+
});
|
|
428
|
+
return {
|
|
429
|
+
successful: true,
|
|
430
|
+
result: {
|
|
431
|
+
prNumber: existingPrForBranch.prNum,
|
|
432
|
+
prUrl: pullRequestResponse2.data.html_url,
|
|
433
|
+
lastUpdate: pullRequestResponse2.data.updated_at
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
let branchExists = false;
|
|
438
|
+
try {
|
|
439
|
+
await octo.rest.git.getRef({
|
|
440
|
+
owner,
|
|
441
|
+
repo,
|
|
442
|
+
ref: `heads/${branchName}`
|
|
443
|
+
});
|
|
444
|
+
branchExists = true;
|
|
445
|
+
} catch (error) {
|
|
446
|
+
if (error.status === 404) {
|
|
447
|
+
await octo.rest.git.createRef({
|
|
448
|
+
owner,
|
|
449
|
+
repo,
|
|
450
|
+
ref: `refs/heads/${branchName}`,
|
|
451
|
+
sha: parentRef.data.object.sha
|
|
452
|
+
});
|
|
453
|
+
} else {
|
|
454
|
+
throw error;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (branchExists) {
|
|
458
|
+
try {
|
|
459
|
+
await octo.repos.merge({
|
|
460
|
+
owner,
|
|
461
|
+
repo,
|
|
462
|
+
base: branchName,
|
|
463
|
+
head: repoData.data.default_branch
|
|
464
|
+
});
|
|
465
|
+
} catch (error) {
|
|
466
|
+
loggingUtils.logErrorIfNeeded(
|
|
467
|
+
this.logger,
|
|
468
|
+
`Could not merge default branch ${repoData.data.default_branch} into import branch ${branchName}`,
|
|
469
|
+
error
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
await repoUtils.createOrUpdateFileInBranch(
|
|
474
|
+
octo,
|
|
475
|
+
owner,
|
|
476
|
+
repo,
|
|
477
|
+
branchName,
|
|
478
|
+
fileName,
|
|
479
|
+
input.catalogInfoContent
|
|
480
|
+
);
|
|
481
|
+
const pullRequestResponse = await octo.rest.pulls.create({
|
|
482
|
+
owner,
|
|
483
|
+
repo,
|
|
484
|
+
title: input.prTitle,
|
|
485
|
+
body: input.prBody,
|
|
486
|
+
head: branchName,
|
|
487
|
+
base: repoData.data.default_branch
|
|
488
|
+
});
|
|
489
|
+
return {
|
|
490
|
+
successful: true,
|
|
491
|
+
result: {
|
|
492
|
+
prNumber: pullRequestResponse.data.number,
|
|
493
|
+
prUrl: pullRequestResponse.data.html_url,
|
|
494
|
+
lastUpdate: pullRequestResponse.data.updated_at,
|
|
495
|
+
hasChanges: true
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
} catch (e) {
|
|
499
|
+
loggingUtils.logErrorIfNeeded(
|
|
500
|
+
this.logger,
|
|
501
|
+
`Couldn't create PR in ${input.repoUrl}`,
|
|
502
|
+
e
|
|
503
|
+
);
|
|
504
|
+
errors.push(e.message);
|
|
505
|
+
return { successful: false };
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
);
|
|
510
|
+
if (result) {
|
|
511
|
+
return result;
|
|
512
|
+
}
|
|
513
|
+
logger.warn(
|
|
514
|
+
`Tried all possible GitHub credentials, but could not create PR in ${input.repoUrl}. Please try again later...`
|
|
515
|
+
);
|
|
516
|
+
return {
|
|
517
|
+
errors
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
async hasFileInRepo(input) {
|
|
521
|
+
const fileExists = await utils.executeFunctionOnFirstSuccessfulIntegration(
|
|
522
|
+
{
|
|
523
|
+
logger: this.logger,
|
|
524
|
+
cache: this.cache,
|
|
525
|
+
config: this.config,
|
|
526
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
527
|
+
},
|
|
528
|
+
this.integrations,
|
|
529
|
+
{
|
|
530
|
+
repoUrl: input.repoUrl,
|
|
531
|
+
fn: async (validatedRepo, octo) => {
|
|
532
|
+
const { owner, repo } = validatedRepo;
|
|
533
|
+
const exists = await repoUtils.fileExistsInDefaultBranch(
|
|
534
|
+
this.logger,
|
|
535
|
+
octo,
|
|
536
|
+
owner,
|
|
537
|
+
repo,
|
|
538
|
+
input.fileName,
|
|
539
|
+
input.defaultBranch
|
|
540
|
+
);
|
|
541
|
+
if (exists === void 0) {
|
|
542
|
+
return { successful: false };
|
|
543
|
+
}
|
|
544
|
+
return { successful: true, result: exists };
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
);
|
|
548
|
+
if (fileExists === void 0) {
|
|
549
|
+
throw new Error(
|
|
550
|
+
`Could not determine if repo at ${input.repoUrl} already has a file named ${input.fileName} in its default branch (${input.defaultBranch})`
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
return fileExists;
|
|
554
|
+
}
|
|
555
|
+
async closeImportPR(logger, input) {
|
|
556
|
+
await utils.executeFunctionOnFirstSuccessfulIntegration(
|
|
557
|
+
{
|
|
558
|
+
logger: this.logger,
|
|
559
|
+
cache: this.cache,
|
|
560
|
+
config: this.config,
|
|
561
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
562
|
+
},
|
|
563
|
+
this.integrations,
|
|
564
|
+
{
|
|
565
|
+
repoUrl: input.repoUrl,
|
|
566
|
+
fn: async (validatedRepo, octo) => {
|
|
567
|
+
const { owner, repo, branchName } = validatedRepo;
|
|
568
|
+
try {
|
|
569
|
+
const existingPrForBranch = await prUtils.findOpenPRForBranch(
|
|
570
|
+
logger,
|
|
571
|
+
this.config,
|
|
572
|
+
octo,
|
|
573
|
+
owner,
|
|
574
|
+
repo,
|
|
575
|
+
branchName
|
|
576
|
+
);
|
|
577
|
+
if (existingPrForBranch.prNum) {
|
|
578
|
+
await prUtils.closePRWithComment(
|
|
579
|
+
octo,
|
|
580
|
+
owner,
|
|
581
|
+
repo,
|
|
582
|
+
existingPrForBranch.prNum,
|
|
583
|
+
input.comment
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
return { successful: true };
|
|
587
|
+
} catch (e) {
|
|
588
|
+
loggingUtils.logErrorIfNeeded(
|
|
589
|
+
this.logger,
|
|
590
|
+
`Couldn't close PR in ${input.repoUrl}`,
|
|
591
|
+
e
|
|
592
|
+
);
|
|
593
|
+
return { successful: false };
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
async deleteImportBranch(input) {
|
|
600
|
+
await utils.executeFunctionOnFirstSuccessfulIntegration(
|
|
601
|
+
{
|
|
602
|
+
logger: this.logger,
|
|
603
|
+
cache: this.cache,
|
|
604
|
+
config: this.config,
|
|
605
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
606
|
+
},
|
|
607
|
+
this.integrations,
|
|
608
|
+
{
|
|
609
|
+
repoUrl: input.repoUrl,
|
|
610
|
+
fn: async (validatedRepo, octo) => {
|
|
611
|
+
const { owner, repo, branchName } = validatedRepo;
|
|
612
|
+
try {
|
|
613
|
+
await octo.git.deleteRef({
|
|
614
|
+
owner,
|
|
615
|
+
repo,
|
|
616
|
+
ref: `heads/${branchName}`
|
|
617
|
+
});
|
|
618
|
+
return { successful: true };
|
|
619
|
+
} catch (e) {
|
|
620
|
+
loggingUtils.logErrorIfNeeded(
|
|
621
|
+
this.logger,
|
|
622
|
+
`Couldn't close import PR and/or delete import branch in ${input.repoUrl}`,
|
|
623
|
+
e
|
|
624
|
+
);
|
|
625
|
+
return { successful: false };
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
async isRepoEmpty(input) {
|
|
632
|
+
return await utils.executeFunctionOnFirstSuccessfulIntegration(
|
|
633
|
+
{
|
|
634
|
+
logger: this.logger,
|
|
635
|
+
cache: this.cache,
|
|
636
|
+
config: this.config,
|
|
637
|
+
githubCredentialsProvider: this.githubCredentialsProvider
|
|
638
|
+
},
|
|
639
|
+
this.integrations,
|
|
640
|
+
{
|
|
641
|
+
repoUrl: input.repoUrl,
|
|
642
|
+
fn: async (validatedRepo, octo) => {
|
|
643
|
+
const { owner, repo } = validatedRepo;
|
|
644
|
+
const resp = await octo.rest.repos.listContributors({
|
|
645
|
+
owner,
|
|
646
|
+
repo,
|
|
647
|
+
page: 1,
|
|
648
|
+
per_page: 1
|
|
649
|
+
});
|
|
650
|
+
const status = resp.status;
|
|
651
|
+
return { successful: true, result: status === 204 };
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
exports.GithubApiService = GithubApiService;
|
|
659
|
+
//# sourceMappingURL=githubApiService.cjs.js.map
|