UNPKG

qforce

Version:

Commands to help with salesforce development.

212 lines (211 loc) 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const command_1 = require("@oclif/command"); const cli_ux_1 = require("cli-ux"); const utility_1 = require("../../helper/utility"); const path = require('path'); const fs = require('fs'); const execa = require('execa'); const YAML = require('yaml'); const sfdx = require('sfdx-node'); const xmljs = require('xml-js'); const _ = require('lodash'); class DevRelease extends command_1.Command { async run() { const { args, flags } = this.parse(DevRelease); cli_ux_1.default.action.start('Working on release'); let settings, sfdxConfig; if (fs.existsSync(utility_1.getAbsolutePath('.qforce/settings.json'))) { settings = JSON.parse(fs.readFileSync(utility_1.getAbsolutePath('.qforce/settings.json'))); } if (fs.existsSync(path.join(process.cwd(), '.sfdx', 'sfdx-config.json'))) { sfdxConfig = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.sfdx', 'sfdx-config.json'))); } const targetusername = flags.username || settings.targetusername || sfdxConfig.defaultusername; const releaseYamlPath = settings.releaseYamlPath || '.qforce/releases'; const releaseMetaPath = settings.releaseMetaPath || '.qforce/releases'; const featureYamlPath = settings.featureYamlPath || '.qforce/features'; let releaseName = args.releaseName.replace('/', '-'); if (flags.start) { let yamlPath = `${releaseYamlPath}/${releaseName}/${releaseName}.yml`; if (!fs.existsSync(path.dirname(yamlPath))) { fs.mkdirSync(path.dirname(yamlPath), { recursive: true }); } if (!fs.existsSync(yamlPath)) { fs.writeFileSync(utility_1.getAbsolutePath(yamlPath), YAML.stringify({ features: [], manualSteps: [], components: [] }), { encoding: 'utf-8' }); } let command = `code ${releaseYamlPath}/${releaseName}/${releaseName}.yml`; execa.commandSync(command); } let yamlPath = `${releaseYamlPath}/${releaseName}/${releaseName}.yml`; if (!fs.existsSync(utility_1.getAbsolutePath(yamlPath))) { cli_ux_1.default.action.stop('File not found. Check file path. Remember to start a feature first.'); } const releaseYaml = YAML.parse(fs.readFileSync(yamlPath, 'utf-8')); //cli.action.start(releaseYaml.features) const retrievePathBase = `${releaseMetaPath}/${releaseName}/metadata`; if (flags.addFeature) { cli_ux_1.default.action.start('Adding feature to the release'); let featureList = flags.addFeature.split(','); releaseYaml.features = _.union(releaseYaml.features, featureList); fs.writeFileSync(utility_1.getAbsolutePath(yamlPath), YAML.stringify(releaseYaml), { encoding: 'utf-8' }); cli_ux_1.default.action.stop(); } if (flags.removeFeature) { cli_ux_1.default.action.start('Adding feature to the release'); let featureList = flags.removeFeature.split(','); releaseYaml.features = _.without(releaseYaml.features, ...featureList); fs.writeFileSync(utility_1.getAbsolutePath(yamlPath), YAML.stringify(releaseYaml), { encoding: 'utf-8' }); cli_ux_1.default.action.stop(); } if (flags.build || flags.addFeature || flags.removeFeature) { cli_ux_1.default.action.start('Building release components.'); releaseYaml.components = {}; for (let feature of releaseYaml.features) { //cli.action.start('processing ' + feature) let featureName = feature.replace('/', '-'); let featurePath = `${featureYamlPath}/${featureName}/${featureName}.yml`; if (fs.existsSync(utility_1.getAbsolutePath(featurePath))) { //cli.action.start('processing path ' + featurePath) let featureYaml = YAML.parse(fs.readFileSync(featurePath, 'utf-8')); for (let key in featureYaml) { if (key == 'ManualSteps') { if (!releaseYaml.manualSteps) releaseYaml.manualSteps = []; releaseYaml.manualSteps = _.union(releaseYaml.manualSteps, featureYaml[key]); releaseYaml.manualSteps = _.uniqWith(releaseYaml.manualSteps, _.isEqual); } else { if (!featureYaml[key]) featureYaml[key] = []; if (!releaseYaml.components[key]) releaseYaml.components[key] = []; releaseYaml.components[key] = _.union(releaseYaml.components[key], featureYaml[key]); } } } else { cli_ux_1.default.action.stop(`${feature} not found at path ${featurePath}`); } } fs.writeFileSync(utility_1.getAbsolutePath(yamlPath), YAML.stringify(releaseYaml), { encoding: 'utf-8' }); cli_ux_1.default.action.stop(); } let releaseXML = utility_1.yaml2xml(releaseYaml.components, '50.0'); let xmlOptions = { spaces: 4, compact: false, declerationKey: 'decleration', attributesKey: 'attributes' }; fs.writeFileSync(utility_1.getAbsolutePath(yamlPath.replace(/yml$/i, 'xml')), xmljs.js2xml(releaseXML, xmlOptions), { encoding: 'utf-8' }); if (flags.retrieve) { cli_ux_1.default.action.start('Retrieving package for ' + args.featureName); await sfdx.source.retrieve({ manifest: yamlPath.replace(/yml$/i, 'xml'), targetusername: targetusername, _quiet: false, _rejectOnError: true }).then((result) => { this.log(result); for (let file of result.inboundFiles) { let retrievePath = `${retrievePathBase}/${file.filePath}`; if (!fs.existsSync(path.dirname(retrievePath))) { fs.mkdirSync(path.dirname(retrievePath), { recursive: true }); } fs.copyFileSync(file.filePath, retrievePath); this.log('Retrieved ' + file.filePath); } }).catch((error) => { this.log(error); }); } if (flags.retrieve && false) { cli_ux_1.default.action.start('Retrieving release ' + args.releaseName); let components = releaseYaml.components; if (!components) cli_ux_1.default.action.stop('No components defined. Execute qforce release --build releaseName'); for (let metadataType in components) { if (metadataType == 'ManualStep') continue; this.log(`Retrieving metadatType: ${metadataType}`); if (components[metadataType]) { for (let metadataName of components[metadataType]) { this.log(`Retrieving: ${metadataType}:${metadataName}`); await sfdx.source.retrieve({ metadata: `${metadataType}:${metadataName}`, targetusername: targetusername, json: true, _quiet: false, _rejectOnError: true }).then((result) => { if (!result.inboundFiles.length) { this.log(`\n\nCould not retrieve ${metadataType}:${metadataName}\n\n`); } for (let file of result.inboundFiles) { let retrievePath = `${retrievePathBase}/${file.filePath}`; if (!fs.existsSync(path.dirname(retrievePath))) { fs.mkdirSync(path.dirname(retrievePath), { recursive: true }); } fs.copyFileSync(file.filePath, retrievePath); //this.log('Retrieved ' + file.filePath) } }).catch((error) => { this.log(`Could Not retrieve ${metadataType}:${metadataName}`); //this.log(error) }); } } else { await sfdx.source.retrieve({ metadata: metadataType, targetusername: targetusername, json: true, _quiet: false, _rejectOnError: true }).then((result) => { if (!result.inboundFiles.length) { this.log(`\n\nCould not retrieve ${metadataType}\n\n`); } for (let file of result.inboundFiles) { let retrievePath = `${retrievePathBase}/${file.filePath}`; if (!fs.existsSync(path.dirname(retrievePath))) { fs.mkdirSync(path.dirname(retrievePath), { recursive: true }); } fs.copyFileSync(file.filePath, retrievePath); this.log('Retrieved ' + file.filePath); } }).catch((error) => { this.log(error); }); } } } if (flags.deploy) { sfdx.source.deploy({ targetusername: targetusername, manifest: yamlPath.replace(/yml$/i, 'xml'), json: true, _rejectOnError: true, _quiet: true }) .then((result) => { cli_ux_1.default.action.stop(JSON.stringify(result, null, 4)); }).catch((error) => { cli_ux_1.default.action.stop(JSON.stringify(error, null, 4)); }); } } } exports.default = DevRelease; DevRelease.description = 'To manage yml based release build, retrieve and deploy.'; DevRelease.aliases = ['release', 'dev:release']; DevRelease.flags = { help: command_1.flags.help({ char: 'h' }), start: command_1.flags.boolean({ char: 's', description: 'Start a new release. Will create YAML file and folder if not already exist.' }), build: command_1.flags.boolean({ char: 'b', description: 'To recalculate components based on features listed.' }), retrieve: command_1.flags.boolean({ char: 'r', description: 'Retrieve source based on YAML configuration.' }), deploy: command_1.flags.boolean({ char: 'd', description: 'Deploys source already retrieved.' }), username: command_1.flags.string({ char: 'u' }), addFeature: command_1.flags.string({ char: 'a', description: 'Adds one or more features to the release specified.' }), removeFeature: command_1.flags.string({ char: 'R', description: 'Removes one or more features from the release specified.' }), }; DevRelease.args = [{ name: 'releaseName' }];