clever-tools 3.0.2 → 3.2.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/README.md +33 -260
- package/bin/clever.js +59 -57
- package/package.json +8 -4
- package/src/command-options.js +42 -0
- package/src/commands/applications.js +8 -5
- package/src/commands/create.js +4 -2
- package/src/commands/deploy.js +27 -5
- package/src/models/addon.js +1 -1
- package/src/models/app_configuration.js +14 -1
- package/src/models/application.js +5 -2
- package/src/models/domain.js +1 -1
- package/src/models/git.js +1 -1
- package/src/models/isomorphic-http-with-agent.js +19 -0
- package/src/models/log-v4.js +11 -3
- package/src/models/send-to-api.js +15 -5
- package/CHANGELOG.md +0 -611
- package/src/get-output-format-option.js +0 -23
package/bin/clever.js
CHANGED
|
@@ -21,7 +21,8 @@ const git = require('../src/models/git.js');
|
|
|
21
21
|
const Parsers = require('../src/parsers.js');
|
|
22
22
|
const handleCommandPromise = require('../src/command-promise-handler.js');
|
|
23
23
|
const Formatter = require('../src/models/format-string.js');
|
|
24
|
-
const {
|
|
24
|
+
const { AVAILABLE_ZONES } = require('../src/models/application.js');
|
|
25
|
+
const { getOutputFormatOption, getSameCommitPolicyOption } = require('../src/command-options.js');
|
|
25
26
|
|
|
26
27
|
// Exit cleanly if the program we pipe to exits abruptly
|
|
27
28
|
process.stdout.on('error', (error) => {
|
|
@@ -98,7 +99,7 @@ function run () {
|
|
|
98
99
|
complete: Drain('listDrainTypes'),
|
|
99
100
|
}),
|
|
100
101
|
drainUrl: cliparse.argument('drain-url', { description: 'Drain URL' }),
|
|
101
|
-
fqdn: cliparse.argument('fqdn', { description: 'Domain name of the
|
|
102
|
+
fqdn: cliparse.argument('fqdn', { description: 'Domain name of the application' }),
|
|
102
103
|
notificationName: cliparse.argument('name', { description: 'Notification name' }),
|
|
103
104
|
notificationId: cliparse.argument('notification-id', { description: 'Notification ID' }),
|
|
104
105
|
webhookUrl: cliparse.argument('url', { description: 'Webhook URL' }),
|
|
@@ -119,7 +120,7 @@ function run () {
|
|
|
119
120
|
},
|
|
120
121
|
}),
|
|
121
122
|
configurationValue: cliparse.argument('configuration-value', { description: 'The new value of the configuration' }),
|
|
122
|
-
ngId: cliparse.argument('ng-id', { description: 'The Network Group
|
|
123
|
+
ngId: cliparse.argument('ng-id', { description: 'The Network Group ID' }),
|
|
123
124
|
ngIdOrLabel: cliparse.argument('ng', {
|
|
124
125
|
description: 'Network Group ID or label',
|
|
125
126
|
parser: Parsers.ngIdOrLabel,
|
|
@@ -136,14 +137,14 @@ function run () {
|
|
|
136
137
|
description: 'Display access logs continuously (ignores before/until, after/since)',
|
|
137
138
|
}),
|
|
138
139
|
importAsJson: cliparse.flag('json', {
|
|
139
|
-
description: 'Import variables as JSON (an array of { "name": "THE_NAME", "value": "
|
|
140
|
+
description: 'Import variables as JSON (an array of { "name": "THE_NAME", "value": "THE_VALUE" } objects)',
|
|
140
141
|
}),
|
|
141
142
|
addonId: cliparse.option('addon', { metavar: 'addon_id', description: 'Addon ID' }),
|
|
142
143
|
after: cliparse.option('after', {
|
|
143
144
|
metavar: 'after',
|
|
144
145
|
aliases: ['since'],
|
|
145
146
|
parser: Parsers.date,
|
|
146
|
-
description: 'Fetch logs after this date (ISO8601)',
|
|
147
|
+
description: 'Fetch logs after this date/time (ISO8601)',
|
|
147
148
|
}),
|
|
148
149
|
aliasCreation: cliparse.option('alias', {
|
|
149
150
|
aliases: ['a'],
|
|
@@ -158,13 +159,13 @@ function run () {
|
|
|
158
159
|
}),
|
|
159
160
|
naturalName: cliparse.flag('natural-name', {
|
|
160
161
|
aliases: ['n'],
|
|
161
|
-
description: 'Show application names or aliases if possible',
|
|
162
|
+
description: 'Show the application names or aliases if possible',
|
|
162
163
|
}),
|
|
163
164
|
before: cliparse.option('before', {
|
|
164
165
|
metavar: 'before',
|
|
165
166
|
aliases: ['until'],
|
|
166
167
|
parser: Parsers.date,
|
|
167
|
-
description: 'Fetch logs before this date (ISO8601)',
|
|
168
|
+
description: 'Fetch logs before this date/time (ISO8601)',
|
|
168
169
|
}),
|
|
169
170
|
branch: cliparse.option('branch', {
|
|
170
171
|
aliases: ['b'],
|
|
@@ -177,11 +178,11 @@ function run () {
|
|
|
177
178
|
}),
|
|
178
179
|
commit: cliparse.option('commit', {
|
|
179
180
|
metavar: 'commit id',
|
|
180
|
-
description: 'Restart the application with a specific commit
|
|
181
|
+
description: 'Restart the application with a specific commit ID',
|
|
181
182
|
}),
|
|
182
183
|
databaseId: cliparse.option('database-id', {
|
|
183
184
|
metavar: 'database_id',
|
|
184
|
-
description: 'The Database ID (postgresql_xxx)',
|
|
185
|
+
description: 'The Database ID (e.g.: postgresql_xxx)',
|
|
185
186
|
}),
|
|
186
187
|
deploymentId: cliparse.option('deployment-id', {
|
|
187
188
|
metavar: 'deployment_id',
|
|
@@ -189,7 +190,7 @@ function run () {
|
|
|
189
190
|
}),
|
|
190
191
|
namespace: cliparse.option('namespace', {
|
|
191
192
|
metavar: 'namespace',
|
|
192
|
-
description: '
|
|
193
|
+
description: 'Namespace in which the TCP redirection should be',
|
|
193
194
|
required: true,
|
|
194
195
|
complete: Organisation('completeNamespaces'),
|
|
195
196
|
}),
|
|
@@ -202,7 +203,7 @@ function run () {
|
|
|
202
203
|
flavor: cliparse.option('flavor', {
|
|
203
204
|
metavar: 'flavor',
|
|
204
205
|
parser: Parsers.flavor,
|
|
205
|
-
description: 'The
|
|
206
|
+
description: 'The instance size of your application',
|
|
206
207
|
complete () {
|
|
207
208
|
return cliparse.autocomplete.words(Application('listAvailableFlavors')());
|
|
208
209
|
},
|
|
@@ -215,6 +216,7 @@ function run () {
|
|
|
215
216
|
aliases: ['f'],
|
|
216
217
|
description: 'Force deploy even if it\'s not fast-forwardable',
|
|
217
218
|
}),
|
|
219
|
+
sameCommitPolicy: getSameCommitPolicyOption(),
|
|
218
220
|
webhookFormat: cliparse.option('format', {
|
|
219
221
|
metavar: 'format',
|
|
220
222
|
default: 'raw',
|
|
@@ -222,17 +224,17 @@ function run () {
|
|
|
222
224
|
}),
|
|
223
225
|
github: cliparse.option('github', {
|
|
224
226
|
metavar: 'OWNER/REPO',
|
|
225
|
-
description: '
|
|
227
|
+
description: 'GitHub application to use for deployments',
|
|
226
228
|
}),
|
|
227
229
|
sshIdentityFile: cliparse.option('identity-file', {
|
|
228
230
|
aliases: ['i'],
|
|
229
231
|
metavar: 'identity-file',
|
|
230
|
-
description: 'SSH
|
|
232
|
+
description: 'SSH identity file',
|
|
231
233
|
}),
|
|
232
234
|
instances: cliparse.option('instances', {
|
|
233
235
|
metavar: 'instances',
|
|
234
236
|
parser: Parsers.instances,
|
|
235
|
-
description: 'The number of
|
|
237
|
+
description: 'The number of parallel instances',
|
|
236
238
|
}),
|
|
237
239
|
linkAddon: cliparse.option('link', {
|
|
238
240
|
aliases: ['l'],
|
|
@@ -240,11 +242,11 @@ function run () {
|
|
|
240
242
|
description: 'Link the created addon to the app with the specified alias',
|
|
241
243
|
complete: Application('listAvailableAliases'),
|
|
242
244
|
}),
|
|
243
|
-
listAllNotifications: cliparse.flag('list-all', { description: 'List all notifications for your user or for an organisation with the
|
|
245
|
+
listAllNotifications: cliparse.flag('list-all', { description: 'List all notifications for your user or for an organisation with the \'--org\' option' }),
|
|
244
246
|
maxFlavor: cliparse.option('max-flavor', {
|
|
245
247
|
metavar: 'maxflavor',
|
|
246
248
|
parser: Parsers.flavor,
|
|
247
|
-
description: 'The maximum
|
|
249
|
+
description: 'The maximum instance size of your application',
|
|
248
250
|
complete () {
|
|
249
251
|
return cliparse.autocomplete.words(Application('listAvailableFlavors')());
|
|
250
252
|
},
|
|
@@ -252,17 +254,17 @@ function run () {
|
|
|
252
254
|
buildFlavor: cliparse.option('build-flavor', {
|
|
253
255
|
metavar: 'buildflavor',
|
|
254
256
|
parser: Parsers.buildFlavor,
|
|
255
|
-
description: 'The size of the build instance, or
|
|
257
|
+
description: 'The size of the build instance, or \'disabled\' if you want to disable dedicated build instances',
|
|
256
258
|
}),
|
|
257
259
|
maxInstances: cliparse.option('max-instances', {
|
|
258
260
|
metavar: 'maxinstances',
|
|
259
261
|
parser: Parsers.instances,
|
|
260
|
-
description: 'The maximum number of
|
|
262
|
+
description: 'The maximum number of parallel instances',
|
|
261
263
|
}),
|
|
262
264
|
minFlavor: cliparse.option('min-flavor', {
|
|
263
265
|
metavar: 'minflavor',
|
|
264
266
|
parser: Parsers.flavor,
|
|
265
|
-
description: 'The minimum scale
|
|
267
|
+
description: 'The minimum scale size of your application',
|
|
266
268
|
complete () {
|
|
267
269
|
return cliparse.autocomplete.words(Application('listAvailableFlavors')());
|
|
268
270
|
},
|
|
@@ -270,7 +272,7 @@ function run () {
|
|
|
270
272
|
minInstances: cliparse.option('min-instances', {
|
|
271
273
|
metavar: 'mininstances',
|
|
272
274
|
parser: Parsers.instances,
|
|
273
|
-
description: 'The minimum number of
|
|
275
|
+
description: 'The minimum number of parallel instances',
|
|
274
276
|
}),
|
|
275
277
|
noUpdateNotifier: cliparse.flag('no-update-notifier', { description: 'Don\'t notify available updates for clever-tools' }),
|
|
276
278
|
emailNotificationTarget: cliparse.option('notify', {
|
|
@@ -289,7 +291,7 @@ function run () {
|
|
|
289
291
|
}),
|
|
290
292
|
output: cliparse.option('output', {
|
|
291
293
|
aliases: ['out'],
|
|
292
|
-
description: '
|
|
294
|
+
description: 'Redirect the output of the command in a file',
|
|
293
295
|
}),
|
|
294
296
|
drainPassword: cliparse.option('password', {
|
|
295
297
|
aliases: ['p'],
|
|
@@ -316,17 +318,17 @@ function run () {
|
|
|
316
318
|
}),
|
|
317
319
|
addonVersion: cliparse.option('addon-version', {
|
|
318
320
|
metavar: 'addon-version',
|
|
319
|
-
description: 'The version to use for the
|
|
321
|
+
description: 'The version to use for the addon',
|
|
320
322
|
}),
|
|
321
323
|
addonOptions: cliparse.option('option', {
|
|
322
324
|
metavar: 'option',
|
|
323
|
-
description: 'Option to enable for the
|
|
325
|
+
description: 'Option to enable for the addon. Multiple --option argument can be passed to enable multiple options',
|
|
324
326
|
}),
|
|
325
327
|
region: cliparse.option('region', {
|
|
326
328
|
aliases: ['r'],
|
|
327
329
|
default: 'par',
|
|
328
330
|
metavar: 'zone',
|
|
329
|
-
description:
|
|
331
|
+
description: `Region, can be ${AVAILABLE_ZONES.map((name) => `'${name}'`).join(', ')}`,
|
|
330
332
|
complete: Application('listAvailableZones'),
|
|
331
333
|
}),
|
|
332
334
|
search: cliparse.option('search', {
|
|
@@ -386,7 +388,7 @@ function run () {
|
|
|
386
388
|
ngLabel: cliparse.option('label', {
|
|
387
389
|
required: true,
|
|
388
390
|
metavar: 'ng_label',
|
|
389
|
-
description: 'Network Group label, also used for
|
|
391
|
+
description: 'Network Group label, also used for DNS context',
|
|
390
392
|
}),
|
|
391
393
|
ngIdOrLabel: cliparse.option('ng', {
|
|
392
394
|
required: true,
|
|
@@ -404,7 +406,7 @@ function run () {
|
|
|
404
406
|
aliases: ['m'],
|
|
405
407
|
required: true,
|
|
406
408
|
metavar: 'member_id',
|
|
407
|
-
description: `The member ID: an app ID (
|
|
409
|
+
description: `The member ID: an app ID (e.g.: ${Formatter.formatCode('app_xxx')}), addon ID (e.g.: ${Formatter.formatCode('addon_xxx')}) or external node category ID`,
|
|
408
410
|
// complete: NetworkGroup('xxx'),
|
|
409
411
|
}),
|
|
410
412
|
ngMemberDomainName: cliparse.option('domain-name', {
|
|
@@ -492,7 +494,7 @@ function run () {
|
|
|
492
494
|
optNgSearchAppId: cliparse.option('app-id', {
|
|
493
495
|
required: false,
|
|
494
496
|
metavar: 'app_id',
|
|
495
|
-
description: 'The app
|
|
497
|
+
description: 'The app ID to search',
|
|
496
498
|
// complete: NetworkGroup('xxx'),
|
|
497
499
|
}),
|
|
498
500
|
wgPublicKey: cliparse.option('public-key', {
|
|
@@ -516,12 +518,12 @@ function run () {
|
|
|
516
518
|
tags: cliparse.option('tags', {
|
|
517
519
|
required: true,
|
|
518
520
|
metavar: 'tags',
|
|
519
|
-
description: 'List of tags separated by a comma',
|
|
521
|
+
description: 'List of tags, separated by a comma',
|
|
520
522
|
parser: Parsers.tags,
|
|
521
523
|
}),
|
|
522
524
|
optTags: cliparse.option('tags', {
|
|
523
525
|
metavar: 'tags',
|
|
524
|
-
description: 'List of tags separated by a comma',
|
|
526
|
+
description: 'List of tags, separated by a comma',
|
|
525
527
|
parser: Parsers.tags,
|
|
526
528
|
}),
|
|
527
529
|
optIpAddress: cliparse.option('ip', {
|
|
@@ -548,7 +550,7 @@ function run () {
|
|
|
548
550
|
// ACTIVITY COMMAND
|
|
549
551
|
const activity = lazyRequirePromiseModule('../src/commands/activity.js');
|
|
550
552
|
const activityCommand = cliparse.command('activity', {
|
|
551
|
-
description: 'Show last deployments of
|
|
553
|
+
description: 'Show last deployments of an application',
|
|
552
554
|
options: [opts.alias, opts.follow, opts.showAllActivity],
|
|
553
555
|
}, activity('activity'));
|
|
554
556
|
|
|
@@ -577,7 +579,7 @@ function run () {
|
|
|
577
579
|
commands: [addonShowProviderCommand],
|
|
578
580
|
}, addon('listProviders'));
|
|
579
581
|
const addonEnvCommand = cliparse.command('env', {
|
|
580
|
-
description: 'List the environment variables for an
|
|
582
|
+
description: 'List the environment variables for an addon',
|
|
581
583
|
options: [opts.addonEnvFormat],
|
|
582
584
|
args: [opts.addonId],
|
|
583
585
|
}, addon('env'));
|
|
@@ -598,7 +600,7 @@ function run () {
|
|
|
598
600
|
// CANCEL DEPLOY COMMAND
|
|
599
601
|
const cancelDeploy = lazyRequirePromiseModule('../src/commands/cancel-deploy.js');
|
|
600
602
|
const cancelDeployCommand = cliparse.command('cancel-deploy', {
|
|
601
|
-
description: 'Cancel an ongoing deployment
|
|
603
|
+
description: 'Cancel an ongoing deployment',
|
|
602
604
|
options: [opts.alias],
|
|
603
605
|
}, cancelDeploy('cancelDeploy'));
|
|
604
606
|
|
|
@@ -625,7 +627,7 @@ function run () {
|
|
|
625
627
|
// CREATE COMMAND
|
|
626
628
|
const create = lazyRequirePromiseModule('../src/commands/create.js');
|
|
627
629
|
const appCreateCommand = cliparse.command('create', {
|
|
628
|
-
description: 'Create
|
|
630
|
+
description: 'Create an application',
|
|
629
631
|
args: [args.appNameCreation],
|
|
630
632
|
options: [opts.instanceType, opts.orgaIdOrName, opts.aliasCreation, opts.region, opts.github, opts.humanJsonOutputFormat],
|
|
631
633
|
}, create('create'));
|
|
@@ -633,15 +635,15 @@ function run () {
|
|
|
633
635
|
// DELETE COMMAND
|
|
634
636
|
const deleteCommandModule = lazyRequirePromiseModule('../src/commands/delete.js');
|
|
635
637
|
const deleteCommand = cliparse.command('delete', {
|
|
636
|
-
description: 'Delete
|
|
638
|
+
description: 'Delete an application',
|
|
637
639
|
options: [opts.alias, opts.confirmApplicationDeletion],
|
|
638
640
|
}, deleteCommandModule('deleteApp'));
|
|
639
641
|
|
|
640
642
|
// DEPLOY COMMAND
|
|
641
643
|
const deploy = lazyRequirePromiseModule('../src/commands/deploy.js');
|
|
642
644
|
const deployCommand = cliparse.command('deploy', {
|
|
643
|
-
description: 'Deploy an application
|
|
644
|
-
options: [opts.alias, opts.branch, opts.quiet, opts.forceDeploy, opts.followDeployLogs],
|
|
645
|
+
description: 'Deploy an application',
|
|
646
|
+
options: [opts.alias, opts.branch, opts.quiet, opts.forceDeploy, opts.followDeployLogs, opts.sameCommitPolicy],
|
|
645
647
|
}, deploy('deploy'));
|
|
646
648
|
|
|
647
649
|
// DIAG COMMAND
|
|
@@ -654,26 +656,26 @@ function run () {
|
|
|
654
656
|
// DOMAIN COMMANDS
|
|
655
657
|
const domain = lazyRequirePromiseModule('../src/commands/domain.js');
|
|
656
658
|
const domainCreateCommand = cliparse.command('add', {
|
|
657
|
-
description: 'Add a domain name to
|
|
659
|
+
description: 'Add a domain name to an application',
|
|
658
660
|
args: [args.fqdn],
|
|
659
661
|
}, domain('add'));
|
|
660
662
|
const domainRemoveCommand = cliparse.command('rm', {
|
|
661
|
-
description: 'Remove a domain name from
|
|
663
|
+
description: 'Remove a domain name from an application',
|
|
662
664
|
args: [args.fqdn],
|
|
663
665
|
}, domain('rm'));
|
|
664
666
|
const domainSetFavouriteCommand = cliparse.command('set', {
|
|
665
|
-
description: 'Set the favourite domain for
|
|
667
|
+
description: 'Set the favourite domain for an application',
|
|
666
668
|
args: [args.fqdn],
|
|
667
669
|
}, domain('setFavourite'));
|
|
668
670
|
const domainUnsetFavouriteCommand = cliparse.command('unset', {
|
|
669
|
-
description: 'Unset the favourite domain for
|
|
671
|
+
description: 'Unset the favourite domain for an application',
|
|
670
672
|
}, domain('unsetFavourite'));
|
|
671
673
|
const domainFavouriteCommands = cliparse.command('favourite', {
|
|
672
|
-
description: 'Manage
|
|
674
|
+
description: 'Manage the favourite domain name for an application',
|
|
673
675
|
commands: [domainSetFavouriteCommand, domainUnsetFavouriteCommand],
|
|
674
676
|
}, domain('getFavourite'));
|
|
675
677
|
const domainCommands = cliparse.command('domain', {
|
|
676
|
-
description: 'Manage
|
|
678
|
+
description: 'Manage domain names for an application',
|
|
677
679
|
options: [opts.alias],
|
|
678
680
|
commands: [domainCreateCommand, domainFavouriteCommands, domainRemoveCommand],
|
|
679
681
|
}, domain('list'));
|
|
@@ -710,7 +712,7 @@ function run () {
|
|
|
710
712
|
args: [args.envVariableName, args.envVariableValue],
|
|
711
713
|
}, env('set'));
|
|
712
714
|
const envRemoveCommand = cliparse.command('rm', {
|
|
713
|
-
description: 'Remove an environment variable from
|
|
715
|
+
description: 'Remove an environment variable from an application',
|
|
714
716
|
args: [args.envVariableName],
|
|
715
717
|
}, env('rm'));
|
|
716
718
|
const envImportCommand = cliparse.command('import', {
|
|
@@ -718,11 +720,11 @@ function run () {
|
|
|
718
720
|
options: [opts.importAsJson],
|
|
719
721
|
}, env('importEnv'));
|
|
720
722
|
const envImportVarsFromLocalEnvCommand = cliparse.command('import-vars', {
|
|
721
|
-
description: 'Add or update environment variables named <variable-names> (comma
|
|
723
|
+
description: 'Add or update environment variables named <variable-names> (comma-separated), taking their values from the current environment',
|
|
722
724
|
args: [args.envVariableNames],
|
|
723
725
|
}, env('importVarsFromLocalEnv'));
|
|
724
726
|
const envCommands = cliparse.command('env', {
|
|
725
|
-
description: 'Manage
|
|
727
|
+
description: 'Manage environment variables of an application',
|
|
726
728
|
options: [opts.alias, opts.sourceableEnvVarsList],
|
|
727
729
|
commands: [envSetCommand, envRemoveCommand, envImportCommand, envImportVarsFromLocalEnvCommand],
|
|
728
730
|
}, env('list'));
|
|
@@ -730,7 +732,7 @@ function run () {
|
|
|
730
732
|
// LINK COMMAND
|
|
731
733
|
const link = lazyRequirePromiseModule('../src/commands/link.js');
|
|
732
734
|
const appLinkCommand = cliparse.command('link', {
|
|
733
|
-
description: 'Link this repo to an existing
|
|
735
|
+
description: 'Link this repo to an existing application',
|
|
734
736
|
args: [args.appIdOrName],
|
|
735
737
|
options: [opts.aliasCreation, opts.orgaIdOrName],
|
|
736
738
|
}, link('link'));
|
|
@@ -787,7 +789,7 @@ function run () {
|
|
|
787
789
|
options: [opts.ngIdOrLabel, opts.naturalName, opts.jsonFormat],
|
|
788
790
|
}, networkgroups('listMembers'));
|
|
789
791
|
const networkGroupsMemberGetCommand = cliparse.command('get', {
|
|
790
|
-
description: 'Get a Network Group member details',
|
|
792
|
+
description: 'Get a Network Group member\'s details',
|
|
791
793
|
options: [opts.ngIdOrLabel, opts.ngMemberId, opts.naturalName, opts.jsonFormat],
|
|
792
794
|
}, networkgroups('getMember'));
|
|
793
795
|
const networkGroupsMemberAddCommand = cliparse.command('add', {
|
|
@@ -811,7 +813,7 @@ function run () {
|
|
|
811
813
|
options: [opts.ngIdOrLabel, opts.jsonFormat],
|
|
812
814
|
}, networkgroups('listPeers'));
|
|
813
815
|
const networkGroupsPeerGetCommand = cliparse.command('get', {
|
|
814
|
-
description: 'Get a Network Group peer details',
|
|
816
|
+
description: 'Get a Network Group peer\'s details',
|
|
815
817
|
options: [opts.ngIdOrLabel, opts.ngPeerId, opts.jsonFormat],
|
|
816
818
|
}, networkgroups('getPeer'));
|
|
817
819
|
const networkGroupsPeerAddCommand = cliparse.command('add-external', {
|
|
@@ -862,14 +864,14 @@ function run () {
|
|
|
862
864
|
// OPEN COMMAND
|
|
863
865
|
const open = lazyRequirePromiseModule('../src/commands/open.js');
|
|
864
866
|
const openCommand = cliparse.command('open', {
|
|
865
|
-
description: 'Open an application in
|
|
867
|
+
description: 'Open an application in your browser',
|
|
866
868
|
options: [opts.alias],
|
|
867
869
|
}, open('open'));
|
|
868
870
|
|
|
869
871
|
// CONSOLE COMMAND
|
|
870
872
|
const consoleModule = lazyRequirePromiseModule('../src/commands/console.js');
|
|
871
873
|
const consoleCommand = cliparse.command('console', {
|
|
872
|
-
description: 'Open an application in the
|
|
874
|
+
description: 'Open an application in the Console',
|
|
873
875
|
options: [opts.alias],
|
|
874
876
|
}, consoleModule('openConsole'));
|
|
875
877
|
|
|
@@ -886,7 +888,7 @@ function run () {
|
|
|
886
888
|
args: [args.envVariableName, args.envVariableValue],
|
|
887
889
|
}, publishedConfig('set'));
|
|
888
890
|
const publishedConfigRemoveCommand = cliparse.command('rm', {
|
|
889
|
-
description: 'Remove a published configuration variable from
|
|
891
|
+
description: 'Remove a published configuration variable from an application',
|
|
890
892
|
args: [args.envVariableName],
|
|
891
893
|
}, publishedConfig('rm'));
|
|
892
894
|
const publishedConfigImportCommand = cliparse.command('import', {
|
|
@@ -902,7 +904,7 @@ function run () {
|
|
|
902
904
|
// RESTART COMMAND
|
|
903
905
|
const restart = lazyRequirePromiseModule('../src/commands/restart.js');
|
|
904
906
|
const restartCommand = cliparse.command('restart', {
|
|
905
|
-
description: 'Start or restart
|
|
907
|
+
description: 'Start or restart an application',
|
|
906
908
|
options: [opts.alias, opts.commit, opts.withoutCache, opts.quiet, opts.followDeployLogs],
|
|
907
909
|
}, restart('restart'));
|
|
908
910
|
|
|
@@ -947,14 +949,14 @@ function run () {
|
|
|
947
949
|
// STATUS COMMAND
|
|
948
950
|
const status = lazyRequirePromiseModule('../src/commands/status.js');
|
|
949
951
|
const statusCommand = cliparse.command('status', {
|
|
950
|
-
description: 'See the status of an application
|
|
952
|
+
description: 'See the status of an application',
|
|
951
953
|
options: [opts.alias],
|
|
952
954
|
}, status('status'));
|
|
953
955
|
|
|
954
956
|
// STOP COMMAND
|
|
955
957
|
const stop = lazyRequirePromiseModule('../src/commands/stop.js');
|
|
956
958
|
const stopCommand = cliparse.command('stop', {
|
|
957
|
-
description: 'Stop a running application
|
|
959
|
+
description: 'Stop a running application',
|
|
958
960
|
options: [opts.alias],
|
|
959
961
|
}, stop('stop'));
|
|
960
962
|
|
|
@@ -981,14 +983,14 @@ function run () {
|
|
|
981
983
|
// UNLINK COMMAND
|
|
982
984
|
const unlink = lazyRequirePromiseModule('../src/commands/unlink.js');
|
|
983
985
|
const appUnlinkCommand = cliparse.command('unlink', {
|
|
984
|
-
description: 'Unlink this repo from an existing
|
|
986
|
+
description: 'Unlink this repo from an existing application',
|
|
985
987
|
args: [args.alias],
|
|
986
988
|
}, unlink('unlink'));
|
|
987
989
|
|
|
988
990
|
// VERSION COMMAND
|
|
989
991
|
const version = lazyRequirePromiseModule('../src/commands/version.js');
|
|
990
992
|
const versionCommand = cliparse.command('version', {
|
|
991
|
-
description: 'Display the version',
|
|
993
|
+
description: 'Display the clever-tools version',
|
|
992
994
|
args: [],
|
|
993
995
|
}, version('version'));
|
|
994
996
|
|
|
@@ -1077,7 +1079,7 @@ function run () {
|
|
|
1077
1079
|
// CLI PARSER
|
|
1078
1080
|
const cliParser = cliparse.cli({
|
|
1079
1081
|
name: 'clever',
|
|
1080
|
-
description: 'CLI tool to manage Clever Cloud data and products',
|
|
1082
|
+
description: 'CLI tool to manage Clever Cloud\'s data and products',
|
|
1081
1083
|
version: pkg.version,
|
|
1082
1084
|
options: [opts.verbose, opts.noUpdateNotifier],
|
|
1083
1085
|
helpCommand: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clever-tools",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Command Line Interface for Clever Cloud.",
|
|
5
5
|
"main": "bin/clever.js",
|
|
6
6
|
"keywords": [
|
|
@@ -25,14 +25,14 @@
|
|
|
25
25
|
"scripts/*.sh"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@clevercloud/client": "^8.0
|
|
28
|
+
"@clevercloud/client": "^8.1.0",
|
|
29
29
|
"clf-date": "^0.2.0",
|
|
30
30
|
"cliparse": "^0.3.3",
|
|
31
31
|
"colors": "1.4.0",
|
|
32
32
|
"common-env": "^6.4.0",
|
|
33
33
|
"curlconverter": "^3.21.0",
|
|
34
34
|
"eventsource": "^1.1.0",
|
|
35
|
-
"isomorphic-git": "^1.
|
|
35
|
+
"isomorphic-git": "^1.25.0",
|
|
36
36
|
"linux-release-info": "^3.0.0",
|
|
37
37
|
"lodash": "^4.17.21",
|
|
38
38
|
"mkdirp": "^1.0.4",
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
"xdg": "^0.1.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
+
"@commitlint/cli": "^18.4.3",
|
|
52
|
+
"@commitlint/config-conventional": "^18.4.3",
|
|
51
53
|
"aws-sdk": "^2.919.0",
|
|
52
54
|
"chai": "^4.3.4",
|
|
53
55
|
"del": "^6.0.0",
|
|
@@ -63,9 +65,11 @@
|
|
|
63
65
|
"grunt-cli": "^1.4.3",
|
|
64
66
|
"grunt-http": "^2.3.3",
|
|
65
67
|
"grunt-mocha-test": "^0.13.3",
|
|
68
|
+
"mime-types": "^2.1.35",
|
|
66
69
|
"mocha": "^8.4.0",
|
|
67
70
|
"pkg": "^5.8.1",
|
|
68
|
-
"semver": "^7.3.5"
|
|
71
|
+
"semver": "^7.3.5",
|
|
72
|
+
"text-table": "^0.2.0"
|
|
69
73
|
},
|
|
70
74
|
"overrides": {
|
|
71
75
|
"pkg-fetch": "3.5.2"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const cliparse = require('cliparse');
|
|
2
|
+
|
|
3
|
+
function getOutputFormatOption (formats = []) {
|
|
4
|
+
const availableFormats = ['human', 'json', ...formats];
|
|
5
|
+
return cliparse.option('format', {
|
|
6
|
+
aliases: ['F'],
|
|
7
|
+
metavar: 'format',
|
|
8
|
+
parser: (format) => {
|
|
9
|
+
return availableFormats.includes(format)
|
|
10
|
+
? cliparse.parsers.success(format)
|
|
11
|
+
: cliparse.parsers.error('The output format must be one of ' + availableFormats.join(', '));
|
|
12
|
+
},
|
|
13
|
+
default: 'human',
|
|
14
|
+
description: `Output format (${availableFormats.join(', ')})`,
|
|
15
|
+
complete () {
|
|
16
|
+
return cliparse.autocomplete.words(availableFormats);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getSameCommitPolicyOption () {
|
|
22
|
+
const availablePolicies = ['error', 'ignore', 'restart', 'rebuild'];
|
|
23
|
+
return cliparse.option('same-commit-policy', {
|
|
24
|
+
aliases: ['p'],
|
|
25
|
+
metavar: 'same-commit-policy',
|
|
26
|
+
parser: (policy) => {
|
|
27
|
+
return availablePolicies.includes(policy)
|
|
28
|
+
? cliparse.parsers.success(policy)
|
|
29
|
+
: cliparse.parsers.error(`The output policy must be one of ${availablePolicies.join(', ')}`);
|
|
30
|
+
},
|
|
31
|
+
default: 'error',
|
|
32
|
+
description: `Which policy to apply when the local commit is the same as the remote one. Available policies are (${availablePolicies.join(', ')})`,
|
|
33
|
+
complete () {
|
|
34
|
+
return cliparse.autocomplete.words(availablePolicies);
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
getOutputFormatOption,
|
|
41
|
+
getSameCommitPolicyOption,
|
|
42
|
+
};
|
|
@@ -28,13 +28,16 @@ function formatApps (apps, onlyAliases, json) {
|
|
|
28
28
|
}
|
|
29
29
|
else {
|
|
30
30
|
return apps
|
|
31
|
-
.map((app) =>
|
|
32
|
-
|
|
31
|
+
.map((app) => {
|
|
32
|
+
const sshUrl = app.git_ssh_url ?? app.deploy_url.replace('https://', 'git+ssh://git@');
|
|
33
|
+
return [
|
|
33
34
|
`Application ${app.name}`,
|
|
34
35
|
` alias: ${colors.bold(app.alias)}`,
|
|
35
|
-
`
|
|
36
|
-
` deployment
|
|
37
|
-
|
|
36
|
+
` ID: ${app.app_id}`,
|
|
37
|
+
` deployment URL: ${app.deploy_url}`,
|
|
38
|
+
` git+ssh URL: ${sshUrl}`,
|
|
39
|
+
].join('\n');
|
|
40
|
+
})
|
|
38
41
|
.join('\n\n');
|
|
39
42
|
}
|
|
40
43
|
}
|
package/src/commands/create.js
CHANGED
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
const Application = require('../models/application.js');
|
|
4
4
|
const AppConfig = require('../models/app_configuration.js');
|
|
5
5
|
const Logger = require('../logger.js');
|
|
6
|
-
const { toNameEqualsValueString } = require('@clevercloud/client/cjs/utils/env-vars.js');
|
|
7
6
|
|
|
8
7
|
async function create (params) {
|
|
9
8
|
const { type: typeName } = params.options;
|
|
10
9
|
const [name] = params.args;
|
|
11
10
|
const { org: orgaIdOrName, alias, region, github: githubOwnerRepo, format } = params.options;
|
|
12
|
-
const
|
|
11
|
+
const { apps } = await AppConfig.loadApplicationConf();
|
|
12
|
+
|
|
13
|
+
AppConfig.checkAlreadyLinked(apps, name, alias);
|
|
13
14
|
|
|
15
|
+
const github = getGithubDetails(githubOwnerRepo);
|
|
14
16
|
const app = await Application.create(name, typeName, region, orgaIdOrName, github);
|
|
15
17
|
await AppConfig.addLinkedApplication(app, alias);
|
|
16
18
|
|
package/src/commands/deploy.js
CHANGED
|
@@ -13,7 +13,7 @@ const { sendToApi } = require('../models/send-to-api.js');
|
|
|
13
13
|
// Once the API call to redeploy() has been triggered successfully,
|
|
14
14
|
// the rest (waiting for deployment state to evolve and displaying logs) is done with auto retry (resilient to network failures)
|
|
15
15
|
async function deploy (params) {
|
|
16
|
-
const { alias, branch: branchName, quiet, force, follow } = params.options;
|
|
16
|
+
const { alias, branch: branchName, quiet, force, follow, 'same-commit-policy': sameCommitPolicy } = params.options;
|
|
17
17
|
|
|
18
18
|
const appData = await AppConfig.getAppDetails({ alias });
|
|
19
19
|
const { ownerId, appId } = appData;
|
|
@@ -26,12 +26,29 @@ async function deploy (params) {
|
|
|
26
26
|
|
|
27
27
|
await git.addRemote(appData.alias, appData.deployUrl);
|
|
28
28
|
|
|
29
|
+
Logger.println(colors.bold.blue(`Remote application is app_id=${appId}, alias=${appData.alias}, name=${appData.name}`));
|
|
30
|
+
|
|
31
|
+
Logger.println(colors.bold.blue(`Remote application belongs to ${ownerId}`));
|
|
32
|
+
|
|
29
33
|
if (commitIdToPush === remoteHeadCommitId) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
switch (sameCommitPolicy) {
|
|
35
|
+
case 'ignore':
|
|
36
|
+
Logger.println(`The clever-cloud application is up-to-date (${colors.green(remoteHeadCommitId)})`);
|
|
37
|
+
return;
|
|
38
|
+
case 'restart':
|
|
39
|
+
return restartOnSameCommit(ownerId, appId, commitIdToPush, quiet, follow, false);
|
|
40
|
+
case 'rebuild':
|
|
41
|
+
return restartOnSameCommit(ownerId, appId, commitIdToPush, quiet, follow, true);
|
|
42
|
+
case 'error':
|
|
43
|
+
default: {
|
|
44
|
+
const upToDateMessage = `The clever-cloud application is up-to-date (${colors.green(remoteHeadCommitId)}).\nYou can set a policy with 'same-commit-policy' to handle differently when remote HEAD has the same commit as the one to push.\nOr try this command to restart the application:`;
|
|
45
|
+
if (commitIdToPush !== deployedCommitId) {
|
|
46
|
+
const restartWithId = `clever restart --commit ${commitIdToPush}`;
|
|
47
|
+
throw new Error(`${upToDateMessage}\n${colors.yellow(restartWithId)}`);
|
|
48
|
+
}
|
|
49
|
+
throw new Error(`${upToDateMessage}\n${colors.yellow('clever restart')}`);
|
|
50
|
+
}
|
|
33
51
|
}
|
|
34
|
-
throw new Error(`${upToDateMessage}\nclever restart`);
|
|
35
52
|
}
|
|
36
53
|
|
|
37
54
|
if (remoteHeadCommitId == null || deployedCommitId == null) {
|
|
@@ -64,4 +81,9 @@ async function deploy (params) {
|
|
|
64
81
|
return Log.watchDeploymentAndDisplayLogs({ ownerId, appId, commitId: commitIdToPush, knownDeployments, quiet, follow });
|
|
65
82
|
}
|
|
66
83
|
|
|
84
|
+
async function restartOnSameCommit (ownerId, appId, commitIdToPush, quiet, follow, withoutCache) {
|
|
85
|
+
const restart = await Application.redeploy(ownerId, appId, commitIdToPush, withoutCache);
|
|
86
|
+
return Log.watchDeploymentAndDisplayLogs({ ownerId, appId, deploymentId: restart.deploymentId, quiet, follow });
|
|
87
|
+
}
|
|
88
|
+
|
|
67
89
|
module.exports = { deploy };
|
package/src/models/addon.js
CHANGED
|
@@ -109,7 +109,7 @@ function validateAddonVersionAndOptions (region, version, addonOptions, provider
|
|
|
109
109
|
const optionNames = availableOptions.map(({ name }) => name).join(',');
|
|
110
110
|
let availableOptionsError = null;
|
|
111
111
|
if (optionNames.length > 0) {
|
|
112
|
-
availableOptionsError = `
|
|
112
|
+
availableOptionsError = `Available options are: ${optionNames}.`;
|
|
113
113
|
}
|
|
114
114
|
else {
|
|
115
115
|
availableOptionsError = 'No options are available for this plan.';
|