Skip to content

Commit

Permalink
Purge flow fixes (#801)
Browse files Browse the repository at this point in the history
  • Loading branch information
nvuillam authored Sep 25, 2024
1 parent def7ad3 commit af58a29
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 39 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

Note: Can be used with `sfdx plugins:install sfdx-hardis@beta` and docker image `hardisgroupcom/sfdx-hardis@beta`

## [5.0.6] 2024-09-25

- Allow to purge flows & flow interviews using `--no-prompt` option
- Fix duplicate `-f` short option by replacing `delete-flow-interviews` short by `-w`

## [5.0.5] 2024-09-24

- When git add / stash failure, display a message explaining to run `git config --system core.longpaths true` to solve the issue.
Expand Down Expand Up @@ -93,7 +98,7 @@ We made many tests but risk zero do not exist, so if you see any bug, please rep
- Rename command **hardis:project:deploy:source:dx** into **hardis:project:deploy:smart** (previous command alias remains, no need to update your pipelines !)
- **commandsPreDeploy** and **commandsPostDeploy**
- New option **context** for a command, defining when it is run and when it is not: **all** (default), **check-deployment-only** or **process-deployment-only**
- New option **runOnlyOnceByOrg**: If set to `true`, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)
- New option **runOnlyOnceByOrg**: If set to `true`, the command will be run only one time per org. A record of SfdxHardisTrace\_\_c is stored to make that possible (it needs to be existing in target org)
- New commands
- **hardis:project:deploy:simulate** to validate the deployment of a single metadata (used by VsCode extension)
- **hardis:org:diagnose:releaseupdates** to check for org Release Updates from Monitoring or locally
Expand Down
76 changes: 38 additions & 38 deletions src/commands/hardis/org/purge/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,9 @@ export default class OrgPurgeFlow extends SfCommand<any> {
public static description = messages.getMessage('orgPurgeFlow');

public static examples = [
`$ sf hardis:org:purge:flow --no-prompt`,
`$ sf hardis:org:purge:flow --target-org [email protected]
Found 1 records:
ID MASTERLABEL VERSIONNUMBER DESCRIPTION STATUS
30109000000kX7uAAE TestFlow 2 test flowwww Obsolete
Are you sure you want to delete this list of records (y/n)?: y
Successfully deleted record: 30109000000kX7uAAE.
Deleted the following list of records:
ID MASTERLABEL VERSIONNUMBER DESCRIPTION STATUS
30109000000kX7uAAE TestFlow 2 test flowwww Obsolete
`,
`$ sf hardis:org:purge:flow --target-org [email protected] --status "Obsolete,Draft,InvalidDraft --name TestFlow"
Found 4 records:
ID MASTERLABEL VERSIONNUMBER DESCRIPTION STATUS
30109000000kX7uAAE TestFlow 2 test flowwww Obsolete
30109000000kX8EAAU TestFlow 6 test flowwww InvalidDraft
30109000000kX8AAAU TestFlow 5 test flowwww InvalidDraft
30109000000kX89AAE TestFlow 4 test flowwww Draft
Are you sure you want to delete this list of records (y/n)?: n
No record deleted
`,
`$ sf hardis:org:purge:flow`,
`$ sf hardis:org:purge:flow --target-org [email protected] --no-prompt --delete-flow-interviews`,
`$ sf hardis:org:purge:flow --target-org [email protected] --status "Obsolete,Draft,InvalidDraft" --name TestFlow`,
];

// public static args = [{name: 'file'}];
Expand All @@ -58,8 +40,8 @@ export default class OrgPurgeFlow extends SfCommand<any> {
char: 's',
description: messages.getMessage('statusFilter'),
}),
"delete-flow-interviews": Flags.boolean({
char: 'f',
'delete-flow-interviews': Flags.boolean({
char: 'w',
default: false,
description: `If the presence of Flow interviews prevent to delete flows versions, delete them before retrying to delete flow versions`,
}),
Expand Down Expand Up @@ -95,6 +77,7 @@ export default class OrgPurgeFlow extends SfCommand<any> {
protected statusFilter: string[] = [];
protected nameFilter: string | null = null;
protected username: string;
protected promptUser = true;
protected deleteFlowInterviews: boolean;
protected allowPurgeFailure: boolean;
protected flowRecordsRaw: any[];
Expand All @@ -105,10 +88,10 @@ export default class OrgPurgeFlow extends SfCommand<any> {

public async run(): Promise<AnyJson> {
const { flags } = await this.parse(OrgPurgeFlow);
const prompt = flags.prompt === false ? false : true;
this.promptUser = flags.prompt === false ? false : true;
this.nameFilter = flags.name || null;
this.allowPurgeFailure = flags.allowpurgefailure === false ? false : true;
this.deleteFlowInterviews = flags["delete-flow-interviews"] || false;
this.deleteFlowInterviews = flags['delete-flow-interviews'] || false;
this.debugMode = flags.debug || false;
this.username = flags['target-org'].getUsername();

Expand All @@ -134,7 +117,7 @@ export default class OrgPurgeFlow extends SfCommand<any> {
this.formatFlowRecords();

// Confirm deletion
if (prompt) {
if (this.promptUser) {
const confirmDelete = await prompts({
type: 'confirm',
name: 'value',
Expand Down Expand Up @@ -171,18 +154,26 @@ export default class OrgPurgeFlow extends SfCommand<any> {
this.deletedErrors.push(deleteRes);
}
}
if (this.deletedErrors.length > 0 && (this.deleteFlowInterviews === true || !isCI) && tryDeleteInterviews === true) {
if (
this.deletedErrors.length > 0 &&
(this.deleteFlowInterviews === true || !isCI) &&
tryDeleteInterviews === true
) {
await this.manageDeleteFlowInterviews(conn);
}

if (this.deletedErrors.length > 0) {
const errMsg = `[sfdx-hardis] There have been errors while deleting ${this.deletedErrors.length} record(s): \n${JSON.stringify(this.deletedErrors)}`;
const errMsg = `[sfdx-hardis] There have been errors while deleting ${
this.deletedErrors.length
} record(s): \n${JSON.stringify(this.deletedErrors)}`;
if (this.allowPurgeFailure) {
uxLog(this, c.yellow(errMsg));
} else {
throw new SfError(
c.yellow(
`There have been errors while deleting ${this.deletedErrors.length} record(s): \n${JSON.stringify(this.deletedErrors)}`
`There have been errors while deleting ${this.deletedErrors.length} record(s): \n${JSON.stringify(
this.deletedErrors
)}`
)
);
}
Expand All @@ -204,7 +195,7 @@ export default class OrgPurgeFlow extends SfCommand<any> {
}
// Display flows & Prompt user if not in CI
await this.displayFlowInterviewToDelete(flowInterviewsIds, conn);
if (!isCI) {
if (!isCI && this.promptUser === true) {
const confirmDelete = await prompts({
type: 'confirm',
name: 'value',
Expand All @@ -217,7 +208,7 @@ export default class OrgPurgeFlow extends SfCommand<any> {
}
// Delete flow interviews
const deleteInterviewResults = await bulkDelete('FlowInterview', flowInterviewsIds, conn);
this.deletedRecords.push(deleteInterviewResults?.successfulResults || [])
this.deletedRecords.push(deleteInterviewResults?.successfulResults || []);
this.deletedErrors = deleteInterviewResults?.failedResults || [];
// Try to delete flow versions again
uxLog(this, c.cyan(`Trying again to delete flow versions after deleting flow interviews...`));
Expand All @@ -236,7 +227,10 @@ export default class OrgPurgeFlow extends SfCommand<any> {
Description: record.Description,
};
});
uxLog(this, `[sfdx-hardis] Found ${c.bold(this.flowRecords.length)} records:\n${c.yellow(columnify(this.flowRecords))}`);
uxLog(
this,
`[sfdx-hardis] Found ${c.bold(this.flowRecords.length)} records:\n${c.yellow(columnify(this.flowRecords))}`
);
}

private async listFlowVersionsToDelete(manageableConstraint: string) {
Expand All @@ -248,7 +242,8 @@ export default class OrgPurgeFlow extends SfCommand<any> {
}
query += ' ORDER BY Definition.DeveloperName,VersionNumber';

const flowQueryCommand = 'sf data query ' + ` --query "${query}"` + ` --target-org ${this.username}` + ' --use-tooling-api';
const flowQueryCommand =
'sf data query ' + ` --query "${query}"` + ` --target-org ${this.username}` + ' --use-tooling-api';
const flowQueryRes = await execSfdxJson(flowQueryCommand, this, {
output: false,
debug: this.debugMode,
Expand All @@ -262,12 +257,13 @@ export default class OrgPurgeFlow extends SfCommand<any> {
if (flags.status) {
// Input parameter used
this.statusFilter = flags.status.split(',');
} else if (isCI) {
} else if (isCI || this.promptUser === false) {
// Obsolete by default for CI
this.statusFilter = ['Obsolete'];
} else {
// Query all flows definitions
const allFlowQueryCommand = 'sf data query ' +
const allFlowQueryCommand =
'sf data query ' +
` --query "SELECT Id,DeveloperName,MasterLabel,ManageableState FROM FlowDefinition WHERE ${manageableConstraint} ORDER BY DeveloperName"` +
` --target-org ${this.username}` +
' --use-tooling-api';
Expand Down Expand Up @@ -309,10 +305,14 @@ export default class OrgPurgeFlow extends SfCommand<any> {
}

private async displayFlowInterviewToDelete(flowVInterviewIds: string[], conn: any) {
const query = "SELECT Name,InterviewLabel,InterviewStatus,CreatedBy.Username,CreatedDate,LastModifiedDate " +
const query =
'SELECT Name,InterviewLabel,InterviewStatus,CreatedBy.Username,CreatedDate,LastModifiedDate ' +
`FROM FlowInterview WHERE Id IN ('${flowVInterviewIds.join("','")}')` +
" ORDER BY Name";
' ORDER BY Name';
const flowsInterviewsToDelete = (await bulkQuery(query, conn)).records;
uxLog(this, c.yellow(`Flow interviews to be deleted would be the following:\n${columnify(flowsInterviewsToDelete)}`));
uxLog(
this,
c.yellow(`Flow interviews to be deleted would be the following:\n${columnify(flowsInterviewsToDelete)}`)
);
}
}

0 comments on commit af58a29

Please sign in to comment.