Newer Version Available

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

deploy()

Uses file representations of components to create, update, or delete those components in a Salesforce org.

Syntax

1AsyncResult = metadatabinding.deploy(base64 zipFile, DeployOptions deployOptions)

Usage

Use this call to take file representations of components and deploy them into an org by creating, updating, or deleting the components they represent.

You can deploy or retrieve up to 10,000 files at once and the maximum size of the deployed or retrieved .zip file is 39 MB. Note the following:

  • If using the Force.com Migration Tool to deploy an unzipped folder, all files in the folder are compressed first. The maximum size of uncompressed components in an unzipped folder is 400 MB or less depending on the compression ratio. If the files have a high compression ratio, you can migrate a total of approximately 400 MB because the compressed size would be under 39 MB. However, if the components can't be compressed much, like binary static resources, you can migrate less than 400 MB.
  • Metadata API base-64 encodes components after they’re compressed. The resulting .zip file can't exceed 50 MB, which is the limit for SOAP messages. Base-64 encoding increases the size of the payload, so your compressed payload can't exceed approximately 39 MB before encoding.

Note

In API version 29.0, Salesforce improved the deployment status properties and removed the requirement to use checkStatus() after a deploy() call to get information about deployments. Salesforce continues to support the use of checkStatus() when using deploy() with API version 28.0 or earlier.

For API version 29.0 or later, deploy (create or update) packaged or unpackaged components using the following steps.

  1. Issue a deploy() call to start the asynchronous deployment. An AsyncResult object is returned. Note the value in the id field and use it for the next step.
  2. 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 started using the deploy() call. When calling checkDeployStatus(), pass in the id value from the AsyncResult object from the first step.

For API version 28.0 or earlier, deploy (create or update) packaged or unpackaged components using the following steps.

  1. Issue a deploy() call to start the asynchronous deployment. An AsyncResult object is returned. If the call is completed, the done field contains true. Most often, the call is not completed quickly enough to be noted in the first result. If it is completed, note the value in the id field returned and skip the next step.
  2. If the call is not complete, issue a checkStatus() call in a loop using the value in the id field of the AsyncResult object returned by the deploy() call in the previous step. Check the AsyncResult object which is returned until the done field contains true. The time taken to complete a deploy() call depends on the size of the zip file being deployed, so a longer wait time between iterations should be used as the size of the zip file increases.
  3. Issue a checkDeployStatus() call to obtain the results of the deploy() call, using the id value returned in the first step.

To track the status of deployments that are in progress or completed in the last 30 days, from Setup, enter Deployment Status in the Quick Find box, then select Deployment Status.

You can cancel a deployment while it’s in progress or in the queue by clicking Cancel next to the deployment. The deployment then has the status Cancel Requested until the deployment is completely canceled. A canceled deployment is listed in the Failed section.

The package.xml file is a project manifest that lists all the components that you want to retrieve or deploy. You can use package.xml to add components. To delete components, add another manifest file. See Deleting Components from an Organization.

Permissions

Your client application must be logged in with the “Modify All Data” permission.

Arguments

Name Type Description
zipFile base64 Base 64-encoded binary data. Client applications must encode the binary data as base64.
deployOptions DeployOptions Encapsulates options for determining which packages or files are deployed.

DeployOptions

The following deployment options can be selected for this call:

Name Type Description
allowMissingFiles boolean If files that are specified in package.xml are not in the .zip file, specifies whether a deployment can still succeed.

Do not set this argument for deployment to production orgs.

autoUpdatePackage boolean If a file is in the .zip file but not specified in package.xml, specifies whether the file is automatically added to the package. A retrieve() is issued with the updated package.xml that includes the .zip file.

Do not set this argument for deployment to production orgs.

checkOnly boolean Defaults to false. Set to true to perform a test deployment (validation) of components without saving the components in the target org. A validation enables you to verify the results of tests that would be generated in a deployment, but doesn’t commit any changes. After a validation finishes with passing tests, it might qualify for deployment without rerunning tests. See deployRecentValidation().
ignoreWarnings boolean Indicates whether a warning should allow a deployment to complete successfully (true) or not (false). Defaults to false.

The DeployMessage object for a warning contains the following values:

  • problemTypeWarning
  • problem—The text of the warning.

If a warning occurs and ignoreWarnings is set to true, the success field in DeployMessage is true. If ignoreWarnings is set to false, success is set to false and the warning is treated like an error.

This field is available in API version 18.0 and later. Prior to version 18.0, there was no distinction between warnings and errors. All problems were treated as errors and prevented a successful deployment.

performRetrieve boolean Indicates whether a retrieve() call is performed immediately after the deployment (true) or not (false). Set to true in order to retrieve whatever was just deployed.
purgeOnDelete boolean If true, the deleted components in the destructiveChanges.xml manifest file aren't stored in the Recycle Bin. Instead, they become immediately eligible for deletion.

This field is available in API version 22.0 and later.

This option only works in Developer Edition or sandbox orgs; it doesn't work in production orgs.

rollbackOnError boolean Indicates whether any failure causes a complete rollback (true) or not (false). If false, whatever actions can be performed without errors are performed, and errors are returned for the remaining actions. This parameter must be set to true if you are deploying to a production org. The default is false.
runAllTests boolean (Deprecated and only available in API version 33.0 and earlier.) This field defaults to false. Set to true to run all Apex tests after deployment, including tests that originate from installed managed packages.

Apex tests that run as part of a deployment always run synchronously and serially.

Note

runTests string[] A list of Apex tests to run during deployment. Specify the class name, one name per instance. The class name can also specify a namespace with a dot notation. For more information, see Running a Subset of Tests in a Deployment.

To use this option, set testLevel to RunSpecifiedTests.

singlePackage boolean Indicates whether the specified .zip file points to a directory structure with a single package (true) or a set of packages (false).
testLevel TestLevel (enumeration of type string) Optional. Specifies which tests are run as part of a deployment. The test level is enforced regardless of the types of components that are present in the deployment package. Valid values are:
  • NoTestRun—No tests are run. This test level applies only to deployments to development environments, such as sandbox, Developer Edition, or trial organizations. This test level is the default for development environments.
  • RunSpecifiedTests—Only the tests that you specify in the runTests option are run. Code coverage requirements differ from the default coverage requirements when using this test level. Each class and trigger in the deployment package must be covered by the executed tests for a minimum of 75% code coverage. This coverage is computed for each class and trigger individually and is different than the overall coverage percentage.
  • RunLocalTestsAll tests in your org are run, except the ones that originate from installed managed packages. This test level is the default for production deployments that include Apex classes or triggers.
  • RunAllTestsInOrgAll tests are run. The tests include all tests in your org, including tests of managed packages.

If you don’t specify a test level, the default test execution behavior is used. See Running Tests in a Deployment.

Apex tests that run as part of a deployment always run synchronously and serially.

Note

This field is available in API version 34.0 and later.

Response

AsyncResult

Sample Code—Java

This sample shows how to deploy components in a zip file. See the retrieve() sample code for details on how to retrieve a zip file.

1package com.doc.samples;
2
3import java.io.*;
4
5import java.rmi.RemoteException;
6
7import com.sforce.soap.metadata.AsyncResult;
8import com.sforce.soap.metadata.DeployDetails;
9import com.sforce.soap.metadata.MetadataConnection;
10import com.sforce.soap.metadata.DeployOptions;
11import com.sforce.soap.metadata.DeployResult;
12import com.sforce.soap.metadata.DeployMessage;
13import com.sforce.soap.metadata.RunTestsResult;
14import com.sforce.soap.metadata.RunTestFailure;
15import com.sforce.soap.metadata.CodeCoverageWarning;
16import com.sforce.soap.enterprise.LoginResult;
17import com.sforce.soap.enterprise.EnterpriseConnection;
18import com.sforce.ws.ConnectionException;
19import com.sforce.ws.ConnectorConfig;
20
21/**
22 * Deploy a zip file of metadata components. 
23 * Prerequisite: Have a deploy.zip file that includes a package.xml manifest file that 
24 * details the contents of the zip file.
25 */
26public class DeploySample {
27    // binding for the metadata WSDL used for making metadata API calls
28    private MetadataConnection metadataConnection;
29
30    static BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
31
32    private static final String ZIP_FILE = "deploy.zip";
33
34    // one second in milliseconds
35    private static final long ONE_SECOND = 1000;
36    // maximum number of attempts to deploy the zip file
37    private static final int MAX_NUM_POLL_REQUESTS = 50; 
38
39    public static void main(String[] args) throws Exception {
40        final String USERNAME = "user@company.com";
41        // This is only a sample. Hard coding passwords in source files is a bad practice.
42        final String PASSWORD = "password"; 
43        final String URL = "https://login.salesforce.com/services/Soap/c/29.0";
44        
45        DeploySample sample = new DeploySample(USERNAME, PASSWORD, URL);
46        sample.deployZip();
47    }
48    
49    public DeploySample(String username, String password, String loginUrl) 
50            throws ConnectionException {
51        createMetadataConnection(username, password, loginUrl);
52    }
53
54    public void deployZip()
55        throws RemoteException, Exception
56    {
57        byte zipBytes[] = readZipFile();
58        DeployOptions deployOptions = new DeployOptions();
59        deployOptions.setPerformRetrieve(false);
60        deployOptions.setRollbackOnError(true);
61        AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
62        String asyncResultId = asyncResult.getId();
63        
64        // Wait for the deploy to complete
65        int poll = 0;
66        long waitTimeMilliSecs = ONE_SECOND;
67        DeployResult deployResult = null;
68        boolean fetchDetails;
69        do {
70            Thread.sleep(waitTimeMilliSecs);
71            // double the wait time for the next iteration
72            waitTimeMilliSecs *= 2;
73            if (poll++ > MAX_NUM_POLL_REQUESTS) {
74                throw new Exception("Request timed out. If this is a large set " +
75                        "of metadata components, check that the time allowed by " +
76                        "MAX_NUM_POLL_REQUESTS is sufficient.");
77            }
78            
79            // Fetch in-progress details once for every 3 polls
80            fetchDetails = (poll % 3 == 0);
81            deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
82            System.out.println("Status is: " + deployResult.getStatus());
83            if (!deployResult.isDone() && fetchDetails) {
84                printErrors(deployResult, "Failures for deployment in progress:\n");
85            }
86        }
87        while (!deployResult.isDone());
88        
89        if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
90            throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
91                    deployResult.getErrorMessage());
92        }
93
94        if (!fetchDetails) {
95            // Get the final result with details if we didn't do it in the last attempt.
96            deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
97        }
98
99        if (!deployResult.isSuccess()) {
100            printErrors(deployResult, "Final list of failures:\n");
101            throw new Exception("The files were not successfully deployed");
102        }
103        
104        System.out.println("The file " + ZIP_FILE + " was successfully deployed");
105    }
106    
107    /**
108     * Read the zip file contents into a byte array.
109     * @return byte[]
110     * @throws Exception - if cannot find the zip file to deploy
111     */
112    private byte[] readZipFile()
113        throws Exception
114    {
115        // We assume here that you have a deploy.zip file.
116        // See the retrieve sample for how to retrieve a zip file.
117        File deployZip = new File(ZIP_FILE);
118        if (!deployZip.exists() || !deployZip.isFile())
119            throw new Exception("Cannot find the zip file to deploy. Looking for " +
120                    deployZip.getAbsolutePath());
121        
122        FileInputStream fos = new FileInputStream(deployZip);
123        ByteArrayOutputStream bos = new ByteArrayOutputStream();
124        int readbyte = -1;
125        while ((readbyte = fos.read()) != -1)  {
126            bos.write(readbyte);
127        }
128        fos.close();
129        bos.close();
130        return bos.toByteArray();
131    }
132    
133 
134    /**
135     * Print out any errors, if any, related to the deploy.
136     * @param result - DeployResult
137     */
138    private void printErrors(DeployResult result, String messageHeader)
139    {
140        DeployDetails deployDetails = result.getDetails();
141        
142        StringBuilder errorMessageBuilder = new StringBuilder();
143        if (deployDetails != null) {
144            DeployMessage[] componentFailures = deployDetails.getComponentFailures();
145            for (DeployMessage message : componentFailures) {
146                String loc = (message.getLineNumber() == 0 ? "" :
147                    ("(" + message.getLineNumber() + "," +
148                            message.getColumnNumber() + ")"));
149                if (loc.length() == 0
150                        && !message.getFileName().equals(message.getFullName())) {
151                    loc = "(" + message.getFullName() + ")";
152                }
153                errorMessageBuilder.append(message.getFileName() + loc + ":" +
154                        message.getProblem()).append('\n');
155            }
156            RunTestsResult rtr = deployDetails.getRunTestResult();
157            if (rtr.getFailures() != null) {
158                for (RunTestFailure failure : rtr.getFailures()) {
159                    String n = (failure.getNamespace() == null ? "" :
160                        (failure.getNamespace() + ".")) + failure.getName();
161                    errorMessageBuilder.append("Test failure, method: " + n + "." +
162                            failure.getMethodName() + " -- " +
163                            failure.getMessage() + " stack " +
164                            failure.getStackTrace() + "\n\n");
165                }
166            }
167            if (rtr.getCodeCoverageWarnings() != null) {
168                for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
169                    errorMessageBuilder.append("Code coverage issue");
170                    if (ccw.getName() != null) {
171                        String n = (ccw.getNamespace() == null ? "" :
172                            (ccw.getNamespace() + ".")) + ccw.getName();
173                        errorMessageBuilder.append(", class: " + n);
174                    }
175                    errorMessageBuilder.append(" -- " + ccw.getMessage() + "\n");
176                }
177            }
178        }
179        
180        if (errorMessageBuilder.length() > 0) {
181            errorMessageBuilder.insert(0, messageHeader);
182            System.out.println(errorMessageBuilder.toString());
183        }
184    }
185    
186    private void createMetadataConnection( 
187        final String username,
188        final String password,
189        final String loginUrl) throws ConnectionException {
190
191        final ConnectorConfig loginConfig = new ConnectorConfig();
192        loginConfig.setAuthEndpoint(loginUrl);
193        loginConfig.setServiceEndpoint(loginUrl);
194        loginConfig.setManualLogin(true);
195        LoginResult loginResult = (new EnterpriseConnection(loginConfig)).login(
196                username, password);
197        
198        final ConnectorConfig metadataConfig = new ConnectorConfig();
199        metadataConfig.setServiceEndpoint(loginResult.getMetadataServerUrl());
200        metadataConfig.setSessionId(loginResult.getSessionId());
201        this.metadataConnection = new MetadataConnection(metadataConfig);
202    }
203
204}