sfdx-hardis
Version:
Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards
239 lines (227 loc) • 9.82 kB
JavaScript
/* jscpd:ignore-start */
import { SfCommand, Flags, requiredOrgFlagWithDeprecations } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import c from 'chalk';
import { execCommand, uxLog, uxLogTable } from '../../../../common/utils/index.js';
import { CONSTANTS, getConfig, getEnvVar } from '../../../../config/index.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('sfdx-hardis', 'org');
export default class MonitorAll extends SfCommand {
static title = 'Monitor org';
static monitoringCommandsDefault = [
{
key: 'AUDIT_TRAIL',
title: 'Detect suspect setup actions in major org',
command: 'sf hardis:org:diagnose:audittrail',
frequency: 'daily',
},
{
key: 'LEGACY_API',
title: 'Detect calls to deprecated API versions',
command: 'sf hardis:org:diagnose:legacyapi',
frequency: 'daily',
},
{
key: 'ORG_LIMITS',
title: 'Detect if org limits are close to be reached',
command: 'sf hardis:org:monitor:limits',
frequency: 'daily',
},
{
key: 'UNSECURED_CONNECTED_APPS',
title: 'Detect unsecured Connected Apps in an org',
command: 'sf hardis:org:diagnose:unsecure-connected-apps',
frequency: 'daily',
},
{
key: 'LICENSES',
title: 'Extract licenses information',
command: 'sf hardis:org:diagnose:licenses',
frequency: 'weekly',
},
{
key: 'LINT_ACCESS',
title: 'Detect custom elements with no access rights defined in permission sets',
command: 'sf hardis:lint:access',
frequency: 'weekly',
},
{
key: 'UNUSED_LICENSES',
title: 'Detect permission set licenses that are assigned to users that do not need them',
command: 'sf hardis:org:diagnose:unusedlicenses',
frequency: 'weekly',
},
{
key: 'UNUSED_USERS',
title: 'Detect active users without recent logins',
command: 'sf hardis:org:diagnose:unusedusers',
frequency: 'weekly',
},
{
key: 'ACTIVE_USERS',
title: 'Detect active users with recent logins',
command: 'sf hardis:org:diagnose:unusedusers --returnactiveusers',
frequency: 'weekly',
},
{
key: 'ORG_INFO',
title: 'Get org info + SF instance info + next major upgrade date',
command: 'sf hardis:org:diagnose:instanceupgrade',
frequency: 'weekly',
},
{
key: 'RELEASE_UPDATES',
title: 'Gather warnings about incoming and overdue Release Updates',
command: 'sf hardis:org:diagnose:releaseupdates',
frequency: 'weekly',
},
{
key: 'UNUSED_METADATAS',
title: 'Detect custom labels and custom permissions that are not in use',
command: 'sf hardis:lint:unusedmetadatas',
frequency: 'weekly',
},
{
key: 'UNUSED_APEX_CLASSES',
title: 'Detect unused Apex classes in an org',
command: 'sf hardis:org:diagnose:unused-apex-classes',
frequency: 'weekly',
},
{
key: 'CONNECTED_APPS',
title: 'Detect unused Connected Apps in an org',
command: 'sf hardis:org:diagnose:unused-connected-apps',
frequency: 'weekly',
},
{
key: 'METADATA_STATUS',
title: 'Detect inactive metadata',
command: 'sf hardis:lint:metadatastatus',
frequency: 'weekly',
},
{
key: 'MISSING_ATTRIBUTES',
title: 'Detect missing description on custom field',
command: 'sf hardis:lint:missingattributes',
frequency: 'weekly',
},
];
static description = `Monitor org, generate reports and sends notifications
You can disable some commands defining either a **monitoringDisable** property in \`.sfdx-hardis.yml\`, or a comma separated list in env variable **MONITORING_DISABLE**
Example in .sfdx-hardis.yml:
\`\`\`yaml
monitoringDisable:
- METADATA_STATUS
- MISSING_ATTRIBUTES
- UNUSED_METADATAS
\`\`\`
Example in env var:
\`\`\`sh
MONITORING_DISABLE=METADATA_STATUS,MISSING_ATTRIBUTES,UNUSED_METADATAS
\`\`\`
A [default list of monitoring commands](${CONSTANTS.DOC_URL_ROOT}/salesforce-monitoring-home/#monitoring-commands) is used, if you want to override it you can define property **monitoringCommands** in your .sfdx-hardis.yml file
Example:
\`\`\`yaml
monitoringCommands:
- title: My Custom command
command: sf my:custom:command
- title: My Custom command 2
command: sf my:other:custom:command
\`\`\`
You can force the daily run of all commands by defining env var \`MONITORING_IGNORE_FREQUENCY=true\`
The default list of commands is the following:
${this.getDefaultCommandsMarkdown()}
`;
static examples = ['$ sf hardis:org:monitor:all'];
static flags = {
debug: Flags.boolean({
char: 'd',
default: false,
description: messages.getMessage('debugMode'),
}),
websocket: Flags.string({
description: messages.getMessage('websocket'),
}),
skipauth: Flags.boolean({
description: 'Skip authentication check when a default username is required',
}),
'target-org': requiredOrgFlagWithDeprecations,
};
// Set this to true if your command requires a project workspace; 'requiresProject' is false by default
static requiresProject = true;
// Trigger notification(s) to MsTeams channel
static triggerNotification = true;
debugMode = false;
/* jscpd:ignore-end */
static getDefaultCommandsMarkdown() {
const mdLines = [
"| Key | Description | Command | Frequency |",
"| :---: | :---- | :---- | :-----: |",
];
for (const cmd of MonitorAll.monitoringCommandsDefault) {
const commandDocUrl = `${CONSTANTS.DOC_URL_ROOT}/${cmd.command.split(" ")[1].replaceAll(":", "/")}`;
mdLines.push(`| [${cmd.key}](${commandDocUrl}) | ${cmd.title} | [${cmd.command}](${commandDocUrl}) | ${cmd.frequency} |`);
}
return mdLines.join("\n");
}
async run() {
const { flags } = await this.parse(MonitorAll);
this.debugMode = flags.debug || false;
// Build target org full manifest
uxLog("action", this, c.cyan('Running monitoring scripts for org ' + c.bold(flags['target-org'].getConnection().instanceUrl)) + ' ...');
const config = await getConfig('user');
const commands = MonitorAll.monitoringCommandsDefault.concat(config.monitoringCommands || []);
const monitoringDisable = config.monitoringDisable ?? (process.env?.MONITORING_DISABLE ? process.env.MONITORING_DISABLE.split(',') : []);
let success = true;
const commandsSummary = [];
for (const command of commands) {
if (monitoringDisable.includes(command.key)) {
uxLog("log", this, c.grey(`Skipped command ${c.bold(command.key)} according to custom configuration`));
continue;
}
if (command?.frequency === 'weekly' &&
new Date().getDay() !== 6 &&
getEnvVar('MONITORING_IGNORE_FREQUENCY') !== 'true') {
uxLog("log", this, c.grey(`Skipped command ${c.bold(command.key)} as its frequency is defined as weekly and we are not Saturday`));
continue;
}
// Run command
uxLog("action", this, c.cyan(`Running monitoring command ${c.bold(command.title)} (key: ${c.bold(command.key)})`));
try {
const execCommandResult = await execCommand(command.command, this, { fail: false, output: true });
if (execCommandResult.status === 0) {
uxLog("success", this, c.green(`Command ${c.bold(command.title)} has been run successfully`));
}
else {
success = false;
uxLog("warning", this, c.yellow(`Command ${c.bold(command.title)} has failed`));
}
commandsSummary.push({
title: command.title,
status: execCommandResult.status === 0 ? 'success' : 'failure',
command: command.command,
});
}
catch (e) {
// Handle unexpected failure
success = false;
uxLog("warning", this, c.yellow(`Command ${c.bold(command.title)} has failed !\n${e.message}`));
commandsSummary.push({
title: command.title,
status: 'error',
command: command.command,
});
}
}
uxLog("action", this, c.cyan('Summary of monitoring scripts'));
uxLogTable(this, commandsSummary);
uxLog("log", this, c.grey('You can check details in reports in Job Artifacts'));
uxLog("warning", this, c.yellow(`To know more about sfdx-hardis monitoring, please check ${CONSTANTS.DOC_URL_ROOT}/salesforce-monitoring-home/`));
// Exit code is 1 if monitoring detected stuff
if (success === false) {
process.exitCode = 1;
}
return { outputString: 'Monitoring processed on org ' + flags['target-org'].getConnection().instanceUrl };
}
}
//# sourceMappingURL=all.js.map