You are using an older browser that might negatively affect how this site is displayed. Please update to a modern browser to have a better experience. Sorry for the inconvenience!

Leveraging Salesforce Metadata API for Incremental Deployments


Metadata API is used to create, modify, and delete Salesforce metadata such as Custom objects, and configurations in a Salesforce organization.  It is the backbone of most migration tools and IDEs. Unlike rest and soap Webservices, metadata API is intended for managing customization and for building tools that can manage the metadata model.

Basic code to retrieve an Apex class source using Metadata API is as follows,

//variable value can be any metadata type such as apex trigger, class, custom field...         

String MetaDataType = 'ApexClass'; 

//For demo, apex class AccountManager is used. 

String MetaDataItem = 'AccountManager'; 

private static final Integer METADATA_API_VERSION =  

   Integer.valueOf(new MetadataService.MetadataPort().endpoint_x.substringAfterLast('/')); 

//Creating instance for metadataport. 

MetadataService.MetadataPort service = new MetadataService.MetadataPort(); 

service.SessionHeader = new MetadataService.SessionHeader_element(); 

//session can be logged in user session or it can another instance session. 

service.SessionHeader.sessionId = Session; 

MetadataService.MetadataPort service = createService(); 

MetadataService.RetrieveRequest retrieveRequest = new MetadataService.RetrieveRequest(); 

retrieveRequest.apiVersion = METADATA_API_VERSION; 

retrieveRequest.packageNames = null; 

retrieveRequest.singlePackage = true; 

retrieveRequest.specificFiles = null; 

retrieveRequest.unpackaged = new MetadataService.Package_x(); 

retrieveRequest.unpackaged.types = new List<MetadataService.PackageTypeMembers>(); 

MetadataService.PackageTypeMembers packageType = new MetadataService.PackageTypeMembers(); 

packageType.name = MetaDataType;  

packageType.members = new String[] { MetaDataItem }; 

   retrieveRequest.unpackaged.types.add(packageType); 

AsyncResult = service.retrieve(retrieveRequest); 

//Asynchrnous calls will not provide zip file immediately.  Poll the service with some time interval to fetch the zipfile. 

MetadataService.RetrieveResult retrieveResult = service.checkRetrieveStatus(AsyncResult.Id, true); 

system.debug('retrieveResult base64 encoded string'+retrieveResult.zipFile); 

The above code will retrieve base64 of zip file.  If we decode the base64 string, then we can see the zip file has apex classes, package.xml, and some dependency files.

Image

Basic code to deploy a base64 zip file to an org via metadata API.

       //Create instance for metadata port. 

       MetadataService.MetadataPort service = new MetadataService.MetadataPort(); 

       service.SessionHeader = new MetadataService.SessionHeader_element(); 

       //pass the session id of the target instance. 

       service.SessionHeader.sessionId = Session; 

       MetadataService.DeployOptions deployOptions = new MetadataService.DeployOptions(); 

       deployOptions.allowMissingFiles = false; 

       deployOptions.autoUpdatePackage = false; 

       deployOptions.checkOnly = false; 

       deployOptions.ignoreWarnings = false; 

       deployOptions.performRetrieve = false; 

       deployOptions.purgeOnDelete = false; 

       deployOptions.rollbackOnError = true; 

       deployOptions.testLevel = 'NoTestRun'; 

       deployOptions.singlePackage = true; 

       //zip is the base64 string of the package zip file. 

       MetadataService.AsyncResult AsyncResult = service.deploy(zip, DeployOptions); 

The above code will deploy the zip file to the target instance.

Use Case: 

Development team frequently performs incremental deployments for set of classes by creating a Change Set in Sandbox, uploading, validating and then deploying the Change Set.  To avoid such repetitive work and to save some time while working on time-sensitive tasks, we can leverage the Metadata API to build custom application to use our day-to-day use.

The above code is implemented and developed as an app that will help us deploy a class right from the sandbox within a few clicks.  Let us look at the process of deployment involved in our custom app.

  1. Selecting the class to deploy: 

Open the class and click the deploy button.  Make sure the test class passes by executing the necessary lines of code.

Deploy button is added by chrome extension. This is used to redirect to the Deployment App.  Deployment App will store the referrer URL that has the Class id which is used to create a zip file with package.xml file.

Image

  1. Selecting the target instance: 

In the Deployment App, there are two buttons placed: one is to authorize sandbox instance and another one is for production instance.  Select the target instance.

Image

  1. Authorize: 

Login your credentials and allow the app to generate access token.  By this way, the metadata will push and deploy the files in the target instance.

Image

  1. Start Deployment: 

Once the authorization is successful, the deploy button will be rendered on the page.  Click the Deploy button to start the deployment.

Image

This is a very simple and effective way of doing incremental deployments.  There are many Metadata API features that can be useful for creating apps that can reduce deployment time.

Reference Link: https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_intro.htm