clever-tools 3.14.0 → 4.0.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.
Files changed (93) hide show
  1. package/README.md +130 -37
  2. package/bin/clever.js +1427 -718
  3. package/package.json +61 -77
  4. package/src/clever-client/auth-bridge.js +9 -12
  5. package/src/clever-client/ng.js +1 -1
  6. package/src/clever-client/operators.js +7 -7
  7. package/src/command-options.js +6 -6
  8. package/src/command-promise-handler.js +6 -6
  9. package/src/commands/accesslogs.js +38 -29
  10. package/src/commands/activity.js +62 -40
  11. package/src/commands/addon.js +65 -69
  12. package/src/commands/applications.js +33 -31
  13. package/src/commands/cancel-deploy.js +7 -7
  14. package/src/commands/config.js +9 -7
  15. package/src/commands/console.js +3 -3
  16. package/src/commands/create.js +32 -31
  17. package/src/commands/curl.js +14 -36
  18. package/src/commands/database.js +10 -30
  19. package/src/commands/delete.js +8 -8
  20. package/src/commands/deploy.js +60 -46
  21. package/src/commands/diag.js +27 -25
  22. package/src/commands/domain.js +89 -91
  23. package/src/commands/drain.js +26 -14
  24. package/src/commands/emails.js +24 -28
  25. package/src/commands/env.js +18 -18
  26. package/src/commands/features.js +12 -18
  27. package/src/commands/keycloak.js +11 -11
  28. package/src/commands/kv.js +13 -13
  29. package/src/commands/link.js +9 -8
  30. package/src/commands/login.js +19 -27
  31. package/src/commands/logout.js +1 -1
  32. package/src/commands/logs.js +20 -12
  33. package/src/commands/makeDefault.js +5 -5
  34. package/src/commands/matomo.js +7 -7
  35. package/src/commands/metabase.js +9 -9
  36. package/src/commands/ng.js +32 -32
  37. package/src/commands/notify-email.js +11 -15
  38. package/src/commands/open.js +1 -1
  39. package/src/commands/otoroshi.js +11 -11
  40. package/src/commands/profile.js +8 -8
  41. package/src/commands/published-config.js +11 -11
  42. package/src/commands/restart.js +15 -8
  43. package/src/commands/scale.js +25 -16
  44. package/src/commands/service.js +18 -9
  45. package/src/commands/ssh-keys.js +25 -29
  46. package/src/commands/ssh.js +1 -2
  47. package/src/commands/status.js +31 -22
  48. package/src/commands/stop.js +3 -3
  49. package/src/commands/tcp-redirs.js +27 -26
  50. package/src/commands/tokens.js +44 -43
  51. package/src/commands/unlink.js +7 -5
  52. package/src/commands/version.js +2 -4
  53. package/src/commands/webhooks.js +8 -10
  54. package/src/experimental-features.js +7 -5
  55. package/src/format-table.js +46 -15
  56. package/src/initial-setup.js +2 -32
  57. package/src/initial-update-notifier.js +18 -0
  58. package/src/lib/has-param.js +16 -0
  59. package/src/lib/ng-print.js +21 -24
  60. package/src/lib/operator-commands.js +58 -53
  61. package/src/lib/prompts.js +5 -5
  62. package/src/lib/slugify.js +1 -1
  63. package/src/logger.js +24 -22
  64. package/src/models/activity.js +3 -3
  65. package/src/models/addon.js +52 -53
  66. package/src/models/app_configuration.js +34 -32
  67. package/src/models/application.js +90 -77
  68. package/src/models/application_configuration.js +19 -27
  69. package/src/models/configuration.js +30 -32
  70. package/src/models/deployments.js +9 -19
  71. package/src/models/domain.js +10 -9
  72. package/src/models/drain.js +16 -15
  73. package/src/models/exit-strategy-option.js +15 -5
  74. package/src/models/fs-utils.js +4 -3
  75. package/src/models/git.js +26 -32
  76. package/src/models/ids-resolver.js +37 -41
  77. package/src/models/isomorphic-http-with-agent.js +3 -3
  78. package/src/models/json-array.js +5 -6
  79. package/src/models/log-v4.js +44 -52
  80. package/src/models/log.js +40 -45
  81. package/src/models/namespaces.js +4 -4
  82. package/src/models/ng-resources.js +49 -39
  83. package/src/models/ng.js +41 -40
  84. package/src/models/node-dns-resolver.js +3 -3
  85. package/src/models/notification.js +7 -10
  86. package/src/models/operator.js +8 -10
  87. package/src/models/organisation.js +5 -8
  88. package/src/models/send-to-api.js +18 -11
  89. package/src/models/user.js +6 -5
  90. package/src/models/utils.js +5 -8
  91. package/src/models/variables.js +18 -20
  92. package/src/parsers.js +34 -34
  93. package/src/load-package-json.cjs +0 -5
@@ -1,16 +1,16 @@
1
+ import { styleText } from 'node:util';
2
+ import { Logger } from '../logger.js';
1
3
  import * as Application from '../models/application.js';
2
4
  import * as ApplicationConfiguration from '../models/application_configuration.js';
3
- import { Logger } from '../logger.js';
4
- import colors from 'colors/safe.js';
5
5
 
6
- export async function list (params) {
6
+ export async function list(params) {
7
7
  const { alias, app: appIdOrName } = params.options;
8
8
  const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
9
9
  const app = await Application.get(ownerId, appId);
10
10
  ApplicationConfiguration.printAllValues(app);
11
11
  }
12
12
 
13
- export async function get (params) {
13
+ export async function get(params) {
14
14
  const [configurationName] = params.args;
15
15
  const { alias, app: appIdOrName } = params.options;
16
16
  const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
@@ -18,7 +18,7 @@ export async function get (params) {
18
18
  ApplicationConfiguration.printValue(app, configurationName);
19
19
  }
20
20
 
21
- export async function set (params) {
21
+ export async function set(params) {
22
22
  const [configurationName, configurationValue] = params.args;
23
23
  const { alias, app: appIdOrName } = params.options;
24
24
  const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
@@ -27,10 +27,12 @@ export async function set (params) {
27
27
  [config.name]: ApplicationConfiguration.parse(config, configurationValue),
28
28
  };
29
29
  const app = await Application.updateOptions(ownerId, appId, options);
30
- Logger.printSuccess(`Config ${colors.green(config.id)} successfully updated to ${colors.green(ApplicationConfiguration.formatValue(config, app[config.name]))}!`);
30
+ Logger.printSuccess(
31
+ `Config ${styleText('green', config.id)} successfully updated to ${styleText('green', ApplicationConfiguration.formatValue(config, app[config.name]).toString())}!`,
32
+ );
31
33
  }
32
34
 
33
- export async function update (params) {
35
+ export async function update(params) {
34
36
  const { alias, app: appIdOrName } = params.options;
35
37
  const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
36
38
  const options = ApplicationConfiguration.parseOptions(params.options);
@@ -1,8 +1,8 @@
1
- import * as Application from '../models/application.js';
2
1
  import * as AppConfig from '../models/app_configuration.js';
2
+ import * as Application from '../models/application.js';
3
3
  import { openBrowser } from '../models/utils.js';
4
4
 
5
- export async function openConsole (params) {
5
+ export async function openConsole(params) {
6
6
  const { alias, app: appIdOrName } = params.options;
7
7
 
8
8
  const { apps } = await AppConfig.loadApplicationConf();
@@ -13,7 +13,7 @@ export async function openConsole (params) {
13
13
  }
14
14
 
15
15
  const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
16
- const prefixPath = (ownerId.startsWith('user_')) ? 'users/me' : `organisations/${ownerId}`;
16
+ const prefixPath = ownerId.startsWith('user_') ? 'users/me' : `organisations/${ownerId}`;
17
17
  const consolePath = `/${prefixPath}/applications/${appId}`;
18
18
 
19
19
  await openBrowser(consolePath, `Opening the Console in your browser for application ${appId}`);
@@ -1,24 +1,22 @@
1
1
  import path from 'node:path';
2
- import colors from 'colors/safe.js';
3
- import * as Application from '../models/application.js';
4
- import * as AppConfig from '../models/app_configuration.js';
2
+ import { styleText } from 'node:util';
5
3
  import { Logger } from '../logger.js';
6
- import { isGitWorkingDirectoryClean, isInsideGitRepo } from '../models/git.js';
4
+ import * as AppConfig from '../models/app_configuration.js';
5
+ import * as Application from '../models/application.js';
7
6
  import { conf } from '../models/configuration.js';
7
+ import { isGitWorkingDirectoryClean, isInsideGitRepo } from '../models/git.js';
8
8
 
9
- export async function create (params) {
9
+ export async function create(params) {
10
10
  const { type: typeName } = params.options;
11
11
  const [rawName] = params.args;
12
12
  const { org: orgaIdOrName, alias, region, github: githubOwnerRepo, format, task: taskCommand } = params.options;
13
13
  const { apps } = await AppConfig.loadApplicationConf();
14
14
 
15
15
  // Application name is optionnal, use current directory name if not specified (empty string)
16
- const name = (rawName !== '') ? rawName : getCurrentDirectoryName();
16
+ const name = rawName !== '' ? rawName : getCurrentDirectoryName();
17
17
 
18
- const isTask = (taskCommand != null);
19
- const envVars = isTask
20
- ? { CC_RUN_COMMAND: taskCommand }
21
- : {};
18
+ const isTask = taskCommand != null;
19
+ const envVars = isTask ? { CC_RUN_COMMAND: taskCommand } : {};
22
20
 
23
21
  AppConfig.checkAlreadyLinked(apps, name, alias);
24
22
 
@@ -42,16 +40,16 @@ export async function create (params) {
42
40
  default:
43
41
  await displayAppCreation(app, alias, github, taskCommand);
44
42
  }
45
- };
43
+ }
46
44
 
47
- function getGithubDetails (githubOwnerRepo) {
45
+ function getGithubDetails(githubOwnerRepo) {
48
46
  if (githubOwnerRepo != null) {
49
47
  const [owner, name] = githubOwnerRepo.split('/');
50
48
  return { owner, name };
51
49
  }
52
50
  }
53
51
 
54
- function getCurrentDirectoryName () {
52
+ function getCurrentDirectoryName() {
55
53
  return path.basename(process.cwd());
56
54
  }
57
55
 
@@ -62,16 +60,15 @@ function getCurrentDirectoryName () {
62
60
  * @param {Object} github - The GitHub details
63
61
  * @param {string} taskCommand - The task command
64
62
  */
65
- async function displayAppCreation (app, alias, github, taskCommand) {
66
-
67
- Logger.printSuccess(`Application ${colors.green(app.name)} successfully created!`);
63
+ async function displayAppCreation(app, alias, github, taskCommand) {
64
+ Logger.printSuccess(`Application ${styleText('green', app.name)} successfully created!`);
68
65
 
69
66
  const hasDistinctAlias = alias != null && alias !== app.name;
70
67
  const isTask = app.instance.lifetime === 'TASK';
71
68
 
72
69
  Logger.println();
73
70
  printFieldsAsTable(2, {
74
- Type: colors.blue(`⬢ ${app.instance.variant.name}`),
71
+ Type: styleText('blue', `⬢ ${app.instance.variant.name}`),
75
72
  ID: app.id,
76
73
  'Organisation ID': app.ownerId,
77
74
  Name: app.name,
@@ -82,21 +79,20 @@ async function displayAppCreation (app, alias, github, taskCommand) {
82
79
  });
83
80
 
84
81
  Logger.println();
85
- Logger.println(' ' + colors.bold('Next steps:'));
82
+ Logger.println(' ' + styleText('bold', 'Next steps:'));
86
83
 
87
84
  if (!github) {
88
85
  const isInsideGit = await isInsideGitRepo();
89
86
  if (!isInsideGit) {
90
- Logger.println(` ${colors.yellow('!')} Initialize a git repository first, for example:`);
87
+ Logger.println(` ${styleText('yellow', '!')} Initialize a git repository first, for example:`);
91
88
  Logger.println(` ${shellCommand('git init')}`);
92
89
  Logger.println(` ${shellCommand('git add .')}`);
93
90
  Logger.println(` ${shellCommand('git commit -m "Initial commit"')}`);
94
91
  Logger.println();
95
- }
96
- else {
92
+ } else {
97
93
  const isClean = await isGitWorkingDirectoryClean();
98
94
  if (!isClean) {
99
- Logger.println(` ${colors.yellow('!')} Commit your changes first:`);
95
+ Logger.println(` ${styleText('yellow', '!')} Commit your changes first:`);
100
96
  Logger.println(` ${shellCommand('git add .')}`);
101
97
  Logger.println(` ${shellCommand('git commit -m "My changes"')}`);
102
98
  Logger.println();
@@ -105,24 +101,29 @@ async function displayAppCreation (app, alias, github, taskCommand) {
105
101
  }
106
102
 
107
103
  if (github) {
108
- Logger.println(` ${colors.blue('→')} Push changes to ${colors.blue(`${github.owner}/${github.name}`)} GitHub repository to trigger a deployment, or ${colors.blue('clever restart')} the latest pushed commit`);
109
- }
110
- else {
111
- Logger.println(` ${colors.blue('→')} Run ${colors.blue('clever deploy')} ${isTask ? 'to execute your task' : 'to deploy your application'}`);
104
+ Logger.println(
105
+ ` ${styleText('blue', '→')} Push changes to ${styleText('blue', `${github.owner}/${github.name}`)} GitHub repository to trigger a deployment, or ${styleText('blue', 'clever restart')} the latest pushed commit`,
106
+ );
107
+ } else {
108
+ Logger.println(
109
+ ` ${styleText('blue', '→')} Run ${styleText('blue', 'clever deploy')} ${isTask ? 'to execute your task' : 'to deploy your application'}`,
110
+ );
112
111
  }
113
112
 
114
- Logger.println(` ${colors.blue('→')} Manage your application at: ${colors.underline(`${conf.GOTO_URL}/${app.id}`)}`);
113
+ Logger.println(
114
+ ` ${styleText('blue', '→')} Manage your application at: ${styleText('underline', `${conf.GOTO_URL}/${app.id}`)}`,
115
+ );
115
116
  Logger.println('');
116
117
  }
117
118
 
118
- function shellCommand (command) {
119
- return `${colors.grey('$')} ${colors.yellow(command)}`;
119
+ function shellCommand(command) {
120
+ return `${styleText('grey', '$')} ${styleText('yellow', command)}`;
120
121
  }
121
122
 
122
- function printFieldsAsTable (indent, fields) {
123
+ function printFieldsAsTable(indent, fields) {
123
124
  const fieldsWithValues = Object.fromEntries(Object.entries(fields).filter(([_, value]) => typeof value === 'string'));
124
125
  const labelMaxWidth = Math.max(...Object.keys(fieldsWithValues).map((label) => label.length));
125
126
  return Object.entries(fieldsWithValues).forEach(([label, value]) => {
126
- Logger.println(`${' '.repeat(indent)}${label.padEnd(labelMaxWidth, ' ')} ${colors.grey(value)}`);
127
+ Logger.println(`${' '.repeat(indent)}${label.padEnd(labelMaxWidth, ' ')} ${styleText('grey', value)}`);
127
128
  });
128
129
  }
@@ -1,12 +1,11 @@
1
- import { spawn } from 'node:child_process';
2
- import { conf, loadOAuthConf } from '../models/configuration.js';
3
1
  import { addOauthHeader } from '@clevercloud/client/esm/oauth.js';
4
- import { Logger } from '../logger.js';
5
- import colors from 'colors/safe.js';
6
- import curlconverter from 'curlconverter';
7
2
  import dedent from 'dedent';
3
+ import { spawn } from 'node:child_process';
4
+ import { styleText } from 'node:util';
5
+ import { Logger } from '../logger.js';
6
+ import { conf, loadOAuthConf } from '../models/configuration.js';
8
7
 
9
- async function loadTokens () {
8
+ async function loadTokens() {
10
9
  const tokens = await loadOAuthConf();
11
10
  return {
12
11
  OAUTH_CONSUMER_KEY: conf.OAUTH_CONSUMER_KEY,
@@ -16,7 +15,7 @@ async function loadTokens () {
16
15
  };
17
16
  }
18
17
 
19
- function printCleverCurlHelp () {
18
+ function printCleverCurlHelp() {
20
19
  Logger.println(dedent`
21
20
  Usage: clever curl
22
21
  Query Clever Cloud's API using Clever Tools credentials. For example:
@@ -34,8 +33,7 @@ function printCleverCurlHelp () {
34
33
  `);
35
34
  }
36
35
 
37
- export async function curl () {
38
-
36
+ export async function curl() {
39
37
  // We remove the first three args: "node", "clever" and "curl"
40
38
  const curlArgs = process.argv.slice(3);
41
39
  const hasNoArgs = curlArgs.length === 0;
@@ -47,47 +45,27 @@ export async function curl () {
47
45
  return;
48
46
  }
49
47
 
50
- // WARNING: Version 3.x of curlconverter uses a fork of yargs.
51
- // For "reasons", when the command has a help param, it stops the parsing and triggers a very short and localized version of some help (WAT?).
52
- // That's why we remove the help param before parsing and "reinstate" it before execution.
53
- const curlArgsNoHelp = curlArgs.filter((arg) => arg !== '--help' && arg !== '-h');
54
- const curlCommand = ['curl', ...curlArgsNoHelp].join(' ');
55
- const requestParams = await parseCurlCommand(curlCommand);
48
+ const curlUrl = curlArgs.find((part) => part.startsWith(conf.API_HOST));
56
49
 
57
50
  // We only allow request to the respective API_HOST
58
- if (!requestParams.url.startsWith(conf.API_HOST)) {
59
- Logger.error('"clever curl" command must be used with ' + colors.blue(conf.API_HOST));
51
+ if (curlUrl == null) {
52
+ Logger.error('"clever curl" command must be used with ' + styleText('blue', conf.API_HOST));
60
53
  process.exit(1);
61
54
  }
62
55
 
63
56
  const lastCurlArg = curlArgs.at(-1);
64
57
  const lastCurlArgIsHelp = lastCurlArg !== '--help' && lastCurlArg !== '-h';
65
58
 
66
- // Add oAuth header, only if last cURL arg is not help
59
+ // Add OAuth header, only if last cURL arg is not help
67
60
  // We do this because cURL's help arg expect a category
68
61
  if (lastCurlArgIsHelp) {
69
-
70
62
  const tokens = await loadTokens();
71
- const oauthHeader = await Promise.resolve(requestParams)
63
+ const oauthHeader = await Promise.resolve({})
72
64
  .then(addOauthHeader(tokens))
73
- .then((request) => request.headers.Authorization);
65
+ .then((request) => request.headers.authorization);
74
66
 
75
- curlArgs.push('-H', `Authorization: ${oauthHeader}`);
67
+ curlArgs.push('-H', `authorization: ${oauthHeader}`);
76
68
  }
77
69
 
78
70
  spawn('curl', curlArgs, { stdio: 'inherit' });
79
-
80
- }
81
-
82
- async function parseCurlCommand (curlCommand) {
83
-
84
- const jsonString = curlconverter.toJsonString(curlCommand);
85
- const curlRequestParams = JSON.parse(jsonString);
86
-
87
- return {
88
- method: curlRequestParams.method,
89
- url: curlRequestParams.url,
90
- headers: curlRequestParams.headers,
91
- queryParams: curlRequestParams.queries,
92
- };
93
71
  }
@@ -1,16 +1,13 @@
1
- import { sendToApi } from '../models/send-to-api.js';
2
1
  import { getBackups } from '@clevercloud/client/esm/api/v2/backups.js';
3
- import { Logger } from '../logger.js';
4
- import { formatTable as initFormatTable } from '../format-table.js';
5
2
  import fs from 'node:fs';
6
3
  import { Writable } from 'node:stream';
4
+ import { formatTable } from '../format-table.js';
5
+ import { Logger } from '../logger.js';
7
6
  import { findOwnerId } from '../models/addon.js';
8
- import { resolveRealId, resolveAddonId } from '../models/ids-resolver.js';
9
-
10
- const formatTable = initFormatTable();
11
-
12
- export async function listBackups (params) {
7
+ import { resolveAddonId, resolveRealId } from '../models/ids-resolver.js';
8
+ import { sendToApi } from '../models/send-to-api.js';
13
9
 
10
+ export async function listBackups(params) {
14
11
  const { org, format } = params.options;
15
12
  const [addonIdOrRealId] = params.args;
16
13
 
@@ -44,29 +41,16 @@ export async function listBackups (params) {
44
41
  break;
45
42
  }
46
43
  case 'human': {
47
- const formattedLines = sortedBackups
48
- .map((backup) => [
49
- backup.backup_id,
50
- backup.creation_date,
51
- backup.status,
52
- ]);
44
+ const formattedLines = sortedBackups.map((backup) => [backup.backup_id, backup.creation_date, backup.status]);
53
45
 
54
- const head = [
55
- 'BACKUP ID',
56
- 'CREATION DATE',
57
- 'STATUS',
58
- ];
46
+ const head = ['BACKUP ID', 'CREATION DATE', 'STATUS'];
59
47
 
60
- Logger.println(formatTable([
61
- head,
62
- ...formattedLines,
63
- ]));
48
+ Logger.println(formatTable([head, ...formattedLines]));
64
49
  }
65
50
  }
66
51
  }
67
52
 
68
- export async function downloadBackups (params) {
69
-
53
+ export async function downloadBackups(params) {
70
54
  const { org, output } = params.options;
71
55
  const [addonIdOrRealId, backupId] = params.args;
72
56
 
@@ -85,9 +69,5 @@ export async function downloadBackups (params) {
85
69
  throw new Error('Failed to download backup');
86
70
  }
87
71
 
88
- await response
89
- .body
90
- .pipeTo(
91
- Writable.toWeb(output ? fs.createWriteStream(output) : process.stdout),
92
- );
72
+ await response.body.pipeTo(Writable.toWeb(output ? fs.createWriteStream(output) : process.stdout));
93
73
  }
@@ -1,24 +1,24 @@
1
+ import { styleText } from 'node:util';
2
+ import { Logger } from '../logger.js';
1
3
  import * as AppConfig from '../models/app_configuration.js';
2
4
  import * as Application from '../models/application.js';
3
- import { Logger } from '../logger.js';
4
- import colors from 'colors/safe.js';
5
5
 
6
- export async function deleteApp (params) {
6
+ export async function deleteApp(params) {
7
7
  const { alias, app: appIdOrName, yes: skipConfirmation } = params.options;
8
8
  const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
9
9
 
10
10
  const app = await Application.get(ownerId, appId);
11
11
  if (app == null) {
12
- throw new Error('The application doesn\'t exist');
12
+ throw new Error("The application doesn't exist");
13
13
  }
14
14
 
15
15
  // delete app
16
16
  await Application.deleteApp(app, skipConfirmation);
17
- Logger.printSuccess(`Application ${colors.green(colors.bold(`${app.name}`))} successfully deleted!`);
18
- Logger.println(` ${colors.grey('•')} Application ID: ${colors.grey(app.id)}`);
17
+ Logger.printSuccess(`Application ${styleText('green', styleText('bold', `${app.name}`))} successfully deleted!`);
18
+ Logger.println(` ${styleText('grey', '•')} Application ID: ${styleText('grey', app.id)}`);
19
19
 
20
20
  const wasUnlinked = await AppConfig.removeLinkedApplication({ appId, alias });
21
21
  if (wasUnlinked) {
22
- Logger.println(` ${colors.blue('→')} Local alias ${colors.blue(alias || app.name)} unlinked`);
22
+ Logger.println(` ${styleText('blue', '→')} Local alias ${styleText('blue', alias || app.name)} unlinked`);
23
23
  }
24
- };
24
+ }
@@ -1,19 +1,27 @@
1
- import colors from 'colors/safe.js';
1
+ import { getAllDeployments } from '@clevercloud/client/esm/api/v2/application.js';
2
2
  import dedent from 'dedent';
3
-
3
+ import { styleText } from 'node:util';
4
+ import { Logger } from '../logger.js';
4
5
  import * as AppConfig from '../models/app_configuration.js';
5
6
  import * as Application from '../models/application.js';
7
+ import * as ExitStrategy from '../models/exit-strategy-option.js';
6
8
  import * as git from '../models/git.js';
7
9
  import * as Log from '../models/log-v4.js';
8
- import { Logger } from '../logger.js';
9
- import { getAllDeployments } from '@clevercloud/client/esm/api/v2/application.js';
10
10
  import { sendToApi } from '../models/send-to-api.js';
11
- import * as ExitStrategy from '../models/exit-strategy-option.js';
12
11
 
13
12
  // Once the API call to redeploy() has been triggered successfully,
14
13
  // the rest (waiting for deployment state to evolve and displaying logs) is done with auto retry (resilient to network failures)
15
- export async function deploy (params) {
16
- const { alias, branch: branchName, tag: tagName, quiet, force, follow, 'same-commit-policy': sameCommitPolicy, 'exit-on': exitOnDeploy } = params.options;
14
+ export async function deploy(params) {
15
+ const {
16
+ alias,
17
+ branch: branchName,
18
+ tag: tagName,
19
+ quiet,
20
+ force,
21
+ follow,
22
+ 'same-commit-policy': sameCommitPolicy,
23
+ 'exit-on': exitOnDeploy,
24
+ } = params.options;
17
25
 
18
26
  const exitStrategy = ExitStrategy.get(follow, exitOnDeploy);
19
27
 
@@ -23,15 +31,14 @@ export async function deploy (params) {
23
31
  const branchRefspec = await getBranchToDeploy(branchName, tagName);
24
32
  const commitIdToPush = await git.getBranchCommit(branchRefspec);
25
33
  const remoteHeadCommitId = await git.getRemoteCommit(appData.deployUrl);
26
- const deployedCommitId = await Application.get(ownerId, appId)
27
- .then(({ commitId }) => commitId);
34
+ const deployedCommitId = await Application.get(ownerId, appId).then(({ commitId }) => commitId);
28
35
 
29
36
  await git.addRemote(appData.alias, appData.deployUrl);
30
37
 
31
38
  if (commitIdToPush === remoteHeadCommitId) {
32
39
  switch (sameCommitPolicy) {
33
40
  case 'ignore':
34
- Logger.printSuccess(`The application is up-to-date (${colors.grey(remoteHeadCommitId)})`);
41
+ Logger.printSuccess(`The application is up-to-date (${styleText('grey', remoteHeadCommitId)})`);
35
42
  return;
36
43
  case 'restart':
37
44
  return restartOnSameCommit(ownerId, appId, commitIdToPush, quiet, false, exitStrategy);
@@ -39,10 +46,11 @@ export async function deploy (params) {
39
46
  return restartOnSameCommit(ownerId, appId, commitIdToPush, quiet, true, exitStrategy);
40
47
  case 'error':
41
48
  default: {
42
- const restartCommand = commitIdToPush !== deployedCommitId ? `clever restart --commit ${commitIdToPush}` : 'clever restart';
49
+ const restartCommand =
50
+ commitIdToPush !== deployedCommitId ? `clever restart --commit ${commitIdToPush}` : 'clever restart';
43
51
  throw new Error(dedent`
44
- Remote HEAD has the same commit as the one to push ${colors.grey(`(${remoteHeadCommitId})`)}, your application is up-to-date.
45
- Create a new commit, use ${colors.blue(restartCommand)} or the ${colors.blue('--same-commit-policy')} option.
52
+ Remote HEAD has the same commit as the one to push ${styleText('grey', `(${remoteHeadCommitId})`)}, your application is up-to-date.
53
+ Create a new commit, use ${styleText('blue', restartCommand)} or the ${styleText('blue', '--same-commit-policy')} option.
46
54
  `);
47
55
  }
48
56
  }
@@ -54,66 +62,72 @@ export async function deploy (params) {
54
62
  const knownDeployments = await getAllDeployments({ id: ownerId, appId, limit: 5 }).then(sendToApi);
55
63
 
56
64
  Logger.println(dedent`
57
- ${colors.bold(`🚀 Deploying ${colors.green(appData.name)}`)}
58
- Application ID ${colors.grey(`${appId}`)}
59
- Organisation ID ${colors.grey(`${ownerId}`)}
65
+ ${styleText('bold', `🚀 Deploying ${styleText('green', appData.name)}`)}
66
+ Application ID ${styleText('grey', `${appId}`)}
67
+ Organisation ID ${styleText('grey', `${ownerId}`)}
60
68
  `);
61
69
 
62
70
  Logger.println();
63
71
 
64
- Logger.println(colors.bold('🔀 Git information'));
72
+ Logger.println(styleText('bold', '🔀 Git information'));
65
73
  if (remoteHeadCommitId == null || deployedCommitId == null) {
66
- Logger.println(` ${colors.yellow('!')} App is brand new, no commits on remote yet`);
67
- }
68
- else {
69
- Logger.println(` Remote head ${colors.yellow(remoteHeadCommitId)} (${branchRefspec})`);
70
- Logger.println(` Deployed commit ${colors.yellow(deployedCommitId)}`);
74
+ Logger.println(` ${styleText('yellow', '!')} App is brand new, no commits on remote yet`);
75
+ } else {
76
+ Logger.println(` Remote head ${styleText('yellow', remoteHeadCommitId)} (${branchRefspec})`);
77
+ Logger.println(` Deployed commit ${styleText('yellow', deployedCommitId)}`);
71
78
  }
72
- Logger.println(` Local commit ${colors.yellow(commitIdToPush)} ${colors.blue('[will be deployed]')}`);
79
+ Logger.println(
80
+ ` Local commit ${styleText('yellow', commitIdToPush)} ${styleText('blue', '[will be deployed]')}`,
81
+ );
73
82
 
74
83
  Logger.println();
75
84
 
76
85
  Logger.println(dedent`
77
- ${colors.bold('🔄 Deployment progress')}
78
- ${colors.blue('→ Pushing source code to Clever Cloud…')}
86
+ ${styleText('bold', '🔄 Deployment progress')}
87
+ ${styleText('blue', '→ Pushing source code to Clever Cloud…')}
79
88
  `);
80
89
 
81
- await git.push(appData.deployUrl, commitIdToPush, force)
82
- .catch(async (e) => {
83
- const isShallow = await git.isShallow();
84
- if (isShallow) {
85
- throw new Error('Failed to push your source code because your repository is shallow and therefore cannot be pushed to the Clever Cloud remote.');
86
- }
87
- else {
88
- throw e;
89
- }
90
- });
91
-
92
- await Logger.println(` ${colors.green('✓ Code pushed to Clever Cloud')}`);
93
-
94
- return Log.watchDeploymentAndDisplayLogs({ ownerId, appId, commitId: commitIdToPush, knownDeployments, quiet, exitStrategy });
90
+ await git.push(appData.deployUrl, commitIdToPush, force).catch(async (e) => {
91
+ const isShallow = await git.isShallow();
92
+ if (isShallow) {
93
+ throw new Error(
94
+ 'Failed to push your source code because your repository is shallow and therefore cannot be pushed to the Clever Cloud remote.',
95
+ );
96
+ } else {
97
+ throw e;
98
+ }
99
+ });
100
+
101
+ await Logger.println(` ${styleText('green', '✓ Code pushed to Clever Cloud')}`);
102
+
103
+ return Log.watchDeploymentAndDisplayLogs({
104
+ ownerId,
105
+ appId,
106
+ commitId: commitIdToPush,
107
+ knownDeployments,
108
+ quiet,
109
+ exitStrategy,
110
+ });
95
111
  }
96
112
 
97
- async function restartOnSameCommit (ownerId, appId, commitIdToPush, quiet, withoutCache, exitStrategy) {
113
+ async function restartOnSameCommit(ownerId, appId, commitIdToPush, quiet, withoutCache, exitStrategy) {
98
114
  const cacheSuffix = withoutCache ? ' without using cache' : '';
99
- Logger.println(`🔄 Restarting ${colors.bold(appId)}${cacheSuffix} ${colors.grey(`(${commitIdToPush})`)}`);
115
+ Logger.println(`🔄 Restarting ${styleText('bold', appId)}${cacheSuffix} ${styleText('grey', `(${commitIdToPush})`)}`);
100
116
 
101
117
  const restart = await Application.redeploy(ownerId, appId, commitIdToPush, withoutCache);
102
118
  return Log.watchDeploymentAndDisplayLogs({ ownerId, appId, deploymentId: restart.deploymentId, quiet, exitStrategy });
103
119
  }
104
120
 
105
- async function getBranchToDeploy (branchName, tagName) {
121
+ async function getBranchToDeploy(branchName, tagName) {
106
122
  if (tagName) {
107
123
  const useTag = await git.isExistingTag(tagName);
108
124
  if (useTag) {
109
125
  const tagRefspec = await git.getFullBranch(tagName);
110
126
  return tagRefspec;
111
- }
112
- else {
127
+ } else {
113
128
  throw new Error(`Tag ${tagName} doesn't exist locally`);
114
129
  }
115
- }
116
- else {
130
+ } else {
117
131
  return await git.getFullBranch(branchName);
118
132
  }
119
133
  }