From 027752add63f250696f6a1961586199b56d0bad9 Mon Sep 17 00:00:00 2001 From: Peter van Gulik Date: Sun, 12 Jul 2026 22:21:41 +0200 Subject: [PATCH] feat: make production deploy test level configurable --- .../connection/metadata/types/deployResult.ts | 2 +- packages/vscode-extension/package.json | 15 +++++ .../__tests__/deployMetadataCommand.test.ts | 56 +++++++++++++++++++ .../metadata/deployMetadataCommand.ts | 12 +++- .../src/lib/vlocodeConfiguration.ts | 1 + 5 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 packages/vscode-extension/src/commands/metadata/__tests__/deployMetadataCommand.test.ts diff --git a/packages/salesforce/src/connection/metadata/types/deployResult.ts b/packages/salesforce/src/connection/metadata/types/deployResult.ts index 3ffadb142..0df6649c6 100644 --- a/packages/salesforce/src/connection/metadata/types/deployResult.ts +++ b/packages/salesforce/src/connection/metadata/types/deployResult.ts @@ -268,7 +268,7 @@ export interface DeployOptions { * * _Note: Apex tests that run as part of a deployment always run synchronously and serially._ */ - testLevel?: 'NoTestRun' | 'RunSpecifiedTests' | 'RunLocalTests' | 'RunAllTestsInOrg'; + testLevel?: 'NoTestRun' | 'RunRelevantTests' | 'RunSpecifiedTests' | 'RunLocalTests' | 'RunAllTestsInOrg'; /** * Indicates whether the specified .zip file points to a directory * structure with a single package (`true`) or a set of packages (`false`). diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index 0f4cf14ec..69b03b362 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -1513,6 +1513,21 @@ "default": false, "markdownDescription": "Automatically deploy metadata files to Salesforce when saved." }, + "vlocity.salesforce.productionDeployTestLevel": { + "type": "string", + "enum": [ + "RunRelevantTests", + "RunLocalTests", + "RunAllTestsInOrg" + ], + "default": "RunRelevantTests", + "enumDescriptions": [ + "Run tests that Salesforce determines are relevant to the deployed metadata.", + "Run all local Apex tests in the production org.", + "Run all Apex tests in the production org, including managed package tests." + ], + "markdownDescription": "Apex test level used for Salesforce metadata deployments to production orgs. `NoTestRun` is not available in production." + }, "vlocity.salesforce.profileActionsInContextMenu": { "type": "boolean", "default": true, diff --git a/packages/vscode-extension/src/commands/metadata/__tests__/deployMetadataCommand.test.ts b/packages/vscode-extension/src/commands/metadata/__tests__/deployMetadataCommand.test.ts new file mode 100644 index 000000000..74370c9c8 --- /dev/null +++ b/packages/vscode-extension/src/commands/metadata/__tests__/deployMetadataCommand.test.ts @@ -0,0 +1,56 @@ +import DeployMetadataCommand from '../deployMetadataCommand'; + +class TestDeployMetadataCommand extends DeployMetadataCommand { + + public execute() { + return undefined; + } + + constructor( + private readonly productionOrg: boolean, + productionDeployTestLevel?: string + ) { + super(); + Object.defineProperty(this, 'vlocode', { + value: { + config: { + salesforce: { + productionDeployTestLevel + } + } + } + }); + } + + protected get salesforce() { + return { + isProductionOrg: async () => this.productionOrg + } as any; + } + + public getOptions() { + return this.getDeploymentStartOptions(); + } +} + +describe('DeployMetadataCommand', () => { + it('defaults production deployments to RunRelevantTests', async () => { + await expect(new TestDeployMetadataCommand(true).getOptions()).resolves.toEqual({ + ignoreWarnings: true, + testLevel: 'RunRelevantTests' + }); + }); + + it('uses the configured production deployment test level', async () => { + await expect(new TestDeployMetadataCommand(true, 'RunLocalTests').getOptions()).resolves.toEqual({ + ignoreWarnings: true, + testLevel: 'RunLocalTests' + }); + }); + + it('does not set a test level for non-production deployments', async () => { + await expect(new TestDeployMetadataCommand(false, 'RunLocalTests').getOptions()).resolves.toEqual({ + ignoreWarnings: true + }); + }); +}); diff --git a/packages/vscode-extension/src/commands/metadata/deployMetadataCommand.ts b/packages/vscode-extension/src/commands/metadata/deployMetadataCommand.ts index 0ddf7f9e7..15beba111 100644 --- a/packages/vscode-extension/src/commands/metadata/deployMetadataCommand.ts +++ b/packages/vscode-extension/src/commands/metadata/deployMetadataCommand.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import open from 'open'; -import { DeployResult, RetrieveDeltaStrategy, SalesforceDeployment, SalesforcePackage, SalesforcePackageBuilder, SalesforcePackageType } from '@vlocode/salesforce'; +import { DeployOptions, DeployResult, RetrieveDeltaStrategy, SalesforceDeployment, SalesforcePackage, SalesforcePackageBuilder, SalesforcePackageType } from '@vlocode/salesforce'; import { VlocodeCommand } from '../../constants'; import { ActivityProgress } from '../../lib/vlocodeActivity'; @@ -196,7 +196,7 @@ export default class DeployMetadataCommand extends MetadataCommand { deployment.cancel(); }); - await deployment.start({ ignoreWarnings: true }); + await deployment.start(await this.getDeploymentStartOptions()); this.logger.info(`Deployment details: ${await this.vlocode.salesforceService.getPageUrl(deployment.setupUrl)}`); const result = await deployment.getResult(); @@ -208,6 +208,14 @@ export default class DeployMetadataCommand extends MetadataCommand { return this.onDeploymentComplete(deployment, result); } + protected async getDeploymentStartOptions(): Promise { + const options: DeployOptions = { ignoreWarnings: true }; + if (await this.salesforce.isProductionOrg()) { + options.testLevel = this.vlocode.config.salesforce.productionDeployTestLevel ?? 'RunRelevantTests'; + } + return options; + } + private onDeploymentComplete(deployment: SalesforceDeployment, result: DeployResult) { // Clear errors before starting the deployment this.clearPreviousErrors(deployment.deploymentPackage.files()); diff --git a/packages/vscode-extension/src/lib/vlocodeConfiguration.ts b/packages/vscode-extension/src/lib/vlocodeConfiguration.ts index e58830b3b..f021628e7 100644 --- a/packages/vscode-extension/src/lib/vlocodeConfiguration.ts +++ b/packages/vscode-extension/src/lib/vlocodeConfiguration.ts @@ -4,6 +4,7 @@ export abstract class VlocodeSalesforceConfiguration extends BaseConfiguration { enabled: boolean; deployOnSave: boolean; apiVersion: string; + productionDeployTestLevel: 'RunRelevantTests' | 'RunLocalTests' | 'RunAllTestsInOrg'; manageMetaXmlFiles: boolean; developerLogsVisible: boolean; developerLogsAutoRefresh: boolean;