UNPKG

ci-sf-plugin

Version:

Set of commands making CI and dev's life easier.

106 lines 5.12 kB
/* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ import * as os from 'os'; import * as util from 'util'; import * as childProcess from 'child_process'; import { readFileSync } from 'fs'; import { SfCommand, Flags, requiredOrgFlagWithDeprecations } from '@salesforce/sf-plugins-core'; import { Messages, SfError } from '@salesforce/core'; import { ux } from '@oclif/core'; // promisify child process const execSync = util.promisify(childProcess.exec); Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); // Load the specific messages for this file. Messages from @salesforce/command, @salesforce/core, // or any library that is using the messages framework can also be loaded this way. const messages = Messages.loadMessages('ci-sf-plugin', 'apex.execute'); export default class Execute extends SfCommand { static description = messages.getMessage('commandDescription'); static examples = messages.getMessage('examples').split(os.EOL); static flags = { 'target-org': requiredOrgFlagWithDeprecations, // flag with a value (-n, --name=VALUE) 'pre-push': Flags.boolean({ default: false, description: messages.getMessage('prepushFlagDescription') }), 'post-push': Flags.boolean({ default: false, description: messages.getMessage('postpushFlagDescription') }), 'ci-config-file': Flags.file({ char: 'x', default: 'ciconfig.json', description: messages.getMessage('ciconfigfileFlagDescription') }) }; // Set this to true if your command requires a project workspace; 'requiresProject' is false by default static requiresProject = false; async run() { try { const { flags } = await this.parse(Execute); // fetch needed flags const targetOrgUsername = flags['target-org'].getUsername(); const prePushFlag = flags['pre-push']; const postPushFlag = flags['post-push']; const ciConfigFileFlag = flags['ci-config-file']; ux.action.start(messages.getMessage('infoExecution', [targetOrgUsername]), 'in progress', { stdout: true }); // load configuration let apexScripts = []; if (prePushFlag === postPushFlag) { throw new Error(`Specify either 'prepush' or 'postpush' flag, not both.`); } else { const propertyKey = prePushFlag ? 'apexPrePush' : 'apexPostPush'; const config = JSON.parse(readFileSync(ciConfigFileFlag, 'utf-8')); if (!config[propertyKey] || !Array.isArray(config[propertyKey])) { throw new Error(`'${propertyKey}' property is missing in the '${ciConfigFileFlag}' file, or is not an array.`); } apexScripts = config[propertyKey]; } const output = { stdout: [], stderr: [] }; let errorMessage = ''; for (const apexScript of apexScripts) { // build the command, without --json to see details const commandStr = `sf apex run --file ${apexScript} --target-org ${targetOrgUsername}`; // execute and print output const commandPromise = execSync(commandStr, { encoding: 'utf8', maxBuffer: 1024 * 1024 }); commandPromise.child.stdout.on('data', (data) => { if (data?.trim()) { const dataOutput = []; data.trim().split('\n').forEach(line => { if (line.startsWith('Error')) { errorMessage += line + '\n'; // make this task fail } if (!line.includes('|HEAP_ALLOCATE|')) { // filter useful info dataOutput.push(line); } }); process.stdout.write(dataOutput.join('\n')); // prints simplified SF console log } }); commandPromise.child.stderr.on('data', (data) => { if (data?.trim()) { // nothing to do } }); const { stdout, stderr } = await commandPromise; output.stdout.push(stdout); output.stderr.push(stderr); } if (errorMessage) { // abort task based on stdout of anonymous apex above throw new Error(errorMessage); } ux.action.stop('done'); // Return an object return { output }; } catch (error) { ux.action.stop('failed'); throw new SfError(messages.getMessage('errorExecutionFailed', [JSON.stringify(error, null, 2)])); } } } //# sourceMappingURL=execute.js.map