@capawesome/cli 4.18.0-dev.9810ff51.1785743282 → 4.18.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 +8 -0
- package/dist/commands/apps/automations/create.js +3 -3
- package/dist/commands/apps/automations/delete.js +1 -1
- package/dist/commands/apps/automations/get.js +1 -1
- package/dist/commands/apps/automations/list.js +1 -1
- package/dist/commands/apps/automations/update.js +3 -3
- package/dist/commands/apps/builds/cancel.js +1 -1
- package/dist/commands/apps/builds/create.js +1 -1
- package/dist/commands/apps/builds/download.js +1 -1
- package/dist/commands/apps/builds/failure-summary.js +1 -1
- package/dist/commands/apps/builds/get.js +1 -1
- package/dist/commands/apps/builds/list.js +1 -1
- package/dist/commands/apps/builds/logs.js +1 -1
- package/dist/commands/apps/builds/run.js +1 -1
- package/dist/commands/apps/builds/share.js +1 -1
- package/dist/commands/apps/builds/unshare.js +1 -1
- package/dist/commands/apps/bundles/create.js +1 -1
- package/dist/commands/apps/bundles/delete.js +1 -1
- package/dist/commands/apps/bundles/update.js +1 -1
- package/dist/commands/apps/certificates/create.js +1 -1
- package/dist/commands/apps/certificates/delete.js +1 -1
- package/dist/commands/apps/certificates/get.js +1 -1
- package/dist/commands/apps/certificates/list.js +1 -1
- package/dist/commands/apps/certificates/update.js +1 -1
- package/dist/commands/apps/channels/create.js +1 -1
- package/dist/commands/apps/channels/delete.js +1 -1
- package/dist/commands/apps/channels/get.js +1 -1
- package/dist/commands/apps/channels/list.js +1 -1
- package/dist/commands/apps/channels/pause.js +1 -1
- package/dist/commands/apps/channels/resume.js +1 -1
- package/dist/commands/apps/channels/update.js +1 -1
- package/dist/commands/apps/configurations/create.js +1 -1
- package/dist/commands/apps/configurations/delete.js +1 -1
- package/dist/commands/apps/configurations/get.js +1 -1
- package/dist/commands/apps/configurations/list.js +1 -1
- package/dist/commands/apps/configurations/update.js +1 -1
- package/dist/commands/apps/create.js +1 -1
- package/dist/commands/apps/delete.js +1 -1
- package/dist/commands/apps/deployments/cancel.js +1 -1
- package/dist/commands/apps/deployments/create.js +1 -1
- package/dist/commands/apps/deployments/failure-summary.js +1 -1
- package/dist/commands/apps/deployments/get.js +1 -1
- package/dist/commands/apps/deployments/list.js +1 -1
- package/dist/commands/apps/deployments/logs.js +1 -1
- package/dist/commands/apps/destinations/create.js +1 -1
- package/dist/commands/apps/destinations/delete.js +1 -1
- package/dist/commands/apps/destinations/get.js +1 -1
- package/dist/commands/apps/destinations/list.js +1 -1
- package/dist/commands/apps/destinations/update.js +1 -1
- package/dist/commands/apps/devices/delete.js +1 -1
- package/dist/commands/apps/devices/forcechannel.js +1 -1
- package/dist/commands/apps/devices/probe.js +1 -1
- package/dist/commands/apps/devices/unforcechannel.js +1 -1
- package/dist/commands/apps/environments/create.js +1 -1
- package/dist/commands/apps/environments/delete.js +1 -1
- package/dist/commands/apps/environments/get.js +1 -1
- package/dist/commands/apps/environments/list.js +1 -1
- package/dist/commands/apps/environments/set.js +1 -1
- package/dist/commands/apps/environments/unset.js +1 -1
- package/dist/commands/apps/get.js +1 -1
- package/dist/commands/apps/link.js +1 -1
- package/dist/commands/apps/list.js +1 -1
- package/dist/commands/apps/liveupdates/bundle.js +1 -1
- package/dist/commands/apps/liveupdates/create.js +1 -1
- package/dist/commands/apps/liveupdates/generate-manifest.js +1 -1
- package/dist/commands/apps/liveupdates/generate-signing-key.js +1 -1
- package/dist/commands/apps/liveupdates/register.js +1 -1
- package/dist/commands/apps/liveupdates/rollback.js +1 -1
- package/dist/commands/apps/liveupdates/rollout.js +1 -1
- package/dist/commands/apps/liveupdates/set-native-versions.js +1 -1
- package/dist/commands/apps/liveupdates/upload.js +1 -1
- package/dist/commands/apps/transfer.js +1 -1
- package/dist/commands/apps/unlink.js +1 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/login.js +4 -4
- package/dist/commands/logout.js +1 -1
- package/dist/commands/manifests/generate.js +1 -1
- package/dist/commands/organizations/create.js +1 -1
- package/dist/commands/organizations/get.js +1 -1
- package/dist/commands/organizations/list.js +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/index.js +2 -4
- package/dist/index.test.js +1 -1
- package/package.json +3 -3
- package/dist/commands/apps/import.js +0 -419
- package/dist/commands/apps/import.test.js +0 -308
- package/dist/utils/app-import.js +0 -10
- package/dist/utils/appflow-export.js +0 -391
- package/dist/utils/appflow-export.test.js +0 -277
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_CONSOLE_BASE_URL } from '../../config/consts.js';
|
|
2
|
-
import appAutomationsService from '../../services/app-automations.js';
|
|
3
|
-
import appCertificatesService from '../../services/app-certificates.js';
|
|
4
|
-
import appChannelsService from '../../services/app-channels.js';
|
|
5
|
-
import appConfigurationsService from '../../services/app-configurations.js';
|
|
6
|
-
import appDestinationsService from '../../services/app-destinations.js';
|
|
7
|
-
import appEnvironmentsService from '../../services/app-environments.js';
|
|
8
|
-
import appGoogleServiceAccountKeysService from '../../services/app-google-service-account-keys.js';
|
|
9
|
-
import appProvisioningProfilesService from '../../services/app-provisioning-profiles.js';
|
|
10
|
-
import appsService from '../../services/apps.js';
|
|
11
|
-
import { generateUniqueAppName } from '../../utils/app-import.js';
|
|
12
|
-
import { parseAppflowExport } from '../../utils/appflow-export.js';
|
|
13
|
-
import { withAuth } from '../../utils/auth.js';
|
|
14
|
-
import { isInteractive } from '../../utils/environment.js';
|
|
15
|
-
import { getMessageFromUnknownError, UserError } from '../../utils/error.js';
|
|
16
|
-
import { isReadable } from '../../utils/file.js';
|
|
17
|
-
import { prompt, promptOrganizationSelection } from '../../utils/prompt.js';
|
|
18
|
-
import zip from '../../utils/zip.js';
|
|
19
|
-
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
20
|
-
import consola from 'consola';
|
|
21
|
-
import fs from 'fs';
|
|
22
|
-
import os from 'os';
|
|
23
|
-
import path from 'path';
|
|
24
|
-
import { z } from 'zod';
|
|
25
|
-
export default defineCommand({
|
|
26
|
-
description: 'Import apps from an Ionic Appflow export.',
|
|
27
|
-
options: defineOptions(z.object({
|
|
28
|
-
dryRun: z.boolean().optional().describe('Preview the import without creating any resources.'),
|
|
29
|
-
file: z.string().optional().describe('Path to the export file (.zip).'),
|
|
30
|
-
include: z
|
|
31
|
-
.array(z.string())
|
|
32
|
-
.optional()
|
|
33
|
-
.describe('Filter which apps to import by name or ID. Can be specified multiple times or comma-separated. Defaults to all apps.'),
|
|
34
|
-
json: z.boolean().optional().describe('Output in JSON format.'),
|
|
35
|
-
organizationId: z.string().optional().describe('ID of the organization to import the apps into.'),
|
|
36
|
-
})),
|
|
37
|
-
action: withAuth(async (options, args) => {
|
|
38
|
-
let { dryRun, file, include, json, organizationId } = options;
|
|
39
|
-
if (!file) {
|
|
40
|
-
if (!isInteractive()) {
|
|
41
|
-
consola.error('You must provide the export file path when running in non-interactive environment.');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
file = await prompt('Enter the path to the export file (.zip):', { type: 'text' });
|
|
45
|
-
if (!file) {
|
|
46
|
-
consola.error('You must provide an export file path.');
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
if (!zip.isZipped(file)) {
|
|
51
|
-
consola.error('The export file must be a `.zip` file.');
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
const fileReadable = await isReadable(file);
|
|
55
|
-
if (!fileReadable) {
|
|
56
|
-
consola.error(`The export file does not exist or is not accessible: ${file}`);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
if (!organizationId) {
|
|
60
|
-
if (!isInteractive()) {
|
|
61
|
-
consola.error('You must provide an organization ID when running in non-interactive environment.');
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
organizationId = await promptOrganizationSelection({
|
|
65
|
-
message: 'Which organization do you want to import the apps into?',
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
const tempDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'capawesome-appflow-import-'));
|
|
69
|
-
try {
|
|
70
|
-
await zip.unzipToFolder(fs.readFileSync(file), tempDirectory);
|
|
71
|
-
const { apps, skippedApps } = await parseAppflowExport(tempDirectory);
|
|
72
|
-
const { selectedApps, selectedSkippedApps } = await selectApps(apps, skippedApps, include);
|
|
73
|
-
if (selectedApps.length === 0 && selectedSkippedApps.length === 0) {
|
|
74
|
-
throw new UserError('No apps found in the export that match the provided filters.');
|
|
75
|
-
}
|
|
76
|
-
await assignUniqueAppNames(selectedApps, organizationId);
|
|
77
|
-
const outcomes = [];
|
|
78
|
-
for (const app of selectedApps) {
|
|
79
|
-
const outcome = {
|
|
80
|
-
app,
|
|
81
|
-
errors: [],
|
|
82
|
-
created: {
|
|
83
|
-
automations: 0,
|
|
84
|
-
certificates: 0,
|
|
85
|
-
channels: 0,
|
|
86
|
-
configurations: 0,
|
|
87
|
-
destinations: 0,
|
|
88
|
-
environments: 0,
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
outcomes.push(outcome);
|
|
92
|
-
if (dryRun) {
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
await importApp(organizationId, outcome);
|
|
96
|
-
}
|
|
97
|
-
const errorCount = outcomes.reduce((count, outcome) => count + outcome.errors.length, 0);
|
|
98
|
-
if (json) {
|
|
99
|
-
printJsonSummary(outcomes, selectedSkippedApps, dryRun === true);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
printSummary(outcomes, selectedSkippedApps, dryRun === true, file);
|
|
103
|
-
}
|
|
104
|
-
if (errorCount > 0) {
|
|
105
|
-
process.exit(1);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
finally {
|
|
109
|
-
fs.rmSync(tempDirectory, { recursive: true, force: true });
|
|
110
|
-
}
|
|
111
|
-
}),
|
|
112
|
-
});
|
|
113
|
-
const selectApps = async (apps, skippedApps, include) => {
|
|
114
|
-
const filters = include
|
|
115
|
-
?.flatMap((value) => value.split(','))
|
|
116
|
-
.map((value) => value.trim())
|
|
117
|
-
.filter((value) => value.length > 0);
|
|
118
|
-
if (filters && filters.length > 0) {
|
|
119
|
-
const matchesFilter = (sourceId, sourceName) => filters.some((filter) => filter === sourceId || filter === sourceName);
|
|
120
|
-
for (const filter of filters) {
|
|
121
|
-
const matched = apps.some((app) => app.sourceId === filter || app.sourceName === filter) ||
|
|
122
|
-
skippedApps.some((app) => app.sourceId === filter || app.sourceName === filter);
|
|
123
|
-
if (!matched) {
|
|
124
|
-
consola.warn(`No app in the export matches the filter \`${filter}\`.`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
selectedApps: apps.filter((app) => matchesFilter(app.sourceId, app.sourceName)),
|
|
129
|
-
selectedSkippedApps: skippedApps.filter((app) => matchesFilter(app.sourceId, app.sourceName)),
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
if (isInteractive() && apps.length > 1) {
|
|
133
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
134
|
-
const selectedIds = await prompt('Which apps do you want to import?', {
|
|
135
|
-
type: 'multiselect',
|
|
136
|
-
options: apps.map((app) => ({ label: `${app.sourceName} (${app.sourceId})`, value: app.sourceId })),
|
|
137
|
-
initial: apps.map((app) => app.sourceId),
|
|
138
|
-
});
|
|
139
|
-
return {
|
|
140
|
-
selectedApps: apps.filter((app) => selectedIds.includes(app.sourceId)),
|
|
141
|
-
selectedSkippedApps: skippedApps,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
return { selectedApps: apps, selectedSkippedApps: skippedApps };
|
|
145
|
-
};
|
|
146
|
-
const assignUniqueAppNames = async (apps, organizationId) => {
|
|
147
|
-
const takenNames = new Set();
|
|
148
|
-
const limit = 50;
|
|
149
|
-
let offset = 0;
|
|
150
|
-
while (true) {
|
|
151
|
-
const page = await appsService.findAll({ organizationId, limit, offset });
|
|
152
|
-
for (const app of page) {
|
|
153
|
-
takenNames.add(app.name);
|
|
154
|
-
}
|
|
155
|
-
if (page.length < limit) {
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
offset += limit;
|
|
159
|
-
}
|
|
160
|
-
for (const app of apps) {
|
|
161
|
-
app.name = generateUniqueAppName(app.sourceName, takenNames);
|
|
162
|
-
takenNames.add(app.name);
|
|
163
|
-
if (app.name !== app.sourceName) {
|
|
164
|
-
app.notes.push(`An app with the name \`${app.sourceName}\` already exists in the organization. The app is imported as \`${app.name}\`.`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
const importApp = async (organizationId, outcome) => {
|
|
169
|
-
const { app } = outcome;
|
|
170
|
-
consola.start(`Importing app \`${app.sourceName}\`...`);
|
|
171
|
-
let appId;
|
|
172
|
-
try {
|
|
173
|
-
const createdApp = await appsService.create({ name: app.name, organizationId, type: app.type });
|
|
174
|
-
appId = createdApp.id;
|
|
175
|
-
outcome.id = appId;
|
|
176
|
-
consola.success(`Created app \`${app.name}\`.`);
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
outcome.errors.push(`Failed to create app: ${getMessageFromUnknownError(error)}`);
|
|
180
|
-
consola.error(`Failed to create app \`${app.name}\`.`);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
for (const certificate of app.certificates) {
|
|
184
|
-
try {
|
|
185
|
-
const provisioningProfileIds = [];
|
|
186
|
-
for (const profilePath of certificate.provisioningProfilePaths) {
|
|
187
|
-
const profile = await appProvisioningProfilesService.create({
|
|
188
|
-
appId,
|
|
189
|
-
buffer: fs.readFileSync(profilePath),
|
|
190
|
-
fileName: path.basename(profilePath),
|
|
191
|
-
});
|
|
192
|
-
provisioningProfileIds.push(profile.id);
|
|
193
|
-
}
|
|
194
|
-
const createdCertificate = await appCertificatesService.create({
|
|
195
|
-
appId,
|
|
196
|
-
buffer: fs.readFileSync(certificate.filePath),
|
|
197
|
-
fileName: path.basename(certificate.filePath),
|
|
198
|
-
name: certificate.name,
|
|
199
|
-
platform: certificate.platform,
|
|
200
|
-
password: certificate.password,
|
|
201
|
-
keyAlias: certificate.keyAlias,
|
|
202
|
-
keyPassword: certificate.keyPassword,
|
|
203
|
-
});
|
|
204
|
-
if (provisioningProfileIds.length > 0) {
|
|
205
|
-
await appProvisioningProfilesService.updateMany({
|
|
206
|
-
appId,
|
|
207
|
-
ids: provisioningProfileIds,
|
|
208
|
-
appCertificateId: createdCertificate.id,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
outcome.created.certificates++;
|
|
212
|
-
consola.success(`Created certificate \`${certificate.name}\`.`);
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
outcome.errors.push(`Failed to create certificate \`${certificate.name}\`: ${getMessageFromUnknownError(error)}`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
for (const environment of app.environments) {
|
|
219
|
-
try {
|
|
220
|
-
const createdEnvironment = await appEnvironmentsService.create({ appId, name: environment.name });
|
|
221
|
-
if (environment.variables.length > 0) {
|
|
222
|
-
await appEnvironmentsService.setVariables({
|
|
223
|
-
appId,
|
|
224
|
-
environmentId: createdEnvironment.id,
|
|
225
|
-
variables: environment.variables,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
if (environment.secrets.length > 0) {
|
|
229
|
-
await appEnvironmentsService.setSecrets({
|
|
230
|
-
appId,
|
|
231
|
-
environmentId: createdEnvironment.id,
|
|
232
|
-
secrets: environment.secrets,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
outcome.created.environments++;
|
|
236
|
-
consola.success(`Created environment \`${environment.name}\`.`);
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
outcome.errors.push(`Failed to create environment \`${environment.name}\`: ${getMessageFromUnknownError(error)}`);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
let existingChannelNames = new Set();
|
|
243
|
-
try {
|
|
244
|
-
const existingChannels = await appChannelsService.findAll({ appId });
|
|
245
|
-
existingChannelNames = new Set(existingChannels.map((channel) => channel.name));
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
// If the lookup fails, channel creation errors are reported individually below.
|
|
249
|
-
}
|
|
250
|
-
for (const channel of app.channels) {
|
|
251
|
-
if (existingChannelNames.has(channel)) {
|
|
252
|
-
outcome.created.channels++;
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
try {
|
|
256
|
-
await appChannelsService.create({ appId, name: channel });
|
|
257
|
-
outcome.created.channels++;
|
|
258
|
-
consola.success(`Created channel \`${channel}\`.`);
|
|
259
|
-
}
|
|
260
|
-
catch (error) {
|
|
261
|
-
outcome.errors.push(`Failed to create channel \`${channel}\`: ${getMessageFromUnknownError(error)}`);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
for (const configuration of app.configurations) {
|
|
265
|
-
try {
|
|
266
|
-
await appConfigurationsService.create({
|
|
267
|
-
appId,
|
|
268
|
-
name: configuration.name,
|
|
269
|
-
displayName: configuration.displayName,
|
|
270
|
-
packageName: configuration.packageName,
|
|
271
|
-
});
|
|
272
|
-
outcome.created.configurations++;
|
|
273
|
-
consola.success(`Created configuration \`${configuration.name}\`.`);
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
outcome.errors.push(`Failed to create configuration \`${configuration.name}\`: ${getMessageFromUnknownError(error)}`);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
for (const destination of app.destinations) {
|
|
280
|
-
try {
|
|
281
|
-
let appGoogleServiceAccountKeyId;
|
|
282
|
-
if (destination.googleServiceAccountKeyPath) {
|
|
283
|
-
const key = await appGoogleServiceAccountKeysService.create({
|
|
284
|
-
appId,
|
|
285
|
-
buffer: fs.readFileSync(destination.googleServiceAccountKeyPath),
|
|
286
|
-
fileName: path.basename(destination.googleServiceAccountKeyPath),
|
|
287
|
-
});
|
|
288
|
-
appGoogleServiceAccountKeyId = key.id;
|
|
289
|
-
}
|
|
290
|
-
await appDestinationsService.create({
|
|
291
|
-
appId,
|
|
292
|
-
name: destination.name,
|
|
293
|
-
platform: destination.platform,
|
|
294
|
-
androidPackageName: destination.androidPackageName,
|
|
295
|
-
androidBuildArtifactType: destination.androidBuildArtifactType,
|
|
296
|
-
googlePlayTrack: destination.googlePlayTrack,
|
|
297
|
-
appGoogleServiceAccountKeyId,
|
|
298
|
-
appleId: destination.appleId,
|
|
299
|
-
appleAppId: destination.appleAppId,
|
|
300
|
-
appleTeamId: destination.appleTeamId,
|
|
301
|
-
appleAppPassword: destination.appleAppPassword,
|
|
302
|
-
});
|
|
303
|
-
outcome.created.destinations++;
|
|
304
|
-
consola.success(`Created destination \`${destination.name}\`.`);
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
outcome.errors.push(`Failed to create destination \`${destination.name}\`: ${getMessageFromUnknownError(error)}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
for (const automation of app.automations) {
|
|
311
|
-
try {
|
|
312
|
-
await appAutomationsService.create({
|
|
313
|
-
appId,
|
|
314
|
-
name: automation.name,
|
|
315
|
-
platform: automation.platform,
|
|
316
|
-
triggerType: 'branch',
|
|
317
|
-
triggerPattern: automation.triggerPattern,
|
|
318
|
-
buildType: automation.buildType,
|
|
319
|
-
enabled: automation.enabled,
|
|
320
|
-
appCertificateName: automation.appCertificateName,
|
|
321
|
-
appChannelName: automation.appChannelName,
|
|
322
|
-
appConfigurationName: automation.appConfigurationName,
|
|
323
|
-
appDestinationName: automation.appDestinationName,
|
|
324
|
-
appEnvironmentName: automation.appEnvironmentName,
|
|
325
|
-
});
|
|
326
|
-
outcome.created.automations++;
|
|
327
|
-
consola.success(`Created automation \`${automation.name}\`.`);
|
|
328
|
-
}
|
|
329
|
-
catch (error) {
|
|
330
|
-
outcome.errors.push(`Failed to create automation \`${automation.name}\`: ${getMessageFromUnknownError(error)}`);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (app.repository) {
|
|
334
|
-
try {
|
|
335
|
-
await appsService.linkRepository({
|
|
336
|
-
appId,
|
|
337
|
-
ownerSlug: app.repository.ownerSlug,
|
|
338
|
-
provider: app.repository.provider,
|
|
339
|
-
repositorySlug: app.repository.repositorySlug,
|
|
340
|
-
projectSlug: app.repository.projectSlug,
|
|
341
|
-
});
|
|
342
|
-
consola.success(`Linked repository \`${app.repository.ownerSlug}/${app.repository.repositorySlug}\`.`);
|
|
343
|
-
}
|
|
344
|
-
catch (error) {
|
|
345
|
-
app.notes.push(`The repository \`${app.repository.ownerSlug}/${app.repository.repositorySlug}\` could not be linked: ${getMessageFromUnknownError(error)} Make sure the git provider is connected in the Capawesome Cloud Console and link the repository manually.`);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
const printSummary = (outcomes, skippedApps, dryRun, file) => {
|
|
350
|
-
consola.log('');
|
|
351
|
-
if (dryRun) {
|
|
352
|
-
consola.info('Dry run. No resources were created.');
|
|
353
|
-
}
|
|
354
|
-
console.table(outcomes.map((outcome) => ({
|
|
355
|
-
App: outcome.app.sourceName,
|
|
356
|
-
'Imported as': dryRun || outcome.id ? outcome.app.name : '—',
|
|
357
|
-
Certificates: formatCount(outcome.created.certificates, outcome.app.certificates.length, dryRun),
|
|
358
|
-
Environments: formatCount(outcome.created.environments, outcome.app.environments.length, dryRun),
|
|
359
|
-
Channels: formatCount(outcome.created.channels, outcome.app.channels.length, dryRun),
|
|
360
|
-
Configurations: formatCount(outcome.created.configurations, outcome.app.configurations.length, dryRun),
|
|
361
|
-
Destinations: formatCount(outcome.created.destinations, outcome.app.destinations.length, dryRun),
|
|
362
|
-
Automations: formatCount(outcome.created.automations, outcome.app.automations.length, dryRun),
|
|
363
|
-
Errors: outcome.errors.length,
|
|
364
|
-
})));
|
|
365
|
-
for (const outcome of outcomes) {
|
|
366
|
-
if (outcome.app.notes.length === 0 && outcome.errors.length === 0) {
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
consola.log(`\n${outcome.app.sourceName}:`);
|
|
370
|
-
for (const note of outcome.app.notes) {
|
|
371
|
-
consola.warn(note);
|
|
372
|
-
}
|
|
373
|
-
for (const error of outcome.errors) {
|
|
374
|
-
consola.error(error);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
for (const outcome of outcomes) {
|
|
378
|
-
if (outcome.id) {
|
|
379
|
-
consola.info(`App URL: ${DEFAULT_CONSOLE_BASE_URL}/apps/${outcome.id}`);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
const retryLaterApps = skippedApps.filter((app) => app.retryLater);
|
|
383
|
-
const otherSkippedApps = skippedApps.filter((app) => !app.retryLater);
|
|
384
|
-
for (const app of otherSkippedApps) {
|
|
385
|
-
consola.warn(`The app \`${app.sourceName}\` was skipped: ${app.reason}`);
|
|
386
|
-
}
|
|
387
|
-
if (retryLaterApps.length > 0) {
|
|
388
|
-
const includeValues = retryLaterApps
|
|
389
|
-
.map((app) => (app.sourceName.includes(',') ? app.sourceId : app.sourceName))
|
|
390
|
-
.join(',');
|
|
391
|
-
consola.info(`The apps ${retryLaterApps.map((app) => `\`${app.sourceName}\``).join(', ')} were skipped because their app type is not yet supported. Support is coming soon. You can import the remaining apps later by running:\n\nnpx @capawesome/cli apps:import --file "${file}" --include "${includeValues}"`);
|
|
392
|
-
}
|
|
393
|
-
if (!dryRun) {
|
|
394
|
-
consola.success('Import completed.');
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
const formatCount = (created, total, dryRun) => {
|
|
398
|
-
return dryRun ? `${total}` : `${created}/${total}`;
|
|
399
|
-
};
|
|
400
|
-
const printJsonSummary = (outcomes, skippedApps, dryRun) => {
|
|
401
|
-
console.log(JSON.stringify({
|
|
402
|
-
dryRun,
|
|
403
|
-
apps: outcomes.map((outcome) => ({
|
|
404
|
-
id: outcome.id ?? null,
|
|
405
|
-
name: outcome.app.name,
|
|
406
|
-
sourceId: outcome.app.sourceId,
|
|
407
|
-
sourceName: outcome.app.sourceName,
|
|
408
|
-
webUrl: outcome.id ? `${DEFAULT_CONSOLE_BASE_URL}/apps/${outcome.id}` : null,
|
|
409
|
-
created: outcome.created,
|
|
410
|
-
notes: outcome.app.notes,
|
|
411
|
-
errors: outcome.errors,
|
|
412
|
-
})),
|
|
413
|
-
skippedApps: skippedApps.map((app) => ({
|
|
414
|
-
sourceId: app.sourceId,
|
|
415
|
-
sourceName: app.sourceName,
|
|
416
|
-
reason: app.reason,
|
|
417
|
-
})),
|
|
418
|
-
}, null, 2));
|
|
419
|
-
};
|