Newer Version Available
deployRecentValidation()
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 10 days.
- As part of the validation, Apex tests in the target org have passed.
- Code coverage requirements are met.
- If all tests in the org or all local tests are run, overall code coverage is at least 75%, and Apex triggers have some coverage.
- If specific tests are run with the RunSpecifiedTests test level, each class and trigger that was deployed is covered by at least 75% individually.
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.
- 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.
- 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}