From 7cfa2ad1a80251fd8be1ff18dd00364b422aa125 Mon Sep 17 00:00:00 2001 From: mshanemc Date: Fri, 17 Nov 2023 16:02:58 -0600 Subject: [PATCH 1/3] feat: commands to enable/disable tracking on an org --- messages/org.disable.tracking.md | 25 ++++++++++ messages/org.enable.tracking.md | 39 +++++++++++++++ package.json | 9 +++- src/commands/org/disable/tracking.ts | 38 ++++++++++++++ src/commands/org/enable/tracking.ts | 44 ++++++++++++++++ test/nut/tracking.nut.ts | 75 ++++++++++++++++++++++++++++ 6 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 messages/org.disable.tracking.md create mode 100644 messages/org.enable.tracking.md create mode 100644 src/commands/org/disable/tracking.ts create mode 100644 src/commands/org/enable/tracking.ts create mode 100644 test/nut/tracking.nut.ts diff --git a/messages/org.disable.tracking.md b/messages/org.disable.tracking.md new file mode 100644 index 00000000..089392d7 --- /dev/null +++ b/messages/org.disable.tracking.md @@ -0,0 +1,25 @@ +# summary + +Disable source tracking in local auth file. + +# description + +This has no effect on the org. It stores the setting in the CLI's configuration file for this org so that no source tracking operations are executed when working with this org. + +# examples + +Disable tracking on an org using an alias + +- <%= config.bin %> <%= command.id %> -o someAlias + +Disable tracking on an org using a username + +- <%= config.bin %> <%= command.id %> -o you@example.com + +Disable tracking on your default org + +- <%= config.bin %> <%= command.id %> + +# success + +Disabled source tracking for %s. diff --git a/messages/org.enable.tracking.md b/messages/org.enable.tracking.md new file mode 100644 index 00000000..b79528f7 --- /dev/null +++ b/messages/org.enable.tracking.md @@ -0,0 +1,39 @@ +# summary + +Enable source tracking in local auth file. + +# description + +This has no effect on the org. It stores the setting in the CLI's configuration file for this org so that source tracking operations are executed when working with this org. + +This command will throw an error if the org does not support tracking. + +# examples + +Enable tracking on an org using an alias + +- <%= config.bin %> <%= command.id %> -o someAlias + +Enable tracking on an org using a username + +- <%= config.bin %> <%= command.id %> -o you@example.com + +Enable tracking on your default org + +- <%= config.bin %> <%= command.id %> + +# success + +Enabled source tracking for %s. + +# error.TrackingNotAvailable + +This org cannot enable source tracking because the SourceMember object is not available, or you do not have access to it. + +# error.TrackingNotAvailable.actions + +- If the org is a sandbox, make sure that your production org has Source Tracking enabled in sandboxes. See https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_setup_enable_source_tracking_sandboxes.htm. + +- Make sure that your user can access the SourceMembers table via the tooling API. + +- If the Org is a production org, source tracking cannot be enabled. diff --git a/package.json b/package.json index 9431cb50..59753d79 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,15 @@ }, "delete": { "description": "Delete scratch orgs, sandboxes, org shapes, and org snapshots." + }, + "enable": { + "description": "description for org.enable" + }, + "disable": { + "description": "description for org.disable" } - } + }, + "external": true }, "force": { "external": true, diff --git a/src/commands/org/disable/tracking.ts b/src/commands/org/disable/tracking.ts new file mode 100644 index 00000000..b1a05181 --- /dev/null +++ b/src/commands/org/disable/tracking.ts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023, 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 { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { SfCommand, Flags } from '@salesforce/sf-plugins-core'; +import { Messages } from '@salesforce/core'; + +Messages.importMessagesDirectory(dirname(fileURLToPath(import.meta.url))); +const messages = Messages.loadMessages('@salesforce/plugin-org', 'org.disable.tracking'); + +export type OrgDisableTrackingResult = { + tracksSource: boolean; + username: string; +}; + +export default class OrgDisableTracking extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + + public static readonly flags = { + 'target-org': Flags.requiredOrg(), + }; + + public async run(): Promise { + const { flags } = await this.parse(OrgDisableTracking); + await flags['target-org'].setTracksSource(false); + this.logSuccess(messages.getMessage('success', [flags['target-org'].getUsername()])); + return { + tracksSource: await flags['target-org'].tracksSource(), + username: flags['target-org'].getUsername() as string, + }; + } +} diff --git a/src/commands/org/enable/tracking.ts b/src/commands/org/enable/tracking.ts new file mode 100644 index 00000000..cd4e26d8 --- /dev/null +++ b/src/commands/org/enable/tracking.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023, 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 { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { SfCommand, Flags } from '@salesforce/sf-plugins-core'; +import { Messages } from '@salesforce/core'; + +Messages.importMessagesDirectory(dirname(fileURLToPath(import.meta.url))); +const messages = Messages.loadMessages('@salesforce/plugin-org', 'org.enable.tracking'); + +export type OrgEnableTrackingResult = { + tracksSource: boolean; + username: string; +}; + +export default class OrgEnableTracking extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + + public static readonly flags = { + 'target-org': Flags.requiredOrg(), + }; + + public async run(): Promise { + const { flags } = await this.parse(OrgEnableTracking); + + // can this org do tracking? + if (!(await flags['target-org'].supportsSourceTracking())) { + throw messages.createError('error.TrackingNotAvailable'); + } + + await flags['target-org'].setTracksSource(true); + this.logSuccess(messages.getMessage('success', [flags['target-org'].getUsername()])); + return { + tracksSource: await flags['target-org'].tracksSource(), + username: flags['target-org'].getUsername() as string, + }; + } +} diff --git a/test/nut/tracking.nut.ts b/test/nut/tracking.nut.ts new file mode 100644 index 00000000..ba2ab70d --- /dev/null +++ b/test/nut/tracking.nut.ts @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, 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 { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { expect } from 'chai'; +import { Messages } from '@salesforce/core'; +import { OrgEnableTrackingResult } from '../../src/commands/org/enable/tracking.js'; +import { OrgDisableTrackingResult } from '../../src/commands/org/disable/tracking.js'; + +Messages.importMessagesDirectory(dirname(fileURLToPath(import.meta.url))); +const messages = Messages.loadMessages('@salesforce/plugin-org', 'org.enable.tracking'); + +describe('org enable/disable tracking NUTs', () => { + let session: TestSession; + + before(async () => { + session = await TestSession.create({ + devhubAuthStrategy: 'AUTO', + project: { name: 'orgEnableDisableTrackingNut' }, + scratchOrgs: [{ setDefault: true, edition: 'developer' }], + }); + }); + + after(async () => { + await session?.clean(); + }); + + it('should disable on scratch org', () => { + const result = execCmd('org disable tracking --json', { ensureExitCode: 0 }).jsonOutput + ?.result; + expect(result?.tracksSource).to.equal(false); + expect(result?.username).to.equal(session.orgs.get('default')?.username); + }); + + it('should disable on scratch org (idempotency)', () => { + const result = execCmd('org disable tracking --json', { ensureExitCode: 0 }).jsonOutput + ?.result; + expect(result?.tracksSource).to.equal(false); + expect(result?.username).to.equal(session.orgs.get('default')?.username); + }); + + it('should re-enable on scratch org', () => { + const result = execCmd('org enable tracking --json', { ensureExitCode: 0 }).jsonOutput + ?.result; + expect(result?.tracksSource).to.equal(true); + expect(result?.username).to.equal(session.orgs.get('default')?.username); + }); + + it('should enable on scratch org (idempotency)', () => { + const result = execCmd('org enable tracking --json', { ensureExitCode: 0 }).jsonOutput + ?.result; + expect(result?.tracksSource).to.equal(true); + expect(result?.username).to.equal(session.orgs.get('default')?.username); + }); + + it('should disable on hub org (idempotency)', () => { + const result = execCmd(`org disable tracking -o ${session.hubOrg.username} --json`, { + ensureExitCode: 0, + }).jsonOutput?.result; + expect(result?.tracksSource).to.equal(false); + expect(result?.username).to.equal(session.hubOrg.username); + }); + + it('should fail to enable on hub org', () => { + const err = execCmd(`org enable tracking -o ${session.hubOrg.username}`, { + ensureExitCode: 1, + }); + expect(err?.shellOutput.stderr).to.include(messages.getMessage('error.TrackingNotAvailable')); + }); +}); From 979d75a2e240135e9784c5b27d20a9e167e85bfd Mon Sep 17 00:00:00 2001 From: mshanemc Date: Fri, 17 Nov 2023 16:04:48 -0600 Subject: [PATCH 2/3] chore: snapshot and schema --- command-snapshot.json | 134 +++++++++++++++++------------- schemas/org-disable-tracking.json | 19 +++++ schemas/org-enable-tracking.json | 19 +++++ 3 files changed, 113 insertions(+), 59 deletions(-) create mode 100644 schemas/org-disable-tracking.json create mode 100644 schemas/org-enable-tracking.json diff --git a/command-snapshot.json b/command-snapshot.json index 2587b002..1a36268b 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -1,7 +1,9 @@ [ { + "alias": [], "command": "force:org:clone", - "plugin": "@salesforce/plugin-org", + "flagAliases": ["apiversion", "targetusername", "u"], + "flagChars": ["a", "f", "o", "s", "t", "w"], "flags": [ "api-version", "definitionfile", @@ -13,13 +15,13 @@ "type", "wait" ], - "alias": [], - "flagChars": ["a", "f", "o", "s", "t", "w"], - "flagAliases": ["apiversion", "targetusername", "u"] + "plugin": "@salesforce/plugin-org" }, { + "alias": [], "command": "force:org:create", - "plugin": "@salesforce/plugin-org", + "flagAliases": ["apiversion", "targetdevhubusername", "targetusername", "u"], + "flagChars": ["a", "c", "d", "f", "i", "n", "o", "s", "t", "v", "w"], "flags": [ "api-version", "clientid", @@ -37,29 +39,29 @@ "type", "wait" ], - "alias": [], - "flagChars": ["a", "c", "d", "f", "i", "n", "o", "s", "t", "v", "w"], - "flagAliases": ["apiversion", "targetdevhubusername", "targetusername", "u"] + "plugin": "@salesforce/plugin-org" }, { - "command": "force:org:delete", - "plugin": "@salesforce/plugin-org", - "flags": ["api-version", "json", "loglevel", "no-prompt", "target-org", "targetdevhubusername"], "alias": [], + "command": "force:org:delete", + "flagAliases": ["apiversion", "noprompt", "targetusername", "u"], "flagChars": ["o", "p", "v"], - "flagAliases": ["apiversion", "noprompt", "targetusername", "u"] + "flags": ["api-version", "json", "loglevel", "no-prompt", "target-org", "targetdevhubusername"], + "plugin": "@salesforce/plugin-org" }, { - "command": "force:org:status", - "plugin": "@salesforce/plugin-org", - "flags": ["api-version", "json", "loglevel", "sandboxname", "setalias", "setdefaultusername", "target-org", "wait"], "alias": [], + "command": "force:org:status", + "flagAliases": ["apiversion", "targetusername", "u"], "flagChars": ["a", "n", "o", "s", "w"], - "flagAliases": ["apiversion", "targetusername", "u"] + "flags": ["api-version", "json", "loglevel", "sandboxname", "setalias", "setdefaultusername", "target-org", "wait"], + "plugin": "@salesforce/plugin-org" }, { + "alias": ["env:create:sandbox"], "command": "org:create:sandbox", - "plugin": "@salesforce/plugin-org", + "flagAliases": [], + "flagChars": ["a", "c", "f", "i", "l", "n", "o", "s", "w"], "flags": [ "alias", "async", @@ -75,13 +77,13 @@ "target-org", "wait" ], - "alias": ["env:create:sandbox"], - "flagChars": ["a", "c", "f", "i", "l", "n", "o", "s", "w"], - "flagAliases": [] + "plugin": "@salesforce/plugin-org" }, { + "alias": ["env:create:scratch"], "command": "org:create:scratch", - "plugin": "@salesforce/plugin-org", + "flagAliases": [], + "flagChars": ["a", "c", "d", "e", "f", "i", "m", "t", "v", "w", "y"], "flags": [ "admin-email", "alias", @@ -104,80 +106,94 @@ "username", "wait" ], - "alias": ["env:create:scratch"], - "flagChars": ["a", "c", "d", "e", "f", "i", "m", "t", "v", "w", "y"], - "flagAliases": [] + "plugin": "@salesforce/plugin-org" }, { - "command": "org:delete:sandbox", - "plugin": "@salesforce/plugin-org", - "flags": ["json", "no-prompt", "target-org"], "alias": ["env:delete:sandbox"], + "command": "org:delete:sandbox", + "flagAliases": ["targetusername", "u"], "flagChars": ["o", "p"], - "flagAliases": ["targetusername", "u"] + "flags": ["json", "no-prompt", "target-org"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:delete:scratch", - "plugin": "@salesforce/plugin-org", - "flags": ["json", "no-prompt", "target-org"], "alias": ["env:delete:scratch"], + "command": "org:delete:scratch", + "flagAliases": ["targetusername", "u"], "flagChars": ["o", "p"], - "flagAliases": ["targetusername", "u"] + "flags": ["json", "no-prompt", "target-org"], + "plugin": "@salesforce/plugin-org" + }, + { + "alias": [], + "command": "org:disable:tracking", + "flagAliases": [], + "flagChars": ["o"], + "flags": ["json", "target-org"], + "plugin": "@salesforce/plugin-org" }, { + "alias": ["force:org:display"], "command": "org:display", - "plugin": "@salesforce/plugin-org", + "flagAliases": ["apiversion", "targetusername", "u"], + "flagChars": ["o"], "flags": ["api-version", "json", "loglevel", "target-org", "verbose"], - "alias": ["force:org:display"], + "plugin": "@salesforce/plugin-org" + }, + { + "alias": [], + "command": "org:enable:tracking", + "flagAliases": [], "flagChars": ["o"], - "flagAliases": ["apiversion", "targetusername", "u"] + "flags": ["json", "target-org"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:list", - "plugin": "@salesforce/plugin-org", - "flags": ["all", "clean", "json", "loglevel", "no-prompt", "skip-connection-status", "verbose"], "alias": ["force:org:list"], + "command": "org:list", + "flagAliases": ["noprompt", "skipconnectionstatus"], "flagChars": ["p"], - "flagAliases": ["noprompt", "skipconnectionstatus"] + "flags": ["all", "clean", "json", "loglevel", "no-prompt", "skip-connection-status", "verbose"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:list:metadata", - "plugin": "@salesforce/plugin-org", - "flags": ["api-version", "folder", "json", "loglevel", "metadata-type", "output-file", "target-org"], "alias": ["force:mdapi:listmetadata"], + "command": "org:list:metadata", + "flagAliases": ["a", "apiversion", "metadatatype", "resultfile", "targetusername", "u"], "flagChars": ["f", "m", "o"], - "flagAliases": ["a", "apiversion", "metadatatype", "resultfile", "targetusername", "u"] + "flags": ["api-version", "folder", "json", "loglevel", "metadata-type", "output-file", "target-org"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:list:metadata-types", - "plugin": "@salesforce/plugin-org", - "flags": ["api-version", "filter-known", "json", "loglevel", "output-file", "target-org"], "alias": ["force:mdapi:describemetadata"], + "command": "org:list:metadata-types", + "flagAliases": ["a", "apiversion", "filterknown", "resultfile", "targetusername", "u"], "flagChars": ["f", "k", "o"], - "flagAliases": ["a", "apiversion", "filterknown", "resultfile", "targetusername", "u"] + "flags": ["api-version", "filter-known", "json", "loglevel", "output-file", "target-org"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:open", - "plugin": "@salesforce/plugin-org", - "flags": ["api-version", "browser", "json", "loglevel", "path", "source-file", "target-org", "url-only"], "alias": ["force:org:open", "force:source:open"], + "command": "org:open", + "flagAliases": ["apiversion", "sourcefile", "targetusername", "u", "urlonly"], "flagChars": ["b", "f", "o", "p", "r"], - "flagAliases": ["apiversion", "sourcefile", "targetusername", "u", "urlonly"] + "flags": ["api-version", "browser", "json", "loglevel", "path", "source-file", "target-org", "url-only"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:resume:sandbox", - "plugin": "@salesforce/plugin-org", - "flags": ["job-id", "json", "name", "target-org", "use-most-recent", "wait"], "alias": ["env:resume:sandbox"], + "command": "org:resume:sandbox", + "flagAliases": [], "flagChars": ["i", "l", "n", "o", "w"], - "flagAliases": [] + "flags": ["job-id", "json", "name", "target-org", "use-most-recent", "wait"], + "plugin": "@salesforce/plugin-org" }, { - "command": "org:resume:scratch", - "plugin": "@salesforce/plugin-org", - "flags": ["job-id", "json", "use-most-recent"], "alias": ["env:resume:scratch"], + "command": "org:resume:scratch", + "flagAliases": [], "flagChars": ["i", "r"], - "flagAliases": [] + "flags": ["job-id", "json", "use-most-recent"], + "plugin": "@salesforce/plugin-org" } ] diff --git a/schemas/org-disable-tracking.json b/schemas/org-disable-tracking.json new file mode 100644 index 00000000..78d7b26d --- /dev/null +++ b/schemas/org-disable-tracking.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/OrgDisableTrackingResult", + "definitions": { + "OrgDisableTrackingResult": { + "type": "object", + "properties": { + "tracksSource": { + "type": "boolean" + }, + "username": { + "type": "string" + } + }, + "required": ["tracksSource", "username"], + "additionalProperties": false + } + } +} diff --git a/schemas/org-enable-tracking.json b/schemas/org-enable-tracking.json new file mode 100644 index 00000000..cbc31e71 --- /dev/null +++ b/schemas/org-enable-tracking.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/OrgEnableTrackingResult", + "definitions": { + "OrgEnableTrackingResult": { + "type": "object", + "properties": { + "tracksSource": { + "type": "boolean" + }, + "username": { + "type": "string" + } + }, + "required": ["tracksSource", "username"], + "additionalProperties": false + } + } +} From 3d676bc92691768312a8b683b5dc80b4b74f9132 Mon Sep 17 00:00:00 2001 From: mshanemc Date: Mon, 20 Nov 2023 14:12:20 -0600 Subject: [PATCH 3/3] docs: pjson topics --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 59753d79..b60139ea 100644 --- a/package.json +++ b/package.json @@ -72,10 +72,10 @@ "description": "Delete scratch orgs, sandboxes, org shapes, and org snapshots." }, "enable": { - "description": "description for org.enable" + "description": "Enable tracking on an org." }, "disable": { - "description": "description for org.disable" + "description": "Disable tracking on an org" } }, "external": true