From 2426e2c1fae560a27fdbaefd3f4379f36fdae6f2 Mon Sep 17 00:00:00 2001 From: Ross Stenersen Date: Fri, 9 Oct 2026 13:51:28 -0500 Subject: [PATCH] fix: warn user when choosen profile is not defined in config --- .changeset/brave-links-mend.md | 5 +++ .changeset/quiet-owls-warn.md | 5 +++ doc/configuration.md | 7 ++++ .../lib/command/smartthings-command.test.ts | 34 +++++++++++++++++++ src/lib/cli-config.ts | 2 +- src/lib/command/smartthings-command.ts | 9 +++++ src/lib/log-utils.ts | 2 +- 7 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 .changeset/brave-links-mend.md create mode 100644 .changeset/quiet-owls-warn.md diff --git a/.changeset/brave-links-mend.md b/.changeset/brave-links-mend.md new file mode 100644 index 000000000..4b5d5e21e --- /dev/null +++ b/.changeset/brave-links-mend.md @@ -0,0 +1,5 @@ +--- +"@smartthings/cli": patch +--- + +Fix broken configuration documentation links in config and logging error messages. diff --git a/.changeset/quiet-owls-warn.md b/.changeset/quiet-owls-warn.md new file mode 100644 index 000000000..a66519950 --- /dev/null +++ b/.changeset/quiet-owls-warn.md @@ -0,0 +1,5 @@ +--- +"@smartthings/cli": patch +--- + +Warn when the selected non-default profile is not defined in configuration. diff --git a/doc/configuration.md b/doc/configuration.md index 85a67776f..86f7d75fb 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -21,6 +21,13 @@ specified. Most users can simply put their configuration options here. environment variable or use the `--profile` (shortcut `-p`) command line argument. (When both are used, the command line argument overrides the environment variable.) +* The CLI warns when the selected profile (other than "default") is not defined in +`config.yaml`. To use a profile without any configuration options, such as one used only to +log in with a different account, define it with an empty value: + + ```yaml + work: {} + ``` The [YAML Primer](https://github.com/darvid/trine/wiki/YAML-Primer) is a good source of information on YAML. Note, however, some features (like merge keys) have been removed in 1.2. The YAML parser diff --git a/src/__tests__/lib/command/smartthings-command.test.ts b/src/__tests__/lib/command/smartthings-command.test.ts index ed396ff37..ae8589750 100644 --- a/src/__tests__/lib/command/smartthings-command.test.ts +++ b/src/__tests__/lib/command/smartthings-command.test.ts @@ -5,6 +5,7 @@ import type { Paths } from 'env-paths' import type log4js from 'log4js' import type { CLIConfig, loadConfig } from '../../../lib/cli-config.js' +import type { yellow } from '../../../lib/colors.js' import type { ensureDir } from '../../../lib/file-util.js' import type { buildDefaultLog4jsConfig, loadLog4jsConfig } from '../../../lib/log-utils.js' import type { SmartThingsCommandFlags } from '../../../lib/command/smartthings-command.js' @@ -30,6 +31,11 @@ jest.unstable_mockModule('../../../lib/cli-config.js', () => ({ loadConfig: loadConfigMock, })) +const yellowMock = jest.fn() +jest.unstable_mockModule('../../../lib/colors.js', () => ({ + yellow: yellowMock, +})) + const ensureDirMock = jest.fn() jest.unstable_mockModule('../../../lib/file-util.js', () => ({ ensureDir: ensureDirMock, @@ -58,6 +64,7 @@ jest.unstable_mockModule('../../../lib/yargs-transition-temp.js', () => ({ })) const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { /* do nothing */ }) +const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => { /* do nothing */ }) const { @@ -94,6 +101,7 @@ describe('smartThingsCommand', () => { .mockReturnValue(true) const cliConfig = { profile: {}, + mergedProfiles: {}, booleanConfigValue: booleanConfigValueMock, } as unknown as CLIConfig loadConfigMock.mockResolvedValue(cliConfig) @@ -121,5 +129,31 @@ describe('smartThingsCommand', () => { }, loggerMock) expect(defaultTableGeneratorMock).toHaveBeenCalledTimes(1) expect(defaultTableGeneratorMock).toHaveBeenCalledWith({ groupRows: true }) + expect(consoleWarnSpy).not.toHaveBeenCalled() + }) + + it('warns when a non-default profile is missing', async () => { + yellowMock.mockReturnValueOnce('yellow warning') + + await smartThingsCommand({ profile: 'other' }) + + expect(yellowMock).toHaveBeenCalledExactlyOnceWith( + 'warning: profile other not found in configuration\n' + + 'To use a profile with no configuration options, add "other: {}" to config.yaml.\n' + + 'See https://github.com/SmartThingsCommunity/smartthings-cli/blob/main/doc/configuration.md#profiles' + + ' for more information.', + ) + expect(consoleWarnSpy).toHaveBeenCalledExactlyOnceWith('yellow warning') + }) + + it('does not warn when a non-default profile exists but is empty', async () => { + loadConfigMock.mockResolvedValueOnce({ + ...cliConfig, + mergedProfiles: { other: {} }, + } as unknown as CLIConfig) + + await smartThingsCommand({ profile: 'other' }) + + expect(consoleWarnSpy).not.toHaveBeenCalled() }) }) diff --git a/src/lib/cli-config.ts b/src/lib/cli-config.ts index c1378f1ec..fe5d142a4 100644 --- a/src/lib/cli-config.ts +++ b/src/lib/cli-config.ts @@ -8,7 +8,7 @@ import { fatalError } from './util.js' export const seeConfigDocs = 'see https://github.com/SmartThingsCommunity/smartthings-cli/blob/' + - 'main/packages/cli/doc/configuration.md for more information' + 'main/doc/configuration.md for more information' export type Profile = Record export type ProfilesByName = Record diff --git a/src/lib/command/smartthings-command.ts b/src/lib/command/smartthings-command.ts index 43f754506..9ae70a0cf 100644 --- a/src/lib/command/smartthings-command.ts +++ b/src/lib/command/smartthings-command.ts @@ -3,6 +3,7 @@ import log4js from 'log4js' import { type Argv } from 'yargs' import { type CLIConfig, loadConfig, type Profile } from '../cli-config.js' +import { yellow } from '../colors.js' import { ensureDir } from '../file-util.js' import { buildDefaultLog4jsConfig, loadLog4jsConfig } from '../log-utils.js' import { defaultTableGenerator, type TableGenerator } from '../table-generator.js' @@ -136,6 +137,9 @@ export const getConfigDirsCheckingForOldConfig = async ( return { configDir, dataDir, logDir } } +const profileDocsURL = + 'https://github.com/SmartThingsCommunity/smartthings-cli/blob/main/doc/configuration.md#profiles' + /** * A function to be called at the start of every CLI command that sets up shared things. */ @@ -162,6 +166,11 @@ export const smartThingsCommand = async ( }, logger) const profile = cliConfig.profile + if (profileName !== 'default' && !(profileName in cliConfig.mergedProfiles)) { + console.warn(yellow(`warning: profile ${profileName} not found in configuration\n` + + `To use a profile with no configuration options, add "${profileName}: {}" to config.yaml.\n` + + `See ${profileDocsURL} for more information.`)) + } const groupRowsFlag = (flags as Pick).groupRows const groupRows = groupRowsFlag ?? cliConfig.booleanConfigValue('groupTableOutputRows', true) diff --git a/src/lib/log-utils.ts b/src/lib/log-utils.ts index 3fc7d560e..996597e74 100644 --- a/src/lib/log-utils.ts +++ b/src/lib/log-utils.ts @@ -11,7 +11,7 @@ import { fatalError } from './util.js' const defaultLogFileSize = 1_000_000 // bytes const loggingDocsURL = 'https://github.com/SmartThingsCommunity/smartthings-cli/' + - 'blob/main/packages/cli/doc/configuration.md#logging' + 'blob/main/doc/configuration.md#logging' export function buildDefaultLog4jsConfig(logFilename: string): Log4jsConfig {