From ddbcb9ce96e4611d82ee50adbcfc955ba6349143 Mon Sep 17 00:00:00 2001 From: shinoni Date: Wed, 15 Apr 2026 09:31:56 -0700 Subject: [PATCH 1/3] fix: exclude UIBundle from source tracking polling Add UIBundle to the typesToNoPollFor list so that source tracking does not poll for UIBundle SourceMembers after deploy/retrieve. Made-with: Cursor --- src/shared/remote/expectedSourceMembers.ts | 1 + .../unit/remote/expectedSourceMembers.test.ts | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/shared/remote/expectedSourceMembers.ts b/src/shared/remote/expectedSourceMembers.ts index cde886ed..7af6024e 100644 --- a/src/shared/remote/expectedSourceMembers.ts +++ b/src/shared/remote/expectedSourceMembers.ts @@ -34,6 +34,7 @@ const typesToNoPollFor = [ 'ManagedContentType', 'CustomObjectTranslation', 'TopicsForObjects', + 'UIBundle', ]; const typesNotToPollForIfNamespace = ['CustomLabels', 'CustomMetadata', 'DuplicateRule', 'WebLink']; diff --git a/test/unit/remote/expectedSourceMembers.test.ts b/test/unit/remote/expectedSourceMembers.test.ts index 7d8e1160..9139a446 100644 --- a/test/unit/remote/expectedSourceMembers.test.ts +++ b/test/unit/remote/expectedSourceMembers.test.ts @@ -113,4 +113,37 @@ describe('expectedSourceMembers', () => { const result = calculateExpectedSourceMembers(registry, input); expect(result.size).to.equal(0); }); + + it('omits UIBundle type from polling', () => { + const input = [ + { + type: 'UIBundle', + fullName: 'myApp', + filePath: 'src/uiBundles/myApp/myApp.uibundle-meta.xml', + state: ComponentStatus.Created, + }, + ]; + const result = calculateExpectedSourceMembers(registry, input); + expect(result.size).to.equal(0); + }); + + it('omits UIBundle while keeping other valid types', () => { + const input = [ + { + type: 'UIBundle', + fullName: 'myApp', + filePath: 'src/uiBundles/myApp/myApp.uibundle-meta.xml', + state: ComponentStatus.Created, + }, + { + type: 'ApexClass', + fullName: 'MyClass', + filePath: 'src/classes/MyClass.cls', + state: ComponentStatus.Created, + }, + ]; + const result = calculateExpectedSourceMembers(registry, input); + expect(result.size).to.equal(1); + expect(result.has('ApexClass###MyClass')).to.equal(true); + }); }); From 21d1ad28256b575aee8cff936b7d8a26860d6333 Mon Sep 17 00:00:00 2001 From: shinoni Date: Wed, 15 Apr 2026 09:43:15 -0700 Subject: [PATCH 2/3] test: add NUT for UIBundle source tracking exclusion Verifies that UIBundle deploy responses produce no expected SourceMembers and that the exclusion does not affect other metadata types in mixed deploys. @W-18405316@ Made-with: Cursor --- test/nuts/local/uiBundleSourceTracking.nut.ts | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 test/nuts/local/uiBundleSourceTracking.nut.ts diff --git a/test/nuts/local/uiBundleSourceTracking.nut.ts b/test/nuts/local/uiBundleSourceTracking.nut.ts new file mode 100644 index 00000000..b6b46f57 --- /dev/null +++ b/test/nuts/local/uiBundleSourceTracking.nut.ts @@ -0,0 +1,118 @@ +/* + * Copyright 2026, Salesforce, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import path from 'node:path'; +import { TestSession } from '@salesforce/cli-plugins-testkit'; +import { expect } from 'chai'; +import { ComponentStatus, RegistryAccess } from '@salesforce/source-deploy-retrieve'; +import { ShadowRepo } from '../../../src/shared/local/localShadowRepo'; +import { calculateExpectedSourceMembers } from '../../../src/shared/remote/expectedSourceMembers'; + +describe('UIBundle excluded from source tracking polling', () => { + let session: TestSession; + let projectPath: string; + const registry = new RegistryAccess(); + const pkgDir = 'force-app'; + + before(async () => { + session = await TestSession.create({ + project: { + sourceDir: path.join('test', 'nuts', 'repros', 'reactinternalapp'), + }, + devhubAuthStrategy: 'NONE', + }); + projectPath = session.project.dir; + }); + + after(async () => { + await session?.clean(); + }); + + it('local tracking resolves UIBundle files', async () => { + const repo = await ShadowRepo.getInstance({ + orgId: 'fakeOrgId-uibundle-tracking', + projectPath, + packageDirs: [{ path: pkgDir, name: pkgDir, fullPath: path.join(projectPath, pkgDir) }], + registry, + }); + + const nonDeletes = await repo.getNonDeleteFilenames(); + const uiBundleFiles = nonDeletes.filter((f) => f.includes('uiBundles')); + expect(uiBundleFiles.length).to.be.greaterThan(0); + }); + + it('UIBundle deploy responses produce no expected SourceMembers', () => { + const uiBundleResponses = [ + { + type: 'UIBundle', + fullName: 'localReact3', + filePath: path.join( + projectPath, + pkgDir, + 'main', + 'default', + 'uiBundles', + 'localReact3', + 'localReact3.uibundle-meta.xml' + ), + state: ComponentStatus.Created, + }, + { + type: 'UIBundle', + fullName: 'localReact3', + filePath: path.join(projectPath, pkgDir, 'main', 'default', 'uiBundles', 'localReact3', 'src', 'app.tsx'), + state: ComponentStatus.Created, + }, + { + type: 'UIBundle', + fullName: 'localReact3', + filePath: path.join(projectPath, pkgDir, 'main', 'default', 'uiBundles', 'localReact3', 'package.json'), + state: ComponentStatus.Changed, + }, + ]; + + const result = calculateExpectedSourceMembers(registry, uiBundleResponses); + expect(result.size).to.equal(0); + }); + + it('UIBundle exclusion does not affect other types in mixed deploys', () => { + const mixedResponses = [ + { + type: 'UIBundle', + fullName: 'localReact3', + filePath: path.join( + projectPath, + pkgDir, + 'main', + 'default', + 'uiBundles', + 'localReact3', + 'localReact3.uibundle-meta.xml' + ), + state: ComponentStatus.Created, + }, + { + type: 'ApexClass', + fullName: 'TestController', + filePath: path.join(projectPath, pkgDir, 'main', 'default', 'classes', 'TestController.cls'), + state: ComponentStatus.Created, + }, + ]; + + const result = calculateExpectedSourceMembers(registry, mixedResponses); + expect(result.size).to.equal(1); + expect(result.has('ApexClass###TestController')).to.equal(true); + }); +}); From f9f44d522c78d435604d783724f8dc372f4e95fb Mon Sep 17 00:00:00 2001 From: shinoni Date: Wed, 15 Apr 2026 11:15:20 -0700 Subject: [PATCH 3/3] chore: bump core to ^8.28.3 and SDR to ^12.32.7 Fix type collisions on external NUT tests. Made-with: Cursor --- package.json | 4 ++-- yarn.lock | 49 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 937379b0..5ffb548f 100644 --- a/package.json +++ b/package.json @@ -50,9 +50,9 @@ "node": ">=18.0.0" }, "dependencies": { - "@salesforce/core": "^8.28.1", + "@salesforce/core": "^8.28.3", "@salesforce/kit": "^3.2.6", - "@salesforce/source-deploy-retrieve": "^12.32.4", + "@salesforce/source-deploy-retrieve": "^12.32.7", "@salesforce/ts-types": "^2.0.12", "fast-xml-parser": "^5.5.7", "graceful-fs": "^4.2.11", diff --git a/yarn.lock b/yarn.lock index 70b7f664..af1b53a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -629,6 +629,11 @@ "@jsonjoy.com/buffers" "^1.0.0" "@jsonjoy.com/codegen" "^1.0.0" +"@nodable/entities@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@nodable/entities/-/entities-1.1.0.tgz#f98e5ee5a6e987b4cad56eb97be81043d9b8d31d" + integrity sha512-bidpxmTBP0pOsxULw6XlxzQpTgrAGLDHGBK/JuWhPDL6ZV0GZ/PmN9CA9do6e+A9lYI6qx6ikJUtJYRxup141g== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -701,10 +706,10 @@ ts-retry-promise "^0.8.1" zod "^4.1.12" -"@salesforce/core@^8.28.1": - version "8.28.1" - resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.28.1.tgz#d83f8d0a8a83057c5a363aa6b5211b583fb9206b" - integrity sha512-k9lPsULo+lOEZvpm1J1nJOFwKp5O5IfNqya7pw627QdKGcsWZm6v9caVHKUX9IjyB+S3dasNqaZT5O7l76C4oQ== +"@salesforce/core@^8.28.3": + version "8.28.3" + resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.28.3.tgz#1344dc408833fb2a6ac19e6c4c09f846b6593ce3" + integrity sha512-DDAeHVwDO8wUlqEGwfp8Vuu7Vp7K+hpubKu6baWkHAXiO1u7ZbQkvwCbpPz9JiYEXVUBvP11JtBQ7zOUIPShlQ== dependencies: "@jsforce/jsforce-node" "^3.10.13" "@salesforce/kit" "^3.2.4" @@ -787,23 +792,23 @@ resolved "https://registry.yarnpkg.com/@salesforce/schemas/-/schemas-1.10.3.tgz#52c867fdd60679cf216110aa49542b7ad391f5d1" integrity sha512-FKfvtrYTcvTXE9advzS25/DEY9yJhEyLvStm++eQFtnAaX1pe4G3oGHgiQ0q55BM5+0AlCh0+0CVtQv1t4oJRA== -"@salesforce/source-deploy-retrieve@^12.32.4": - version "12.32.4" - resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.32.4.tgz#d9dc6653b31b2e60b0b6411cc0619da7c9fb8fbe" - integrity sha512-Eqo+OkbHkJWrgp9lRiz0l1NmJZ/N6SQdFcY+EtdA0wqKABtmV05BSvkgOA1Iab4e/fjcQCoi01v+oozPHat1Ag== +"@salesforce/source-deploy-retrieve@^12.32.7": + version "12.32.7" + resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.32.7.tgz#acc2377987095fc9abd0f5256442d5042b54dd68" + integrity sha512-nxrMUYyLi171EllPssXKfr/D3+DBeTeeV+VUSqHVgTyRrGVVvlV86dVgyWaC7d5E8C6wgLMKiMu43zs4GRb9XQ== dependencies: "@salesforce/core" "^8.27.1" "@salesforce/kit" "^3.2.4" "@salesforce/ts-types" "^2.0.12" "@salesforce/types" "^1.6.0" fast-levenshtein "^3.0.0" - fast-xml-parser "^5.5.9" + fast-xml-parser "^5.5.11" got "^11.8.6" graceful-fs "^4.2.11" ignore "^5.3.2" jszip "^3.10.1" mime "2.6.0" - minimatch "^9.0.7" + minimatch "^9.0.9" proxy-agent "^6.5.0" yaml "^2.8.3" @@ -2780,7 +2785,17 @@ fast-xml-builder@^1.1.4: dependencies: path-expression-matcher "^1.1.3" -fast-xml-parser@^5.5.7, fast-xml-parser@^5.5.9: +fast-xml-parser@^5.5.11: + version "5.6.0" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.6.0.tgz#4ade6df478c2532a462b693278fa6393c295a9e3" + integrity sha512-5G+uaEBbOm9M4dgMOV3K/rBzfUNGqGqoUTaYJM3hBwM8t71w07gxLQZoTsjkY8FtfjabqgQHEkeIySBDYeBmJw== + dependencies: + "@nodable/entities" "^1.1.0" + fast-xml-builder "^1.1.4" + path-expression-matcher "^1.5.0" + strnum "^2.2.3" + +fast-xml-parser@^5.5.7: version "5.5.9" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.5.9.tgz#e59637abebec3dbfbb4053b532d787af6ea11527" integrity sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g== @@ -4429,7 +4444,7 @@ minimatch@^5.0.1, minimatch@^5.1.6: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.4, minimatch@^9.0.5, minimatch@^9.0.7: +minimatch@^9.0.4, minimatch@^9.0.5, minimatch@^9.0.9: version "9.0.9" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== @@ -4878,6 +4893,11 @@ path-expression-matcher@^1.1.3, path-expression-matcher@^1.2.0: resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz#9bdae3787f43b0857b0269e9caaa586c12c8abee" integrity sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ== +path-expression-matcher@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz#3b98545dc88ffebb593e2d8458d0929da9275f4a" + integrity sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" @@ -5910,6 +5930,11 @@ strnum@^2.2.2: resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.2.tgz#f11fd94ab62b536ba2ecc615858f3747c2881b3f" integrity sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA== +strnum@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.3.tgz#0119fce02749a11bb126a4d686ac5dbdf6e57586" + integrity sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg== + supports-color@^7, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"