Skip to content

Commit 6a5aa9d

Browse files
committed
Added feature of metadata deploy result panel
Fixed bug of custom fields metadata query
1 parent 6bf23f5 commit 6a5aa9d

File tree

9 files changed

+462
-34
lines changed

9 files changed

+462
-34
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"font-awesome": "^5.0.13",
1818
"moment": "^2.22.2",
1919
"js-xlsx": "^0.14.0",
20-
"xlsx-populate": "^1.17.0"
20+
"xlsx-populate": "^1.17.0",
21+
"progressbar.js": "^1.0.1"
2122
}
2223
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "pipeline",
33
"description": "Be less busy, less mistake in Salesforce metadata deploy",
4-
"version": "1.2.0",
4+
"version": "1.3.0",
55
"private": false,
66
"main": "src/main.js",
77
"dependencies": {

src/class/Pipeline.js

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -173,19 +173,58 @@ class Pipeline {
173173
ev.sender.send('data-pipeline-log-callback',utils.serialize(err), result);
174174
}
175175
try{
176-
let index = 1;
177-
176+
let pipeline = this.storage.get(arg.id);
177+
if(pipeline.deployResult && pipeline.deployResult.done != true) {
178+
// Uncompleted deploy, clean cache and reload
179+
this.storage.getAll({ cache : false });
180+
pipeline = this.storage.get(arg.id);
181+
}
178182
const metadata = new Metadata();
179183
const pPath = metadata.getPipelineFolder();
180-
const logPath = path.join(pPath, arg.id, 'pipeline.log');
184+
const logPath = path.join(pPath, pipeline.id, 'pipeline.log');
181185
if(!fs.existsSync(logPath)) {
182186
return callback(null);
183187
}
184188
fs.readFile(logPath, 'utf-8', function(err, data) {
185189
//console.log('>>> getPipelineLog' + index, (new Date()));
186-
index++;
187190
if(err) return callback(err);
188-
const result = data;
191+
// read deployResult
192+
const drPath = path.join(pPath, pipeline.id, 'deployResult.json');
193+
let deployResult = {};
194+
if(fs.existsSync(drPath)) {
195+
deployResult = JSON.parse(fs.readFileSync(drPath));
196+
}
197+
const result = { body : data, deployResult : deployResult };
198+
return callback(null, result);
199+
});
200+
}catch(err) {
201+
console.error('[ERROR]', err);
202+
Raven.captureException(err);
203+
return callback(err);
204+
}
205+
}
206+
207+
/**
208+
* Export pipeline metadata zip file
209+
* @param {Object} ev
210+
* @param {Object} arg
211+
*/
212+
exportMetadata(ev, arg) {
213+
const callback = function(err, result) {
214+
ev.sender.send('data-pipeline-export-metadata-callback',utils.serialize(err), result);
215+
}
216+
try{
217+
const metadata = new Metadata();
218+
const pPath = metadata.getPipelineFolder();
219+
const packagePath = path.join(pPath, arg.id, 'package.zip');
220+
if(!fs.existsSync(packagePath)) {
221+
return callback(null);
222+
}
223+
fs.readFile(packagePath, 'base64', function(err, data) {
224+
//new Buffer(data).toString('base64')
225+
//console.log('>>> getPipelineLog' + index, (new Date()));
226+
if(err) return callback(err);
227+
const result = { data : data };
189228
return callback(null, result);
190229
});
191230
}catch(err) {
@@ -229,6 +268,7 @@ class Pipeline {
229268
const pPath = metadata.mkdirPipelineFolder(pipeline.id);
230269

231270
const logPath = path.join(pPath, 'pipeline.log');
271+
const deployResultPath = path.join(pPath, 'deployResult.json');
232272
const pipelineLog = function(line) {
233273
line = moment().format('HH:mm:ss') + ' ' + line + '\n';
234274
fs.appendFileSync(logPath, line);
@@ -288,20 +328,22 @@ class Pipeline {
288328
// Do Destruct
289329
opts['purgeOnDelete'] = true;
290330
return metadata.deploy(fromConn, zipPath, opts, function(deployResult) {
331+
deployResult = self.saveDeployResult(deployResultPath, fromConn, deployResult);
291332
self.outputDeployProcessLog(pipelineLog, deployResult);
292333
});
293334
} else {
294335
// Do Deploy
295336
opts['runAllTests'] = (pipeline.runTests === true);
296337
return metadata.deploy(toConn, zipPath, opts, function(deployResult) {
338+
deployResult = self.saveDeployResult(deployResultPath, toConn, deployResult);
297339
self.outputDeployProcessLog(pipelineLog, deployResult);
298340
});
299341
}
300342
})
301343
.then(function(deployResult) {
302344
// Save deploy result
303345
const targetConn = (pipeline.action == 'destruct') ? fromConn : toConn;
304-
deployResult['url'] = targetConn.instanceUrl + '/changemgmt/monitorDeploymentsDetails.apexp?asyncId=' + deployResult.id
346+
deployResult = self.saveDeployResult(deployResultPath, targetConn, deployResult);
305347
self.outputDeployLog(pipelineLog, deployResult);
306348
const now = new Date();
307349
const endTime = now.toISOString();
@@ -366,18 +408,53 @@ class Pipeline {
366408
* @param {Object} deployResult
367409
*/
368410
outputDeployLog(pipelineLog, deployResult) {
369-
pipelineLog('[Metadata] Deploy Done : ');
370-
//pipelineLog(' Id: ' + deployResult.id);
371-
pipelineLog(' Success: ' + deployResult.success);
372-
pipelineLog(' Components Total: ' + deployResult.numberComponentsTotal);
373-
pipelineLog(' Components Error: ' + deployResult.numberComponentErrors);
374-
pipelineLog(' Components Deployed: ' + deployResult.numberComponentsDeployed);
375-
pipelineLog(' Tests Total: ' + deployResult.numberTestsTotal);
376-
pipelineLog(' Tests Error: ' + deployResult.numberTestErrors);
377-
pipelineLog(' Tests Completed: ' + deployResult.numberTestsCompleted);
411+
pipelineLog('[Metadata] Deploy done');
378412
pipelineLog('[Metadata] Deploy result: @see ' + deployResult.url);
379413
}
380414

415+
/**
416+
* Set component type label to deploy result and export to json file
417+
*/
418+
saveDeployResult(filePath, targetConn, deployResult) {
419+
// Set Entity Label to deployResult
420+
const sfdcApi = new SfdcApi(targetConn);
421+
const componentLables = sfdcApi.getComponentLabels(targetConn.language);
422+
deployResult['instanceUrl'] = targetConn.instanceUrl;
423+
deployResult['url'] = targetConn.instanceUrl + '/changemgmt/monitorDeploymentsDetails.apexp?asyncId=' + deployResult.id
424+
425+
const getStatus = function(cmp) {
426+
let status = 'No Change';
427+
if(cmp.changed == 'true') status = 'Updated';
428+
if(cmp.created == 'true') status = 'Created';
429+
if(cmp.deleted == 'true') status = 'Deleted';
430+
if(cmp.problem && cmp.problemType) {
431+
status = 'Error: ' + cmp.problem + ' (line ' + (cmp.lineNumber || 0) + ', column ' + (cmp.columnNumber || 0) + ')';
432+
}
433+
return status;
434+
}
435+
436+
if(deployResult.details && deployResult.details.componentSuccesses) {
437+
for(let i = 0; i < deployResult.details.componentSuccesses.length; i++) {
438+
let componentType = deployResult.details.componentSuccesses[i].componentType;
439+
if(utils.isBlank(componentType)) continue;
440+
if(!componentLables.hasOwnProperty(componentType)) continue;
441+
deployResult.details.componentSuccesses[i]['componentTypeLabel'] = componentLables[componentType];
442+
deployResult.details.componentSuccesses[i]['status'] = getStatus(deployResult.details.componentSuccesses[i]);
443+
}
444+
}
445+
if(deployResult.details && deployResult.details.componentFailures) {
446+
for(let i = 0; i < deployResult.details.componentFailures.length; i++) {
447+
let componentType = deployResult.details.componentFailures[i].componentType;
448+
if(utils.isBlank(componentType)) continue;
449+
if(!componentLables.hasOwnProperty(componentType)) continue;
450+
deployResult.details.componentFailures[i]['componentTypeLabel'] = componentLables[componentType];
451+
deployResult.details.componentSuccesses[i]['status'] = getStatus(deployResult.details.componentSuccesses[i]);
452+
}
453+
}
454+
fs.writeFileSync(filePath, JSON.stringify(deployResult));
455+
return deployResult;
456+
}
457+
381458
}
382459

383460
module.exports = Pipeline;

src/class/SfdcApi.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,9 @@ class SfdcApi {
468468
let metaType;
469469
if(!Array.isArray(metadata)) console.log('[ERROR]', metadata);
470470
for(let meta of metadata) {
471+
// Filter object which has not fields,
472+
// to fix sf:UNKNOWN_EXCEPTION: UNKNOWN_EXCEPTION bug
473+
if(!objLabelMap.hasOwnProperty(meta.fullName)) continue;
471474
metaType = meta.type;
472475
fullNames.push(meta.fullName);
473476
}

src/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ ipc.on('data-pipelines', (event, arg) => {
119119
ipc.on('data-pipeline-log', (event, arg) => {
120120
pipeline.getPipelineLog(event, arg);
121121
});
122+
ipc.on('data-pipeline-export-metadata', (event, arg) => {
123+
pipeline.exportMetadata(event, arg);
124+
});
122125
ipc.on('pipeline-run', (event, arg) => {
123126
pipeline.runPipeline(event, arg);
124127
});

src/view/css/style.css

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@
9898
#sidebar .sidebar-body .menu-button .slds-icon {
9999
fill: #16325c;
100100
}
101+
#sidebar .sidebar-body .menu.fix-bottom {
102+
position: absolute;
103+
bottom: 5px;
104+
}
105+
#sidebar .sidebar-body .menu.fix-bottom .github-button{
106+
font-size: 1.4rem;
107+
}
108+
101109
/**
102110
* #main
103111
*/
@@ -443,23 +451,107 @@
443451
.pipeline-detail .detail-header .status .duration{
444452
margin-right: 0.5rem;
445453
}
446-
.pipeline-detail .detail-body{
454+
/** .detail-process-panel */
455+
.pipeline-detail .detail-process-panel{
456+
margin: 0.5rem;
457+
height: 200px;
458+
background-color: #F4F6F9;
459+
color: #514f4d;
460+
font-size: 0.9rem;
461+
line-height: 1.5rem;
462+
}
463+
.pipeline-detail .detail-process-panel .slds-card__body {
464+
margin-bottom: 0px;
465+
}
466+
.pipeline-detail .detail-process-panel .process-detail,
467+
.pipeline-detail .detail-process-panel .component-progress,
468+
.pipeline-detail .detail-process-panel .testclass-progress {
469+
padding: 18px 5px 18px 18px;
470+
}
471+
.pipeline-detail .detail-process-panel .progressbar__label {
472+
line-height: 1.2;
473+
}
474+
.pipeline-detail .detail-process-panel .process-detail label {
475+
color: #16325c;
476+
}
477+
.pipeline-detail .detail-process-panel .component-progress {
478+
border-left: 1px solid #d8dde6;
479+
height: 100%;
480+
}
481+
.pipeline-detail .detail-process-panel .circle {
482+
width: 120px;
483+
height: 120px;
484+
text-align: center;
485+
margin: 0 auto;
486+
}
487+
.pipeline-detail .detail-process-panel .circle > svg {
488+
width: 100%;
489+
display: block;
490+
}
491+
.pipeline-detail .detail-process-panel h3.title {
492+
text-align: center;
493+
margin-top: 1rem;
494+
font-size: 1.1rem;
495+
}
496+
497+
/** .detail-process-panel */
498+
.pipeline-detail .detail-component-panel {
499+
margin: 0.5rem;
500+
background-color: #F4F6F9;
501+
color: #514f4d;
502+
height: calc(100% - 224px); /* 200px + 24px */
503+
overflow-y: auto;
504+
}
505+
.pipeline-detail .detail-component-panel .slds-card__header {
506+
padding-top: 0.5rem;
507+
margin-bottom: 0.5rem;
508+
}
509+
510+
.pipeline-detail .detail-component-panel .slds-truncate {
511+
white-space: normal;
512+
min-height: 1rem;
513+
}
514+
515+
.pipeline-detail .pipeline-log{
516+
position: relative;
447517
display: block;
448518
height: calc(100% - 50px);
449-
padding: 0.5rem 1rem;
450-
line-height: 1.25rem;
451-
overflow-y: scroll;
519+
overflow: hidden;
452520
}
453-
.pipeline-detail .detail-body p{
521+
.pipeline-detail .pipeline-log.collapsed {
522+
height: 110px;
523+
}
524+
.pipeline-detail .pipeline-log > .btn-collapse {
525+
position: absolute;
526+
right: 3px;
527+
top: 3px;
528+
padding: 3px;
529+
}
530+
.pipeline-detail .pipeline-log p{
454531
word-wrap: break-word;
455532
word-break: break-all;
533+
display: block;
534+
height: 100%;
535+
overflow-y: auto;
536+
padding: 0.5rem 1rem;
537+
line-height: 1.25rem;
456538
}
457-
.pipeline-detail .detail-body p > a,
458-
.pipeline-detail .detail-body p > a:hover,
459-
.pipeline-detail .detail-body p > a:focus{
539+
.pipeline-detail .pipeline-log p > a,
540+
.pipeline-detail .pipeline-log p > a:hover,
541+
.pipeline-detail .pipeline-log p > a:focus{
460542
color: #dce5f5;
461543
text-decoration: underline;
462544
}
545+
/* Detail body */
546+
.pipeline-detail .detail-body {
547+
height: calc(100% - 160px);
548+
overflow: hidden;
549+
border-bottom: 1px solid #d8dde6;
550+
}
551+
.pipeline-detail .detail-body .btn-export-metadata {
552+
margin-top: 0.5rem;
553+
}
554+
463555
#main .pipeline-detail .pipeline-status.success{
464556
color: #4bc076;
465557
}

src/view/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ <h1 class="">{{ page.title }}</h1>
4646
<script type="text/javascript" src="components/moment/min/moment-with-locales.min.js"></script>
4747
<script type="text/javascript" src="components/xlsx-populate/browser/xlsx-populate.min.js"></script>
4848
<script type="text/javascript" src="components/js-xlsx/dist/xlsx.full.min.js"></script>
49+
<script type="text/javascript" src="components/progressbar.js/dist/progressbar.min.js"></script>
4950
<script type="text/javascript" src="js/include/ExcelHandler.js"></script>
5051
<script type="text/javascript" src="js/include/master.js"></script>
5152
<script type="text/javascript" src="js/include/ga.js"></script>

0 commit comments

Comments
 (0)