From 49b609175aee3ca748a852ba9d301d898247b9e7 Mon Sep 17 00:00:00 2001 From: taub Date: Tue, 13 Jan 2026 11:08:20 -0500 Subject: [PATCH 1/3] add config-validation flag and check for it every time getFullConfig is called --- src/BaseCommand.js | 52 +++++++++++-------- src/commands/app/add/action.js | 6 +-- src/commands/app/add/event.js | 8 +-- src/commands/app/add/extension.js | 6 +-- src/commands/app/add/web-assets.js | 4 +- src/commands/app/config/get/log-forwarding.js | 7 +-- .../app/config/get/log-forwarding/errors.js | 9 ++-- src/commands/app/config/set/log-forwarding.js | 7 +-- src/commands/app/delete/action.js | 24 ++++----- src/commands/app/delete/extension.js | 14 ++--- src/commands/app/delete/web-assets.js | 6 +-- src/commands/app/deploy.js | 10 ++-- src/commands/app/get-url.js | 12 ++--- src/commands/app/info.js | 6 +-- src/commands/app/logs.js | 6 +-- src/commands/app/pack.js | 26 +++++----- src/commands/app/test.js | 16 +++--- src/commands/app/undeploy.js | 8 +-- 18 files changed, 118 insertions(+), 109 deletions(-) diff --git a/src/BaseCommand.js b/src/BaseCommand.js index 83c1e5b6d..839534269 100644 --- a/src/BaseCommand.js +++ b/src/BaseCommand.js @@ -32,13 +32,13 @@ const { class BaseCommand extends Command { // default error handler for app commands - async catch (error) { + async catch(error) { const { flags } = await this.parse(this.prototype) aioLogger.error(error) // debug log this.error(flags.verbose && error.stack ? error.stack : error.message) } - async init () { + async init() { await super.init() // setup a prompt that outputs to stderr this.prompt = inquirer.createPromptModule({ output: process.stderr }) @@ -51,7 +51,7 @@ class BaseCommand extends Command { `aio-cli-plugin-app/${vs?.cliVersion} (${vs?.architecture}; ${vs?.nodeVersion}; ${vs?.shell})` } - async getLibConsoleCLI () { + async getLibConsoleCLI() { if (!this.consoleCLI) { // requires valid login const { accessToken, env } = await getAccessToken() @@ -61,12 +61,12 @@ class BaseCommand extends Command { return this.consoleCLI } - async cleanConsoleCLIOutput () { + async cleanConsoleCLIOutput() { LibConsoleCLI.cleanStdOut() } - async getAppExtConfigs (flags, options = {}) { - const all = (await this.getFullConfig(options)).all + async getAppExtConfigs(flags, options = {}) { + const all = (await this.getFullConfig(options, flags)).all // default case: no flags, return all let ret = all @@ -96,41 +96,41 @@ class BaseCommand extends Command { return ret } - async getRuntimeManifestConfigFile (implName) { + async getRuntimeManifestConfigFile(implName, flags) { let configKey if (implName === APPLICATION_CONFIG_KEY) { configKey = APPLICATION_CONFIG_KEY } else { configKey = `${EXTENSIONS_CONFIG_KEY}.${implName}` } - let configData = await this.getConfigFileForKey(`${configKey}.runtimeManifest`) + let configData = await this.getConfigFileForKey(`${configKey}.runtimeManifest`, flags) if (!configData.file) { // first action manifest is not defined - configData = await this.getConfigFileForKey(`${configKey}`) + configData = await this.getConfigFileForKey(`${configKey}`, flags) configData.key = configData.key + '.runtimeManifest' } return configData } - async getEventsConfigFile (implName) { + async getEventsConfigFile(implName, flags) { let configKey if (implName === APPLICATION_CONFIG_KEY) { configKey = APPLICATION_CONFIG_KEY } else { configKey = `${EXTENSIONS_CONFIG_KEY}.${implName}` } - let configData = await this.getConfigFileForKey(`${configKey}.events`) + let configData = await this.getConfigFileForKey(`${configKey}.events`, flags) if (!configData.file) { // first events manifest is not defined - configData = await this.getConfigFileForKey(`${configKey}`) + configData = await this.getConfigFileForKey(`${configKey}`, flags) configData.key = configData.key + '.events' } return configData } - async getConfigFileForKey (fullKey) { + async getConfigFileForKey(fullKey, flags = {}) { // NOTE: the index returns undefined if the key is loaded from a legacy configuration file - const fullConfig = await this.getFullConfig() + const fullConfig = await this.getFullConfig({}, flags) // full key like 'extensions.dx/excshell/1.runtimeManifest' // returns { key: relKey, file: configFile} const configData = fullConfig.includeIndex[fullKey] @@ -142,9 +142,10 @@ class BaseCommand extends Command { return configData || {} } - async getFullConfig (options = {}) { - // validate appConfig defaults to false for now - const validateAppConfig = options.validateAppConfig === true + async getFullConfig(options = {}, flags = {}) { + // validate appConfig defaults to true unless flag is explicitly set to off + const validateAppConfig = flags['config-validation'] !== false + aioLogger.debug(`validateAppConfig=${validateAppConfig}`) if (!this.appConfig) { // this will explicitly set validateAppConfig=false if not set @@ -153,7 +154,7 @@ class BaseCommand extends Command { return this.appConfig } - getLaunchUrlPrefix () { + getLaunchUrlPrefix() { // todo: it might make sense to have a value that defines if this is an ExC hosted app, or otherwise // so we can decide what type of url to return here. // at some point we could also just delete the .env value and return our expected url here. @@ -172,26 +173,31 @@ class BaseCommand extends Command { return (launchPrefix || defaultLaunchPrefix) } - get pjson () { + get pjson() { return this.config.pjson } - get appName () { + get appName() { return this.pjson.name } - get appVersion () { + get appVersion() { return this.pjson.version } - preRelease () { + preRelease() { this.log(chalk.yellow('Pre-release warning: This command is in pre-release, and not suitable for production.')) } } BaseCommand.flags = { verbose: Flags.boolean({ char: 'v', description: 'Verbose output' }), - version: Flags.boolean({ description: 'Show version' }) + version: Flags.boolean({ description: 'Show version' }), + 'config-validation': Flags.boolean({ + description: '[default: true] Validate the app configuration before deploying', + default: true, + allowNo: true + }) } BaseCommand.args = {} diff --git a/src/commands/app/add/action.js b/src/commands/app/add/action.js index 56f6c4afd..ed8a9da89 100644 --- a/src/commands/app/add/action.js +++ b/src/commands/app/add/action.js @@ -18,7 +18,7 @@ const TemplateRegistryAPI = require('@adobe/aio-lib-templates') const inquirer = require('inquirer') class AddActionCommand extends TemplatesCommand { - async run () { + async run() { const { flags } = await this.parse(AddActionCommand) aioLogger.debug(`add actions with flags: ${JSON.stringify(flags)}`) @@ -32,7 +32,7 @@ class AddActionCommand extends TemplatesCommand { const config = entries[0][1] const actionFolder = path.relative(config.root, config.actions.src) - const configData = await this.getRuntimeManifestConfigFile(configName) + const configData = await this.getRuntimeManifestConfigFile(configName, flags) const projectOrgId = aioConfigLoader.get('project.org.id') if (!projectOrgId) { @@ -63,7 +63,7 @@ class AddActionCommand extends TemplatesCommand { } } - async getSearchCriteria (orgSupportedServices) { + async getSearchCriteria(orgSupportedServices) { const choices = [ { name: 'All Action Templates', diff --git a/src/commands/app/add/event.js b/src/commands/app/add/event.js index 218e5545c..58c313f6e 100644 --- a/src/commands/app/add/event.js +++ b/src/commands/app/add/event.js @@ -17,7 +17,7 @@ const path = require('path') const TemplateRegistryAPI = require('@adobe/aio-lib-templates') class AddEventCommand extends TemplatesCommand { - async run () { + async run() { const { flags } = await this.parse(AddEventCommand) aioLogger.debug(`add events with flags: ${JSON.stringify(flags)}`) @@ -31,8 +31,8 @@ class AddEventCommand extends TemplatesCommand { const configName = entries[0][0] const config = entries[0][1] const actionFolder = path.relative(config.root, config.actions.src) - const runtimeManifestData = await this.getRuntimeManifestConfigFile(configName) - const eventsData = await this.getEventsConfigFile(configName) + const runtimeManifestData = await this.getRuntimeManifestConfigFile(configName, flags) + const eventsData = await this.getEventsConfigFile(configName, flags) const templateOptions = { 'skip-prompt': false, 'action-folder': actionFolder, @@ -56,7 +56,7 @@ class AddEventCommand extends TemplatesCommand { } } - async getSearchCriteria () { + async getSearchCriteria() { const TEMPLATE_CATEGORIES = ['events', 'helper-template'] const searchCriteria = { [TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED, diff --git a/src/commands/app/add/extension.js b/src/commands/app/add/extension.js index a7e7aea3b..f61e959df 100644 --- a/src/commands/app/add/extension.js +++ b/src/commands/app/add/extension.js @@ -15,7 +15,7 @@ const { Flags } = require('@oclif/core') const TemplateRegistryAPI = require('@adobe/aio-lib-templates') class AddExtensionCommand extends TemplatesCommand { - async run () { + async run() { const { flags } = await this.parse(AddExtensionCommand) aioLogger.debug(`add extensions with flags: ${JSON.stringify(flags)}`) @@ -24,7 +24,7 @@ class AddExtensionCommand extends TemplatesCommand { this.error('--extension= must also be provided when using --yes') } - const fullConfig = await this.getFullConfig({ allowNoImpl: true }) + const fullConfig = await this.getFullConfig({ allowNoImpl: true }, flags) const alreadyImplemented = fullConfig.implements if (flags.extension) { @@ -34,7 +34,7 @@ class AddExtensionCommand extends TemplatesCommand { } } - async selectExtensionsToInstall (alreadyImplemented, useDefaultValues, installNpm) { + async selectExtensionsToInstall(alreadyImplemented, useDefaultValues, installNpm) { const excludeExtensions = alreadyImplemented.map(e => `${TemplateRegistryAPI.SEARCH_CRITERIA_FILTER_NOT}${e}`) const orderByCriteria = { diff --git a/src/commands/app/add/web-assets.js b/src/commands/app/add/web-assets.js index 00d619b62..24d689f4d 100644 --- a/src/commands/app/add/web-assets.js +++ b/src/commands/app/add/web-assets.js @@ -15,11 +15,11 @@ const { Flags } = require('@oclif/core') const TemplateRegistryAPI = require('@adobe/aio-lib-templates') class AddWebAssetsCommand extends TemplatesCommand { - async run () { + async run() { const { flags } = await this.parse(AddWebAssetsCommand) aioLogger.debug(`add web-assets with flags: ${JSON.stringify(flags)}`) - const projectName = (await this.getFullConfig()).packagejson.name + const projectName = (await this.getFullConfig({}, flags)).packagejson.name // guaranteed to have at least one, otherwise would throw in config load or in matching the ext name const entries = Object.entries(await this.getAppExtConfigs(flags)) if (entries.length > 1) { diff --git a/src/commands/app/config/get/log-forwarding.js b/src/commands/app/config/get/log-forwarding.js index 7962e4589..e5a677edf 100644 --- a/src/commands/app/config/get/log-forwarding.js +++ b/src/commands/app/config/get/log-forwarding.js @@ -14,8 +14,9 @@ const LogForwarding = require('../../../../lib/log-forwarding') const { setRuntimeApiHostAndAuthHandler } = require('../../../../lib/auth-helper') class LogForwardingCommand extends BaseCommand { - async run () { - let aioConfig = (await this.getFullConfig()).aio + async run() { + const { flags } = await this.parse(LogForwardingCommand) + let aioConfig = (await this.getFullConfig({}, flags)).aio aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig) const lf = await LogForwarding.init(aioConfig) @@ -37,7 +38,7 @@ class LogForwardingCommand extends BaseCommand { this.printConfig(serverConfig) } - printConfig (config) { + printConfig(config) { if (config.isDefined()) { this.log(`destination: ${config.getDestination()}`) this.log('settings:', config.getSettings()) diff --git a/src/commands/app/config/get/log-forwarding/errors.js b/src/commands/app/config/get/log-forwarding/errors.js index f35ab16df..794a87d1e 100644 --- a/src/commands/app/config/get/log-forwarding/errors.js +++ b/src/commands/app/config/get/log-forwarding/errors.js @@ -15,9 +15,10 @@ const ora = require('ora') const { setRuntimeApiHostAndAuthHandler } = require('../../../../../lib/auth-helper') class ErrorsCommand extends BaseCommand { - async run () { + async run() { + const { flags } = await this.parse(ErrorsCommand) const spinner = ora() - const lf = await this.getLogForwarding() + const lf = await this.getLogForwarding(flags) spinner.start('Checking for errors...') const res = await lf.getErrors() const destinationMessage = res.configured_forwarder !== undefined @@ -30,8 +31,8 @@ class ErrorsCommand extends BaseCommand { } } - async getLogForwarding () { - let aioConfig = (await this.getFullConfig()).aio + async getLogForwarding(flags) { + let aioConfig = (await this.getFullConfig({}, flags)).aio aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig) const runtimeConfig = aioConfig.runtime diff --git a/src/commands/app/config/set/log-forwarding.js b/src/commands/app/config/set/log-forwarding.js index b64de2210..58cbcb39e 100644 --- a/src/commands/app/config/set/log-forwarding.js +++ b/src/commands/app/config/set/log-forwarding.js @@ -15,8 +15,9 @@ const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin- const { setRuntimeApiHostAndAuthHandler } = require('../../../../lib/auth-helper') class LogForwardingCommand extends BaseCommand { - async run () { - let aioConfig = (await this.getFullConfig()).aio + async run() { + const { flags } = await this.parse(LogForwardingCommand) + let aioConfig = (await this.getFullConfig({}, flags)).aio aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig) const lf = await LogForwarding.init(aioConfig) @@ -37,7 +38,7 @@ class LogForwardingCommand extends BaseCommand { }) } - async promptDestination (supportedDestinations) { + async promptDestination(supportedDestinations) { const responses = await this.prompt([{ name: 'type', message: 'select log forwarding destination', diff --git a/src/commands/app/delete/action.js b/src/commands/app/delete/action.js index 585f8684d..23db72a60 100644 --- a/src/commands/app/delete/action.js +++ b/src/commands/app/delete/action.js @@ -20,7 +20,7 @@ const { EOL } = require('os') const { atLeastOne, deleteUserConfig } = require('../../../lib/app-helper') class DeleteActionCommand extends BaseCommand { - async run () { + async run() { const { args, flags } = await this.parse(DeleteActionCommand) aioLogger.debug(`deleting actions from the project, with args ${JSON.stringify(args)}, and flags: ${JSON.stringify(flags)}`) @@ -30,8 +30,8 @@ class DeleteActionCommand extends BaseCommand { this.error(' must also be provided when using --yes') } - const fullConfig = await this.getFullConfig() - const { actions, actionsByImpl } = await this.getAllActions(fullConfig) + const fullConfig = await this.getFullConfig({}, flags) + const { actions, actionsByImpl } = await this.getAllActions(fullConfig, flags) if (actions.length <= 0) { this.error('There are no actions in this project!') } @@ -108,7 +108,7 @@ class DeleteActionCommand extends BaseCommand { ))) } - async getAllActions (config) { + async getAllActions(config, flags = {}) { const actions = [] const actionsByImpl = {} const allConfigEntries = Object.entries(config.all) @@ -121,7 +121,7 @@ class DeleteActionCommand extends BaseCommand { for (const [actionName, action] of actionEntries) { const fullActionName = `${pkgName}/${actionName}` const startKey = implName === 'application' ? 'application' : `extensions.${implName}` - const configData = await this.getConfigFileForKey(`${startKey}.runtimeManifest.packages.${pkgName}.actions.${actionName}`) + const configData = await this.getConfigFileForKey(`${startKey}.runtimeManifest.packages.${pkgName}.actions.${actionName}`, flags) const actionObj = { // assumes path is not relative path: action.function, @@ -157,13 +157,13 @@ DeleteActionCommand.flags = { } DeleteActionCommand.args = - { - 'action-name': Args.string({ - description: 'Action `pkg/name` to delete, you can specify multiple actions via a comma separated list', - default: '', - required: false - }) - } +{ + 'action-name': Args.string({ + description: 'Action `pkg/name` to delete, you can specify multiple actions via a comma separated list', + default: '', + required: false + }) +} DeleteActionCommand.aliases = ['app:delete:actions'] diff --git a/src/commands/app/delete/extension.js b/src/commands/app/delete/extension.js index 221316b7c..43fb2fc5e 100644 --- a/src/commands/app/delete/extension.js +++ b/src/commands/app/delete/extension.js @@ -19,7 +19,7 @@ const fs = require('fs-extra') const { EOL } = require('os') class DeleteExtensionCommand extends BaseCommand { - async run () { + async run() { const { flags } = await this.parse(DeleteExtensionCommand) aioLogger.debug(`delete extension with flags: ${JSON.stringify(flags)}`) @@ -28,7 +28,7 @@ class DeleteExtensionCommand extends BaseCommand { this.error('--extension= must also be provided when using --yes') } - const fullConfig = await this.getFullConfig({ allowNoImpl: true }) + const fullConfig = await this.getFullConfig({ allowNoImpl: true }, flags) const configs = await this.selectOrGetConfigsToDelete(flags, fullConfig) const resConfirm = await this.prompt([ @@ -44,7 +44,7 @@ class DeleteExtensionCommand extends BaseCommand { this.error('aborting..') } - await this.deleteImplementations(configs) + await this.deleteImplementations(configs, flags) this.log(chalk.bold(chalk.green( `✔ Successfully deleted implementation(s) '${Object.keys(configs)}'` + EOL + @@ -52,7 +52,7 @@ class DeleteExtensionCommand extends BaseCommand { ))) } - async selectOrGetConfigsToDelete (flags, config) { + async selectOrGetConfigsToDelete(flags, config) { const alreadyImplemented = config.implements if (alreadyImplemented.length <= 0) { throw new Error('There are no implementations left in the project') @@ -71,7 +71,7 @@ class DeleteExtensionCommand extends BaseCommand { return await this.getAppExtConfigs(flags) } - async deleteImplementations (configs) { + async deleteImplementations(configs, flags) { for (const [id, c] of Object.entries(configs)) { // delete actions if (c.app.hasBackend) { @@ -89,12 +89,12 @@ class DeleteExtensionCommand extends BaseCommand { // delete config // try to find another config file => case of init extension in another folder const configKey = id === 'application' ? 'application' : `extensions.${id}` - const configDataOp = await this.getConfigFileForKey(configKey + '.operations') + const configDataOp = await this.getConfigFileForKey(configKey + '.operations', flags) if (configDataOp.file) { fs.removeSync(configDataOp.file) } // delete config in parent config file - const configData = await this.getConfigFileForKey(configKey) + const configData = await this.getConfigFileForKey(configKey, flags) deleteUserConfig(configData) } } diff --git a/src/commands/app/delete/web-assets.js b/src/commands/app/delete/web-assets.js index 4e72c3193..4b85c3065 100644 --- a/src/commands/app/delete/web-assets.js +++ b/src/commands/app/delete/web-assets.js @@ -20,12 +20,12 @@ const { EOL } = require('os') const path = require('path') class DeleteWebAssetsCommand extends BaseCommand { - async run () { + async run() { const { flags } = await this.parse(DeleteWebAssetsCommand) aioLogger.debug(`deleting web assets from the project, using flags: ${JSON.stringify(flags)}`) - const fullConfig = await this.getFullConfig() + const fullConfig = await this.getFullConfig({}, flags) const webAssetsByImpl = this.getAllWebAssets(fullConfig) if (!webAssetsByImpl) { this.error('web-assets not found') @@ -71,7 +71,7 @@ class DeleteWebAssetsCommand extends BaseCommand { } } - getAllWebAssets (config) { + getAllWebAssets(config) { let webAssetsByImpl = {} Object.entries(config.all).forEach(([implName, implConfig]) => { if (implConfig.app.hasFrontend) { diff --git a/src/commands/app/deploy.js b/src/commands/app/deploy.js index 03fa59bb2..2413dc065 100644 --- a/src/commands/app/deploy.js +++ b/src/commands/app/deploy.js @@ -33,7 +33,7 @@ const PRE_DEPLOY_EVENT_REG = 'pre-deploy-event-reg' const POST_DEPLOY_EVENT_REG = 'post-deploy-event-reg' class Deploy extends BuildCommand { - async run () { + async run() { // cli input const { flags } = await this.parse(Deploy) @@ -57,7 +57,7 @@ class Deploy extends BuildCommand { const spinner = ora() try { - const { aio: aioConfig, packagejson: packageJson } = await this.getFullConfig() + const { aio: aioConfig, packagejson: packageJson } = await this.getFullConfig({}, flags) const cliDetails = await getAccessToken({ useCachedToken: !flags.publish }) const appInfo = { name: packageJson.name, @@ -172,7 +172,7 @@ class Deploy extends BuildCommand { this.log(chalk.green(chalk.bold('Successful deployment 🏄'))) } - async deploySingleConfig ({ name, config, originalConfig, flags, spinner }) { + async deploySingleConfig({ name, config, originalConfig, flags, spinner }) { const onProgress = !flags.verbose ? info => { spinner.text = info @@ -300,7 +300,7 @@ class Deploy extends BuildCommand { } } - async publishExtensionPoints (deployConfigs, aioConfig, force) { + async publishExtensionPoints(deployConfigs, aioConfig, force) { const libConsoleCLI = await this.getLibConsoleCLI() const payload = buildExtensionPointPayloadWoMetadata(deployConfigs) @@ -320,7 +320,7 @@ class Deploy extends BuildCommand { return newPayload } - async getApplicationExtension (aioConfig) { + async getApplicationExtension(aioConfig) { const libConsoleCLI = await this.getLibConsoleCLI() const { appId } = await libConsoleCLI.getProject(aioConfig.project.org.id, aioConfig.project.id) diff --git a/src/commands/app/get-url.js b/src/commands/app/get-url.js index 0e304dade..6cdac31a6 100644 --- a/src/commands/app/get-url.js +++ b/src/commands/app/get-url.js @@ -20,7 +20,7 @@ const { getActionUrls } = require('@adobe/aio-lib-runtime').utils const yaml = require('js-yaml') class GetUrlCommand extends BaseCommand { - async run () { + async run() { // cli input const { args, flags } = await this.parse(GetUrlCommand) @@ -30,7 +30,7 @@ class GetUrlCommand extends BaseCommand { options.cdn = flags.cdn const urls = {} - const fullConfig = await this.getFullConfig() + const fullConfig = await this.getFullConfig({}, flags) if (options.action) { let action // search for action @@ -107,9 +107,9 @@ GetUrlCommand.flags = { } GetUrlCommand.args = - { - action: Args.string({ - }) - } +{ + action: Args.string({ + }) +} module.exports = GetUrlCommand diff --git a/src/commands/app/info.js b/src/commands/app/info.js index c63a2cf7a..ae764b4ee 100644 --- a/src/commands/app/info.js +++ b/src/commands/app/info.js @@ -16,10 +16,10 @@ const yaml = require('js-yaml') const deepCopy = require('lodash.clonedeep') class Info extends BaseCommand { - async run () { + async run() { // cli input const { flags } = await this.parse(Info) - const appConfig = deepCopy(await this.getFullConfig({ allowNoImpl: true })) + const appConfig = deepCopy(await this.getFullConfig({ allowNoImpl: true }, flags)) // includes .env secret delete all aio config for now delete appConfig.aio @@ -47,7 +47,7 @@ class Info extends BaseCommand { } /** @private */ -function mask (k) { +function mask(k) { return k ? '' : 'undefined' } diff --git a/src/commands/app/logs.js b/src/commands/app/logs.js index d0af82d6b..546df3b3c 100644 --- a/src/commands/app/logs.js +++ b/src/commands/app/logs.js @@ -19,7 +19,7 @@ const LogForwarding = require('../../lib/log-forwarding') const SECURED = 'require-adobe-auth' class Logs extends BaseCommand { - _processEachAction (fullConfig, processFn) { + _processEachAction(fullConfig, processFn) { const isSecuredAction = (pkg, aName) => pkg && pkg.actions && pkg.actions[aName] && pkg.actions[aName].annotations && pkg.actions[aName].annotations[SECURED] @@ -34,9 +34,9 @@ class Logs extends BaseCommand { }) } - async run () { + async run() { const { flags } = await this.parse(Logs) - const fullConfig = await this.getFullConfig() + const fullConfig = await this.getFullConfig({}, flags) // has any backend const hasAnyBackend = Object.values(fullConfig.all).reduce((hasBackend, config) => hasBackend && config.app.hasBackend, true) diff --git a/src/commands/app/pack.js b/src/commands/app/pack.js index 89e46e905..e3130d820 100644 --- a/src/commands/app/pack.js +++ b/src/commands/app/pack.js @@ -33,7 +33,7 @@ const DEFAULTS = { } class Pack extends BaseCommand { - async run () { + async run() { const { args, flags } = await this.parse(Pack) aioLogger.debug(`flags: ${JSON.stringify(flags, null, 2)}`) @@ -120,7 +120,7 @@ class Pack extends BaseCommand { this.spinner.succeed('Packaging done.') } - get spinner () { + get spinner() { if (!this._spinner) { this._spinner = ora() } @@ -132,7 +132,7 @@ class Pack extends BaseCommand { * * @param {object} appConfig the app's configuration file */ - async createDeployYamlFile (appConfig) { + async createDeployYamlFile(appConfig) { // get extensions let extensions if (appConfig.implements?.filter(item => item !== 'application').length > 0) { @@ -216,7 +216,7 @@ class Pack extends BaseCommand { * @param {string} destinationFolder the destination folder for the files * @param {Array} filesList a list of files to copy */ - async copyPackageFiles (destinationFolder, filesList) { + async copyPackageFiles(destinationFolder, filesList) { for (const src of filesList) { const dest = path.join(destinationFolder, src) if (await fs.pathExists(src)) { @@ -236,7 +236,7 @@ class Pack extends BaseCommand { * @param {boolean} pathInZip internal path in zip * @returns {Promise} returns with a blank promise when done */ - zipHelper (filePath, out, pathInZip = false) { + zipHelper(filePath, out, pathInZip = false) { aioLogger.debug(`Creating zip of file/folder '${filePath}'`) const stream = fs.createWriteStream(out) const archive = archiver('zip', { zlib: { level: 9 } }) @@ -274,7 +274,7 @@ class Pack extends BaseCommand { * @param {string} options.workingDirectory the working directory to run `npm pack` in * @returns {Array} a list of files that are to be packed */ - async filesToPack ({ filesToExclude = [], filesToInclude = [], workingDirectory = process.cwd() } = {}) { + async filesToPack({ filesToExclude = [], filesToInclude = [], workingDirectory = process.cwd() } = {}) { const { stdout } = await execa('npm', ['pack', '--dry-run', '--json'], { cwd: workingDirectory }) const noJunkFiles = (file) => { @@ -313,7 +313,7 @@ class Pack extends BaseCommand { * * @param {object} appConfig the app's configuration file */ - async addCodeDownloadAnnotation (appConfig) { + async addCodeDownloadAnnotation(appConfig) { // get each annotation key relative to the file it is defined in /// iterate only over extensions that have actions defined const fileToAnnotationKey = {} @@ -383,11 +383,11 @@ Pack.flags = { } Pack.args = - { - path: Args.string({ - description: 'Path to the app directory to package', - default: '.' - }) - } +{ + path: Args.string({ + description: 'Path to the app directory to package', + default: '.' + }) +} module.exports = Pack diff --git a/src/commands/app/test.js b/src/commands/app/test.js index a02e6c5e1..94b4e1d6f 100644 --- a/src/commands/app/test.js +++ b/src/commands/app/test.js @@ -18,7 +18,7 @@ const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin- const path = require('path') class Test extends BaseCommand { - async run () { + async run() { const { flags } = await this.parse(Test) let { all, unit, e2e, action, extension } = flags @@ -31,7 +31,7 @@ class Test extends BaseCommand { unit = true } - const buildConfigs = await this.getAppExtConfigs({ extension }) + const buildConfigs = await this.getAppExtConfigs(flags, { extension }) aioLogger.debug(`run buildConfigs:${JSON.stringify(buildConfigs, null, 2)}`) const totalResults = [] @@ -51,7 +51,7 @@ class Test extends BaseCommand { return exitCode } - printReport (totalResults) { + printReport(totalResults) { if (totalResults.length > 0) { const greenCheckMark = chalk.green('√') const redX = chalk.red('×') @@ -66,7 +66,7 @@ class Test extends BaseCommand { } } - normalizedActionList (extensionConfig) { + normalizedActionList(extensionConfig) { const actionList = [] const packages = extensionConfig.manifest.full.packages for (const [packageName, pkg] of Object.entries(packages)) { @@ -79,21 +79,21 @@ class Test extends BaseCommand { return actionList } - escapeBackslashes (pathString) { + escapeBackslashes(pathString) { // for Jest: // - replace backslashes with forward slashes, // - OR on Windows you need to escape forward slashes return pathString.replace(/\\/g, '/') } - testFolders (extensionConfig) { + testFolders(extensionConfig) { return { // add leading period path for jest unit: './' + this.escapeBackslashes(path.relative(extensionConfig.root, extensionConfig.tests.unit)), e2e: './' + this.escapeBackslashes(path.relative(extensionConfig.root, extensionConfig.tests.e2e)) } } - filterActions (actionFilters, extensionConfig, flags) { + filterActions(actionFilters, extensionConfig, flags) { const { unit, e2e } = flags const commandList = [] const { unit: unitTestFolder, e2e: e2eTestFolder } = this.testFolders(extensionConfig) @@ -140,7 +140,7 @@ class Test extends BaseCommand { return commandList } - async runExtensionTest (extensionName, extensionConfig, flags) { + async runExtensionTest(extensionName, extensionConfig, flags) { const { unit, e2e, action } = flags const commandList = [] const { unit: unitTestFolder, e2e: e2eTestFolder } = this.testFolders(extensionConfig) diff --git a/src/commands/app/undeploy.js b/src/commands/app/undeploy.js index d1609b785..df321c867 100644 --- a/src/commands/app/undeploy.js +++ b/src/commands/app/undeploy.js @@ -23,7 +23,7 @@ const { sendAppAssetsUndeployedAuditLog, sendAppUndeployAuditLog } = require('.. const { setRuntimeApiHostAndAuthHandler, getAccessToken } = require('../../lib/auth-helper') class Undeploy extends BaseCommand { - async run () { + async run() { // cli input const { flags } = await this.parse(Undeploy) @@ -51,7 +51,7 @@ class Undeploy extends BaseCommand { const spinner = ora() try { - const { aio: aioConfig, packagejson: packageJson } = await this.getFullConfig() + const { aio: aioConfig, packagejson: packageJson } = await this.getFullConfig({}, flags) const cliDetails = await getAccessToken({ useCachedToken: !flags.unpublish }) const appInfo = { name: packageJson.name, @@ -121,7 +121,7 @@ class Undeploy extends BaseCommand { this.log(chalk.green(chalk.bold('Undeploy done!'))) } - async undeployOneExt (extName, config, flags, spinner) { + async undeployOneExt(extName, config, flags, spinner) { const onProgress = !flags.verbose ? info => { spinner.text = info @@ -183,7 +183,7 @@ class Undeploy extends BaseCommand { } } - async unpublishExtensionPoints (libConsoleCLI, deployConfigs, aioConfig, force) { + async unpublishExtensionPoints(libConsoleCLI, deployConfigs, aioConfig, force) { const payload = buildExtensionPointPayloadWoMetadata(deployConfigs) let res if (force) { From 722a81141800bb298be1a2733c4424fb5caf3b51 Mon Sep 17 00:00:00 2001 From: taub Date: Tue, 13 Jan 2026 13:51:15 -0500 Subject: [PATCH 2/3] add unit tests for config-validate and fix formatting --- src/BaseCommand.js | 29 +++++++++---------- src/commands/app/add/action.js | 4 +-- src/commands/app/add/event.js | 4 +-- src/commands/app/add/extension.js | 4 +-- src/commands/app/add/web-assets.js | 2 +- src/commands/app/config/get/log-forwarding.js | 4 +-- .../app/config/get/log-forwarding/errors.js | 4 +-- src/commands/app/config/set/log-forwarding.js | 4 +-- src/commands/app/delete/action.js | 4 +-- src/commands/app/delete/extension.js | 6 ++-- src/commands/app/delete/web-assets.js | 4 +-- src/commands/app/deploy.js | 8 ++--- src/commands/app/get-url.js | 2 +- src/commands/app/info.js | 4 +-- src/commands/app/logs.js | 4 +-- src/commands/app/pack.js | 14 ++++----- src/commands/app/test.js | 14 ++++----- src/commands/app/undeploy.js | 6 ++-- test/BaseCommand.test.js | 28 +++++++++++++----- test/commands/app/add/event.test.js | 2 +- test/commands/app/deploy.test.js | 2 ++ test/commands/app/info.test.js | 8 ++--- test/commands/app/undeploy.test.js | 1 + 23 files changed, 89 insertions(+), 73 deletions(-) diff --git a/src/BaseCommand.js b/src/BaseCommand.js index 839534269..50c29d91c 100644 --- a/src/BaseCommand.js +++ b/src/BaseCommand.js @@ -32,13 +32,13 @@ const { class BaseCommand extends Command { // default error handler for app commands - async catch(error) { + async catch (error) { const { flags } = await this.parse(this.prototype) aioLogger.error(error) // debug log this.error(flags.verbose && error.stack ? error.stack : error.message) } - async init() { + async init () { await super.init() // setup a prompt that outputs to stderr this.prompt = inquirer.createPromptModule({ output: process.stderr }) @@ -51,7 +51,7 @@ class BaseCommand extends Command { `aio-cli-plugin-app/${vs?.cliVersion} (${vs?.architecture}; ${vs?.nodeVersion}; ${vs?.shell})` } - async getLibConsoleCLI() { + async getLibConsoleCLI () { if (!this.consoleCLI) { // requires valid login const { accessToken, env } = await getAccessToken() @@ -61,11 +61,11 @@ class BaseCommand extends Command { return this.consoleCLI } - async cleanConsoleCLIOutput() { + async cleanConsoleCLIOutput () { LibConsoleCLI.cleanStdOut() } - async getAppExtConfigs(flags, options = {}) { + async getAppExtConfigs (flags, options = {}) { const all = (await this.getFullConfig(options, flags)).all // default case: no flags, return all @@ -96,7 +96,7 @@ class BaseCommand extends Command { return ret } - async getRuntimeManifestConfigFile(implName, flags) { + async getRuntimeManifestConfigFile (implName, flags) { let configKey if (implName === APPLICATION_CONFIG_KEY) { configKey = APPLICATION_CONFIG_KEY @@ -112,7 +112,7 @@ class BaseCommand extends Command { return configData } - async getEventsConfigFile(implName, flags) { + async getEventsConfigFile (implName, flags) { let configKey if (implName === APPLICATION_CONFIG_KEY) { configKey = APPLICATION_CONFIG_KEY @@ -128,7 +128,7 @@ class BaseCommand extends Command { return configData } - async getConfigFileForKey(fullKey, flags = {}) { + async getConfigFileForKey (fullKey, flags = {}) { // NOTE: the index returns undefined if the key is loaded from a legacy configuration file const fullConfig = await this.getFullConfig({}, flags) // full key like 'extensions.dx/excshell/1.runtimeManifest' @@ -142,19 +142,18 @@ class BaseCommand extends Command { return configData || {} } - async getFullConfig(options = {}, flags = {}) { + async getFullConfig (options = {}, flags = {}) { // validate appConfig defaults to true unless flag is explicitly set to off const validateAppConfig = flags['config-validation'] !== false aioLogger.debug(`validateAppConfig=${validateAppConfig}`) if (!this.appConfig) { - // this will explicitly set validateAppConfig=false if not set this.appConfig = await appConfig.load({ ...options, validateAppConfig }) } return this.appConfig } - getLaunchUrlPrefix() { + getLaunchUrlPrefix () { // todo: it might make sense to have a value that defines if this is an ExC hosted app, or otherwise // so we can decide what type of url to return here. // at some point we could also just delete the .env value and return our expected url here. @@ -173,19 +172,19 @@ class BaseCommand extends Command { return (launchPrefix || defaultLaunchPrefix) } - get pjson() { + get pjson () { return this.config.pjson } - get appName() { + get appName () { return this.pjson.name } - get appVersion() { + get appVersion () { return this.pjson.version } - preRelease() { + preRelease () { this.log(chalk.yellow('Pre-release warning: This command is in pre-release, and not suitable for production.')) } } diff --git a/src/commands/app/add/action.js b/src/commands/app/add/action.js index ed8a9da89..f7f034f42 100644 --- a/src/commands/app/add/action.js +++ b/src/commands/app/add/action.js @@ -18,7 +18,7 @@ const TemplateRegistryAPI = require('@adobe/aio-lib-templates') const inquirer = require('inquirer') class AddActionCommand extends TemplatesCommand { - async run() { + async run () { const { flags } = await this.parse(AddActionCommand) aioLogger.debug(`add actions with flags: ${JSON.stringify(flags)}`) @@ -63,7 +63,7 @@ class AddActionCommand extends TemplatesCommand { } } - async getSearchCriteria(orgSupportedServices) { + async getSearchCriteria (orgSupportedServices) { const choices = [ { name: 'All Action Templates', diff --git a/src/commands/app/add/event.js b/src/commands/app/add/event.js index 58c313f6e..a6f796329 100644 --- a/src/commands/app/add/event.js +++ b/src/commands/app/add/event.js @@ -17,7 +17,7 @@ const path = require('path') const TemplateRegistryAPI = require('@adobe/aio-lib-templates') class AddEventCommand extends TemplatesCommand { - async run() { + async run () { const { flags } = await this.parse(AddEventCommand) aioLogger.debug(`add events with flags: ${JSON.stringify(flags)}`) @@ -56,7 +56,7 @@ class AddEventCommand extends TemplatesCommand { } } - async getSearchCriteria() { + async getSearchCriteria () { const TEMPLATE_CATEGORIES = ['events', 'helper-template'] const searchCriteria = { [TemplateRegistryAPI.SEARCH_CRITERIA_STATUSES]: TemplateRegistryAPI.TEMPLATE_STATUS_APPROVED, diff --git a/src/commands/app/add/extension.js b/src/commands/app/add/extension.js index f61e959df..7f0ec266f 100644 --- a/src/commands/app/add/extension.js +++ b/src/commands/app/add/extension.js @@ -15,7 +15,7 @@ const { Flags } = require('@oclif/core') const TemplateRegistryAPI = require('@adobe/aio-lib-templates') class AddExtensionCommand extends TemplatesCommand { - async run() { + async run () { const { flags } = await this.parse(AddExtensionCommand) aioLogger.debug(`add extensions with flags: ${JSON.stringify(flags)}`) @@ -34,7 +34,7 @@ class AddExtensionCommand extends TemplatesCommand { } } - async selectExtensionsToInstall(alreadyImplemented, useDefaultValues, installNpm) { + async selectExtensionsToInstall (alreadyImplemented, useDefaultValues, installNpm) { const excludeExtensions = alreadyImplemented.map(e => `${TemplateRegistryAPI.SEARCH_CRITERIA_FILTER_NOT}${e}`) const orderByCriteria = { diff --git a/src/commands/app/add/web-assets.js b/src/commands/app/add/web-assets.js index 24d689f4d..e25cc8819 100644 --- a/src/commands/app/add/web-assets.js +++ b/src/commands/app/add/web-assets.js @@ -15,7 +15,7 @@ const { Flags } = require('@oclif/core') const TemplateRegistryAPI = require('@adobe/aio-lib-templates') class AddWebAssetsCommand extends TemplatesCommand { - async run() { + async run () { const { flags } = await this.parse(AddWebAssetsCommand) aioLogger.debug(`add web-assets with flags: ${JSON.stringify(flags)}`) diff --git a/src/commands/app/config/get/log-forwarding.js b/src/commands/app/config/get/log-forwarding.js index e5a677edf..9cf1effda 100644 --- a/src/commands/app/config/get/log-forwarding.js +++ b/src/commands/app/config/get/log-forwarding.js @@ -14,7 +14,7 @@ const LogForwarding = require('../../../../lib/log-forwarding') const { setRuntimeApiHostAndAuthHandler } = require('../../../../lib/auth-helper') class LogForwardingCommand extends BaseCommand { - async run() { + async run () { const { flags } = await this.parse(LogForwardingCommand) let aioConfig = (await this.getFullConfig({}, flags)).aio aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig) @@ -38,7 +38,7 @@ class LogForwardingCommand extends BaseCommand { this.printConfig(serverConfig) } - printConfig(config) { + printConfig (config) { if (config.isDefined()) { this.log(`destination: ${config.getDestination()}`) this.log('settings:', config.getSettings()) diff --git a/src/commands/app/config/get/log-forwarding/errors.js b/src/commands/app/config/get/log-forwarding/errors.js index 794a87d1e..2ba0fcf01 100644 --- a/src/commands/app/config/get/log-forwarding/errors.js +++ b/src/commands/app/config/get/log-forwarding/errors.js @@ -15,7 +15,7 @@ const ora = require('ora') const { setRuntimeApiHostAndAuthHandler } = require('../../../../../lib/auth-helper') class ErrorsCommand extends BaseCommand { - async run() { + async run () { const { flags } = await this.parse(ErrorsCommand) const spinner = ora() const lf = await this.getLogForwarding(flags) @@ -31,7 +31,7 @@ class ErrorsCommand extends BaseCommand { } } - async getLogForwarding(flags) { + async getLogForwarding (flags) { let aioConfig = (await this.getFullConfig({}, flags)).aio aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig) diff --git a/src/commands/app/config/set/log-forwarding.js b/src/commands/app/config/set/log-forwarding.js index 58cbcb39e..d7937c9d4 100644 --- a/src/commands/app/config/set/log-forwarding.js +++ b/src/commands/app/config/set/log-forwarding.js @@ -15,7 +15,7 @@ const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin- const { setRuntimeApiHostAndAuthHandler } = require('../../../../lib/auth-helper') class LogForwardingCommand extends BaseCommand { - async run() { + async run () { const { flags } = await this.parse(LogForwardingCommand) let aioConfig = (await this.getFullConfig({}, flags)).aio aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig) @@ -38,7 +38,7 @@ class LogForwardingCommand extends BaseCommand { }) } - async promptDestination(supportedDestinations) { + async promptDestination (supportedDestinations) { const responses = await this.prompt([{ name: 'type', message: 'select log forwarding destination', diff --git a/src/commands/app/delete/action.js b/src/commands/app/delete/action.js index 23db72a60..d04dc5afd 100644 --- a/src/commands/app/delete/action.js +++ b/src/commands/app/delete/action.js @@ -20,7 +20,7 @@ const { EOL } = require('os') const { atLeastOne, deleteUserConfig } = require('../../../lib/app-helper') class DeleteActionCommand extends BaseCommand { - async run() { + async run () { const { args, flags } = await this.parse(DeleteActionCommand) aioLogger.debug(`deleting actions from the project, with args ${JSON.stringify(args)}, and flags: ${JSON.stringify(flags)}`) @@ -108,7 +108,7 @@ class DeleteActionCommand extends BaseCommand { ))) } - async getAllActions(config, flags = {}) { + async getAllActions (config, flags = {}) { const actions = [] const actionsByImpl = {} const allConfigEntries = Object.entries(config.all) diff --git a/src/commands/app/delete/extension.js b/src/commands/app/delete/extension.js index 43fb2fc5e..9dfee888d 100644 --- a/src/commands/app/delete/extension.js +++ b/src/commands/app/delete/extension.js @@ -19,7 +19,7 @@ const fs = require('fs-extra') const { EOL } = require('os') class DeleteExtensionCommand extends BaseCommand { - async run() { + async run () { const { flags } = await this.parse(DeleteExtensionCommand) aioLogger.debug(`delete extension with flags: ${JSON.stringify(flags)}`) @@ -52,7 +52,7 @@ class DeleteExtensionCommand extends BaseCommand { ))) } - async selectOrGetConfigsToDelete(flags, config) { + async selectOrGetConfigsToDelete (flags, config) { const alreadyImplemented = config.implements if (alreadyImplemented.length <= 0) { throw new Error('There are no implementations left in the project') @@ -71,7 +71,7 @@ class DeleteExtensionCommand extends BaseCommand { return await this.getAppExtConfigs(flags) } - async deleteImplementations(configs, flags) { + async deleteImplementations (configs, flags) { for (const [id, c] of Object.entries(configs)) { // delete actions if (c.app.hasBackend) { diff --git a/src/commands/app/delete/web-assets.js b/src/commands/app/delete/web-assets.js index 4b85c3065..ccd9a773b 100644 --- a/src/commands/app/delete/web-assets.js +++ b/src/commands/app/delete/web-assets.js @@ -20,7 +20,7 @@ const { EOL } = require('os') const path = require('path') class DeleteWebAssetsCommand extends BaseCommand { - async run() { + async run () { const { flags } = await this.parse(DeleteWebAssetsCommand) aioLogger.debug(`deleting web assets from the project, using flags: ${JSON.stringify(flags)}`) @@ -71,7 +71,7 @@ class DeleteWebAssetsCommand extends BaseCommand { } } - getAllWebAssets(config) { + getAllWebAssets (config) { let webAssetsByImpl = {} Object.entries(config.all).forEach(([implName, implConfig]) => { if (implConfig.app.hasFrontend) { diff --git a/src/commands/app/deploy.js b/src/commands/app/deploy.js index 2413dc065..ecb4261ef 100644 --- a/src/commands/app/deploy.js +++ b/src/commands/app/deploy.js @@ -33,7 +33,7 @@ const PRE_DEPLOY_EVENT_REG = 'pre-deploy-event-reg' const POST_DEPLOY_EVENT_REG = 'post-deploy-event-reg' class Deploy extends BuildCommand { - async run() { + async run () { // cli input const { flags } = await this.parse(Deploy) @@ -172,7 +172,7 @@ class Deploy extends BuildCommand { this.log(chalk.green(chalk.bold('Successful deployment 🏄'))) } - async deploySingleConfig({ name, config, originalConfig, flags, spinner }) { + async deploySingleConfig ({ name, config, originalConfig, flags, spinner }) { const onProgress = !flags.verbose ? info => { spinner.text = info @@ -300,7 +300,7 @@ class Deploy extends BuildCommand { } } - async publishExtensionPoints(deployConfigs, aioConfig, force) { + async publishExtensionPoints (deployConfigs, aioConfig, force) { const libConsoleCLI = await this.getLibConsoleCLI() const payload = buildExtensionPointPayloadWoMetadata(deployConfigs) @@ -320,7 +320,7 @@ class Deploy extends BuildCommand { return newPayload } - async getApplicationExtension(aioConfig) { + async getApplicationExtension (aioConfig) { const libConsoleCLI = await this.getLibConsoleCLI() const { appId } = await libConsoleCLI.getProject(aioConfig.project.org.id, aioConfig.project.id) diff --git a/src/commands/app/get-url.js b/src/commands/app/get-url.js index 6cdac31a6..a58b39369 100644 --- a/src/commands/app/get-url.js +++ b/src/commands/app/get-url.js @@ -20,7 +20,7 @@ const { getActionUrls } = require('@adobe/aio-lib-runtime').utils const yaml = require('js-yaml') class GetUrlCommand extends BaseCommand { - async run() { + async run () { // cli input const { args, flags } = await this.parse(GetUrlCommand) diff --git a/src/commands/app/info.js b/src/commands/app/info.js index ae764b4ee..c9d9a68aa 100644 --- a/src/commands/app/info.js +++ b/src/commands/app/info.js @@ -16,7 +16,7 @@ const yaml = require('js-yaml') const deepCopy = require('lodash.clonedeep') class Info extends BaseCommand { - async run() { + async run () { // cli input const { flags } = await this.parse(Info) const appConfig = deepCopy(await this.getFullConfig({ allowNoImpl: true }, flags)) @@ -47,7 +47,7 @@ class Info extends BaseCommand { } /** @private */ -function mask(k) { +function mask (k) { return k ? '' : 'undefined' } diff --git a/src/commands/app/logs.js b/src/commands/app/logs.js index 546df3b3c..20a64edbe 100644 --- a/src/commands/app/logs.js +++ b/src/commands/app/logs.js @@ -19,7 +19,7 @@ const LogForwarding = require('../../lib/log-forwarding') const SECURED = 'require-adobe-auth' class Logs extends BaseCommand { - _processEachAction(fullConfig, processFn) { + _processEachAction (fullConfig, processFn) { const isSecuredAction = (pkg, aName) => pkg && pkg.actions && pkg.actions[aName] && pkg.actions[aName].annotations && pkg.actions[aName].annotations[SECURED] @@ -34,7 +34,7 @@ class Logs extends BaseCommand { }) } - async run() { + async run () { const { flags } = await this.parse(Logs) const fullConfig = await this.getFullConfig({}, flags) diff --git a/src/commands/app/pack.js b/src/commands/app/pack.js index e3130d820..e51789a3e 100644 --- a/src/commands/app/pack.js +++ b/src/commands/app/pack.js @@ -33,7 +33,7 @@ const DEFAULTS = { } class Pack extends BaseCommand { - async run() { + async run () { const { args, flags } = await this.parse(Pack) aioLogger.debug(`flags: ${JSON.stringify(flags, null, 2)}`) @@ -120,7 +120,7 @@ class Pack extends BaseCommand { this.spinner.succeed('Packaging done.') } - get spinner() { + get spinner () { if (!this._spinner) { this._spinner = ora() } @@ -132,7 +132,7 @@ class Pack extends BaseCommand { * * @param {object} appConfig the app's configuration file */ - async createDeployYamlFile(appConfig) { + async createDeployYamlFile (appConfig) { // get extensions let extensions if (appConfig.implements?.filter(item => item !== 'application').length > 0) { @@ -216,7 +216,7 @@ class Pack extends BaseCommand { * @param {string} destinationFolder the destination folder for the files * @param {Array} filesList a list of files to copy */ - async copyPackageFiles(destinationFolder, filesList) { + async copyPackageFiles (destinationFolder, filesList) { for (const src of filesList) { const dest = path.join(destinationFolder, src) if (await fs.pathExists(src)) { @@ -236,7 +236,7 @@ class Pack extends BaseCommand { * @param {boolean} pathInZip internal path in zip * @returns {Promise} returns with a blank promise when done */ - zipHelper(filePath, out, pathInZip = false) { + zipHelper (filePath, out, pathInZip = false) { aioLogger.debug(`Creating zip of file/folder '${filePath}'`) const stream = fs.createWriteStream(out) const archive = archiver('zip', { zlib: { level: 9 } }) @@ -274,7 +274,7 @@ class Pack extends BaseCommand { * @param {string} options.workingDirectory the working directory to run `npm pack` in * @returns {Array} a list of files that are to be packed */ - async filesToPack({ filesToExclude = [], filesToInclude = [], workingDirectory = process.cwd() } = {}) { + async filesToPack ({ filesToExclude = [], filesToInclude = [], workingDirectory = process.cwd() } = {}) { const { stdout } = await execa('npm', ['pack', '--dry-run', '--json'], { cwd: workingDirectory }) const noJunkFiles = (file) => { @@ -313,7 +313,7 @@ class Pack extends BaseCommand { * * @param {object} appConfig the app's configuration file */ - async addCodeDownloadAnnotation(appConfig) { + async addCodeDownloadAnnotation (appConfig) { // get each annotation key relative to the file it is defined in /// iterate only over extensions that have actions defined const fileToAnnotationKey = {} diff --git a/src/commands/app/test.js b/src/commands/app/test.js index 94b4e1d6f..9b2e59aae 100644 --- a/src/commands/app/test.js +++ b/src/commands/app/test.js @@ -18,7 +18,7 @@ const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin- const path = require('path') class Test extends BaseCommand { - async run() { + async run () { const { flags } = await this.parse(Test) let { all, unit, e2e, action, extension } = flags @@ -51,7 +51,7 @@ class Test extends BaseCommand { return exitCode } - printReport(totalResults) { + printReport (totalResults) { if (totalResults.length > 0) { const greenCheckMark = chalk.green('√') const redX = chalk.red('×') @@ -66,7 +66,7 @@ class Test extends BaseCommand { } } - normalizedActionList(extensionConfig) { + normalizedActionList (extensionConfig) { const actionList = [] const packages = extensionConfig.manifest.full.packages for (const [packageName, pkg] of Object.entries(packages)) { @@ -79,21 +79,21 @@ class Test extends BaseCommand { return actionList } - escapeBackslashes(pathString) { + escapeBackslashes (pathString) { // for Jest: // - replace backslashes with forward slashes, // - OR on Windows you need to escape forward slashes return pathString.replace(/\\/g, '/') } - testFolders(extensionConfig) { + testFolders (extensionConfig) { return { // add leading period path for jest unit: './' + this.escapeBackslashes(path.relative(extensionConfig.root, extensionConfig.tests.unit)), e2e: './' + this.escapeBackslashes(path.relative(extensionConfig.root, extensionConfig.tests.e2e)) } } - filterActions(actionFilters, extensionConfig, flags) { + filterActions (actionFilters, extensionConfig, flags) { const { unit, e2e } = flags const commandList = [] const { unit: unitTestFolder, e2e: e2eTestFolder } = this.testFolders(extensionConfig) @@ -140,7 +140,7 @@ class Test extends BaseCommand { return commandList } - async runExtensionTest(extensionName, extensionConfig, flags) { + async runExtensionTest (extensionName, extensionConfig, flags) { const { unit, e2e, action } = flags const commandList = [] const { unit: unitTestFolder, e2e: e2eTestFolder } = this.testFolders(extensionConfig) diff --git a/src/commands/app/undeploy.js b/src/commands/app/undeploy.js index df321c867..aca2ecc05 100644 --- a/src/commands/app/undeploy.js +++ b/src/commands/app/undeploy.js @@ -23,7 +23,7 @@ const { sendAppAssetsUndeployedAuditLog, sendAppUndeployAuditLog } = require('.. const { setRuntimeApiHostAndAuthHandler, getAccessToken } = require('../../lib/auth-helper') class Undeploy extends BaseCommand { - async run() { + async run () { // cli input const { flags } = await this.parse(Undeploy) @@ -121,7 +121,7 @@ class Undeploy extends BaseCommand { this.log(chalk.green(chalk.bold('Undeploy done!'))) } - async undeployOneExt(extName, config, flags, spinner) { + async undeployOneExt (extName, config, flags, spinner) { const onProgress = !flags.verbose ? info => { spinner.text = info @@ -183,7 +183,7 @@ class Undeploy extends BaseCommand { } } - async unpublishExtensionPoints(libConsoleCLI, deployConfigs, aioConfig, force) { + async unpublishExtensionPoints (libConsoleCLI, deployConfigs, aioConfig, force) { const payload = buildExtensionPointPayloadWoMetadata(deployConfigs) let res if (force) { diff --git a/test/BaseCommand.test.js b/test/BaseCommand.test.js index 3cb5a8941..c77d56f00 100644 --- a/test/BaseCommand.test.js +++ b/test/BaseCommand.test.js @@ -123,15 +123,22 @@ describe('getFullConfig', () => { mockConfigLoader.load.mockResolvedValue({ a: 'hello' }) const config = await cmd.getFullConfig({ someOptions: {} }) expect(config).toEqual({ a: 'hello' }) - expect(mockConfigLoader.load).toHaveBeenCalledWith({ someOptions: {}, validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ someOptions: {}, validateAppConfig: true }) }) - test('with validateAppConfig=true', async () => { + test('with config-validation=true', async () => { const cmd = new TheCommand() mockConfigLoader.load.mockResolvedValue({ a: 'hello' }) - const config = await cmd.getFullConfig({ someOptions: {}, validateAppConfig: true }) + const config = await cmd.getFullConfig({ someOptions: {} }, { 'config-validation': true }) expect(config).toEqual({ a: 'hello' }) expect(mockConfigLoader.load).toHaveBeenCalledWith({ someOptions: {}, validateAppConfig: true }) }) + test('with config-validation=false', async () => { + const cmd = new TheCommand() + mockConfigLoader.load.mockResolvedValue({ a: 'hello' }) + const config = await cmd.getFullConfig({ someOptions: {} }, { 'config-validation': false }) + expect(config).toEqual({ a: 'hello' }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ someOptions: {}, validateAppConfig: false }) + }) }) describe('getConfigFileForKey', () => { @@ -139,7 +146,7 @@ describe('getConfigFileForKey', () => { mockConfigLoader.load.mockResolvedValue(getMockConfig('exc', {})) const cmd = new TheCommand() expect(await cmd.getConfigFileForKey('notexist.key.abc')).toEqual({}) - expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: true }) }) test('returns file and key if found', async () => { const config = getMockConfig('exc', {}) @@ -154,7 +161,7 @@ describe('getRuntimeManifestConfigFile', () => { mockConfigLoader.load.mockResolvedValue(getMockConfig('app-no-actions', {})) const cmd = new TheCommand() expect(await cmd.getRuntimeManifestConfigFile('application')).toEqual({ file: 'app.config.yaml', key: 'application.runtimeManifest' }) - expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: true }) }) test('multiple implementations', async () => { const config = getMockConfig('app-exc-nui', {}) @@ -171,7 +178,7 @@ describe('getEventsConfigFile', () => { mockConfigLoader.load.mockResolvedValue(getMockConfig('app-no-actions', {})) const cmd = new TheCommand() expect(await cmd.getEventsConfigFile('application')).toEqual({ file: 'app.config.yaml', key: 'application.events' }) - expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: true }) }) test('multiple implementations', async () => { const config = getMockConfig('app-exc-nui', {}) @@ -189,13 +196,20 @@ describe('getAppExtConfigs', () => { mockConfigLoader.load.mockResolvedValue(config) const cmd = new TheCommand() expect(await cmd.getAppExtConfigs({})).toEqual(config.all) - expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ validateAppConfig: true }) }) test('with options', async () => { const config = getMockConfig('app-exc-nui', {}) mockConfigLoader.load.mockResolvedValue(config) const cmd = new TheCommand() expect(await cmd.getAppExtConfigs({}, { some: 'options' })).toEqual(config.all) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ some: 'options', validateAppConfig: true }) + }) + test('with flag validateAppConfig=false', async () => { + const config = getMockConfig('app-exc-nui', {}) + mockConfigLoader.load.mockResolvedValue(config) + const cmd = new TheCommand() + expect(await cmd.getAppExtConfigs({ 'config-validation': false }, { some: 'options' })).toEqual(config.all) expect(mockConfigLoader.load).toHaveBeenCalledWith({ some: 'options', validateAppConfig: false }) }) test('-e exc -e asset', async () => { diff --git a/test/commands/app/add/event.test.js b/test/commands/app/add/event.test.js index 48cf2c7fa..468ebcbe1 100644 --- a/test/commands/app/add/event.test.js +++ b/test/commands/app/add/event.test.js @@ -98,7 +98,7 @@ describe('good flags', () => { command.selectTemplates.mockResolvedValue(['@adobe/generator-add-events-generic']) await command.run() expect(command.installTemplates).toHaveBeenCalledWith(installOptions) - expect(await command.getConfigFileForKey).toHaveBeenCalledWith('application.events') + expect(await command.getConfigFileForKey).toHaveBeenCalledWith('application.events', { 'config-validation': true, extension: ['application'], install: true, yes: false }) }) test('multiple ext configs', async () => { diff --git a/test/commands/app/deploy.test.js b/test/commands/app/deploy.test.js index 054b58367..864af55e9 100644 --- a/test/commands/app/deploy.test.js +++ b/test/commands/app/deploy.test.js @@ -1328,6 +1328,7 @@ describe('run', () => { cliCommandFlags: { actions: true, build: true, + 'config-validation': true, 'content-hash': true, 'force-build': true, 'force-deploy': false, @@ -1451,6 +1452,7 @@ describe('run', () => { cliCommandFlags: { actions: true, build: true, + 'config-validation': true, 'content-hash': true, 'force-build': true, 'force-deploy': false, diff --git a/test/commands/app/info.test.js b/test/commands/app/info.test.js index fdbc6c214..ea3d055d9 100644 --- a/test/commands/app/info.test.js +++ b/test/commands/app/info.test.js @@ -75,7 +75,7 @@ describe('run', () => { command.error = jest.fn() command.log = jest.fn() await command.run() - expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: true }) expect(command.error).toHaveBeenCalledTimes(0) checkHiddenSecrets(command.log) const json = JSON.parse(command.log.mock.calls[0][0]) @@ -92,7 +92,7 @@ describe('run', () => { command.error = jest.fn() command.log = jest.fn() await command.run() - expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: true }) expect(command.error).toHaveBeenCalledTimes(0) checkHiddenSecrets(command.log) const json = JSON.parse(command.log.mock.calls[0][0]) @@ -108,7 +108,7 @@ describe('run', () => { command.error = jest.fn() command.log = jest.fn() await command.run() - expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: true }) expect(command.error).toHaveBeenCalledTimes(0) checkHiddenSecrets(command.log) const json = yaml.load(command.log.mock.calls[0][0]) @@ -124,7 +124,7 @@ describe('run', () => { command.error = jest.fn() command.log = jest.fn() await command.run() - expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: false }) + expect(mockConfigLoader.load).toHaveBeenCalledWith({ allowNoImpl: true, validateAppConfig: true }) expect(command.error).toHaveBeenCalledTimes(0) checkHiddenSecrets(command.log) const json = JSON.parse(command.log.mock.calls[0][0]) diff --git a/test/commands/app/undeploy.test.js b/test/commands/app/undeploy.test.js index 7bdebeca5..68a96e233 100644 --- a/test/commands/app/undeploy.test.js +++ b/test/commands/app/undeploy.test.js @@ -579,6 +579,7 @@ describe('run', () => { }, cliCommandFlags: { actions: true, + 'config-validation': true, events: true, 'force-unpublish': false, unpublish: false, From cc8cb928e1ecc7d27ca1444d5875b54df8fec286 Mon Sep 17 00:00:00 2001 From: taub Date: Thu, 15 Jan 2026 10:11:53 -0500 Subject: [PATCH 3/3] update config-validation flag message, make sure all commands that use it inherit BaseCommand flags --- src/BaseCommand.js | 2 +- src/commands/app/config/get/log-forwarding.js | 4 ++++ src/commands/app/config/get/log-forwarding/errors.js | 3 +++ src/commands/app/config/set/log-forwarding.js | 3 +++ src/commands/app/test.js | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/BaseCommand.js b/src/BaseCommand.js index 50c29d91c..54a8326cd 100644 --- a/src/BaseCommand.js +++ b/src/BaseCommand.js @@ -193,7 +193,7 @@ BaseCommand.flags = { verbose: Flags.boolean({ char: 'v', description: 'Verbose output' }), version: Flags.boolean({ description: 'Show version' }), 'config-validation': Flags.boolean({ - description: '[default: true] Validate the app configuration before deploying', + description: '[default: true] Validate the app configuration file(s) before continuing.', default: true, allowNo: true }) diff --git a/src/commands/app/config/get/log-forwarding.js b/src/commands/app/config/get/log-forwarding.js index 9cf1effda..60e8fbaf2 100644 --- a/src/commands/app/config/get/log-forwarding.js +++ b/src/commands/app/config/get/log-forwarding.js @@ -51,4 +51,8 @@ class LogForwardingCommand extends BaseCommand { LogForwardingCommand.description = 'Get log forwarding destination configuration' LogForwardingCommand.aliases = ['app:config:get:log-forwarding', 'app:config:get:lf'] +LogForwardingCommand.flags = { + ...BaseCommand.flags +} + module.exports = LogForwardingCommand diff --git a/src/commands/app/config/get/log-forwarding/errors.js b/src/commands/app/config/get/log-forwarding/errors.js index 2ba0fcf01..175e9150b 100644 --- a/src/commands/app/config/get/log-forwarding/errors.js +++ b/src/commands/app/config/get/log-forwarding/errors.js @@ -47,5 +47,8 @@ class ErrorsCommand extends BaseCommand { ErrorsCommand.description = 'Get log forwarding errors' ErrorsCommand.aliases = ['app:config:get:log-forwarding:errors', 'app:config:get:lf:errors'] +ErrorsCommand.flags = { + ...BaseCommand.flags +} module.exports = ErrorsCommand diff --git a/src/commands/app/config/set/log-forwarding.js b/src/commands/app/config/set/log-forwarding.js index d7937c9d4..f307dc740 100644 --- a/src/commands/app/config/set/log-forwarding.js +++ b/src/commands/app/config/set/log-forwarding.js @@ -51,5 +51,8 @@ class LogForwardingCommand extends BaseCommand { LogForwardingCommand.description = 'Set log forwarding destination configuration' LogForwardingCommand.aliases = ['app:config:set:log-forwarding', 'app:config:set:lf'] +LogForwardingCommand.flags = { + ...BaseCommand.flags +} module.exports = LogForwardingCommand diff --git a/src/commands/app/test.js b/src/commands/app/test.js index 9b2e59aae..81b57d5ef 100644 --- a/src/commands/app/test.js +++ b/src/commands/app/test.js @@ -202,6 +202,7 @@ class Test extends BaseCommand { } Test.flags = { + ...BaseCommand.flags, extension: Flags.string({ char: 'e', description: 'the extension(s) to test',