From 8db51357fd5278008543165043a2af6283103c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Berkefeld?= Date: Tue, 23 Apr 2024 15:56:52 +0200 Subject: [PATCH] #1275: add --metadata for deploy-method --- lib/Deployer.js | 67 +++++++++++++++++++++++++++++++++--------------- lib/cli.js | 11 +++++--- lib/index.js | 2 +- lib/util/util.js | 21 +++++++++++++++ 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/lib/Deployer.js b/lib/Deployer.js index ef0a24824..ecae55a39 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -23,6 +23,7 @@ import auth from './util/auth.js'; * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo */ /** @@ -57,7 +58,7 @@ class Deployer { * Deploys all metadata located in the 'deploy' directory to the specified business unit * * @param {string} businessUnit references credentials from properties.json - * @param {string[]} [selectedTypesArr] limit deployment to given metadata type + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit deployment to given metadata type * @param {string[]} [keyArr] limit deployment to given metadata keys * @returns {Promise.>} deployed metadata per BU (first key: bu name, second key: metadata type) */ @@ -73,25 +74,44 @@ class Deployer { if (Util.OPTIONS.fromRetrieve) { properties.directories.deploy = properties.directories.retrieve; } - if (Array.isArray(selectedTypesArr)) { - // types and keys can be provided but for each type all provided keys are applied as filter - for (const selectedType of selectedTypesArr) { + if (selectedTypesArr) { + for (const selectedType of Array.isArray(selectedTypesArr) + ? selectedTypesArr + : Object.keys(selectedTypesArr)) { if (!Util._isValidType(selectedType)) { return; } } } - if ( - Util.OPTIONS.fromRetrieve && - (!selectedTypesArr || - !Array.isArray(selectedTypesArr) || - !selectedTypesArr.length || - !keyArr || - !Array.isArray(keyArr) || - !keyArr.length) - ) { - Util.logger.error('type & key need to be defined to deploy from retrieve folder'); - return; + if (Util.OPTIONS.fromRetrieve) { + // check if either type & key or typeKeyCombo including keys was supplied + // we dont want to allow deploying without key from the retrieve dir for safety reasons + let keysFound = false; + if ( + Array.isArray(selectedTypesArr) && + selectedTypesArr.length && + Array.isArray(keyArr) && + keyArr.length + ) { + // check legacy way of passing in type(s) and key(s) + keysFound = true; + } else if ( + selectedTypesArr && + !Array.isArray(selectedTypesArr) && + Object.values(selectedTypesArr).length + ) { + // TypeKeyCombo - a single null value (== no keys for one type) should lead to the error + for (const keys of Object.values(selectedTypesArr)) { + if (!Array.isArray(keys)) { + keysFound = false; + break; + } + } + } + if (!keysFound) { + Util.logger.error('type & key need to be defined to deploy from retrieve folder'); + return; + } } let counter_credBu = 0; if (businessUnit === '*') { @@ -201,7 +221,7 @@ class Deployer { * @param {string} cred name of Credential * @param {string} bu name of BU * @param {Mcdevrc} properties General configuration to be used in retrieve - * @param {string[]} [typeArr] limit deployment to given metadata type + * @param {string[] | TypeKeyCombo} [typeArr] limit deployment to given metadata type * @param {string[]} [keyArr] limit deployment to given metadata keys * @returns {Promise.} ensure that BUs are worked on sequentially */ @@ -227,20 +247,27 @@ class Deployer { /** * Deploy all metadata that is located in the deployDir * - * @param {string[]} [typeArr] limit deployment to given metadata type (can include subtype) + * @param {string[] | TypeKeyCombo} [types] limit deployment to given metadata type (can include subtype) * @param {string[]} [keyArr] limit deployment to given metadata keys * @returns {Promise.} Promise of all deployed metadata */ - async _deploy(typeArr, keyArr) { + async _deploy(types, keyArr) { + const typeArr = !types || Array.isArray(types) ? types : Object.keys(types); + const typeKeyCombo = Array.isArray(types) + ? Util.createTypeKeyCombo(typeArr, keyArr) + : types; if (await File.pathExists(this.deployDir)) { /** @type {MultiMetadataTypeMap} */ this.metadata = Deployer.readBUMetadata(this.deployDir, typeArr); // filter found metadata by key if given - if (typeArr && Array.isArray(keyArr)) { + if (typeArr && Array.isArray(typeArr)) { for (const selectedType of typeArr) { const type = selectedType.split('-')[0]; - this.metadata[type] = Util.filterObjByKeys(this.metadata[type], keyArr); + this.metadata[type] = Util.filterObjByKeys( + this.metadata[type], + typeKeyCombo[selectedType] + ); } } } else { diff --git a/lib/cli.js b/lib/cli.js index a879f1d08..8fa1b9578 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -125,7 +125,12 @@ yargs(hideBin(process.argv)) handler: (argv) => { Mcdev.setOptions(argv); - Mcdev.deploy(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + const typeKeyCombo = metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.deploy(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.deploy(argv.BU, typeKeyCombo); + } }, }) // @ts-expect-error @@ -729,7 +734,7 @@ function csvToArray(csv) { * @param {string|string[]} metadataOption potentially comma-separated value or null * @param {string[]} [allowedIdentifiers] 'key', 'id', 'name' * @param {boolean} [firstOnly] removes all but the first entry if enabled - * @returns {void|TypeKeyCombo} values split into an array. + * @returns {TypeKeyCombo} values split into an array. */ function metadataToTypeKey( metadataOption, @@ -737,7 +742,7 @@ function metadataToTypeKey( firstOnly = false ) { if (!metadataOption) { - return; + return undefined; // eslint-disable-line unicorn/no-useless-undefined } else if (!Array.isArray(metadataOption)) { metadataOption = [metadataOption]; } diff --git a/lib/index.js b/lib/index.js index 8c76c6849..863429fb1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -447,7 +447,7 @@ class Mcdev { * Deploys all metadata located in the 'deploy' directory to the specified business unit * * @param {string} businessUnit references credentials from properties.json - * @param {string[]} [selectedTypesArr] limit deployment to given metadata type + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit deployment to given metadata type * @param {string[]} [keyArr] limit deployment to given metadata keys * @returns {Promise.>} deployed metadata per BU (first key: bu name, second key: metadata type) */ diff --git a/lib/util/util.js b/lib/util/util.js index 82aeb541a..8f105b871 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -929,6 +929,27 @@ export const Util = { capitalizeFirstLetter(str) { return str.charAt(0).toUpperCase() + str.slice(1); }, + /** + * helper for Retriever and Deployer class + * + * @param {string[]} typeArr - + * @param {string[]} keyArr - + * @returns {TypeKeyCombo} - + */ + createTypeKeyCombo(typeArr, keyArr) { + if (!keyArr || (Array.isArray(keyArr) && !keyArr.length)) { + // no keys were provided, ensure we retrieve all + keyArr = [null]; + } + /** @type {TypeKeyCombo} */ + const typeKeyMap = {}; + // no keys or array of keys was provided (likely called via CLI or to retrieve all) + // transform into TypeKeyCombo to iterate over it + for (const type of typeArr) { + typeKeyMap[type] = keyArr; + } + return typeKeyMap; + }, }; Util.startLogger(false, true);