diff --git a/package-lock.json b/package-lock.json index 82ed62bf..5806ef67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20259,6 +20259,22 @@ "has-flag": "^3.0.0" } }, + "supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "requires": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + } + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -20284,6 +20300,15 @@ "execa": "^0.7.0" } }, + "terminal-link": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-1.3.0.tgz", + "integrity": "sha512-nFaWG/gs3brGi3opgWU2+dyFGbQ7tueSRYOBOD8URdDXCbAGqDEZzuskCc+okCClYcJFDPwn8e2mbv4FqAnWFA==", + "requires": { + "ansi-escapes": "^3.2.0", + "supports-hyperlinks": "^1.0.1" + } + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", diff --git a/package.json b/package.json index 8b67c021..2e8484fb 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "normalize.css": "^8.0.1", "ora": "^3.3.1", "pkg-install": "^1.0.0", + "terminal-link": "^1.3.0", "title": "^3.4.1", "twilio": "^3.33.0", "type-fest": "^0.6.0", diff --git a/src/commands/activate.ts b/src/commands/activate.ts index 20b8cb91..c27e3ba2 100644 --- a/src/commands/activate.ts +++ b/src/commands/activate.ts @@ -6,14 +6,13 @@ import { Ora } from 'ora'; import { Argv } from 'yargs'; import { checkConfigForCredentials } from '../checks/check-credentials'; import { ActivateCliFlags, getConfigFromFlags } from '../config/activate'; -import { printActivateConfig } from '../printers/activate'; +import { printActivateConfig, printActivateResult } from '../printers/activate'; import { getDebugFunction, getOraSpinner, logger, setLogLevelByName, } from '../utils/logger'; -import { writeOutput } from '../utils/output'; import { ExternalCliOptions, sharedCliOptions } from './shared'; import { CliInfo } from './types'; @@ -68,7 +67,7 @@ export async function handler( spinner.succeed( `Activated new build ${details} on ${config.targetEnvironment}` ); - writeOutput(result.domain); + printActivateResult(result); } catch (err) { handleError(err, spinner); } diff --git a/src/printers/activate.ts b/src/printers/activate.ts index 53d5c2cf..c211994a 100644 --- a/src/printers/activate.ts +++ b/src/printers/activate.ts @@ -1,8 +1,10 @@ -import { ActivateConfig } from '@twilio-labs/serverless-api'; +import { ActivateConfig, ActivateResult } from '@twilio-labs/serverless-api'; import { stripIndent } from 'common-tags'; import { logger } from '../utils/logger'; -import { redactPartOfString } from './utils'; +import { writeOutput } from '../utils/output'; +import { getTwilioConsoleDeploymentUrl, redactPartOfString } from './utils'; import chalk = require('chalk'); +import terminalLink = require('terminal-link'); export function printActivateConfig(config: ActivateConfig) { const message = chalk` @@ -11,3 +13,24 @@ export function printActivateConfig(config: ActivateConfig) { `; logger.info(stripIndent(message) + '\n'); } + +export function printActivateResult(result: ActivateResult) { + logger.info(chalk.cyan.bold('\nActive build available at:')); + writeOutput(result.domain); + + const twilioConsoleLogsLink = terminalLink( + 'Open the Twilio Console', + getTwilioConsoleDeploymentUrl(result.serviceSid, result.environmentSid), + { + fallback: (text: string, url: string) => chalk.dim(url), + } + ); + + logger.info( + '\n' + + stripIndent(chalk` + {cyan.bold View Live Logs:} + ${twilioConsoleLogsLink} + `) + ); +} diff --git a/src/printers/deploy.ts b/src/printers/deploy.ts index 15ce95a6..d8dd139a 100644 --- a/src/printers/deploy.ts +++ b/src/printers/deploy.ts @@ -7,10 +7,12 @@ import { import chalk from 'chalk'; import columnify from 'columnify'; import { stripIndent } from 'common-tags'; +import terminalLink from 'terminal-link'; import { MergeExclusive } from 'type-fest'; import { logger } from '../utils/logger'; import { writeOutput } from '../utils/output'; import { + getTwilioConsoleDeploymentUrl, printObjectWithoutHeaders, redactPartOfString, shouldPrettyPrint, @@ -58,6 +60,10 @@ function plainPrintDeployedResources( environmentSuffix: config.functionsEnv, environmentSid: result.environmentSid, buildSid: result.buildSid, + viewLiveLogs: getTwilioConsoleDeploymentUrl( + result.serviceSid, + result.environmentSid + ), }; const output = ` @@ -110,6 +116,14 @@ function prettyPrintDeployedResources( config: DeployLocalProjectConfig, result: DeployResult ) { + const twilioConsoleLogsLink = terminalLink( + 'Open the Twilio Console', + getTwilioConsoleDeploymentUrl(result.serviceSid, result.environmentSid), + { + fallback: (text: string, url: string) => chalk.dim(url), + } + ); + writeOutput( chalk` {bold.cyan.underline Deployment Details} @@ -120,6 +134,8 @@ function prettyPrintDeployedResources( ${config.functionsEnv} {dim (${result.environmentSid})} {bold.cyan Build SID:} ${result.buildSid} +{bold.cyan View Live Logs:} + ${twilioConsoleLogsLink} `.trim() ); diff --git a/src/printers/utils.ts b/src/printers/utils.ts index 25db4b6a..d992bb99 100644 --- a/src/printers/utils.ts +++ b/src/printers/utils.ts @@ -8,6 +8,13 @@ export const shouldPrettyPrint = process.stdout.isTTY && !isCi; export const supportsEmoji = process.platform !== 'win32' || isCi || process.env.TERM === 'xterm-256color'; +export function getTwilioConsoleDeploymentUrl( + serviceSid: string, + environmentSid: string +) { + return `https://www.twilio.com/console/assets/api/${serviceSid}/environment/${environmentSid}`; +} + export function printObjectWithoutHeaders(obj: {}): string { return columnify(obj, { showHeaders: false }); }