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/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 { getOutputFormatOption } = require('../src/get-output-format-option.js');
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 Clever Cloud application' }),
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 id' }),
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": "the value" } objects)',
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 id',
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: 'namespace in which the TCP redirection should be',
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 scale of your application',
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: 'Github application to use for deployments',
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 Identity file',
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 parallels instances',
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 `--org` option' }),
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 scale for your application',
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 `disabled` if you want to disable dedicated build instances',
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 parallels instances',
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 for your application',
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 parallels instances',
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: 'redirect the output of the command in a file',
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 add-on',
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 add-on. Multiple --option argument can be passed to enable multiple options',
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: 'Region, can be \'par\' for Paris or \'mtl\' for Montreal',
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 dns context',
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 (i.e. ${Formatter.formatCode('app_xxx')}), add-on ID (i.e. ${Formatter.formatCode('addon_xxx')}) or external node category 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 id to search',
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 a Clever Cloud application',
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 add-on',
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 on Clever Cloud',
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 a Clever Cloud application',
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 a Clever Cloud application',
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 to Clever Cloud',
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 a Clever Cloud application',
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 a Clever Cloud application',
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 a Clever Cloud application',
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 a Clever Cloud application',
671
+ description: 'Unset the favourite domain for an application',
670
672
  }, domain('unsetFavourite'));
671
673
  const domainFavouriteCommands = cliparse.command('favourite', {
672
- description: 'Manage Clever Cloud application favourite domain name',
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 Clever Cloud application domain names',
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 a Clever Cloud application',
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 separated), taking their values from the current environment',
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 Clever Cloud application environment',
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 Clever Cloud application',
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 the browser',
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 console',
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 a Clever Cloud application',
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 a Clever Cloud application',
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 on Clever Cloud',
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 on Clever Cloud',
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 Clever Cloud application',
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.2",
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.2",
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.8.2",
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
- ` id: ${app.app_id}`,
36
- ` deployment url: ${app.deploy_url}`].join('\n'),
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
  }
@@ -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 github = getGithubDetails(githubOwnerRepo);
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
 
@@ -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
- const upToDateMessage = `The clever-cloud application is up-to-date (${remoteHeadCommitId}). Try this command to restart the application:`;
31
- if (commitIdToPush !== deployedCommitId) {
32
- throw new Error(`${upToDateMessage}\nclever restart --commit ${commitIdToPush}`);
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 };
@@ -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 = `Avalailble options are: ${optionNames}.`;
112
+ availableOptionsError = `Available options are: ${optionNames}.`;
113
113
  }
114
114
  else {
115
115
  availableOptionsError = 'No options are available for this plan.';