diff --git a/docs/design/0013-flow-and-permission-set-assignment-cleanup.md b/docs/design/0013-flow-and-permission-set-assignment-cleanup.md index 84f110b..0615882 100644 --- a/docs/design/0013-flow-and-permission-set-assignment-cleanup.md +++ b/docs/design/0013-flow-and-permission-set-assignment-cleanup.md @@ -66,17 +66,21 @@ Resolution: ```sh sf simply flow version prune --target-org my-org --source-dir sfdx-source/core sf simply flow version prune --target-org my-org --source-dir sfdx-source/core --dry-run +sf simply flow version prune --target-org my-org --flow-name My_Flow --flow-name Another_Flow ``` -| Flag | Char | Required | Purpose | -| -------------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `--target-org` | `-o` | Yes | | -| `--source-dir` | `-d` | Yes | One or more directories to glob `**/*.flow-meta.xml` under — replaces the original's implicit glob from `cwd`, matching every other command in this repo taking an explicit source scope rather than assuming the working directory. | -| `--dry-run` | | No | List what would be deleted without deleting anything. Default `false`. New relative to the original, which had no preview before deleting org-wide flow-version history. | +| Flag | Char | Required | Purpose | +| -------------- | ---- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--target-org` | `-o` | Yes | | +| `--source-dir` | `-d` | One of\* | One or more directories to glob `**/*.flow-meta.xml` under — replaces the original's implicit glob from `cwd`, matching every other command in this repo taking an explicit source scope rather than assuming the working directory. | +| `--flow-name` | `-n` | One of\* | Explicit Flow `DeveloperName`(s), repeatable — an alternative to `--source-dir` for scripted or one-off use, matching `flow delete`'s `--flow-name`. Added after the initial release, when it became clear a caller who already knows the flow name shouldn't need a local checkout just to prune it. | +| `--dry-run` | | No | List what would be deleted without deleting anything. Default `false`. New relative to the original, which had no preview before deleting org-wide flow-version history. | + +\* Exactly one of `--source-dir`/`--flow-name` — same XOR shape as `flow delete`'s `--manifest`/`--flow-name`. Resolution: -1. Glob `**/*.flow-meta.xml` under each `--source-dir`; derive Flow developer names from file basenames. +1. Resolve the flow developer names: glob `**/*.flow-meta.xml` under each `--source-dir` and derive names from file basenames, or `--flow-name` directly. 2. Tooling API, chunked: `SELECT Id, Definition.DeveloperName FROM Flow WHERE Status = 'Obsolete' AND Definition.DeveloperName IN (...)`. 3. `--dry-run`: print/return the candidate list, delete nothing. 4. Otherwise: delete each version (failure-collection, not throw-on-first, same as `flow delete`), print a summary, `process.exitCode = 1` on any failure. @@ -151,15 +155,16 @@ Parses a `......... -d ... [--json] [--flags-dir ] [--api-version ] - [--dry-run] + $ sf simply flow version prune -o [--json] [--flags-dir ] [--api-version ] [-d ...] [-n + ...] [--dry-run] FLAGS - -d, --source-dir=... (required) Directories to scan for *.flow-meta.xml files + -d, --source-dir=... Directories to scan for *.flow-meta.xml files + -n, --flow-name=... Flow DeveloperName(s) to prune obsolete versions for -o, --target-org= (required) Username or alias of the target org. Not required if the `target-org` configuration variable is already set. --api-version= Override the api version used for api requests made by this command @@ -89,10 +90,11 @@ GLOBAL FLAGS DESCRIPTION Delete obsolete versions of Flows found in local source. - Scans one or more source directories for `*.flow-meta.xml` files, then deletes any Tooling API Flow version already - `Status = 'Obsolete'` for those flows — keeping an org's Flow version history from accumulating indefinitely. Unlike - `simply flow delete`, this never touches an active Flow; it only removes versions the org itself already marked - obsolete. + Flows can be named either via one or more `--source-dir` directories, scanned for `*.flow-meta.xml` files, or via one + or more `--flow-name` flags for scripted or one-off use. Exactly one of the two must be given. The command then + deletes any Tooling API Flow version already `Status = 'Obsolete'` for those flows — keeping an org's Flow version + history from accumulating indefinitely. Unlike `simply flow delete`, this never touches an active Flow; it only + removes versions the org itself already marked obsolete. Use `--dry-run` to see what would be deleted without deleting anything. @@ -100,6 +102,8 @@ EXAMPLES $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core --dry-run + + $ sf simply flow version prune --target-org myOrg --flow-name My_Flow --flow-name Another_Flow ``` _See code: [lib/commands/simply/flow/version/prune.js](https://github.com/SimplySF/simply-node/blob/@simplysf/simply-flow@0.2.0/packages/simply-flow/lib/commands/simply/flow/version/prune.js)_ diff --git a/packages/simply-flow/command-snapshot.json b/packages/simply-flow/command-snapshot.json index b971458..6e01990 100644 --- a/packages/simply-flow/command-snapshot.json +++ b/packages/simply-flow/command-snapshot.json @@ -11,8 +11,8 @@ "alias": [], "command": "simply:flow:version:prune", "flagAliases": [], - "flagChars": ["d", "o"], - "flags": ["api-version", "dry-run", "flags-dir", "json", "source-dir", "target-org"], + "flagChars": ["d", "n", "o"], + "flags": ["api-version", "dry-run", "flags-dir", "flow-name", "json", "source-dir", "target-org"], "plugin": "@simplysf/simply-flow" } ] diff --git a/packages/simply-flow/messages/simply.flow.version.prune.md b/packages/simply-flow/messages/simply.flow.version.prune.md index 3fdfd86..ad5052b 100644 --- a/packages/simply-flow/messages/simply.flow.version.prune.md +++ b/packages/simply-flow/messages/simply.flow.version.prune.md @@ -4,7 +4,7 @@ Delete obsolete versions of Flows found in local source. # description -Scans one or more source directories for `*.flow-meta.xml` files, then deletes any Tooling API Flow version already `Status = 'Obsolete'` for those flows — keeping an org's Flow version history from accumulating indefinitely. Unlike `simply flow delete`, this never touches an active Flow; it only removes versions the org itself already marked obsolete. +Flows can be named either via one or more `--source-dir` directories, scanned for `*.flow-meta.xml` files, or via one or more `--flow-name` flags for scripted or one-off use. Exactly one of the two must be given. The command then deletes any Tooling API Flow version already `Status = 'Obsolete'` for those flows — keeping an org's Flow version history from accumulating indefinitely. Unlike `simply flow delete`, this never touches an active Flow; it only removes versions the org itself already marked obsolete. Use `--dry-run` to see what would be deleted without deleting anything. @@ -12,6 +12,10 @@ Use `--dry-run` to see what would be deleted without deleting anything. Directories to scan for *.flow-meta.xml files +# flags.flow-name.summary + +Flow DeveloperName(s) to prune obsolete versions for + # flags.dry-run.summary List obsolete versions without deleting them @@ -22,6 +26,12 @@ List obsolete versions without deleting them - <%= config.bin %> <%= command.id %> --target-org myOrg --source-dir sfdx-source/core --dry-run +- <%= config.bin %> <%= command.id %> --target-org myOrg --flow-name My_Flow --flow-name Another_Flow + +# error.sourceDirOrFlowNameRequired + +You must specify either --source-dir or --flow-name, but not both. + # info.scanningLocalSource Scanning local source for Flows... diff --git a/packages/simply-flow/src/commands/simply/flow/version/prune.ts b/packages/simply-flow/src/commands/simply/flow/version/prune.ts index 8fa3fba..9dadf32 100644 --- a/packages/simply-flow/src/commands/simply/flow/version/prune.ts +++ b/packages/simply-flow/src/commands/simply/flow/version/prune.ts @@ -56,8 +56,8 @@ function developerNameFromFlowFile(flowFile: string): string { /** * Deletes obsolete Flow versions (`Status = 'Obsolete'`) for the Flows found under `--source-dir`, - * to keep an org's Flow version history from accumulating indefinitely. Unlike `flow delete`, this - * never removes an active Flow — only versions the org itself already marked obsolete. + * or for explicitly named Flows via `--flow-name`. Unlike `flow delete`, this never removes an + * active Flow — only versions the org itself already marked obsolete. */ export default class FlowVersionPrune extends SfCommand { public static readonly summary = messages.getMessage('summary'); @@ -72,7 +72,11 @@ export default class FlowVersionPrune extends SfCommand char: 'd', exists: true, multiple: true, - required: true, + }), + 'flow-name': Flags.string({ + summary: messages.getMessage('flags.flow-name.summary'), + char: 'n', + multiple: true, }), 'dry-run': Flags.boolean({ summary: messages.getMessage('flags.dry-run.summary'), default: false }), }; @@ -81,14 +85,24 @@ export default class FlowVersionPrune extends SfCommand public async run(): Promise { const { flags } = await this.parse(FlowVersionPrune); - this.spinner.start(messages.getMessage('info.scanningLocalSource')); - const flowFiles = ( - await Promise.all( - flags['source-dir'].map((sourceDir) => glob(`${sourceDir.replaceAll('\\', '/')}/**/*.flow-meta.xml`)), - ) - ).flat(); - const flowNames = [...new Set(flowFiles.map(developerNameFromFlowFile))]; - this.spinner.stop(); + const hasSourceDir = Boolean(flags['source-dir']?.length); + const hasFlowNames = Boolean(flags['flow-name']?.length); + if ((hasSourceDir && hasFlowNames) || (!hasSourceDir && !hasFlowNames)) { + throw messages.createError('error.sourceDirOrFlowNameRequired'); + } + + let flowNames: string[]; + if (hasSourceDir) { + this.spinner.start(messages.getMessage('info.scanningLocalSource')); + const sourceDirs = flags['source-dir'] as string[]; + const flowFiles = ( + await Promise.all(sourceDirs.map((sourceDir) => glob(`${sourceDir.replaceAll('\\', '/')}/**/*.flow-meta.xml`))) + ).flat(); + flowNames = [...new Set(flowFiles.map(developerNameFromFlowFile))]; + this.spinner.stop(); + } else { + flowNames = flags['flow-name'] as string[]; + } const connection = requireConnection(flags); diff --git a/packages/simply-flow/test/commands/simply/flow/version/prune.test.ts b/packages/simply-flow/test/commands/simply/flow/version/prune.test.ts index 31e72b3..e8b8bfe 100644 --- a/packages/simply-flow/test/commands/simply/flow/version/prune.test.ts +++ b/packages/simply-flow/test/commands/simply/flow/version/prune.test.ts @@ -79,4 +79,34 @@ describe('simply flow version prune', () => { expect(result.failures).to.deep.equal([]); expect(process.exitCode).to.equal(undefined); }); + + it('prunes obsolete versions for explicitly named flows via --flow-name, without scanning source', async () => { + const autoFetchQuery = $$.SANDBOX.stub(Connection.prototype, 'autoFetchQuery').resolves({ + records: [{ Id: '301000000000001AAA', Definition: { DeveloperName: 'My_Flow' } }], + done: true, + totalSize: 1, + } as never); + + const result = await FlowVersionPrune.run([ + '--target-org', + testOrg.username, + '--flow-name', + 'My_Flow', + '--dry-run', + ]); + + expect(result.dryRun).to.be.true; + expect(result.candidates).to.deep.equal([{ id: '301000000000001AAA', developerName: 'My_Flow' }]); + expect(autoFetchQuery.getCall(0).args[0]).to.include("Definition.DeveloperName IN ('My_Flow')"); + }); + + it('rejects --source-dir combined with --flow-name', async () => { + await expect( + FlowVersionPrune.run(['--target-org', testOrg.username, '--source-dir', tmpDir, '--flow-name', 'My_Flow']), + ).rejects.toThrow(); + }); + + it('rejects when neither --source-dir nor --flow-name is given', async () => { + await expect(FlowVersionPrune.run(['--target-org', testOrg.username])).rejects.toThrow(); + }); }); diff --git a/packages/simply/README.md b/packages/simply/README.md index fd556c5..99bd8aa 100644 --- a/packages/simply/README.md +++ b/packages/simply/README.md @@ -1037,11 +1037,12 @@ Delete obsolete versions of Flows found in local source. ``` USAGE - $ sf simply flow version prune -o -d ... [--json] [--flags-dir ] [--api-version ] - [--dry-run] + $ sf simply flow version prune -o [--json] [--flags-dir ] [--api-version ] [-d ...] [-n + ...] [--dry-run] FLAGS - -d, --source-dir=... (required) Directories to scan for *.flow-meta.xml files + -d, --source-dir=... Directories to scan for *.flow-meta.xml files + -n, --flow-name=... Flow DeveloperName(s) to prune obsolete versions for -o, --target-org= (required) Username or alias of the target org. Not required if the `target-org` configuration variable is already set. --api-version= Override the api version used for api requests made by this command @@ -1054,10 +1055,11 @@ GLOBAL FLAGS DESCRIPTION Delete obsolete versions of Flows found in local source. - Scans one or more source directories for `*.flow-meta.xml` files, then deletes any Tooling API Flow version already - `Status = 'Obsolete'` for those flows — keeping an org's Flow version history from accumulating indefinitely. Unlike - `simply flow delete`, this never touches an active Flow; it only removes versions the org itself already marked - obsolete. + Flows can be named either via one or more `--source-dir` directories, scanned for `*.flow-meta.xml` files, or via one + or more `--flow-name` flags for scripted or one-off use. Exactly one of the two must be given. The command then + deletes any Tooling API Flow version already `Status = 'Obsolete'` for those flows — keeping an org's Flow version + history from accumulating indefinitely. Unlike `simply flow delete`, this never touches an active Flow; it only + removes versions the org itself already marked obsolete. Use `--dry-run` to see what would be deleted without deleting anything. @@ -1065,6 +1067,8 @@ EXAMPLES $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core --dry-run + + $ sf simply flow version prune --target-org myOrg --flow-name My_Flow --flow-name Another_Flow ``` _See code: [@simplysf/simply-flow](https://github.com/SimplySF/simply-node/blob/@simplysf/simply-flow@0.2.0/packages/simply-flow/lib/commands/simply/flow/version/prune.js)_ diff --git a/packages/simply/command-snapshot.json b/packages/simply/command-snapshot.json index 8027a1f..fccace2 100644 --- a/packages/simply/command-snapshot.json +++ b/packages/simply/command-snapshot.json @@ -236,8 +236,8 @@ "alias": [], "command": "simply:flow:version:prune", "flagAliases": [], - "flagChars": ["d", "o"], - "flags": ["api-version", "dry-run", "flags-dir", "json", "source-dir", "target-org"], + "flagChars": ["d", "n", "o"], + "flags": ["api-version", "dry-run", "flags-dir", "flow-name", "json", "source-dir", "target-org"], "plugin": "@simplysf/simply-flow" }, { diff --git a/site/src/content/docs/plugins/simply-flow.md b/site/src/content/docs/plugins/simply-flow.md index ac3d057..d2b2d1d 100644 --- a/site/src/content/docs/plugins/simply-flow.md +++ b/site/src/content/docs/plugins/simply-flow.md @@ -60,11 +60,12 @@ Delete obsolete versions of Flows found in local source. ``` USAGE - $ sf simply flow version prune -o -d ... [--json] [--flags-dir ] [--api-version ] - [--dry-run] + $ sf simply flow version prune -o [--json] [--flags-dir ] [--api-version ] [-d ...] [-n + ...] [--dry-run] FLAGS - -d, --source-dir=... (required) Directories to scan for *.flow-meta.xml files + -d, --source-dir=... Directories to scan for *.flow-meta.xml files + -n, --flow-name=... Flow DeveloperName(s) to prune obsolete versions for -o, --target-org= (required) Username or alias of the target org. Not required if the `target-org` configuration variable is already set. --api-version= Override the api version used for api requests made by this command @@ -77,10 +78,11 @@ GLOBAL FLAGS DESCRIPTION Delete obsolete versions of Flows found in local source. - Scans one or more source directories for `*.flow-meta.xml` files, then deletes any Tooling API Flow version already - `Status = 'Obsolete'` for those flows — keeping an org's Flow version history from accumulating indefinitely. Unlike - `simply flow delete`, this never touches an active Flow; it only removes versions the org itself already marked - obsolete. + Flows can be named either via one or more `--source-dir` directories, scanned for `*.flow-meta.xml` files, or via one + or more `--flow-name` flags for scripted or one-off use. Exactly one of the two must be given. The command then + deletes any Tooling API Flow version already `Status = 'Obsolete'` for those flows — keeping an org's Flow version + history from accumulating indefinitely. Unlike `simply flow delete`, this never touches an active Flow; it only + removes versions the org itself already marked obsolete. Use `--dry-run` to see what would be deleted without deleting anything. @@ -88,6 +90,8 @@ EXAMPLES $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core --dry-run + + $ sf simply flow version prune --target-org myOrg --flow-name My_Flow --flow-name Another_Flow ``` _See code: [lib/commands/simply/flow/version/prune.js](https://github.com/SimplySF/simply-node/blob/@simplysf/simply-flow@0.2.0/packages/simply-flow/lib/commands/simply/flow/version/prune.js)_ diff --git a/site/src/content/docs/plugins/simply.md b/site/src/content/docs/plugins/simply.md index 113d893..7d2e509 100644 --- a/site/src/content/docs/plugins/simply.md +++ b/site/src/content/docs/plugins/simply.md @@ -994,11 +994,12 @@ Delete obsolete versions of Flows found in local source. ``` USAGE - $ sf simply flow version prune -o -d ... [--json] [--flags-dir ] [--api-version ] - [--dry-run] + $ sf simply flow version prune -o [--json] [--flags-dir ] [--api-version ] [-d ...] [-n + ...] [--dry-run] FLAGS - -d, --source-dir=... (required) Directories to scan for *.flow-meta.xml files + -d, --source-dir=... Directories to scan for *.flow-meta.xml files + -n, --flow-name=... Flow DeveloperName(s) to prune obsolete versions for -o, --target-org= (required) Username or alias of the target org. Not required if the `target-org` configuration variable is already set. --api-version= Override the api version used for api requests made by this command @@ -1011,10 +1012,11 @@ GLOBAL FLAGS DESCRIPTION Delete obsolete versions of Flows found in local source. - Scans one or more source directories for `*.flow-meta.xml` files, then deletes any Tooling API Flow version already - `Status = 'Obsolete'` for those flows — keeping an org's Flow version history from accumulating indefinitely. Unlike - `simply flow delete`, this never touches an active Flow; it only removes versions the org itself already marked - obsolete. + Flows can be named either via one or more `--source-dir` directories, scanned for `*.flow-meta.xml` files, or via one + or more `--flow-name` flags for scripted or one-off use. Exactly one of the two must be given. The command then + deletes any Tooling API Flow version already `Status = 'Obsolete'` for those flows — keeping an org's Flow version + history from accumulating indefinitely. Unlike `simply flow delete`, this never touches an active Flow; it only + removes versions the org itself already marked obsolete. Use `--dry-run` to see what would be deleted without deleting anything. @@ -1022,6 +1024,8 @@ EXAMPLES $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core $ sf simply flow version prune --target-org myOrg --source-dir sfdx-source/core --dry-run + + $ sf simply flow version prune --target-org myOrg --flow-name My_Flow --flow-name Another_Flow ``` _See code: [@simplysf/simply-flow](https://github.com/SimplySF/simply-node/blob/@simplysf/simply-flow@0.2.0/packages/simply-flow/lib/commands/simply/flow/version/prune.js)_