Skip to content

Releases: Accenture/sfmc-devtools

v7.5.0

18 Nov 20:11
Compare
Choose a tag to compare

Features

  • #37 add support to deploy (update/create) automation wait activities by @JoernBerkefeld in #1829
  • #1729 option to disable auto-formatting on save via config (options.formatOnSave) and --no-format option for when you want or need to retain whatever manual formatting you applied. inspired by @AndrewEllis91, code by @JoernBerkefeld in #1846
  • #1850 add method validate journey for multi-step journeys by @JoernBerkefeld in #1860
  • #1851 add --ignoreFolder option to deploy --matchName by @JoernBerkefeld in #1863
  • #1852 add option --ignoreSfFields / --isf to deploy, allowing you to skip false-positive errors about missing Salesforce fields for Salesforce-triggered journeys/events by @JoernBerkefeld in #1864
  • #1294 include dataExtension retention policy in the created markdown file by @JoernBerkefeld in #1865
  • #1825 add auto-renaming to avoid duplicate-name error for automation, query and senderProfile if deployed without --matchName. This already existed for dataExtension and asset before. by @JoernBerkefeld in #1827

Bugfixes

Chores

  • #1805 build now asks if the BU's deploy folder should be emptied before running buildDefinition, making it easier to run a clean deployment afterwards by @JoernBerkefeld in #1815
  • #1814 filter journey builder triggeredSends from being saved to disk as all relevant info is also present in the journey itself by @JoernBerkefeld in #1816
  • #1818 no longer include triggeredSend keys in templated journeys to ensure the resulting journey metadata shows most current info. Otherwise, journey builder will reference the latest triggeredSend but show the info from the first version of it instead. by @JoernBerkefeld in #1819
  • #1808 set newly introduced iconUrl of events during deploy/ retrieve by @JoernBerkefeld in #1822
  • #1800 improved error messages issues by deploy in general and by deploy --matchName errors by @JoernBerkefeld in #1823
  • #1842 groundwork for supporting automation-triggered events by resolving the automationid in event by @JoernBerkefeld in #1845
  • #1807 cross-check salesforce-triggered events with associated dataExtensions to ensure all required fields are present by @JoernBerkefeld in #1849

Dependencies

Full Changelog: v7.4.4...v7.5.0

Details

Standard Commands

retrieve

Command: mcdev retrieve [business unit] [metadata type] [metadata key] [--like] [--metadata] [--format] [--no-format]

...

retrieve with --format or --no-format option:

If you need to retrieve code in a raw format, you may use mcdev retrieve --no-format to disable auto-formatting. On the other hand, if options.formatOnSave is set to false, then mcdev retrieve --format enables formatting.

deploy

Command: mcdev deploy [business unit] [metadata type] [metadata key] [--metadata] [--fromRetrieve] [--refresh] [--keySuffix] [--noMidSuffix] [--changeKeyValue=yourNewKey] [--changeKeyField=otherFieldInJson] [--execute] [--schedule] [--fixShared] [--noUpdate] [--publish] [--skipStatusCheck] [--matchName] [--ignoreFolder] [--skipValidation] [--format] [--no-format] [--ignoreSfFields]

...

deploy with --format or --no-format option:

After deploying, the deployed item is saved in the respective retrieve folder. If you need to retrieve code in a raw format, you may use mcdev deploy --no-format to disable auto-formatting. On the other hand, if options.formatOnSave is set to false, then mcdev deploy --format enables formatting.

deploy with --matchName (and --ignoreFolder):
...
If running --matchName returns many single matches but the found items reside in a different folder, using --ignoreFolder lets you still override these items automatically, easing your cleanup job. So far, this is supported for dataExtensions only.

deploy with --ignoreSfFields:

When deploying Salesforce-triggered journeys you might encounter false positives regarding missing fields for a Salesforce object. In these cases, the option --ignoreSfFields allows you to reduce the error to a warning and deploy it.

validate

Command: mcdev validate <business unit> [metadata type] [metadata key] [--like] [--metadata]

Alias: n/a

Currently supported types:

Name CLI Argument Effect
Journey journey Validates a Draft-version of a journey

You can validate a draft journey using this command, without having to actually publish it. This is the same as clicking on the Validate-button in the web interface.

mcdev validate cred/bu journey myJourneyKey
mcdev validate cred/bu journey id:myJourneyId
mcdev validate cred/bu -m journey:myJourneyKey -m journey:id:myJourneyId

Advanced Configuration

Config Options

Setting Default Description
options.formatOnSave true Allows disabling auto-formatting for all retrieve/deploy operations

v7.4.4

03 Oct 10:58
Compare
Choose a tag to compare

Bugfixes

Chores

Full Changelog: v7.4.3...v7.4.4

v7.4.3

30 Sep 12:01
Compare
Choose a tag to compare

Bugfixes

  • #1738 stop if all publish actions failed and do not re-retrieve journey & transactionalEmails by @JoernBerkefeld in #1739
  • #1740 fix javascript error for ccEmail by adding missing preDeployment handling for journey activities by @JoernBerkefeld in #1741
  • #1742 correctly retrieve all related transactionalEmails after publishing a transactional send journey instead of just the first one by @JoernBerkefeld in #1744
  • #1323 ensure newly mcdev-created senderProfiles are selectable in journey message configuration by @JoernBerkefeld in #1745

Chores

Full Changelog: v7.4.2...v7.4.3

v7.4.2

19 Sep 14:11
Compare
Choose a tag to compare

Bugfixes

Chores

Dependencies

Full Changelog: v7.4.1...v7.4.2

v7.4.1

12 Sep 14:15
Compare
Choose a tag to compare

Bugfixes

Chores

  • #1679 gitignore .BAK files in project folders. These get created by mcdev upgrade. by @JoernBerkefeld in #1691
  • #1695 properly warn about potentially missing SF object access and how to fix it in journey and event by @JoernBerkefeld in #1697
  • #1680 list CC and BCC values on journey email activities as arrays and remove them from triggeredSend (because those fields were always returned empty by the API) by @JoernBerkefeld in #1699
  • #1674 ensure journey activities and entry-event fields are sorted alphabetically to ease pull request reviews by @JoernBerkefeld in #1700

Dependencies

Special Thanks

Thank you to community member @Dipasree-ghosh for supporting the research around how common-fields are used in Salesforce-triggered journeys (#1692) and for pointing out an issue regarding missing hints for how to fix config issues when the command was run via VSCode extension (#1690).

Full Changelog: v7.4.0...v7.4.1

v7.4.0 - Validation rules

04 Sep 16:57
Compare
Choose a tag to compare

Features

Bugfixes

  • #1505 fix incorrect asset links in journeys when retrieved together with triggeredSends by @JoernBerkefeld in #1640
  • #1472 fix dependency-not-found deploy-error by adapting order in which assets are deployed, solving the inter-type dependencies by @JoernBerkefeld in #1502
  • #1646 fix config files not actually getting updated during mcdev upgrade when it was presented as optional by @JoernBerkefeld in #1647
  • #1644 automatic workaround, not solution for the "string or binary data would be truncated"-error by @JoernBerkefeld in #1660
  • #1657 fix journey/event eventDataSummary not getting saved correctly by @JoernBerkefeld in #1658
  • #1668 sf object checks for events and journeys fail if multiple entries are retrieved-by-key due to race conditions by @JoernBerkefeld in #1669

Chores

Full Changelog: v7.3.1...v7.4.0

Details

Standard Commands

deploy

Command: mcdev deploy [business unit] [metadata type] [metadata key] [--metadata] [--fromRetrieve] [--refresh] [--keySuffix] [--noMidSuffix] [--changeKeyValue=yourNewKey] [--changeKeyField=otherFieldInJson] [--execute] [--schedule] [--fixShared] [--noUpdate] [--publish] [--skipStatusCheck] [--matchName] [--skipValidation]

New option --skipValidation

deploy with --matchName:

Currently supported types:

Name CLI Argument
Asset asset
Data Extension dataExtension

deploy --matchName now supports dataExtensions

execute

Command: mcdev execute <business unit> [type] [key] [--like] [--schedule] [--metadata]

Alias: mcdev exec / mcdev start / mcdev resume

Currently supported types:

Name CLI Argument Effect
Automation automation RunOnce or Schedules automation according to already existing schedule
Query query Starts query execution
Journey journey Resumes a paused journey

Now supports journey

publish

Command: mcdev publish <business unit> [metadata type] [metadata key] [--like] [--skipStatusCheck] [--metadata]

Alias: mcdev activate

Currently supported types:

Name CLI Argument Effect
Journey journey Activates a Draft-version of a journey (creates related transactionalEmail or event record)

New alias activate to mimic the lingo in Journey Builder

Templating Commands

build

Command: mcdev build <--buFrom> <--marketFrom> <--buTo> <--marketTo> <--metadata> [--bulk] [--dependencies] [--retrieve] [--skipValidation]

New option --skipValidation

buildDefinition

Command: mcdev buildDefinition <business unit> [type] [template name] [market] [--metadata] [--market] [--skipValidation]

New option --skipValidation

buildDefinitionBulk

Command: mcdev buildDefinitionBulk <market list name> <type> <template name> [--metadata] [--skipValidation]

New option --skipValidation

Advanced Configuration

.mcdevrc.json

The central config in .mcdevrc.json holds multiple adjustable settings:

{
  "options": {
    "validation": {
        "retrieve": {
            "noGuidKeys": "warn",
            "noRootFolder": "warn",
            "overrides": [
                {
                    "type": [
                        "journey"
                    ],
                    "options": {
                        "noGuidKeys": "off",
                    }
                }
            ]
        },
        "buildDefinition": {
            "noGuidKeys": "warn",
            "noRootFolder": "warn",
            "overrides": [
                {
                    "type": [
                        "journey"
                    ],
                    "options": {
                        "noGuidKeys": "off",
                    }
                }
            ]
        },
        "deploy": {
            "noGuidKeys": "error",
            "noRootFolder": "error",
            "overrides": [
                {
                    "type": [
                        "journey"
                    ],
                    "options": {
                        "noGuidKeys": "off",
                    }
                }
            ]
        }
    },
  },
}
Setting Default Description
options.validation current default and custom rules Allows setting validation rules to "off", "warn" or "error

Validation rules

You can define validation rules for retrieve, buildDefinition and deploy.
The following rules exist out of the box:

  • noGuidKeys: test for metadata that has a GUID / UUID as key.
  • noRootFolder: test if metadata that does exist in a folder resides in the root for that particular type or in a subfolder.

Possible rule settings are:

  • not set, which implicitly turns off the rule
  • "off" explicitly turns off the rule
  • "warn" shows a log message of type warning
  • "error" shows a log message of type error AND blocks further execution
    • for retrieve that prevents download
    • for buildDefintion (and build) that prevents the creation of the corresponding file in the deploy folder
    • for deploy this will prevent deployment.

Please keep in mind that you can always skip validation rules all together at run-time by adding --skipValidation to your command (deploy / build / buildDefinition / buildDefinitionBulk)

Custom Validation rules - .mcdev-validation.js

Optionally one can create a file named .mcdev-validations.js in the root of your project to specify your own validation rules. That gives you full flexibility to test for whatever guidelines you might have as you can literally parse the JSON of the metadata yourself.

One example that depends on BU names and hence is not part of the standard set could look like this:

'use strict';

const buSuffixMap = {
    _ParentBU_: '',
    DEV: '_DEV',
    QA: '_QA',
    PROD: '',
};

/**
 *
 * @param {any} definition type defintiion
 * @param {any} item metadata json
 * @param {string} targetDir where the metadata is stored ("deploy/cred/bu")
 * @param {any} Util helper methods
 * @returns {Promise.<any>} validation rule
 */
export function validation(definition, item, targetDir, Util) {
    const bu = targetDir.includes('/') ? targetDir.split('/').pop() : targetDir.split('\\').pop();
    const suffix = buSuffixMap[bu];

    if (suffix === undefined) {
        Util.logger.error(
            `BU '${bu}' not defined for keySuffix validation in .mcdev-validations.js`
        );
    }
    return {
        keySuffix: {
            failedMsg: 'Key Suffix expected but not found: ' + suffix,
            /**
             * @returns {boolean} true=test passed
             */
            passed: function () {
                // exclude non-relevant items
                const relevantTypes = ['asset', 'dataExtension'];
                if (!relevantTypes.includes(definition.type)) {
                    return true;
                }
                if (
                    definition.type === 'dataExtension' &&
                    item.r__folder_ContentType !== 'shared_dataextension'
                ) {
                    // only shared DEs need a suffix
                    return true;
                }

                // actual test
                const key = item[definition.keyField] + '';
                if (key) {
                    return key.endsWith(suffix);
                } else {
                    Util.logger.debug('validation-keySuffix: key not found');
                    return true;
                }
            },
        },
    };
}

To control how a custom rule is applied, simply add its name (in the above example, keySuffix) to options.validation like you would for the default rules. Because custom rules are configured in the same way as default rules, you can also use the same override logic for them

    "validation": {
            "retrieve": {
                "keySuffix": "warn",
                "noGuidKeys": "warn",
                "noRootFolder": "warn",
            },
            "buildDefinition": {
                "keySuffix": "warn",
                "noGuidKeys": "warn",
                "no...
Read more

v7.3.1 - Fixes for Salesforce-Entry-Event journeys and for users

30 Aug 11:40
Compare
Choose a tag to compare

Bugfixes

Chores

  • #1631 improve configurationArgument checks incl. common vs contact logic for salesforce data entry events by @JoernBerkefeld in #1632

Special Thanks

Thank you @stijnhoste for pointing out and analyzing the issue of missing timezones that only occurred if you tried to download users and roles together (#1510)!

Full Changelog: v7.3.0...v7.3.1

v7.3.0 - manage journeys

28 Aug 23:23
Compare
Choose a tag to compare

Features

Bugfixes

Chores

Full Changelog: v7.2.0...v7.3.0

Details

Standard Commands

delete

Command: mcdev delete <business unit> [type] [external key] [--metadata]

Alias: mcdev del

Deletes the given metadata from your server. This needs to be run with care as any data stored in the deleted meta-data will be lost.

Currently supported types: Metadata Type Support

Example:

mcdev delete MyProject/_ParentBU_ dataExtension MyUserTable

You can also delete multiple keys at once, even across types:

mcdev delete MyProject/_ParentBU_ -m dataExtension:MyUserTable -m query:myKey -m query:myKey2

mcdev delete MyProject/_ParentBU_ dataExtensionField MyUserTable.MyFieldName

Journeys are somewhat special because they are the only metadata type in SFMC that has versions stored in the platform itself. Therefore, when deleting a journey, you need to specify what version you want to delete - or if you want to delete the journey with all its versions. You achieve that by appending "/3" for deleting version 3 or "/*" for deleting all versions.
You can even provide the journey ID instead of the key. In the first example below, we are trying to delete version 4 of ID "5cfb1bcb-9cb7-42c9-81de-033943bbc18c".

mcdev del MyProject/_ParentBU_  journey id:%235cfb1bcb-9cb7-42c9-81de-033943bbc18c/4
mcdev del MyProject/_ParentBU_ journey id:5cfb1bcb-9cb7-42c9-81de-033943bbc18c/4
mcdev del MyProject/_ParentBU_ -m journey:id:5cfb1bcb-9cb7-42c9-81de-033943bbc18c/4
mcdev del MyProject/_ParentBU_ -m journey:myJourneyKey/4

mcdev del MyProject/_ParentBU_ -m journey:myJourneyKey/*

Note for nerds: When copying the ID from the URL, you might notice it's prefixed with "%23". If you do copy that together with the Id, mcdev del will automatically filter it for you. It, therefore, works with or without the leading "%23".

pause

Command: mcdev pause <business unit> [type] [key] [--like] [--metadata]

Alias: mcdev p

This command lets you pause metadata of a given type and key.

Currently supported types:

Name CLI Argument Effect
Automation automation pauses scheduled automation
Journey journey pauses running journey

Example:

mcdev pause MyProject/DEV automation key1
mcdev pause MyProject/DEV journey key3
mcdev pause MyProject/DEV journey key3/4
mcdev pause MyProject/DEV journey key3/*
mcdev pause MyProject/DEV automation "key1,key2,key3"
mcdev pause MyProject/DEV -m automation:key1 -m automation:key2
mcdev pause MyProject/DEV -m automation:key1 automation:key2 journey:key3

For journeys you can choose to specify a specific version to pause by appending "/4" (to pause version 4) or all versions by appending "/*". If you do not append a version, mcdev will attempt to pause the latest version.

pause with --like operator:

mcdev pause MyProject/DEV automation --like.key "myprefix_%"
mcdev pause MyProject/DEV automation --like.key "myprefix_%" --like.r__folder_Path "Query/Testing%"

pause on all BUs:

This is a variation of pause command that allows you to pause specified items on all BUs. mcdev will look for the items of specified types and keys on all BUs and pause them.

Example:

mcdev pause MyProject/* automation key1
mcdev pause MyProject/* automation "key1,key2,key3"

stop

Command: mcdev stop <business unit> [type] [key] [--like] [--metadata]

Alias: -

This command lets you stop metadata of a given type and key.

Currently supported types:

Name CLI Argument Effect
Journey journey stops running journey

Example:

mcdev stop MyProject/DEV journey key3
mcdev stop MyProject/DEV journey "key1,key2,key3"
mcdev stop MyProject/DEV -m journey:key1 journey:key2

For journeys you can choose to specify a specific version to stop by appending "/4" (to stop version 4). If you do not append a version, mcdev will attempt to stop the latest version. Currently, you cannot stop all versions at once with a single command.

stop with --like operator:

mcdev stop MyProject/DEV journey --like.key "myprefix_%"
mcdev stop MyProject/DEV journey --like.key "myprefix_%" --like.r__folder_Path "my Journeys/Testing%"

stop on all BUs:

This is a variation of stop command that allows you to stop specified items on all BUs. mcdev will look for the items of specified types and keys on all BUs and stop hem.

Example:

mcdev stop MyProject/* journey key1
mcdev stop MyProject/* journey "key1,key2,key3"
mcdev stop MyProject/* -m journey:key1 journey:key2 journey:key3

Templating Commands

build

Command: mcdev build <--buFrom> <--marketFrom> <--buTo> <--marketTo> <--metadata> [--bulk] [--dependencies] [--retrieve]

This combines the power of buildTemplate and buildDefinition in one command, making it easier if you continuously use both commands sequentially.

Example:

// before
mcdev bt MyProject/DEV --market pilotMarketDEV1 -m dataExtension:table1 -m dataExtension:table2 -m dataExtension:table3 -m query:sql1 -m query:sql2
mcdev bd MyProject/QA --market pilotMarketQA1 -m dataExtension:table1 -m dataExtension:table2 -m dataExtension:table3 -m query:sql1 -m query:sql2

// after
mcdev build --buFrom MyProject/DEV --buTo MyProject/QA --marketFrom pilotMarketDEV1 --marketTo pilotMarketQA1 -m dataExtension:name:table1 dataExtension:table2 dataExtension:table3 query:sql1 query:name:sql2

Note how you can also use names instead of keys to select metadata by prefixing the name with "name" (e.g query:name:sql2). That however, only works if the name exists only once. Otherwise, the system will show an error, providing the found keys for you to select.

And if you already have market lists set up and want to use buildDefinitionBulk instead all you need to do is append --bulk:

Example:

// before
mcdev bt MyProject/DEV --market pilotMarketDEV1 -m dataExtension:table1 -m dataExtension:table2 -m dataExtension:table3 -m query:sql1 -m query:sql2
mcdev bdb pilotMarketsQA -m dataExtension:table1 -m dataExtension:table2 -m dataExtension:table3 -m query:sql1 -m query:sql2

// after
mcdev build --buFrom MyProject/DEV --marketFrom pilotMarketDEV1 --marketTo pilotMarketsQA --bulk -m dataExtension:table1 -m dataExtension:table2 -m dataExtension:table3 -m query:sql1 -m query:sql2

Note how in this bulk-example the parameter --buTo MyProject/QA was omitted and that --marketTo pilotMarketsQA now holds the name of the market list that bdb needs to work.

build with --dependencies (and with --retrieve):

These two parameters are passed through to buildTemplate. Please see that commands documentation for details. The resulting list of types & keys of whatever buildTemplate will create are then handed over to buildDefinition(Bulk), making this a powerful solution.

build with multiple chained markets

If you have more complex scenarios that would otherwise require setting up lots of mostly cloned markets. Instead, you may define multiple markets that can combined to form one new set of variables that then get applied.

mcdev build --buFrom MyProject/DEV --marketFrom pilotMarketDEV1 addtionalMarketDEV --marketTo pilotMarketsQA addtionalMarketQA --bulk -m dataExtension:table1 -m dataExtension:table2 -m dataExtension:table3 -m query:sql1 -m query:sql2

This will take pilotMarketDEV1 and add whatever is defined in addtionalMarketDEV. If there is an overlap in defined attributes, whatever market is set second, overwrites what is set first in the command. You can chain as many markets as you want. The order of how the markets are defined in the config does not have an effect.

"markets": {
  "addtionalMarketDEV": {
    "c": 6,
    "d": 4,
    "e": 5,
  },
  "pilotMarketDEV1": {
    "a": 1,
    "b": 2,
    "c": 3,
  }
}

The resulting market would be

  {
    "a": 1,
    "b": 2,
    "c": 6,
    "d": 4,
    "e": 5,
  }

buildTemplate

Command: mcdev buildTemplate <business unit> [type] [key] [market] [--metadata] [--market] [--dependencies] [--retrieve]

Alias: mcdev bt

The bt command uses previously retrieved metadata on your local computer and uses your market c...

Read more

v7.2.0 - Transactional Send Journeys

23 Aug 11:01
Compare
Choose a tag to compare

Feautures

Bugfixes

Chores

Dependencies

New Contributors

Special Thanks

Community member @SanskarVaidya inspired me to revisit how transactionalEmails are created, highlighting that SFMC's GUI creates the journey first, and the transactionalEmail second, once you click on 'Activate', triggering a complete rewrite of the logic for Transactional Journeys in #1592, #1590, #1588, and #1589

Full Changelog: v7.1.4...v7.2.0

v7.1.4

09 Aug 06:26
Compare
Choose a tag to compare

Bugfixes

  • #1536 (regression) fixed error during folder deployments claiming it cannot find the parent folder (which was just created) by @JoernBerkefeld in #1556

Dependencies

Full Changelog: v7.1.3...v7.1.4