Newer Version Available

This content describes an older version of this product. View Latest

deployRecentValidation()

Deploys a recently validated component set without running Apex tests.

Syntax

1string = metadatabinding.deployRecentValidation(ID validationID)

Usage

Use deployRecentValidation() to deploy your components to production in less time by skipping the execution of Apex tests. Ensure that the following requirements are met before deploying a recent validation.
  • The components have been validated successfully for the target environment within the last four days (96 hours).
  • As part of the validation, all Apex tests in the target organization have passed.
  • The overall code coverage in the organization is at least 75%, and Apex triggers have some coverage.

This call is equivalent to performing a quick deployment of a recent validation on the Deployment Status page in the Salesforce user interface.

Before you call deployRecentValidation(), your organization must have a validation that was recently run. You can run a validation on a set of components by calling deploy() with the checkOnly property of the deployOptions parameter set to true. Note the ID that you obtained from the deploy() call. You’ll use this ID for the deployRecentValidation() call in the next step.

After you’ve run a validation successfully, use these steps to quick-deploy the validation to the same target environment.

  1. To start an asynchronous quick deployment, call deployRecentValidation() and pass it the ID of a recent validation. This ID is obtained from the previous deploy() call. The deployRecentValidation() call returns the ID of the quick deployment. Note this value. You’ll use it in the next step.
  2. Check for the completion of the call. This process is similar to that of deploy(). Issue a checkDeployStatus() call in a loop until the done field of the returned DeployResult contains true, which means that the call is completed. The DeployResult object contains information about an in-progress or completed deployment that was started by using the deployRecentValidation() call. When calling checkDeployStatus(), pass in the ID value that you obtained in the first step.

Version

Available in API version 33.0 and later.

Arguments

Name Type Description
validationID string The ID of a recent validation.

Response

Type: string

The ID of the quick deployment.

Sample Code—Java

1package com.salesforce.test.metadata;
2
3import java.rmi.RemoteException;
4
5import com.sforce.soap.metadata.CodeCoverageWarning;
6import com.sforce.soap.metadata.DeployDetails;
7import com.sforce.soap.metadata.DeployMessage;
8import com.sforce.soap.metadata.DeployResult;
9import com.sforce.soap.metadata.MetadataConnection;
10import com.sforce.soap.metadata.RunTestFailure;
11import com.sforce.soap.metadata.RunTestsResult;
12import com.sforce.soap.partner.Connector;
13import com.sforce.ws.ConnectionException;
14import com.sforce.ws.ConnectorConfig;
15
16/**
17 * Quick-deploy a recent validation. 
18 * Prerequisite: A successful validation (check-only deploy) has been done in the org recently. 
19 */
20public class DeployRecentValidationSample {
21    // binding for the metadata WSDL used for making metadata API calls
22    private MetadataConnection metadataConnection;
23
24    // one second in milliseconds
25    private static final long ONE_SECOND = 1000;
26    // maximum number of attempts to deploy the zip file
27    private static final int MAX_NUM_POLL_REQUESTS = 50; 
28
29    public static void main(String[] args) throws Exception {
30        final String USERNAME = args[0];
31        final String PASSWORD = args[1]; 
32        final String URL = args[2];
33        
34        final String recentValidationId = args[3];
35        
36        DeployRecentValidationSample sample = new DeployRecentValidationSample(
37                          USERNAME, PASSWORD, URL);
38        sample.deployRecentValidation(recentValidationId);
39    }
40    
41    public DeployRecentValidationSample(String username, String password, String loginUrl) 
42            throws ConnectionException {
43        createMetadataConnection(username, password, loginUrl);
44    }
45
46    public void deployRecentValidation(String recentValidationId)
47        throws RemoteException, Exception
48    {
49        String asyncResultId = metadataConnection.deployRecentValidation(recentValidationId);
50        
51        // Wait for the deploy to complete
52        int poll = 0;
53        long waitTimeMilliSecs = ONE_SECOND;
54        DeployResult deployResult = null;
55        boolean fetchDetails;
56        do {
57            Thread.sleep(waitTimeMilliSecs);
58            // double the wait time for the next iteration
59            waitTimeMilliSecs *= 2;
60            if (poll++ > MAX_NUM_POLL_REQUESTS) {
61                throw new Exception("Request timed out. If this is a large set " +
62                        "of metadata components, check that the time allowed by " +
63                        "MAX_NUM_POLL_REQUESTS is sufficient.");
64            }
65            
66            // Fetch in-progress details once for every 3 polls
67            fetchDetails = (poll % 3 == 0);
68            deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
69            System.out.println("Status is: " + deployResult.getStatus());
70            if (!deployResult.isDone() && fetchDetails) {
71                printErrors(deployResult, "Failures for deployment in progress:\n");
72            }
73        }
74        while (!deployResult.isDone());
75        
76        if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
77            throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
78                    deployResult.getErrorMessage());
79        }
80
81        if (!fetchDetails) {
82            // Get the final result with details if we didn't do it in the last attempt.
83            deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
84        }
85
86        if (!deployResult.isSuccess()) {
87            printErrors(deployResult, "Final list of failures:\n");
88            throw new Exception("The files were not successfully deployed");
89        }
90        
91        System.out.println("The recent validation " + recentValidationId + 
92                            " was successfully deployed");
93    }
94    
95    /**
96     * Print out any errors, if any, related to the deploy.
97     * @param result - DeployResult
98     */
99    private void printErrors(DeployResult result, String messageHeader)
100    {
101        DeployDetails deployDetails = result.getDetails();
102        
103        StringBuilder errorMessageBuilder = new StringBuilder();
104        if (deployDetails != null) {
105            DeployMessage[] componentFailures = deployDetails.getComponentFailures();
106            for (DeployMessage message : componentFailures) {
107                String loc = (message.getLineNumber() == 0 ? "" :
108                    ("(" + message.getLineNumber() + "," +
109                            message.getColumnNumber() + ")"));
110                if (loc.length() == 0
111                        && !message.getFileName().equals(message.getFullName())) {
112                    loc = "(" + message.getFullName() + ")";
113                }
114                errorMessageBuilder.append(message.getFileName() + loc + ":" +
115                        message.getProblem()).append('\n');
116            }
117            RunTestsResult rtr = deployDetails.getRunTestResult();
118            if (rtr.getFailures() != null) {
119                for (RunTestFailure failure : rtr.getFailures()) {
120                    String n = (failure.getNamespace() == null ? "" :
121                        (failure.getNamespace() + ".")) + failure.getName();
122                    errorMessageBuilder.append("Test failure, method: " + n + "." +
123                            failure.getMethodName() + " -- " +
124                            failure.getMessage() + " stack " +
125                            failure.getStackTrace() + "\n\n");
126                }
127            }
128            if (rtr.getCodeCoverageWarnings() != null) {
129                for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
130                    errorMessageBuilder.append("Code coverage issue");
131                    if (ccw.getName() != null) {
132                        String n = (ccw.getNamespace() == null ? "" :
133                            (ccw.getNamespace() + ".")) + ccw.getName();
134                        errorMessageBuilder.append(", class: " + n);
135                    }
136                    errorMessageBuilder.append(" -- " + ccw.getMessage() + "\n");
137                }
138            }
139        }
140        
141        if (errorMessageBuilder.length() > 0) {
142            errorMessageBuilder.insert(0, messageHeader);
143            System.out.println(errorMessageBuilder.toString());
144        }
145    }
146    
147    private void createMetadataConnection( 
148        final String username,
149        final String password,
150        final String loginUrl) throws ConnectionException {
151
152        final ConnectorConfig loginConfig = new ConnectorConfig();
153        loginConfig.setUsername(username);
154        loginConfig.setPassword(password);
155        loginConfig.setAuthEndpoint(loginUrl);
156        
157        Connector.newConnection(loginConfig);
158        
159        
160        final ConnectorConfig metadataConfig = new ConnectorConfig();
161        metadataConfig.setServiceEndpoint(
162            loginConfig.getServiceEndpoint().replace("/u/", "/m/"));
163        metadataConfig.setSessionId(loginConfig.getSessionId());
164        this.metadataConnection = com.sforce.soap.metadata.Connector.
165            newConnection(metadataConfig);
166    }
167
168}