Skip to content

Commit

Permalink
Merge pull request #591 from Accenture/feature/554-auto-generate-mark…
Browse files Browse the repository at this point in the history
…ets-and-marketlist-upon-mcdev-init

Feature/554 auto generate markets and marketlist upon mcdev init + fixes #590 bug around git user names/emails
  • Loading branch information
DougMidgley authored Dec 8, 2022
2 parents 967c23d + 6f5cb4d commit e1af95e
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 21 deletions.
8 changes: 2 additions & 6 deletions boilerplate/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,10 @@
},
"marketList": {
"deployment-source": {
"description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list",
"MySandbox/DEV-NL": "DEV-NL"
"description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list"
},
"deployment-target": {
"description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like",
"MySandbox/QA-DE": "QA-DE",
"MyProduction/PROD-DE": "PROD-DE",
"MyProduction/PROD-NL": "PROD-NL"
"description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like"
}
},
"metaDataTypes": {
Expand Down
38 changes: 34 additions & 4 deletions docs/dist/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4867,7 +4867,7 @@ CLI entry for SFMC DevTools
* [.inverseGet(objs, val)](#Util.inverseGet) ⇒ <code>string</code>
* [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ <code>Array.&lt;string&gt;</code>
* [.resolveObjPath(path, obj)](#Util.resolveObjPath) ⇒ <code>any</code>
* [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ <code>undefined</code>
* [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ <code>string</code>
* [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ <code>TYPE.MetadataTypeItem</code>
* [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ <code>void</code>

Expand Down Expand Up @@ -5064,10 +5064,11 @@ let's you dynamically walk down an object and get a value

<a name="Util.execSync"></a>

### Util.execSync(cmd, [args], [hideOutput]) ⇒ <code>undefined</code>
### Util.execSync(cmd, [args], [hideOutput]) ⇒ <code>string</code>
helper to run other commands as if run manually by user

**Kind**: static method of [<code>Util</code>](#Util)
**Returns**: <code>string</code> - output of command if hideOutput is true

| Param | Type | Description |
| --- | --- | --- |
Expand Down Expand Up @@ -5709,6 +5710,7 @@ CLI helper class
* [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ <code>void</code>
* [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.&lt;{&#x27;user.name&#x27;: string, &#x27;user.email&#x27;: string}&gt;</code>
* [.initProject(properties, credentialName)](#Init.initProject) ⇒ <code>Promise.&lt;void&gt;</code>
* [._initMarkets()](#Init._initMarkets)
* [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ <code>Promise.&lt;void&gt;</code>
* [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.&lt;boolean&gt;</code>
* [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.&lt;string&gt;</code>
Expand Down Expand Up @@ -5831,6 +5833,12 @@ Creates template file for properties.json
| properties | <code>TYPE.Mcdevrc</code> | config file's json |
| credentialName | <code>string</code> | identifying name of the installed package / project |

<a name="Init._initMarkets"></a>

### Init.\_initMarkets()
helper for @initProject that optionally creates markets and market lists for all BUs

**Kind**: static method of [<code>Init</code>](#Init)
<a name="Init._downloadAllBUs"></a>

### Init.\_downloadAllBUs(bu, gitStatus) ⇒ <code>Promise.&lt;void&gt;</code>
Expand Down Expand Up @@ -5916,6 +5924,7 @@ CLI helper class
* [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ <code>void</code>
* [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.&lt;{&#x27;user.name&#x27;: string, &#x27;user.email&#x27;: string}&gt;</code>
* [.initProject(properties, credentialName)](#Init.initProject) ⇒ <code>Promise.&lt;void&gt;</code>
* [._initMarkets()](#Init._initMarkets)
* [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ <code>Promise.&lt;void&gt;</code>
* [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.&lt;boolean&gt;</code>
* [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.&lt;string&gt;</code>
Expand Down Expand Up @@ -6038,6 +6047,12 @@ Creates template file for properties.json
| properties | <code>TYPE.Mcdevrc</code> | config file's json |
| credentialName | <code>string</code> | identifying name of the installed package / project |

<a name="Init._initMarkets"></a>

### Init.\_initMarkets()
helper for @initProject that optionally creates markets and market lists for all BUs

**Kind**: static method of [<code>Init</code>](#Init)
<a name="Init._downloadAllBUs"></a>

### Init.\_downloadAllBUs(bu, gitStatus) ⇒ <code>Promise.&lt;void&gt;</code>
Expand Down Expand Up @@ -6123,6 +6138,7 @@ CLI helper class
* [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ <code>void</code>
* [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.&lt;{&#x27;user.name&#x27;: string, &#x27;user.email&#x27;: string}&gt;</code>
* [.initProject(properties, credentialName)](#Init.initProject) ⇒ <code>Promise.&lt;void&gt;</code>
* [._initMarkets()](#Init._initMarkets)
* [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ <code>Promise.&lt;void&gt;</code>
* [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.&lt;boolean&gt;</code>
* [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.&lt;string&gt;</code>
Expand Down Expand Up @@ -6245,6 +6261,12 @@ Creates template file for properties.json
| properties | <code>TYPE.Mcdevrc</code> | config file's json |
| credentialName | <code>string</code> | identifying name of the installed package / project |

<a name="Init._initMarkets"></a>

### Init.\_initMarkets()
helper for @initProject that optionally creates markets and market lists for all BUs

**Kind**: static method of [<code>Init</code>](#Init)
<a name="Init._downloadAllBUs"></a>

### Init.\_downloadAllBUs(bu, gitStatus) ⇒ <code>Promise.&lt;void&gt;</code>
Expand Down Expand Up @@ -6330,6 +6352,7 @@ CLI helper class
* [._updateGitConfigUser()](#Init._updateGitConfigUser) ⇒ <code>void</code>
* [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.&lt;{&#x27;user.name&#x27;: string, &#x27;user.email&#x27;: string}&gt;</code>
* [.initProject(properties, credentialName)](#Init.initProject) ⇒ <code>Promise.&lt;void&gt;</code>
* [._initMarkets()](#Init._initMarkets)
* [._downloadAllBUs(bu, gitStatus)](#Init._downloadAllBUs) ⇒ <code>Promise.&lt;void&gt;</code>
* [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.&lt;boolean&gt;</code>
* [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.&lt;string&gt;</code>
Expand Down Expand Up @@ -6452,6 +6475,12 @@ Creates template file for properties.json
| properties | <code>TYPE.Mcdevrc</code> | config file's json |
| credentialName | <code>string</code> | identifying name of the installed package / project |

<a name="Init._initMarkets"></a>

### Init.\_initMarkets()
helper for @initProject that optionally creates markets and market lists for all BUs

**Kind**: static method of [<code>Init</code>](#Init)
<a name="Init._downloadAllBUs"></a>

### Init.\_downloadAllBUs(bu, gitStatus) ⇒ <code>Promise.&lt;void&gt;</code>
Expand Down Expand Up @@ -6542,7 +6571,7 @@ Util that contains logger and simple util methods
* [.inverseGet(objs, val)](#Util.inverseGet) ⇒ <code>string</code>
* [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ <code>Array.&lt;string&gt;</code>
* [.resolveObjPath(path, obj)](#Util.resolveObjPath) ⇒ <code>any</code>
* [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ <code>undefined</code>
* [.execSync(cmd, [args], [hideOutput])](#Util.execSync) ⇒ <code>string</code>
* [.templateSearchResult(results, keyToSearch, searchValue)](#Util.templateSearchResult) ⇒ <code>TYPE.MetadataTypeItem</code>
* [.setLoggingLevel(argv)](#Util.setLoggingLevel) ⇒ <code>void</code>

Expand Down Expand Up @@ -6739,10 +6768,11 @@ let's you dynamically walk down an object and get a value

<a name="Util.execSync"></a>

### Util.execSync(cmd, [args], [hideOutput]) ⇒ <code>undefined</code>
### Util.execSync(cmd, [args], [hideOutput]) ⇒ <code>string</code>
helper to run other commands as if run manually by user

**Kind**: static method of [<code>Util</code>](#Util)
**Returns**: <code>string</code> - output of command if hideOutput is true

| Param | Type | Description |
| --- | --- | --- |
Expand Down
20 changes: 14 additions & 6 deletions lib/util/init.git.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,11 @@ const Init = {
]);
}
/* eslint-enable unicorn/prefer-ternary */

responses.gitRemoteUrl = responses.gitRemoteUrl.trim();
Util.execSync('git', ['remote', 'add', 'origin', responses.gitRemoteUrl]);
return responses.gitRemoteUrl.split('/').pop().split('.')[0];
if (typeof responses.gitRemoteUrl === 'string') {
responses.gitRemoteUrl = responses.gitRemoteUrl.trim();
Util.execSync('git', ['remote', 'add', 'origin', responses.gitRemoteUrl]);
return responses.gitRemoteUrl.split('/').pop().split('.')[0];
}
}
},
/**
Expand Down Expand Up @@ -258,15 +259,22 @@ const Init = {

for (const file of Object.keys(gitConfigs.values)) {
if (gitConfigs.values[file]['user.name']) {
result['user.name'] = gitConfigs.values[file]['user.name'];
// sometimes the config has more than one entry per key - take the last one
result['user.name'] = Array.isArray(gitConfigs.values[file]['user.name'])
? gitConfigs.values[file]['user.name'].pop()
: gitConfigs.values[file]['user.name'];
}
if (gitConfigs.values[file]['user.email']) {
result['user.email'] = gitConfigs.values[file]['user.email'];
// sometimes the config has more than one entry per key - take the last one
result['user.email'] = Array.isArray(gitConfigs.values[file]['user.email'])
? gitConfigs.values[file]['user.email'].pop()
: gitConfigs.values[file]['user.email'];
}
}
if (!result['user.name'] || !result['user.email']) {
return null;
}

return result;
},
};
Expand Down
64 changes: 64 additions & 0 deletions lib/util/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ const Init = {
return;
}

// set up markets and market lists initially
await Init._initMarkets();

// create first commit to backup the project configuration
if (initGit.status === 'init') {
Util.logger.info(`Committing initial setup to Git:`);
Expand All @@ -182,6 +185,67 @@ const Init = {
);
}
},

/**
* helper for @initProject that optionally creates markets and market lists for all BUs
*/
async _initMarkets() {
const skipInteraction = Util.skipInteraction;
const properties = await config.getProperties(true);

// get list of business units
const firstCredentialName = Object.keys(properties.credentials)[0];
const businessUnits = Object.keys(
properties.credentials[firstCredentialName].businessUnits
);

// set up empty markets for them
const markets = {};
for (const bu of businessUnits) {
markets[bu] = { suffix: '_' + bu };
}
properties.markets = markets;

let sourceBuName;
// set up default deployment market lists
if (skipInteraction) {
// don't ask, list all BUs in deployment-target and set deployment-source to ???
if (!businessUnits.includes(skipInteraction.developmentBu)) {
Util.logger.warn(
`Could not find developmentBu=${skipInteraction.developmentBu} in business units. Skipping.`
);
delete skipInteraction.developmentBu;
}
sourceBuName = skipInteraction.developmentBu || '???';
if (!skipInteraction.developmentBu) {
Util.logger.info(
'Market List "deployment-source" will need to be set up manually. Marking all BUs as target BUs in "deployment-target".'
);
}
} else {
const responses = await inquirer.prompt([
{
type: 'list',
name: 'developmentBu',
message: 'Please select your development business unit:',
choices: businessUnits.map((bu) => ({ name: bu, value: bu })),
},
]);
sourceBuName = responses.developmentBu;
}
// set source list
properties.marketList['deployment-source'][firstCredentialName + '/' + sourceBuName] =
sourceBuName;

// set target list
for (const bu of businessUnits) {
// filter out source BU & parent BU to ensure they dont get deployed to automatically
if (bu !== sourceBuName && bu !== '_ParentBU_') {
properties.marketList['deployment-target'][firstCredentialName + '/' + bu] = bu;
}
}
await File.saveConfigFile(properties);
},
/**
* helper for {@link Init.initProject}
*
Expand Down
18 changes: 13 additions & 5 deletions lib/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,24 @@ const Util = {
* @param {string} cmd to be executed command
* @param {string[]} [args] list of arguments
* @param {boolean} [hideOutput] if true, output of command will be hidden from CLI
* @returns {undefined}
* @returns {string} output of command if hideOutput is true
*/
execSync(cmd, args, hideOutput) {
args = args || [];
Util.logger.info('⚡ ' + cmd + ' ' + args.join(' '));

// the following options ensure the user sees the same output and
// interaction options as if the command was manually run
const options = hideOutput ? {} : { stdio: [0, 1, 2] };
return child_process.execSync(cmd + ' ' + args.join(' '), options);
if (hideOutput) {
// no output displayed to user but instead returned to parsed elsewhere
return child_process
.execSync(cmd + ' ' + args.join(' '))
.toString()
.trim();
} else {
// the following options ensure the user sees the same output and
// interaction options as if the command was manually run
child_process.execSync(cmd + ' ' + args.join(' '), { stdio: [0, 1, 2] });
return null;
}
},
/**
* standardize check to ensure only one result is returned from template search
Expand Down

0 comments on commit e1af95e

Please sign in to comment.