Skip to content

Commit 44fe97e

Browse files
author
Adam Rutland
authored
Merge pull request #99 from vlocityinc/feature/build_manifest
Update Readme to include Manifest info. Add ability to build manifest as a command. Better test for breaking JSON responses. Updates for better error handling Show more consistent time. Add "key" as argument alternative to manifest style.
2 parents c38a8bd + 09a197e commit 44fe97e

File tree

15 files changed

+1099
-1125
lines changed

15 files changed

+1099
-1125
lines changed

README.md

Lines changed: 105 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,12 @@ Authentication with Salesforce DX credentials is now possible. Use `-sfdx.userna
5151
* [All Commands](#all-commands)
5252
* [Example Commands](#example-commands)
5353
* [Additional Command Line Options ](#additional-command-line-options)
54-
* [Advanced Job File Settings](#advanced-job-file-settings)
54+
* [Developer Workflow](#developer-workflow)
55+
* [Other Job File Settings](#other-job-file-settings)
5556
* [Supported DataPack Types](#supported-datapack-types)
5657
* [Advanced](#advanced)
5758
* [Matching Keys](#matching-keys)
58-
* [OmniOut](#OmniOut)
59+
* [OmniOut](#omniout)
5960

6061
# Installation Instructions
6162
-----------
@@ -520,17 +521,17 @@ This will provide a list of files that are different locally than in the org. In
520521
-----------
521522

522523
## Primary
523-
`packExport`: Export from a Salesforce org into a DataPack Directory
524-
`packExportSingle`: Export a Single DataPack by Id
525-
`packExportAllDefault`: Export All Default DataPacks as listed in Supported Types Table
526-
`packDeploy`: Deploy all contents of a DataPacks Directory
524+
`packExport`: Export from a Salesforce org into a DataPack Directory
525+
`packExportSingle`: Export a Single DataPack by Id
526+
`packExportAllDefault`: Export All Default DataPacks as listed in Supported Types Table
527+
`packDeploy`: Deploy all contents of a DataPacks Directory
527528

528529
## Troubleshooting
529530
`packContinue`: Continues a job that failed due to an error
530-
`packRetry`: Continues a Job retrying all deploy errors or re-running all export queries
531-
`validateLocalData`: Check for Missing Global Keys in Data.
532-
`cleanOrgData`: Run Scripts to Clean Data in the Org and Add Global Keys to SObjects missing them
533-
`refreshProject`: Refresh the Project's Data to the latest format for this tool
531+
`packRetry`: Continues a Job retrying all deploy errors or re-running all export queries
532+
`validateLocalData`: Check for Missing Global Keys in Data.
533+
`cleanOrgData`: Run Scripts to Clean Data in the Org and Add Global Keys to SObjects missing them
534+
`refreshProject`: Refresh the Project's Data to the latest format for this tool
534535

535536
## Additional
536537
`packGetDiffsAndDeploy`: Deploy only files that are modified compared to the target Org
@@ -667,7 +668,99 @@ The Job file additionally supports some Vlocity Build based options and the opti
667668
| type | DataPack Type used for packExportSingle command | String | none |
668669
| verbose | Show additional logging statements | Boolean | false |
669670

670-
# Advanced Job File Settings
671+
# Developer Workflow
672+
------
673+
When developing on a large project, exporting DataPacks through Queires is not the ideal process. Instead, each developer should keep track of the major items that they are working on and extract those items as needed to commit to Version Control.
674+
675+
## Manifest Driven Workflow
676+
The `manifest` section of the Job File can be used to create a collection of DataPacks to be exported or deployed. Manifests are based on the VlocityDataPackKey of each DataPack.
677+
678+
### VlocityDataPackKey Overview
679+
Each DataPack has a VlocityDataPackKey that represents its Unique Name in the DataPacks system. After Exporting a DataPack this VlocityDataPackKey is also the `VlocityDataPackType/FolderName` of the DataPack.
680+
681+
For Product2 DataPacks, the VlocityDataPackKey is built using the `vlocity_namespace__GlobalKey__c`. Given the Product2:
682+
``` json
683+
{
684+
"%vlocity_namespace%__GlobalKey__c": "7e0b4fa5-4290-d439-ba96-f1a1c3708b0b",
685+
"Family": "Phones",
686+
"IsActive": true,
687+
"Name": "iPhone 6s Plus",
688+
"VlocityDataPackType": "SObject",
689+
"VlocityRecordSObjectType": "Product2"
690+
}
691+
```
692+
693+
The VlocityDataPackKey would be `Product2/7e0b4fa5-4290-d439-ba96-f1a1c3708b0b`. This is also the same as the Folder Name of the Product2 DataPack when saved to the file system. This is because the `GlobalKey__c` of the Product2 is meant to be a unique field, and the Folders must also have unique names.
694+
695+
Here is the `iPhone 6s Plus` Product2 DataPack in its folder with the same VlocityDataPackKey as shown above:
696+
697+
![iPhone6sPlus](doc/iPhone6sPlus.png)
698+
699+
### Using the VlocityDataPackKey in the Manifest
700+
This VlocityDataPackKey can be added to the `manifest` of the Job File to drive Export of this Product along with all its dependencies.
701+
702+
```yaml
703+
projectPath: .
704+
manifest:
705+
- Product2/7e0b4fa5-4290-d439-ba96-f1a1c3708b0b
706+
```
707+
708+
You can see all the available VlocityDataPackKeys for your Manifest by running:
709+
`vlocity packGetAllAvailableExports --nojob`
710+
711+
![GetAllOutput](doc/GetAllOutput.png)
712+
713+
This will additionally create the file `VlocityBuildLog.yaml` which will save all the results in a format that you can move to your job file.
714+
715+
```yaml
716+
manifest:
717+
- AttributeCategory/CLOUD_SERVICES
718+
- AttributeCategory/MOBILE_HANDSET
719+
- AttributeCategory/INTERNET
720+
- AttributeCategory/MOBILE_CONTRACT
721+
- AttributeCategory/MOBILE_TRADE_IN
722+
- AttributeCategory/SIM_CARD
723+
- AttributeCategory/WATCH
724+
- CalculationMatrix/AgeRating
725+
- DataRaptor/Billing Import Bundle
726+
```
727+
728+
### Adding to Job Files
729+
When defining your project through a Manifest, it is best to create 2 Job Files.
730+
731+
1. Export Job File
732+
2. Deploy Job File
733+
734+
#### Export Job File
735+
The Export Job File will be used to *only* export the listed manifest items plus their dependencies. For someone only working on a set of Products, this Job File would look like:
736+
737+
**Export.yaml**
738+
```yaml
739+
projectPath: .
740+
expansionPath: vlocity
741+
manifest:
742+
- Product2/1b1b6c6f-c1b0-1c1d-e068-4651202cb07b
743+
- Product2/6e28982d-57c8-5bd3-e6db-d66c02c20e43
744+
- Product2/7e0b4fa5-4290-d439-ba96-f1a1c3708b0b
745+
- Product2/9a86f5d9-2e05-ef0d-3492-3479db233ef8
746+
```
747+
748+
Running `packExport -job Export.yaml` would also export any DataPacks that these Products depend on by default. To only export the exact manifest you can use `-depth 0` to your command.
749+
750+
#### Deploy Job File
751+
The manifest is also used to control what is deployed, but in the deploy case it will only deploy waht is specified. This allows deploying only a specific set of local folders to the Org, as the VlocityDataPackKeys are the Folder Paths of the DataPacks.
752+
753+
Therefore, it is best to create a second job file for Deploy. This job file only needs projectPath as it will deploy the entire contents of the project by default.
754+
755+
**Deploy.yaml**
756+
``` yaml
757+
projectPath: .
758+
expansionPath: vlocity
759+
```
760+
761+
Running `packDeploy -job Deploy.yaml` will then deploy all of the DataPacks in the `vlocity` folder as there is no manifest being defined.
762+
763+
# Other Job File Settings
671764
------------
672765
The Job File has a number of additonal runtime settings that can be used to define your project and aid in making Exports / Deploys run successfully. However, the Default settings should only be modified to account for unique issues in your Org.
673766

@@ -789,6 +882,7 @@ These types are what would be specified when creating a Query or Manifest for th
789882
| OrchestrationPlanDefinition | OrchestrationPlanDefinition__c |
790883
| Pricebook2<br>(Salesforce Standard Object) | Pricebook2 |
791884
| PriceList | PriceList__c<br>PricingElement__c<br>PricingVariable__c<br>PricingVariableBinding__c |
885+
| PricingPlan | PricingPlan__c<br>PricingPlanStep__c |
792886
| PricingVariable | PricingVariable__c |
793887
| Product2<br>(Salesforce Standard Object) | Product2<br>PricebookEntry<br>AttributeAssignment__c<br>ProductChildItem__c<br>OverrideDefinition__c<br>ProductConfigurationProcedure__c<br>ProductRelationship__c<br>ProductEligibility__c<br>ProductAvailability__c<br>RuleAssignment__c<br>ProductRequirement__c<br>ObjectFieldAttribute__c<br>PricingElement__c<br>PriceListEntry__c<br>DecompositionRelationship__c<br>OrchestrationScenario__c |
794888
| Promotion | Promotion__c<br>PromotionItem__c |
@@ -870,37 +964,6 @@ module.exports = function(vlocity, currentContextData, jobInfo, callback) {
870964
});
871965
```
872966

873-
##### Export by Manifest
874-
If Exporting with a Manifest, each JSON Object will be one entry in the Manifest in the form of:
875-
```yaml
876-
manifest:
877-
VlocityCard:
878-
- Campaign-Story
879-
```
880-
```json
881-
{
882-
"VlocityDataPackType": "VlocityCard",
883-
"Id": "Campaign-Story"
884-
}
885-
```
886-
"Id" is the default JSON key in the Manifest, but Manifests also support YAML Key/Value pair syntax:
887-
```yaml
888-
manifest:
889-
OmniScript:
890-
- Type: Insurance
891-
SubType: Billing
892-
Language: English
893-
```
894-
Which becomes:
895-
```json
896-
{
897-
"VlocityDataPackType": "OmniScript",
898-
"Type": "Insurance",
899-
"SubType": "Billing",
900-
"Language": "English"
901-
}
902-
```
903-
904967
##### Export by Queries
905968
For a Query, each result from the Query will be a JSON Object with the appropriate DataPack Type.
906969
```yaml

codeship/publish.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
#!/usr/bin/env bash
22
set -e
33

4-
./codeship/decryptFiles.sh
5-
6-
cp codeship/unencrypted_files/npmrc .npmrc
7-
8-
if [ $CI_BRANCH == "master" ]; then
9-
npm publish .
10-
else
11-
npm publish . --tag="next"
12-
fi
13-
144
npm run-script build
155

166
P_VERSION=`cat package.json | jq -r '. | .version'`
177

188
GITHUB_ASSETS="dist/vlocity-linux-x64,dist/vlocity-macos-x64,dist/vlocity-win-x64.exe,dist/vlocity-win-x86.exe"
199

10+
./codeship/decryptFiles.sh
11+
2012
if [ $CI_BRANCH == "master" ]; then
2113
publish-release --notes "$P_VERSION" --token $GITHUB --target_commitish $CI_BRANCH --owner vlocityinc --repo vlocity_build --name "v$P_VERSION" --tag "v$P_VERSION" --assets "$GITHUB_ASSETS" --draft
2214
else
2315
publish-release --notes "Beta - v$P_VERSION" --token $GITHUB --target_commitish $CI_BRANCH --prerelease --reuseRelease --owner vlocityinc --repo vlocity_build --name "Beta-v$P_VERSION" --editRelease --tag next --assets "$GITHUB_ASSETS" --draft
16+
fi
17+
18+
cp codeship/unencrypted_files/npmrc .npmrc
19+
20+
if [ $CI_BRANCH == "master" ]; then
21+
npm publish .
22+
else
23+
npm publish . --tag="next"
2424
fi

codeship/test.sh

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env bash
22
set -e
33

4-
# Will recreate all files in codeship/unencrypted_files
54
./codeship/decryptFiles.sh
65

76
SF_AUTH_ORG=`sfdx force:auth:sfdxurl:store -f codeship/unencrypted_files/test.sfdx --json`
@@ -11,4 +10,17 @@ npm run-script unitTest
1110

1211
npm link
1312

14-
vlocity -sfdx.username $SF_USERNAME runTestJob
13+
vlocity -sfdx.username $SF_USERNAME runTestJob
14+
15+
# Must return a JSON with a result
16+
vlocity -sfdx.username $SF_USERNAME runTestJob --json | jq .
17+
18+
npm run-script build
19+
20+
./dist/vlocity-linux-x64 -sfdx.username $SF_USERNAME --nojob packExport -key VlocityCard/datapacktest-card
21+
22+
./dist/vlocity-linux-x64 -sfdx.username $SF_USERNAME --nojob packGetAllAvailableExports --json | jq .
23+
24+
./dist/vlocity-linux-x64 -sfdx.username $SF_USERNAME -projectPath "vlocity-temp" --nojob packExport -key VlocityCard/datapacktest-card
25+
26+
./dist/vlocity-linux-x64 -sfdx.username $SF_USERNAME -projectPath "vlocity-temp" --nojob packDeploy -key VlocityCard/datapacktest-card --json | jq .

doc/GetAllOutput.png

233 KB
Loading

doc/iPhone6sPlus.png

259 KB
Loading
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
module.exports = function(vlocity, dataPackData, jobInfo, callback) {
2-
3-
//console.log(dataPackData);
42
delete dataPackData.VlocityDataPackData.Product2[0].PricebookEntry;
5-
6-
// console.log(JSON.stringify(dataPackData));
73
callback();
84
}

javascript/testDataRaptor.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ module.exports = function(vlocity, dataPackData, jobInfo, callback) {
4040
var currentTime = Date.now();
4141

4242
vlocity.jsForceConnection.apex.post('/' + vlocity.namespace + '/v2/DataRaptor/', body, function(err, result) {
43-
if (err) { return console.error(err); }
43+
if (err) { return VlocityUtils.error(err); }
4444

4545
var thisTime = (Date.now() - currentTime);
4646

47-
console.log(dataRaptorName + ' - ' + ((isRolledBack == "true") ? 'Old' : 'New') +': ' + result.ACTUAL + ' CPU: ' + result.CPU);
47+
VlocityUtils.log(dataRaptorName + ' - ' + ((isRolledBack == "true") ? 'Old' : 'New') +': ' + result.ACTUAL + ' CPU: ' + result.CPU);
4848

4949
totalCpuTime += result.CPU;
5050
totalTime += result.ACTUAL;
5151

5252
timingCallback();
5353
});
5454
}, function(err, result) {
55-
console.log(dataRaptorName + ' - Final Total: ' + totalTime + ' Final Avg: ' + (totalTime / TOTAL_TO_RUN) + ' CPU ' + (totalCpuTime / TOTAL_TO_RUN));
55+
VlocityUtils.log(dataRaptorName + ' - Final Total: ' + totalTime + ' Final Avg: ' + (totalTime / TOTAL_TO_RUN) + ' CPU ' + (totalCpuTime / TOTAL_TO_RUN));
5656
seriesCallback();
5757
});
5858
});

lib/datapacksbuilder.js

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -399,42 +399,44 @@ DataPacksBuilder.prototype.initializeImportStatus = function(importPath, jobInfo
399399
if (dataPackLabel == null || !self.vlocity.datapacksutils.fileExists(metadataFilename)) {
400400
return;
401401
}
402-
403-
self.loadFilesAtPath(path.join(dataPackTypeDir, dataPackName), jobInfo, dataPackKey);
404-
var sobjectData = JSON.parse(self.getFileData(metadataFilename));
405-
var generatedDataPackKey = dataPackType + '/' + self.vlocity.datapacksexpand.getDataPackFolder(dataPackType, sobjectData.VlocityRecordSObjectType, sobjectData);
402+
try {
403+
self.loadFilesAtPath(path.join(dataPackTypeDir, dataPackName), jobInfo, dataPackKey);
404+
var sobjectData = JSON.parse(self.getFileData(metadataFilename));
405+
var generatedDataPackKey = dataPackType + '/' + self.vlocity.datapacksexpand.getDataPackFolder(dataPackType, sobjectData.VlocityRecordSObjectType, sobjectData);
406406

407-
jobInfo.keysToDirectories[generatedDataPackKey] = dataPackType + '/' + dataPackName;
407+
jobInfo.keysToDirectories[generatedDataPackKey] = dataPackType + '/' + dataPackName;
408408

409-
if (self.isInManifest(jobInfo, dataPackType, generatedDataPackKey, dataPackName)) {
410-
411-
if (!jobInfo.currentStatus[generatedDataPackKey]) {
412-
jobInfo.currentStatus[generatedDataPackKey] = 'Ready';
413-
}
409+
if (self.isInManifest(jobInfo, dataPackType, generatedDataPackKey, dataPackName)) {
410+
411+
if (!jobInfo.currentStatus[generatedDataPackKey]) {
412+
jobInfo.currentStatus[generatedDataPackKey] = 'Ready';
413+
}
414414

415-
if (sobjectData.Name) {
416-
jobInfo.generatedKeysToNames[generatedDataPackKey] = sobjectData.Name;
417-
}
415+
if (sobjectData.Name) {
416+
jobInfo.generatedKeysToNames[generatedDataPackKey] = sobjectData.Name;
417+
}
418418

419-
if (jobInfo.allParents.indexOf(generatedDataPackKey) == -1) {
420-
jobInfo.allParents.push(generatedDataPackKey);
421-
}
419+
if (jobInfo.allParents.indexOf(generatedDataPackKey) == -1) {
420+
jobInfo.allParents.push(generatedDataPackKey);
421+
}
422422

423-
var apexImportData = {};
423+
var apexImportData = {};
424424

425-
self.vlocity.datapacksutils.getApexImportDataKeys(sobjectData.VlocityRecordSObjectType).forEach(function(field) {
426-
apexImportData[field] = sobjectData[field];
427-
});
425+
self.vlocity.datapacksutils.getApexImportDataKeys(sobjectData.VlocityRecordSObjectType).forEach(function(field) {
426+
apexImportData[field] = sobjectData[field];
427+
});
428428

429-
apexImportData.VlocityRecordSourceKey = sobjectData.VlocityRecordSourceKey;
430-
jobInfo.preDeployDataSummary.push(apexImportData);
431-
jobInfo.allDataSummary[generatedDataPackKey] = apexImportData;
432-
jobInfo.dataPackKeyToPrimarySourceKey[sobjectData.VlocityRecordSourceKey] = generatedDataPackKey;
429+
apexImportData.VlocityRecordSourceKey = sobjectData.VlocityRecordSourceKey;
430+
jobInfo.preDeployDataSummary.push(apexImportData);
431+
jobInfo.allDataSummary[generatedDataPackKey] = apexImportData;
432+
jobInfo.dataPackKeyToPrimarySourceKey[sobjectData.VlocityRecordSourceKey] = generatedDataPackKey;
433+
}
434+
} catch (e) {
435+
jobInfo.currentStatus[dataPackKey] = 'Error';
436+
jobInfo.hasError = true;
437+
jobInfo.errors.push(`Error Loading >> ${dataPackKey} - ${e.message}`);
438+
VlocityUtils.error('Error Loading', dataPackKey, e.message);
433439
}
434-
// }
435-
// } catch (e) {
436-
// VlocityUtils.error('Error Initializing', dataPackKey, e.stack);
437-
// }
438440
});
439441
});
440442

@@ -446,7 +448,7 @@ DataPacksBuilder.prototype.initializeImportStatus = function(importPath, jobInfo
446448
// Ignore when passed in as type
447449
if (key.indexOf('/') != -1 && !jobInfo.manifestFound[key]) {
448450
jobInfo.hasError = true;
449-
jobInfo.errors.push('Manifest Item Missing >> ' + key)
451+
jobInfo.errors.push('Manifest Item Missing >> ' + key);
450452
VlocityUtils.error('Manifest Item Missing', key);
451453
}
452454
});

0 commit comments

Comments
 (0)