@unito/integration-cli 1.2.0 → 1.3.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/dist/boilerplate/src/handlers/me.ts +3 -1
- package/dist/boilerplate/src/handlers/root.ts +3 -1
- package/dist/schemas/configuration.json +6 -0
- package/dist/src/commands/publish.d.ts +3 -0
- package/dist/src/commands/publish.js +39 -7
- package/dist/src/commands/upgrade.js +2 -1
- package/dist/src/configurationTypes.d.ts +8 -0
- package/dist/src/configurationTypes.js +9 -1
- package/dist/src/services/integrationsPlatform.js +1 -0
- package/dist/test/commands/publish.test.js +187 -0
- package/dist/test/services/integrationsPlatform.test.js +2 -0
- package/oclif.manifest.json +26 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GetCredentialAccountHandler } from '@unito/integration-sdk';
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/require-await -- Remove when adding async provider calls
|
|
4
|
-
|
|
4
|
+
const getCredentialAccount: GetCredentialAccountHandler = async function getCredentialAccount() {
|
|
5
5
|
return {
|
|
6
6
|
id: 'me',
|
|
7
7
|
displayName: 'Me',
|
|
@@ -9,3 +9,5 @@ export const getCredentialAccount: GetCredentialAccountHandler = async () => {
|
|
|
9
9
|
partition: undefined,
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
|
+
|
|
13
|
+
export { getCredentialAccount };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { GetItemHandler } from '@unito/integration-sdk';
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/require-await -- Remove when adding async provider calls
|
|
4
|
-
|
|
4
|
+
const getItem: GetItemHandler = async function getItem() {
|
|
5
5
|
return {
|
|
6
6
|
fields: {},
|
|
7
7
|
relations: [],
|
|
8
8
|
};
|
|
9
9
|
};
|
|
10
|
+
|
|
11
|
+
export { getItem };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseCommand } from '../baseCommand';
|
|
2
2
|
import * as GlobalConfiguration from '../resources/globalConfiguration';
|
|
3
|
+
import { Visibility } from '../configurationTypes';
|
|
3
4
|
export default class Publish extends BaseCommand<typeof Publish> {
|
|
4
5
|
static description: string;
|
|
5
6
|
static examples: string[];
|
|
@@ -8,6 +9,8 @@ export default class Publish extends BaseCommand<typeof Publish> {
|
|
|
8
9
|
'registry-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
10
|
preview: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
11
|
'live-preview': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
visibility: import("@oclif/core/lib/interfaces").OptionFlag<Visibility | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
'display-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
14
|
'config-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
15
|
force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
16
|
};
|
|
@@ -16,6 +16,7 @@ const integrations_1 = require("../resources/integrations");
|
|
|
16
16
|
const GlobalConfiguration = tslib_1.__importStar(require("../resources/globalConfiguration"));
|
|
17
17
|
const IntegrationsPlatform = tslib_1.__importStar(require("../services/integrationsPlatform"));
|
|
18
18
|
const IntegrationConfiguration = tslib_1.__importStar(require("../resources/configuration"));
|
|
19
|
+
const configurationTypes_1 = require("../configurationTypes");
|
|
19
20
|
const fileSystem_1 = require("../resources/fileSystem");
|
|
20
21
|
const integrationsPlatform_1 = require("../resources/integrationsPlatform");
|
|
21
22
|
class Publish extends baseCommand_1.BaseCommand {
|
|
@@ -42,6 +43,15 @@ class Publish extends baseCommand_1.BaseCommand {
|
|
|
42
43
|
default: false,
|
|
43
44
|
exclusive: ['registry-only', 'preview'],
|
|
44
45
|
}),
|
|
46
|
+
visibility: core_1.Flags.custom({
|
|
47
|
+
description: 'visibility of the preview integration. Accepts "public" or "private" (default). Only valid with --preview. --visibility=public is additionally restricted to --environment=staging or --environment=local.',
|
|
48
|
+
options: Object.values(configurationTypes_1.Visibility),
|
|
49
|
+
exclusive: ['live-preview', 'registry-only'],
|
|
50
|
+
})(),
|
|
51
|
+
'display-name': core_1.Flags.string({
|
|
52
|
+
description: 'override the integration display name. Only valid with --preview, --live-preview, or --environment=local. On preview flows, the mode suffix (e.g. "Preview - {hash}", "Live Preview - {hash}") is still appended.',
|
|
53
|
+
exclusive: ['registry-only'],
|
|
54
|
+
}),
|
|
45
55
|
'config-path': core_1.Flags.string({
|
|
46
56
|
summary: 'relative path to a custom ".unito.json" file',
|
|
47
57
|
description: `Use a custom configuration file instead of the default '.unito.json' or other environment specific
|
|
@@ -71,7 +81,36 @@ class Publish extends baseCommand_1.BaseCommand {
|
|
|
71
81
|
// Read the configurations.
|
|
72
82
|
const globalConfiguration = await GlobalConfiguration.read(this.config.configDir);
|
|
73
83
|
const environment = flags.environment ?? GlobalConfiguration.Environment.Production;
|
|
84
|
+
// Runtime guards. oclif's dependsOn/relationships can't be used for the
|
|
85
|
+
// "--visibility=public requires --preview" rule because --preview has
|
|
86
|
+
// `default: false` and oclif treats defaulted booleans as "present".
|
|
87
|
+
if (flags.visibility === configurationTypes_1.Visibility.Public) {
|
|
88
|
+
if (!flags.preview) {
|
|
89
|
+
core_1.ux.log(chalk_1.default.redBright('--visibility=public is only supported in combination with --preview.'));
|
|
90
|
+
this.exit(-1);
|
|
91
|
+
}
|
|
92
|
+
if (environment === GlobalConfiguration.Environment.Production) {
|
|
93
|
+
core_1.ux.log(chalk_1.default.redBright('--visibility=public is not supported on --environment=production. ' +
|
|
94
|
+
'Publish privately first; changing visibility on production is handled by a separate process.'));
|
|
95
|
+
this.exit(-1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (flags['display-name'] !== undefined &&
|
|
99
|
+
!flags.preview &&
|
|
100
|
+
!flags['live-preview'] &&
|
|
101
|
+
environment !== GlobalConfiguration.Environment.Local) {
|
|
102
|
+
core_1.ux.log(chalk_1.default.redBright('--display-name is only supported with --preview, --live-preview, or --environment=local.'));
|
|
103
|
+
this.exit(-1);
|
|
104
|
+
}
|
|
74
105
|
const integrationConfiguration = await IntegrationConfiguration.getConfiguration(environment, flags['config-path']);
|
|
106
|
+
if (flags['display-name'] !== undefined) {
|
|
107
|
+
// Set the base display name. Mode-specific suffixes ("Preview - {hash}", "Live Preview - {hash}")
|
|
108
|
+
// are appended later inside the corresponding preview methods.
|
|
109
|
+
integrationConfiguration.ui = { ...(integrationConfiguration.ui ?? {}), displayName: flags['display-name'] };
|
|
110
|
+
}
|
|
111
|
+
if (flags.visibility !== undefined) {
|
|
112
|
+
integrationConfiguration.visibility = flags.visibility;
|
|
113
|
+
}
|
|
75
114
|
if (integrationConfiguration.authorizations) {
|
|
76
115
|
integrationConfiguration.authorizations = integrationConfiguration.authorizations.filter(authorization => !authorization.development);
|
|
77
116
|
}
|
|
@@ -220,18 +259,13 @@ class Publish extends baseCommand_1.BaseCommand {
|
|
|
220
259
|
child_process_1.default.execSync('git init . --initial-branch=main');
|
|
221
260
|
}
|
|
222
261
|
async previewIntegration(integrationConfiguration) {
|
|
223
|
-
// Get the profile.
|
|
224
262
|
core_1.ux.action.start('Get profile', undefined, { stdout: true });
|
|
225
263
|
const profile = await IntegrationsPlatform.getProfile();
|
|
226
264
|
core_1.ux.action.stop();
|
|
227
|
-
// Generate a new name.
|
|
228
265
|
const newName = `${integrationConfiguration.name}-preview-${this.hashEmail(profile.email)}`;
|
|
229
|
-
// Update the secrets.
|
|
230
266
|
const updatedConfiguration = await this.generateNewSecrets(integrationConfiguration, newName);
|
|
231
267
|
core_1.ux.action.start('Creating preview', undefined, { stdout: true });
|
|
232
|
-
// Update the name.
|
|
233
268
|
updatedConfiguration.name = newName;
|
|
234
|
-
// Update the display name.
|
|
235
269
|
if (updatedConfiguration.ui?.displayName) {
|
|
236
270
|
updatedConfiguration.ui.displayName = [
|
|
237
271
|
updatedConfiguration.ui.displayName,
|
|
@@ -239,10 +273,8 @@ class Publish extends baseCommand_1.BaseCommand {
|
|
|
239
273
|
this.hashEmail(profile.email),
|
|
240
274
|
].join(' - ');
|
|
241
275
|
}
|
|
242
|
-
// Write the updated configuration on disk.
|
|
243
276
|
await IntegrationConfiguration.writeConfiguration(updatedConfiguration);
|
|
244
277
|
core_1.ux.action.stop();
|
|
245
|
-
// Publish the integration.
|
|
246
278
|
await this.publishIntegration(updatedConfiguration);
|
|
247
279
|
}
|
|
248
280
|
async publishIntegration(integrationConfiguration) {
|
|
@@ -53,7 +53,8 @@ class Upgrade extends baseCommand_1.BaseCommand {
|
|
|
53
53
|
//
|
|
54
54
|
core_1.ux.action.start(`${latestVersion ? 'Validating' : 'Upgrading'} the package`, undefined, { stdout: true });
|
|
55
55
|
// To make sure we have a clean version of the CLI, with updated packages, we force the re-installation.
|
|
56
|
-
|
|
56
|
+
// --min-release-age=0 bypasses the npm release age safeguard for this internal trusted package.
|
|
57
|
+
child_process_1.default.execSync(`npm install --force --min-release-age=0 ${npmOptions} ${packageName}`, {
|
|
57
58
|
...execOptions,
|
|
58
59
|
stdio: ['ignore', 'ignore', 'inherit'],
|
|
59
60
|
});
|
|
@@ -85,6 +85,7 @@ export interface Configuration {
|
|
|
85
85
|
*/
|
|
86
86
|
[k: string]: string;
|
|
87
87
|
};
|
|
88
|
+
visibility?: Visibility;
|
|
88
89
|
}
|
|
89
90
|
/**
|
|
90
91
|
* An authorization is a way to obtain and generate credentials for an integration
|
|
@@ -231,3 +232,10 @@ export declare enum Format {
|
|
|
231
232
|
EMAIL = "email",
|
|
232
233
|
URI = "uri"
|
|
233
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* The visibility of the integration.
|
|
237
|
+
*/
|
|
238
|
+
export declare enum Visibility {
|
|
239
|
+
Private = "private",
|
|
240
|
+
Public = "public"
|
|
241
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* and run json-schema-to-typescript to regenerate this file.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.Format = exports.Type = exports.PkceCodeChallengeMethod = exports.RequestContentType = exports.GrantType = exports.Method = void 0;
|
|
9
|
+
exports.Visibility = exports.Format = exports.Type = exports.PkceCodeChallengeMethod = exports.RequestContentType = exports.GrantType = exports.Method = void 0;
|
|
10
10
|
/**
|
|
11
11
|
* The method of authorization
|
|
12
12
|
*/
|
|
@@ -57,3 +57,11 @@ var Format;
|
|
|
57
57
|
Format["EMAIL"] = "email";
|
|
58
58
|
Format["URI"] = "uri";
|
|
59
59
|
})(Format || (exports.Format = Format = {}));
|
|
60
|
+
/**
|
|
61
|
+
* The visibility of the integration.
|
|
62
|
+
*/
|
|
63
|
+
var Visibility;
|
|
64
|
+
(function (Visibility) {
|
|
65
|
+
Visibility["Private"] = "private";
|
|
66
|
+
Visibility["Public"] = "public";
|
|
67
|
+
})(Visibility || (exports.Visibility = Visibility = {}));
|
|
@@ -153,6 +153,7 @@ async function updateIntegration(integrationId, configuration) {
|
|
|
153
153
|
authorizations: authorizationsToCreate.concat(authorizationsToArchive).concat(authorizationsToUpdate),
|
|
154
154
|
secrets: configuration.secrets,
|
|
155
155
|
ui: configuration.ui,
|
|
156
|
+
visibility: configuration.visibility,
|
|
156
157
|
archived: configuration.archived,
|
|
157
158
|
});
|
|
158
159
|
}
|
|
@@ -360,4 +360,191 @@ describe('Publish', () => {
|
|
|
360
360
|
(0, test_1.expect)(ctx.stdout).to.contain('image: <unset>');
|
|
361
361
|
(0, test_1.expect)(ctx.stdout).to.contain('markdown: <unset>');
|
|
362
362
|
});
|
|
363
|
+
test_1.test
|
|
364
|
+
.stdout()
|
|
365
|
+
.stderr()
|
|
366
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
|
|
367
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
|
|
368
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
369
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
370
|
+
.command(['publish', '--preview', '--visibility=public', '--environment=production'])
|
|
371
|
+
.exit(-1)
|
|
372
|
+
.it('rejects --visibility=public on production', ctx => {
|
|
373
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('--visibility=public is not supported on --environment=production');
|
|
374
|
+
});
|
|
375
|
+
test_1.test
|
|
376
|
+
.stdout()
|
|
377
|
+
.stderr()
|
|
378
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
|
|
379
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
|
|
380
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
381
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
382
|
+
.command(['publish', '--visibility=public', '--environment=staging'])
|
|
383
|
+
.exit(-1)
|
|
384
|
+
.it('rejects --visibility=public without --preview', ctx => {
|
|
385
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('--visibility=public is only supported in combination with --preview');
|
|
386
|
+
});
|
|
387
|
+
test_1.test
|
|
388
|
+
.stdout()
|
|
389
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
|
|
390
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
|
|
391
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
|
|
392
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
393
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
394
|
+
.command(['publish', '--preview', '--visibility=public', '--environment=staging'])
|
|
395
|
+
.it('--preview --visibility=public on staging writes visibility into the archive config', ctx => {
|
|
396
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('foo-preview-9c88 is being published');
|
|
397
|
+
ctx.sandbox.assert.calledWithMatch(
|
|
398
|
+
// @ts-expect-error syntax accepted by sinon.
|
|
399
|
+
IntegrationConfiguration.writeConfiguration, {
|
|
400
|
+
name: 'foo-preview-9c88',
|
|
401
|
+
ui: { displayName: 'Foo - Preview - 9c88' },
|
|
402
|
+
visibility: 'public',
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
test_1.test
|
|
406
|
+
.stdout()
|
|
407
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyLocal: 'foo' }))
|
|
408
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
|
|
409
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
|
|
410
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
411
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
412
|
+
.command(['publish', '--preview', '--visibility=public', '--environment=local'])
|
|
413
|
+
.it('--preview --visibility=public on local — also allowed', ctx => {
|
|
414
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('foo-preview-9c88 is being published');
|
|
415
|
+
ctx.sandbox.assert.calledWithMatch(
|
|
416
|
+
// @ts-expect-error syntax accepted by sinon.
|
|
417
|
+
IntegrationConfiguration.writeConfiguration, { visibility: 'public' });
|
|
418
|
+
});
|
|
419
|
+
test_1.test
|
|
420
|
+
.stdout()
|
|
421
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
|
|
422
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
|
|
423
|
+
name: 'myIntegration',
|
|
424
|
+
authorizations: [{ name: 'oauth2', oauth2: { clientSecret: 'unito-secret-' } }],
|
|
425
|
+
secrets: { secret1: 'unito-secret-', invalidSecret: 'Should never happen anyway' },
|
|
426
|
+
}))
|
|
427
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns({
|
|
428
|
+
name: 'myIntegration',
|
|
429
|
+
authorizations: [{ name: 'oauth2', oauth2: { clientSecret: 'unito-secret-' } }],
|
|
430
|
+
secrets: { secret1: 'unito-secret-', invalidSecret: 'Should never happen anyway' },
|
|
431
|
+
}))
|
|
432
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
433
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
434
|
+
.command(['publish', '--preview', '--visibility=public', '--environment=staging'])
|
|
435
|
+
.it('reencrypts the clientSecret on --preview --visibility=public', ctx => {
|
|
436
|
+
(0, test_1.expect)(ctx.stdout).to.contain('Reencrypting oauth2:clientSecret');
|
|
437
|
+
(0, test_1.expect)(ctx.stdout).to.contain('Reencrypting secrets:secret1');
|
|
438
|
+
(0, test_1.expect)(ctx.stdout).to.contain('Skipping secrets:invalidSecret');
|
|
439
|
+
});
|
|
440
|
+
test_1.test
|
|
441
|
+
.stdout()
|
|
442
|
+
.stderr()
|
|
443
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
|
|
444
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
|
|
445
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
446
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
447
|
+
.command(['publish', '--display-name', 'PR-1234'])
|
|
448
|
+
.exit(-1)
|
|
449
|
+
.it('rejects --display-name without --preview or --live-preview', ctx => {
|
|
450
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('--display-name is only supported with --preview, --live-preview, or --environment=local');
|
|
451
|
+
});
|
|
452
|
+
test_1.test
|
|
453
|
+
.stdout()
|
|
454
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
|
|
455
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
|
|
456
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
|
|
457
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
458
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
459
|
+
.command(['publish', '--preview', '--visibility=public', '--environment=staging', '--display-name', 'PR-1234'])
|
|
460
|
+
.it('public preview with --display-name — overrides base, Preview+hash suffix still appended', ctx => {
|
|
461
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('foo-preview-9c88 is being published');
|
|
462
|
+
ctx.sandbox.assert.calledWithMatch(
|
|
463
|
+
// @ts-expect-error syntax accepted by sinon.
|
|
464
|
+
IntegrationConfiguration.writeConfiguration, {
|
|
465
|
+
name: 'foo-preview-9c88',
|
|
466
|
+
ui: { displayName: 'PR-1234 - Preview - 9c88' },
|
|
467
|
+
visibility: 'public',
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
test_1.test
|
|
471
|
+
.stdout()
|
|
472
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
|
|
473
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
|
|
474
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
475
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
|
|
476
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
477
|
+
.command(['publish', '--preview', '--display-name', 'PR-1234'])
|
|
478
|
+
.it('private preview - --display-name overrides the base, hash suffix still appended', ctx => {
|
|
479
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('foo-preview-9c88 is being published');
|
|
480
|
+
ctx.sandbox.assert.calledWithMatch(
|
|
481
|
+
// @ts-expect-error syntax accepted by sinon.
|
|
482
|
+
IntegrationConfiguration.writeConfiguration, {
|
|
483
|
+
name: 'foo-preview-9c88',
|
|
484
|
+
ui: { displayName: 'PR-1234 - Preview - 9c88' },
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
test_1.test
|
|
488
|
+
.stdout()
|
|
489
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyLocal: 'foo' }))
|
|
490
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
|
|
491
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
|
|
492
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
493
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
494
|
+
.command(['publish', '--environment=local', '--display-name', 'PR-1234'])
|
|
495
|
+
.it('--display-name on a plain publish is allowed on local and overrides displayName', ctx => {
|
|
496
|
+
(0, test_1.expect)(ctx.stdout).to.contain('published');
|
|
497
|
+
ctx.sandbox.assert.calledWithMatch(
|
|
498
|
+
// @ts-expect-error syntax accepted by sinon.
|
|
499
|
+
IntegrationConfiguration.writeConfiguration, {
|
|
500
|
+
name: 'foo',
|
|
501
|
+
ui: { displayName: 'PR-1234' },
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
// oclif-declared constraints — verify they fire at parse time (exit 2).
|
|
505
|
+
// Error messages go to the real process.stderr and aren't captured by fancy-test.
|
|
506
|
+
test_1.test
|
|
507
|
+
.stdout()
|
|
508
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
|
|
509
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
|
|
510
|
+
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
|
|
511
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
512
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
513
|
+
.command(['publish', '--preview', '--visibility=private', '--environment=staging'])
|
|
514
|
+
.it('accepts --visibility=private as explicit intent and publishes normally', ctx => {
|
|
515
|
+
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('foo-preview-9c88 is being published');
|
|
516
|
+
ctx.sandbox.assert.calledWithMatch(
|
|
517
|
+
// @ts-expect-error syntax accepted by sinon.
|
|
518
|
+
IntegrationConfiguration.writeConfiguration, { visibility: 'private' });
|
|
519
|
+
});
|
|
520
|
+
test_1.test
|
|
521
|
+
.stdout()
|
|
522
|
+
.stderr()
|
|
523
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
|
|
524
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
|
|
525
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
526
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
527
|
+
.command(['publish', '--visibility=public', '--live-preview', '--environment=staging'])
|
|
528
|
+
.exit(2)
|
|
529
|
+
.it('oclif rejects --visibility + --live-preview (exclusive)', _ctx => { });
|
|
530
|
+
test_1.test
|
|
531
|
+
.stdout()
|
|
532
|
+
.stderr()
|
|
533
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
|
|
534
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
|
|
535
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
536
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
537
|
+
.command(['publish', '--visibility=public', '--registry-only'])
|
|
538
|
+
.exit(2)
|
|
539
|
+
.it('oclif rejects --visibility + --registry-only (exclusive)', _ctx => { });
|
|
540
|
+
test_1.test
|
|
541
|
+
.stdout()
|
|
542
|
+
.stderr()
|
|
543
|
+
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
|
|
544
|
+
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
|
|
545
|
+
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
|
|
546
|
+
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
|
|
547
|
+
.command(['publish', '--display-name=Foo', '--registry-only'])
|
|
548
|
+
.exit(2)
|
|
549
|
+
.it('oclif rejects --display-name + --registry-only (exclusive)', _ctx => { });
|
|
363
550
|
});
|
|
@@ -151,6 +151,7 @@ describe('integrations platform', function () {
|
|
|
151
151
|
credentialAccountRelativeUrl: '/me',
|
|
152
152
|
graphRelativeUrl: '/',
|
|
153
153
|
secrets: configuration.secrets,
|
|
154
|
+
visibility: undefined,
|
|
154
155
|
webhookAcknowledgeRelativeUrl: undefined,
|
|
155
156
|
webhookParsingRelativeUrl: undefined,
|
|
156
157
|
webhookSubscriptionsRelativeUrl: undefined,
|
|
@@ -176,6 +177,7 @@ describe('integrations platform', function () {
|
|
|
176
177
|
credentialAccountRelativeUrl: '/me',
|
|
177
178
|
graphRelativeUrl: '/',
|
|
178
179
|
secrets: configuration.secrets,
|
|
180
|
+
visibility: undefined,
|
|
179
181
|
webhookAcknowledgeRelativeUrl: undefined,
|
|
180
182
|
webhookParsingRelativeUrl: undefined,
|
|
181
183
|
webhookSubscriptionsRelativeUrl: undefined,
|
package/oclif.manifest.json
CHANGED
|
@@ -663,6 +663,31 @@
|
|
|
663
663
|
"allowNo": false,
|
|
664
664
|
"type": "boolean"
|
|
665
665
|
},
|
|
666
|
+
"visibility": {
|
|
667
|
+
"description": "visibility of the preview integration. Accepts \"public\" or \"private\" (default). Only valid with --preview. --visibility=public is additionally restricted to --environment=staging or --environment=local.",
|
|
668
|
+
"exclusive": [
|
|
669
|
+
"live-preview",
|
|
670
|
+
"registry-only"
|
|
671
|
+
],
|
|
672
|
+
"name": "visibility",
|
|
673
|
+
"hasDynamicHelp": false,
|
|
674
|
+
"multiple": false,
|
|
675
|
+
"options": [
|
|
676
|
+
"private",
|
|
677
|
+
"public"
|
|
678
|
+
],
|
|
679
|
+
"type": "option"
|
|
680
|
+
},
|
|
681
|
+
"display-name": {
|
|
682
|
+
"description": "override the integration display name. Only valid with --preview, --live-preview, or --environment=local. On preview flows, the mode suffix (e.g. \"Preview - {hash}\", \"Live Preview - {hash}\") is still appended.",
|
|
683
|
+
"exclusive": [
|
|
684
|
+
"registry-only"
|
|
685
|
+
],
|
|
686
|
+
"name": "display-name",
|
|
687
|
+
"hasDynamicHelp": false,
|
|
688
|
+
"multiple": false,
|
|
689
|
+
"type": "option"
|
|
690
|
+
},
|
|
666
691
|
"config-path": {
|
|
667
692
|
"description": "Use a custom configuration file instead of the default '.unito.json' or other environment specific\n ones.\n\n If you want to force the CLI to use a specific configuration file, you can use this flag to specify the relative\n path from your integration's root folder (with a leading '/').\n\n Usage: <%= config.bin %> <%= command.id %> --config-path=/myCustomConfig.json",
|
|
668
693
|
"name": "config-path",
|
|
@@ -1005,5 +1030,5 @@
|
|
|
1005
1030
|
]
|
|
1006
1031
|
}
|
|
1007
1032
|
},
|
|
1008
|
-
"version": "1.
|
|
1033
|
+
"version": "1.3.0"
|
|
1009
1034
|
}
|