@forge/cli-shared 9.10.0-next.1-experimental-1e95696 → 9.10.0-next.10

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/out/ui/text.js CHANGED
@@ -29,11 +29,15 @@ const go = (link) => buildTerminalLink(`https://go.atlassian.com/${link}`);
29
29
  const gettingStartedDACLink = go('dac/platform/forge/getting-started/#log-in-with-an-atlassian-api-token');
30
30
  const command = (...args) => chalk_1.default.bold(args.join(' '));
31
31
  const forge = (...args) => command('forge', ...args);
32
+ const autoSpaceSentences = (...sentences) => sentences
33
+ .filter((sentence) => sentence.length > 0)
34
+ .join(' ');
32
35
  function itemList(items, indent) {
33
36
  return items.map((item) => `${indent ?? ' '}- ${item}`).join(`\n${indent ?? ''}`);
34
37
  }
35
38
  const fatalError = (message) => chalk_1.default.bold(chalk_1.default.red(message));
36
39
  const approveRuleDescription = 'list of validation rules to approve';
40
+ const keytarAccessErrorBase = (message) => `Keytar error detected: ${message}`;
37
41
  const capitalise = (word) => word.charAt(0).toUpperCase() + word.slice(1);
38
42
  exports.capitalise = capitalise;
39
43
  const getLintMessage = (line, column, message, level, colourFunction, reference) => `${chalk_1.default.dim(`${line}:${column}`.padEnd(7))} ${colourFunction(level.padEnd(8))} ${message} ${chalk_1.default.dim(reference)}\n`;
@@ -45,6 +49,16 @@ const checkLintTotalPlurals = (numErrors, numWarnings, numApprovals, numFixableE
45
49
  pluralCheckedFixableErrors: `${numFixableErrors} ${numFixableErrors === 1 ? 'error' : 'errors'}`,
46
50
  pluralCheckedFixableWarnings: `${numFixableWarnings} ${numFixableWarnings === 1 ? 'warning' : 'warnings'}`
47
51
  });
52
+ const platformKeytarRecommendations = () => {
53
+ switch (process.platform) {
54
+ case 'darwin':
55
+ return 'Ensure you enable access to the macOS keychain when prompted.';
56
+ case 'linux':
57
+ return `Ensure you have ${chalk_1.default.bold('libsecret')} installed.`;
58
+ default:
59
+ return '';
60
+ }
61
+ };
48
62
  const globalTargetLocation = ({ unit, org }) => unit && org
49
63
  ? `in unit ${chalk_1.default.bold(unit)} in organization ${chalk_1.default.bold(org)}`
50
64
  : unit
@@ -54,9 +68,15 @@ exports.Text = {
54
68
  buildTerminalLink,
55
69
  go,
56
70
  error: {
57
- noTokenStored: `Not logged in. Run ${forge('login')}, or set the FORGE_EMAIL and FORGE_API_TOKEN environment variables before trying again. See ${gettingStartedDACLink} for more.`,
58
- credentialsFilePermissions: `The CLI couldn't securely store your login credentials in the local credentials file. ` +
59
- `Set the FORGE_EMAIL and FORGE_API_TOKEN environment variables instead. See ${gettingStartedDACLink} for more.`,
71
+ noKeytar: autoSpaceSentences(`The CLI couldn't securely store your login credentials in a local keychain.`, platformKeytarRecommendations(), `If a local keychain is not available, use environment variables before trying again. See ${gettingStartedDACLink} for more.`),
72
+ noTokenStored: `Not logged in. If a local keychain is available, run ${forge('login')}, otherwise set environment variables before trying again. See ${gettingStartedDACLink} for more.`,
73
+ keytarAccessError: {
74
+ other: (message) => keytarAccessErrorBase(message),
75
+ mac: (message) => keytarAccessErrorBase(message) +
76
+ `\nSomething went wrong while accessing Keychain Access. Try locking and unlocking the login keychain.`,
77
+ linux: (message) => keytarAccessErrorBase(message) + `\nSomething went wrong while accessing Secret Service API.`,
78
+ windows: (message) => keytarAccessErrorBase(message) + `\nSomething went wrong while accessing Credentials Vault.`
79
+ },
60
80
  outdatedCLIVersion: (installed, latest) => `Warning: Your version of Forge CLI is out of date. We recommend you update to the latest version to get the latest features and bug fixes.` +
61
81
  `\nRun ${command('npm', 'install', '-g', `${cli_details_1.FORGE_CLI_PACKAGE}@latest`)} to update from version ${chalk_1.default.bold(installed)} to ${chalk_1.default.bold(latest)}.` +
62
82
  `\n`,
@@ -69,7 +89,7 @@ exports.Text = {
69
89
  invalidSite: 'The site you entered is not an Atlassian site. Rerun the command with the URL to an Atlassian site to install the app.',
70
90
  invalidWorkspace: 'The workspace you entered is not a valid workspace. Rerun the command with the URL to a valid workspace to install the app.',
71
91
  invalidInstallationContext: 'Could not find an installation for the provided Atlassian app',
72
- invalidTokenInCredentialFile: `Your API token is no longer valid. Run ${forge('login')} to reset your login credentials.`,
92
+ invalidTokenInKeytar: `Your API token is no longer valid. Run ${forge('login')} to reset your login credentials.`,
73
93
  invalidUpgradeTarget: 'You must specify either "all" or "code" as the upgrade target.',
74
94
  invalidTokenInEnv: (instructionsUrl, emailVar, tokenVar) => `The API token on your machine is no longer valid.` +
75
95
  `\n 1) Get a new API token: ${instructionsUrl}` +
@@ -102,6 +122,9 @@ exports.Text = {
102
122
  environmentIsNotDefined: (envKey) => `Environment with name ${envKey} not defined. Create this environment with ${chalk_1.default.bold(`forge environments create -e ${envKey}`)} before proceeding.`
103
123
  },
104
124
  warning: {
125
+ plaintextCredentialsFound: (url) => `Your credentials were stored in plaintext by a previous version of the Forge CLI. For additional security, revoke your existing API token by visting this URL ${buildTerminalLink(url)}.`,
126
+ plaintextCredentialsMigrated: 'The credentials found in plaintext have been migrated to your local keychain.',
127
+ plaintextCredentialsNotMigrated: autoSpaceSentences(`The CLI couldn't securely store your login credentials in a local keychain.`, platformKeytarRecommendations(), `If a local keychain is not available, use environment variables instead. See ${gettingStartedDACLink} for more information.`),
105
128
  unsupportedNodeVersion: (_userNodeVersion, supportedNodeVersions) => log_color_1.LogColor.warn(`Warning: Forge CLI supports Node.js ${supportedNodeVersions}.` +
106
129
  `\nUnsupported Node.js versions are not guaranteed to work correctly.\n`),
107
130
  deprecation: {
@@ -218,7 +241,7 @@ exports.Text = {
218
241
  },
219
242
  error: {
220
243
  personalCredentialsEnv: (emailKey, apiTokenKey) => `We couldn't get your Atlassian account information. Check the ${emailKey} and ${apiTokenKey} environment variables.`,
221
- personalCredentialsFile: `We couldn't get your Atlassian account information. You may need to run ${forge('login')} to log in again.`
244
+ personalCredentialsKeytar: `We couldn't get your Atlassian account information. You may need to run ${forge('login')} to log in again.`
222
245
  }
223
246
  },
224
247
  feedback: {
@@ -272,6 +295,7 @@ What do you like or don't like about Forge? Share your feedback below or press C
272
295
  taskRegister: 'Registering app',
273
296
  taskCreateEnvironments: 'Creating environments',
274
297
  taskPackages: 'Installing dependencies',
298
+ taskModules: 'Adding modules',
275
299
  error: {
276
300
  dirtyDirectory: 'Destination directory is not empty',
277
301
  app: {
@@ -289,6 +313,11 @@ What do you like or don't like about Forge? Share your feedback below or press C
289
313
  noTemplates: 'There are no templates to choose from.',
290
314
  unexpectedArchiveFormat: 'Unexpected template format.'
291
315
  },
316
+ preset: {
317
+ notFound: (preset) => `The preset ${preset} doesn't exist. Run ${forge('create')} using a different preset.`,
318
+ withTemplate: `Run ${forge('create')} with either --template or --preset, not both.`,
319
+ modulesFailed: `Your app was created, but some preset modules couldn't be added. Run ${forge('module add')} from the app directory to add them.`
320
+ },
292
321
  packages: {
293
322
  installFail: `Something went wrong while installing app dependencies. Try running ${forge('create')} again.`
294
323
  }
@@ -442,6 +471,7 @@ What do you like or don't like about Forge? Share your feedback below or press C
442
471
  defaultEnv: {
443
472
  info: 'You do not have a default development environment set. This is required to run commands without specifying an environment. Make sure not to use sensitive information when naming your default development environment.',
444
473
  prompt: 'Enter a name for your default development environment:',
474
+ notSetNonInteractive: `No environment was given and you don't have a default development environment. Pass --environment, or set a default with ${forge('settings', 'set', 'default-environment', '<environment>')}.`,
445
475
  warn: `${chalk_1.default.bold('Warning:')} A development environment with this name already exists. If you continue, you may be using the same environment as another contributor.`,
446
476
  confirm: 'Do you want to continue?',
447
477
  setSuccess: (envKey, envType) => `${exports.Text.env.displayEnvironment(envKey, envType)} has been set as your default development environment`,
@@ -1297,6 +1327,51 @@ ${buildTerminalLink(link)}\n`,
1297
1327
  banner: `Showing latest deployments of your app:`,
1298
1328
  noDeployments: `No deployments found for this app.\nRun ${forge('deploy')} to deploy your app to an environment.`
1299
1329
  },
1330
+ deployStatus: {
1331
+ cmd: 'show the placement deployment status of an app version in an environment',
1332
+ majorVersionOption: 'specify the major version to show (defaults to the latest deployed version)',
1333
+ banner: (envKey, envType, version) => `${log_symbols_1.default.info} Environment: ${exports.Text.env.displayEnvironment(envKey, envType)} (Version: ${version})`,
1334
+ artifactUploaded: (createdAt, buildTag) => {
1335
+ const buildTagText = buildTag ? ` from build with tag ${buildTag}` : '';
1336
+ return `${log_symbols_1.default.success} App artifact uploaded${buildTagText} at ${createdAt}`;
1337
+ },
1338
+ overall: {
1339
+ succeeded: (succeeded, total) => `${log_symbols_1.default.success} Deployment succeeded (${succeeded}/${total} placements)`,
1340
+ failed: (succeeded, total) => `${log_symbols_1.default.error} Deployment failed (${succeeded}/${total} placements succeeded)`,
1341
+ inProgress: (succeeded, total, inProgress) => `${log_symbols_1.default.info} Deployment still in progress (${succeeded}/${total} placements succeeded, ${inProgress} in progress)`
1342
+ },
1343
+ checkAgain: (envKey, majorVersion) => `Run ${forge('deploy status', '-e', (0, environment_1.environmentToOption)(envKey), ...(majorVersion ? ['-v', String(majorVersion)] : []))} again to check for updates.`,
1344
+ table: {
1345
+ placementType: 'Placement type',
1346
+ placement: 'Placement',
1347
+ status: 'Status',
1348
+ failedStep: 'Failed step',
1349
+ lastUpdated: 'Last updated'
1350
+ },
1351
+ placementTypeLabel: (placementType) => ({
1352
+ [graphql_runtime_enums_1.AppPlacementType.Region]: 'Region',
1353
+ [graphql_runtime_enums_1.AppPlacementType.CustomerDataPlane]: 'Customer data plane',
1354
+ [graphql_runtime_enums_1.AppPlacementType.IsolationContext]: 'Isolation context'
1355
+ })[placementType] ?? placementType,
1356
+ groupLabel: (placementTypeLabel, succeeded, total) => `${placementTypeLabel} (${succeeded}/${total})`,
1357
+ statusLabel: (status) => ({
1358
+ [graphql_runtime_enums_1.AppVersionDeploymentStatus.Succeeded]: chalk_1.default.green('Succeeded'),
1359
+ [graphql_runtime_enums_1.AppVersionDeploymentStatus.Failed]: chalk_1.default.red('Failed'),
1360
+ [graphql_runtime_enums_1.AppVersionDeploymentStatus.InProgress]: chalk_1.default.yellow('In progress')
1361
+ })[status] ?? status,
1362
+ stepLabel: (step) => ({
1363
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.Artifact]: 'Artifact',
1364
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.Function]: 'Function',
1365
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.Containers]: 'Containers',
1366
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.HostedResources]: 'Hosted resources',
1367
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.CustomScopes]: 'Custom scopes',
1368
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.OauthClient]: 'OAuth client',
1369
+ [graphql_runtime_enums_1.AppVersionDeploymentStep.ScheduledTriggers]: 'Scheduled triggers'
1370
+ })[step] ?? step,
1371
+ noPlacements: `No placements found for this version. Placements are added when your app is installed.\nRun ${forge('install')} to install your app.`,
1372
+ noVersion: (envKey, envType) => `No deployed version found in the ${exports.Text.env.displayEnvironment(envKey, envType)} environment. Run ${forge('deploy')} to deploy your app first.`,
1373
+ noStatus: (version, envKey, envType) => `No deployment status is available for version ${version} in the ${exports.Text.env.displayEnvironment(envKey, envType)} environment yet.`
1374
+ },
1300
1375
  tunnel: {
1301
1376
  cmd: 'start a tunnel to connect your local code with the app running in the development environment',
1302
1377
  optionDebugger: 'enable debugger mode',
@@ -1696,6 +1771,10 @@ ${buildTerminalLink(link)}\n`,
1696
1771
  description: 'Change your default development environment',
1697
1772
  info: `To view all environments for this app, run ${forge('environments', 'list')}.`
1698
1773
  },
1774
+ nonInteractive: {
1775
+ description: 'Run commands without prompts: auto (when an agent runs the command, not in CI), on, or off. FORGE_NON_INTERACTIVE overrides it',
1776
+ invalidValue: 'Invalid value specified. Valid values: auto, on, off'
1777
+ },
1699
1778
  customEffects: {
1700
1779
  description: 'Enable custom spinner effects',
1701
1780
  setupError: chalk_1.default.yellow('Failed to fetch custom spinner config. Custom spinner effects can be disabled via forge settings')
@@ -1769,7 +1848,10 @@ When errors occur during Forge command execution, error details will be sent to
1769
1848
  description: 'run the command without input prompts',
1770
1849
  error: {
1771
1850
  missingRequiredOption: (command, requiredOptions) => `${command} --non-interactive requires ${requiredOptions.join(' ')}`,
1772
- missingAnalyticsPreferences: `--non-interactive requires an analytics setting. Use ${forge('settings', 'set', 'usage-analytics', '<value>')}.`
1851
+ missingAnalyticsPreferences: `--non-interactive requires an analytics setting. Use ${forge('settings', 'set', 'usage-analytics', '<value>')}.`,
1852
+ promptReached: (question) => `${question ? `"${question.trim()}" needs an answer, but` : 'This command needs input, but'} the CLI is ` +
1853
+ `running in non-interactive mode, so it can't ask. Pass the answer as an option. Run the command with ` +
1854
+ `--help to see its options.`
1773
1855
  }
1774
1856
  },
1775
1857
  customScopes: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/cli-shared",
3
- "version": "9.10.0-next.1-experimental-1e95696",
3
+ "version": "9.10.0-next.10",
4
4
  "description": "Common functionality for Forge CLI",
5
5
  "author": "Atlassian",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
@@ -13,8 +13,8 @@
13
13
  "prebuild": "yarn generate-graphql-types"
14
14
  },
15
15
  "dependencies": {
16
- "@forge/manifest": "13.8.1-next.0-experimental-1e95696",
17
- "@forge/util": "3.1.0-next.0-experimental-1e95696",
16
+ "@forge/manifest": "13.9.0-next.5",
17
+ "@forge/util": "4.0.0-next.2",
18
18
  "@forge/i18n": "1.0.1",
19
19
  "@sentry/node": "7.106.0",
20
20
  "@vercel/detect-agent": "^1.2.5",
@@ -39,6 +39,7 @@
39
39
  "inquirer": "^8.2.6",
40
40
  "inquirer-autocomplete-prompt": "^2.0.1",
41
41
  "io-ts": "^2.2.22",
42
+ "keytar": "^7.9.0",
42
43
  "ora": "^5.4.1",
43
44
  "recursive-readdir": "^2.2.3",
44
45
  "semver": "^7.6.0",