diff --git a/CHANGELOG.md b/CHANGELOG.md index 481ce859a..17305ce18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +## [12.27.2](https://github.com/forcedotcom/source-deploy-retrieve/compare/12.27.1...12.27.2) (2025-11-12) + + +### Bug Fixes + +* add support for `DataObjectSearchIndexConf` metadata ([#1649](https://github.com/forcedotcom/source-deploy-retrieve/issues/1649)) ([46a3b00](https://github.com/forcedotcom/source-deploy-retrieve/commit/46a3b00b45c833728ebba6d734e975fd73f610c1)) + + + +## [12.27.1](https://github.com/forcedotcom/source-deploy-retrieve/compare/12.27.0...12.27.1) (2025-11-11) + + +### Bug Fixes + +* add support for `LightningOutApp` metadata ([#1648](https://github.com/forcedotcom/source-deploy-retrieve/issues/1648)) ([bdc1fb0](https://github.com/forcedotcom/source-deploy-retrieve/commit/bdc1fb057c5ce5a325c296fb4a0999e3ced26b55)) + + + +# [12.27.0](https://github.com/forcedotcom/source-deploy-retrieve/compare/12.26.1...12.27.0) (2025-11-11) + + +### Features + +* added RunRelevantTests test-level @W-20152151@ ([#1644](https://github.com/forcedotcom/source-deploy-retrieve/issues/1644)) ([96a176f](https://github.com/forcedotcom/source-deploy-retrieve/commit/96a176f7bc28d3671a9f50a89079373ffe1fcea9)) + + + +## [12.26.1](https://github.com/forcedotcom/source-deploy-retrieve/compare/12.26.0...12.26.1) (2025-11-11) + + +### Bug Fixes + +* web support without cwd W-20175875 ([#1647](https://github.com/forcedotcom/source-deploy-retrieve/issues/1647)) ([6dd7c70](https://github.com/forcedotcom/source-deploy-retrieve/commit/6dd7c708defdd064ac34ba77d154cc91ab2cee2b)) + + + # [12.26.0](https://github.com/forcedotcom/source-deploy-retrieve/compare/12.25.0...12.26.0) (2025-11-07) diff --git a/METADATA_SUPPORT.md b/METADATA_SUPPORT.md index ab525d112..6e84d1270 100644 --- a/METADATA_SUPPORT.md +++ b/METADATA_SUPPORT.md @@ -4,7 +4,7 @@ This list compares metadata types found in Salesforce v65 with the [metadata reg This repository is used by both the Salesforce CLIs and Salesforce's VSCode Extensions. -Currently, there are 675/719 supported metadata types. +Currently, there are 678/719 supported metadata types. For status on any existing gaps, please search or file an issue in the [Salesforce CLI issues only repo](https://github.com/forcedotcom/cli/issues). To contribute a new metadata type, please see the [Contributing Metadata Types to the Registry](./contributing/metadata.md) @@ -45,6 +45,7 @@ To contribute a new metadata type, please see the [Contributing Metadata Types t |AgentforceAccountManagementSettings|✅|| |AgentforceForDevelopersSettings|✅|| |Ai4mSettings|✅|| +|AiAuthoringBundle|✅|| |AiEvaluationDefinition|⚠️|Supports deploy/retrieve but not source tracking| |AiPlannerVoiceDef|❌|Not supported, but support could be added (but not for tracking)| |AnalyticSnapshot|✅|| @@ -207,7 +208,7 @@ To contribute a new metadata type, please see the [Contributing Metadata Types t |DataKitObjectDependency|✅|| |DataKitObjectTemplate|✅|| |DataObjectBuildOrgTemplate|✅|| -|DataObjectSearchIndexConf|❌|Not supported, but support could be added (but not for tracking)| +|DataObjectSearchIndexConf|⚠️|Supports deploy/retrieve but not source tracking| |DataPackageKitDefinition|✅|| |DataPackageKitObject|✅|| |DataSource|✅|| @@ -437,7 +438,7 @@ To contribute a new metadata type, please see the [Contributing Metadata Types t |LightningExperienceTheme|✅|| |LightningMessageChannel|✅|| |LightningOnboardingConfig|✅|| -|LightningOutApp|❌|Not supported, but support could be added| +|LightningOutApp|✅|| |LightningTypeBundle|✅|| |ListView|✅|| |LiveAgentSettings|✅|| @@ -715,7 +716,6 @@ To contribute a new metadata type, please see the [Contributing Metadata Types t |WebStoreBundle|✅|| |WebStoreTemplate|✅|| |WebToXSettings|✅|| -|WelcomeRecommendation|❌|Not supported, but support could be added| |WorkDotComSettings|✅|| |WorkSkillRouting|✅|| |Workflow|✅|| @@ -750,8 +750,8 @@ v66 introduces the following new types. Here's their current level of support |DynamicGanttSettings|✅|| |EmergencySettings|✅|| |ExtlClntAppAttestSettings|✅|| -|GENComputingSummaryDEF|❌|Not supported, but support could be added| |GRCIntelligenceUddSettings|✅|| +|GenComputingSummaryDef|❌|Not supported, but support could be added| |GeneralConfigSettings|✅|| |GeocodeSettings|✅|| |GiftEntryGridTemplate|✅|| @@ -774,6 +774,7 @@ v66 introduces the following new types. Here's their current level of support |StockRotationSettings|✅|| |SynchronizeSettings|✅|| |TriggerConfigurationsSettings|✅|| +|UnifiedSalesIntelligenceSettings|✅|| ## Additional Types @@ -786,7 +787,6 @@ v66 introduces the following new types. Here's their current level of support - AccessControlPolicy - AIAssistantTemplate -- AiAuthoringBundle - AssignmentRule - AssistantRecommendationType - AutoResponseRule diff --git a/messages/sdr.md b/messages/sdr.md index 32d31dec9..5b71679d9 100644 --- a/messages/sdr.md +++ b/messages/sdr.md @@ -22,6 +22,10 @@ Could not find parent type for %s (%s) Component conversion failed: %s +# error_invalid_test_level + +TestLevel cannot be '%s' unless API version is %s or later + # error_merge_metadata_target_unsupported Merge convert for metadata target format currently unsupported diff --git a/package.json b/package.json index 56bf3580a..680fffa0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@salesforce/source-deploy-retrieve", - "version": "12.26.0", + "version": "12.27.2", "description": "JavaScript library to run Salesforce metadata deploys and retrieves", "main": "lib/src/index.js", "author": "Salesforce", diff --git a/src/client/metadataApiDeploy.ts b/src/client/metadataApiDeploy.ts index 1e2bbb2bf..2d3ca0b6f 100644 --- a/src/client/metadataApiDeploy.ts +++ b/src/client/metadataApiDeploy.ts @@ -116,6 +116,7 @@ export class MetadataApiDeploy extends MetadataTransfer< public constructor(options: MetadataApiDeployOptions) { super(options); options.apiOptions = { ...MetadataApiDeploy.DEFAULT_OPTIONS.apiOptions, ...options.apiOptions }; + validateOptions(options); this.options = Object.assign({}, options); this.isRestDeploy = !!options.apiOptions?.rest; this.registry = options.registry ?? new RegistryAccess(); @@ -524,6 +525,17 @@ const buildFileResponsesFromComponentSet = } return fileResponses; }; + +const validateOptions = (options: MetadataApiDeployOptions): void => { + const runningRelevantTestsOnly = options.apiOptions?.testLevel === 'RunRelevantTests'; + const beforeApiV66 = options.apiVersion && Number(options.apiVersion) < 66.0; + if (runningRelevantTestsOnly && beforeApiV66) { + throw new SfError( + messages.getMessage('error_invalid_test_level', ['RunRelevantTests', '66.0']), + 'InvalidTestLevelSelection' + ); + } +}; /** * register a listener to `scopedPreDeploy` */ diff --git a/src/client/types.ts b/src/client/types.ts index 5da3ece36..dacbfd0c3 100644 --- a/src/client/types.ts +++ b/src/client/types.ts @@ -364,7 +364,7 @@ export type MetadataApiDeployOptions = { runAllTests?: boolean; runTests?: string[]; singlePackage?: boolean; - testLevel?: 'NoTestRun' | 'RunSpecifiedTests' | 'RunLocalTests' | 'RunAllTestsInOrg'; + testLevel?: 'NoTestRun' | 'RunSpecifiedTests' | 'RunLocalTests' | 'RunAllTestsInOrg' | 'RunRelevantTests'; /** * Set to true to use the REST API for deploying. */ diff --git a/src/registry/metadataRegistry.json b/src/registry/metadataRegistry.json index 2f0a7b51a..b13df815f 100644 --- a/src/registry/metadataRegistry.json +++ b/src/registry/metadataRegistry.json @@ -566,7 +566,9 @@ "dataMapperDefinition": "datamapperdefinition", "integrationProcdDefinition": "integrationprocddefinition", "omniscriptDefinition": "omniscriptdefinition", - "computeExtension": "computeextension" + "computeExtension": "computeextension", + "dataObjectSearchIndexConf": "dataobjectsearchindexconf", + "lightningOutApp": "lightningoutapp" }, "types": { "accesscontrolpolicy": { @@ -5051,6 +5053,22 @@ "directoryName": "computeExtensions", "inFolder": false, "strictDirectoryName": false + }, + "dataobjectsearchindexconf": { + "id": "dataobjectsearchindexconf", + "name": "DataObjectSearchIndexConf", + "suffix": "dataObjectSearchIndexConf", + "directoryName": "dataObjectSearchIndexConfs", + "inFolder": false, + "strictDirectoryName": false + }, + "lightningoutapp": { + "id": "lightningoutapp", + "name": "LightningOutApp", + "suffix": "lightningOutApp", + "directoryName": "lightningOutApp", + "inFolder": false, + "strictDirectoryName": false } } } diff --git a/src/resolve/treeContainers.ts b/src/resolve/treeContainers.ts index a49abae3b..24192686a 100644 --- a/src/resolve/treeContainers.ts +++ b/src/resolve/treeContainers.ts @@ -36,6 +36,12 @@ const messages = Messages.loadMessages('@salesforce/source-deploy-retrieve', 'sd * Extend this base class to implement a custom container. */ export abstract class TreeContainer { + protected cwd?: string; + + /** specify a cwd to use instead of the real cwd. Useful for tests and web environments where process.cwd is undefined */ + public constructor(cwd?: string) { + this.cwd = cwd; + } /** * Searches for a metadata component file in a container directory. * @@ -46,14 +52,20 @@ export abstract class TreeContainer { */ public find(fileType: 'content' | 'metadataXml', name: string, directory: string): string | undefined { const fileName = this.readDirectory(directory).find((entry) => { - const parsed = parseMetadataXml(join(directory, entry)); + const parsed = parseMetadataXml(this.getUpdatedFsPath(join(directory, entry))); const metaXmlCondition = fileType === 'metadataXml' ? !!parsed : !parsed; return baseName(entry) === name && metaXmlCondition; }); if (fileName) { - return join(directory, fileName); + return this.getUpdatedFsPath(join(directory, fileName)); } } + + /** if the container has cwd set, apply it to the path */ + protected getUpdatedFsPath(fsPath: SourcePath): string { + return this.cwd ? join(this.cwd, fsPath) : fsPath; + } + /** * Whether or not a file path exists in the container. * @@ -104,31 +116,31 @@ export abstract class TreeContainer { export class NodeFSTreeContainer extends TreeContainer { public isDirectory(fsPath: SourcePath): boolean { // use stat instead of lstat to follow symlinks - return statSync(fsPath).isDirectory(); + return statSync(this.getUpdatedFsPath(fsPath)).isDirectory(); } public exists(fsPath: SourcePath): boolean { - return existsSync(fsPath); + return existsSync(this.getUpdatedFsPath(fsPath)); } public readDirectory(fsPath: SourcePath): string[] { - return readdirSync(fsPath); + return readdirSync(this.getUpdatedFsPath(fsPath)); } public readFile(fsPath: SourcePath): Promise { // significant enough performance increase using sync instead of fs.promise version - return Promise.resolve(readFileSync(fsPath)); + return Promise.resolve(readFileSync(this.getUpdatedFsPath(fsPath))); } public readFileSync(fsPath: SourcePath): Buffer { - return readFileSync(fsPath); + return readFileSync(this.getUpdatedFsPath(fsPath)); } public stream(fsPath: SourcePath): Readable { if (!this.exists(fsPath)) { throw new Error(`File not found: ${fsPath}`); } - return createReadStream(fsPath); + return createReadStream(this.getUpdatedFsPath(fsPath)); } } diff --git a/test/client/metadataApiDeploy.test.ts b/test/client/metadataApiDeploy.test.ts index c8da492d7..ace098fd6 100644 --- a/test/client/metadataApiDeploy.test.ts +++ b/test/client/metadataApiDeploy.test.ts @@ -1256,6 +1256,30 @@ describe('MetadataApiDeploy', () => { expect(mdOpts.zipPath).to.equal('foo/myZip.zip'); }); + it('should disallow "RunRelevantTests" for API versions <66.0', () => { + const testCases = ['8.0', '10.0', '60.0', '65.0']; + const constructorError = { + name: 'InvalidTestLevelSelection', + message: messages.getMessage('error_invalid_test_level', ['RunRelevantTests', '66.0']), + }; + try { + testCases.forEach((v) => { + new MetadataApiDeploy({ + usernameOrConnection: 'testing', + apiOptions: { + testLevel: 'RunRelevantTests', + }, + apiVersion: v, + }); + assert.fail(`Should have thrown an error for API version ${v}`); + }); + } catch (e) { + assert(e instanceof Error); + expect(e.name).to.equal(constructorError.name); + expect(e.message).to.equal(constructorError.message); + } + }); + it('should allow mdapi path', () => { const mdApiDeploy = new MetadataApiDeploy({ usernameOrConnection: 'testing',