UNPKG

@flxbl-io/sfp

Version:

sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model

181 lines 18.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@salesforce/core"); const SfpCommand_1 = __importDefault(require("../../SfpCommand")); const PrepareImpl_1 = __importDefault(require("../../impl/prepare/PrepareImpl")); const SFPStatsSender_1 = __importDefault(require("../../core/stats/SFPStatsSender")); const Stage_1 = require("../../impl/Stage"); const fs = __importStar(require("fs-extra")); const ScratchOrgInfoFetcher_1 = __importDefault(require("../../core/scratchorg/pool/services/fetchers/ScratchOrgInfoFetcher")); const ajv_1 = __importDefault(require("ajv")); const path = require("path"); const PoolError_1 = require("../../core/scratchorg/pool/PoolError"); const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger")); const GetFormattedTime_1 = __importDefault(require("../../core/utils/GetFormattedTime")); const sfp_logger_2 = require("@flxbl-io/sfp-logger"); const SFPOrg_1 = __importDefault(require("../../core/org/SFPOrg")); const core_2 = require("@oclif/core"); const sfdxflags_1 = require("../../flags/sfdxflags"); core_1.Messages.importMessagesDirectory(__dirname); const messages = core_1.Messages.loadMessages('@flxbl-io/sfp', 'prepare'); class Prepare extends SfpCommand_1.default { async execute() { let executionStartTime = Date.now(); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`command: ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(`prepare`)}`)); //Read pool config try { let poolConfig = fs.readJSONSync(this.flags.poolconfig); this.validatePoolConfig(poolConfig); //Assign Keys to the config if (this.flags.keys) poolConfig.keys = this.flags.keys; this.displayHeader(poolConfig); //Assign npmrcPath to the config if (this.flags.npmrcpath) { if (poolConfig.fetchArtifacts?.npm) poolConfig.fetchArtifacts.npm.npmrcPath = this.flags.npmrcpath; else sfp_logger_1.default.log((0, sfp_logger_2.COLOR_WARNING)('npmrcPath found in flag, however the configuration doesnt seem to use npm, Are you sure your schema is good?')); } let tags = { stage: Stage_1.Stage.PREPARE, poolName: poolConfig.tag, }; await this.hubOrg.refreshAuth(); const hubConn = this.hubOrg.getConnection(); this.flags.apiversion = this.flags.apiversion || (await hubConn.retrieveMaxApiVersion()); let hubOrgAsSfPOrg = await SFPOrg_1.default.create({ connection: this.hubOrg.getConnection() }); let prepareImpl = new PrepareImpl_1.default(hubOrgAsSfPOrg, poolConfig, this.flags.loglevel); let results = await prepareImpl.exec(); if (results.isOk()) { let totalElapsedTime = Date.now() - executionStartTime; sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_SUCCESS)(`Provisioned {${results.value.scratchOrgs.length}} scratchorgs out of ${results.value.to_allocate} requested with ${(0, sfp_logger_1.COLOR_ERROR)(results.value.failedToCreate)} failed in ${(0, sfp_logger_1.COLOR_TIME)((0, GetFormattedTime_1.default)(totalElapsedTime))} `)); sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO); await this.getCurrentRemainingNumberOfOrgsInPoolAndReport(poolConfig); SFPStatsSender_1.default.logGauge('prepare.succeededorgs', results.value.scratchOrgs.length, tags); if (results.value.scratchOrgs.length > 0) SFPStatsSender_1.default.logGauge('prepare.duration', Date.now() - executionStartTime, tags); } else if (results.isErr()) { sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_ERROR)(results.error.message), sfp_logger_1.LoggerLevel.ERROR); sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO); switch (results.error.errorCode) { case PoolError_1.PoolErrorCodes.Max_Capacity: process.exitCode = 0; break; case PoolError_1.PoolErrorCodes.No_Capacity: process.exitCode = 0; break; case PoolError_1.PoolErrorCodes.PrerequisiteMissing: process.exitCode = 1; break; case PoolError_1.PoolErrorCodes.UnableToProvisionAny: SFPStatsSender_1.default.logGauge('prepare.failedorgs', results.error.failed, tags); process.exitCode = 1; break; } } } catch (err) { throw new Error('Unable to execute command .. ' + err); } } displayHeader(poolConfig) { sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Pool Name: ${poolConfig.tag}`)); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Requested Count of Orgs: ${poolConfig.maxAllocation}`)); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Scratch Orgs to be submitted to pool in case of failures: ${poolConfig.succeedOnDeploymentErrors ? 'true' : 'false'}`)); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`All packages in the repo to be installed: ${poolConfig.installAll ? 'true' : 'false'}`)); sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Enable Source Tracking: ${poolConfig.enableSourceTracking || poolConfig.enableSourceTracking === undefined ? 'true' : 'false'}`)); if (poolConfig.enableVlocity) sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Enable Vlocity Config: true`)); if (poolConfig.fetchArtifacts) { if (poolConfig.fetchArtifacts.artifactFetchScript) sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Script provided to fetch artifacts: ${poolConfig.fetchArtifacts.artifactFetchScript}`)); if (poolConfig.fetchArtifacts.npm) { sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Fetch artifacts from pre-authenticated NPM registry: true`)); } } sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO); } async getCurrentRemainingNumberOfOrgsInPoolAndReport(poolConfig) { try { const results = await new ScratchOrgInfoFetcher_1.default(this.hubOrg).getScratchOrgsByTag(this.flags.tag, false, true); let tags = { stage: Stage_1.Stage.PREPARE, poolName: poolConfig.tag, }; let availableSo = results.records.filter((soInfo) => soInfo.Allocation_status__c === 'Available'); SFPStatsSender_1.default.logGauge('pool.available', availableSo.length, tags); } catch (error) { //do nothing, we are not reporting anything if anything goes wrong here } } validatePoolConfig(poolConfig) { let ajv = new ajv_1.default({ allErrors: true }); let schema = fs.readJSONSync(path.join(__dirname, '..', '..', '..', 'resources', 'schemas', 'pooldefinition.schema.json'), { encoding: 'UTF-8' }); let validator = ajv.compile(schema); let isSchemaValid = validator(poolConfig); if (!isSchemaValid) { let errorMsg = `The pool configuration is invalid, Please fix the following errors\n`; validator.errors.forEach((error, errorNum) => { errorMsg += `\n${errorNum + 1}: ${error.instancePath}: ${error.message} ${JSON.stringify(error.params, null, 4)}`; }); throw new Error(errorMsg); } } } Prepare.aliases = ['orchestrator:prepare', 'prepare']; Prepare.requiresDevhubUsername = true; Prepare.requiresProject = true; Prepare.flags = { targetdevhubusername: sfdxflags_1.targetdevhubusername, poolconfig: core_2.Flags.file({ required: false, default: 'config/poolconfig.json', char: 'f', description: messages.getMessage('poolConfigFlagDescription'), }), npmrcpath: core_2.Flags.file({ description: messages.getMessage('npmrcPathFlagDescription'), required: false, }), keys: core_2.Flags.string({ required: false, description: messages.getMessage('keysDescription'), }), logsgroupsymbol: sfdxflags_1.logsgroupsymbol, loglevel: sfdxflags_1.loglevel }; Prepare.description = messages.getMessage('commandDescription'); Prepare.examples = [`$ sfp prepare -f config/mypoolconfig.json -v <devhub>`]; exports.default = Prepare; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlcGFyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9wb29sL3ByZXBhcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJDQUE0QztBQUM1QyxrRUFBMEM7QUFDMUMsaUZBQXlEO0FBQ3pELHFGQUE2RDtBQUM3RCw0Q0FBeUM7QUFDekMsNkNBQStCO0FBQy9CLCtIQUF1RztBQUN2Ryw4Q0FBc0I7QUFDdEIsNkJBQThCO0FBQzlCLG9FQUFzRTtBQUN0RSxtRUFPOEI7QUFDOUIseUZBQWlFO0FBRWpFLHFEQUFxRDtBQUNyRCxtRUFBMkM7QUFDM0Msc0NBQW9DO0FBQ3BDLHFEQUF3RjtBQUV4RixlQUFRLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDNUMsTUFBTSxRQUFRLEdBQUcsZUFBUSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFFbkUsTUFBcUIsT0FBUSxTQUFRLG9CQUFVO0lBK0JwQyxLQUFLLENBQUMsT0FBTztRQUNoQixJQUFJLGtCQUFrQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVwQyxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxJQUFBLHlCQUFZLEVBQUMsWUFBWSxJQUFBLDhCQUFpQixFQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRXhFLGtCQUFrQjtRQUNsQixJQUFJLENBQUM7WUFDRCxJQUFJLFVBQVUsR0FBZSxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3BDLDJCQUEyQjtZQUMzQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSTtnQkFBRSxVQUFVLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENB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