When exploring the Salesforce Migration Tool as an option to propagate change between different Salesforce instances, I faced the problem that custom fields where not accessible by any user. This is quite problematic, since I would like to use the migration tool as one central piece for automating the deployments of changes in Salesforce together with changes of a connected Heroku app.

Doing research about the problem, I found the suggestion to manage the permissions manually. This is the opposite of automating anything. So I looked around into options how I could modify the retrieved metadata in an automated way, so that I would be able to migrate changes between instances without having to apply the point-and-click pattern.

The case

In my current setup, I have a sandbox for a staging system. Since the process of handling change is not yet streamlined, sometimes a need to migrate changes from production to staging arises.

When I tried to deploy to the staging system, I ran into the following issues:

  • The first time I only added my custom object. Retrieving the metadata from production and deploying it to staging went just fine. I got stuck, once I tried to add a new custom field into the Heroku Connect mapping: The field did not appear.

    After a short investigation, it turned out that field permissions where not included. This can be addressed by including also the layouts and the profiles.

  • For the second attempt, I added all profiles and the default layout for my custom object. Now the deployment failed due to issues around unknown permissions.

The problem with permissions

It turns out that some permissions do not exist in sandboxes. This means if you retrieve the metadata of a profile from a production instance, then you will not be able to deploy this metadata into a sandbox.

Here is how it looked on the command line:

$ ant deployCode
Buildfile: /Users/johannes/test-migration-tool/build.xml

deployCode:
[sf:deploy] Request for a deploy submitted successfully.
[sf:deploy] Request ID for the current deploy task: 0Be2E0000064kkDKAQ
[sf:deploy] Waiting for server to finish processing the request...
[sf:deploy] Request Status: Pending
[sf:deploy] Request Status: InProgress (3/190)  -- Processing Type: CustomObject
[sf:deploy] Request Status: Failed

BUILD FAILED
/Users/johannes/test-migration-tool/build.xml:51:
*********** DEPLOYMENT FAILED ***********
Request ID: 0Be2E0000064kkDKAQ

All Component Failures:
1.  profiles/Admin.profile -- Error: Unknown user permission: ManageSandboxes
2.  profiles/API.profile -- Error: Unknown user permission: ManageSandboxes

*********** DEPLOYMENT FAILED ***********


Total time: 26 seconds

Remove problematic permissions

So I wondered what I could do about such permissions. Based on further research I concluded that the correct way to handle this would be to remove the corresponding entries from the .profile files. I am describing in this section the approach and also the implementation to get it into a working state.

Approach

The approach which I found is based on the following thoughts and assumptions:

  • The generated .profile files are just plain XML. I could modify them with existing XML tooling like xsltproc and a XSLT stylesheet.
  • Ant is already used and it provides a task called xslt. This task can be used to apply the XSLT stylesheet as part of the target which retrieves the metadata.

Making it happen requires two steps:

  • First a suitable XSLT file has to be developed.
  • As a second step, this XSLT has to be integrated into the build file for Ant.

Creating the XSLT stylesheet

XSLT is based on matching and the more precise matches take priority. I started out by using the identity function, so that I would have a stylesheet which just copies everything from the input into the output.

The final step was then to add a specific match for the offending permissions, so that they would not be copied into the output anymore.

While developing the stylesheet, I used xsltproc which is part of libxslt. It is straightforward to use it on the command line and many Linux like systems have it already available.

Here is the final version of the XSLT stylesheet I ended up using:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:meta="http://soap.sforce.com/2006/04/metadata">

  <!-- Filter out problematic permissions -->
  <xsl:template match="meta:userPermissions[contains(meta:name, 'EditBillingInfo')]" />
  <xsl:template match="meta:userPermissions[contains(meta:name, 'ManageSandboxes')]" />

  <!-- Identity function, copy everything into the output -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Testing it out via xsltproc can be done in the following way:

xsltproc fix-up-permissions.xslt Admin.profile

Adding the Ant target

The next step was to make it work as part of the Ant build file build.xml. I decided to create a new target only for fixing up the profiles, this way it is easier to test it out. In a second step I updated the target which retrieves the metadata so that it will call the new target after retrieving the data.

I came up with the following definitions inside of the file build.xml:

<target name="retrieveCode">
  <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="src" unpackaged="src/package.xml"/>
  <antcall target="fixUpPermissions" />
</target>

<target name="fixUpPermissions">
  <tempfile property="temp.file" />
  <mkdir dir="${temp.file}" />
  <copy todir="${temp.file}">
    <fileset dir="src/profiles" />
  </copy>
  <xslt basedir="${temp.file}"
        destdir="src/profiles"
        extension=".profile"
        style="fix-up-permissions.xslt" />
  <delete dir="${temp.file}" />
</target>

Conclusions

For this particular use case the problem is solved. It seems as if this will bring me one step closer to automate the deployment pipeline for a setup where handling of change in a Salesforce system is part of the pipeline.

For now I am using the migration tool to move changes between different sandboxes instead of using the refresh mechanism. If this proves to work out well, the next steps would be to plug these pieces together with other snippets for a related Heroku app, so that the deployments could happen in an automated and somewhat predictable manner, including the Salesforce part.

Pointers

Ant

The build tool which I remember out of the Java world.

Details including the documentation of tasks can be found on the project homepage at http://ant.apache.org/.

XSLT
Working with XSLT is in my experience always a bit challenging if I did not work with it for a few quarters. The standards are essential readings, esp. the XSLT standard at https://www.w3.org/TR/xslt together with the XPATH one at https://www.w3.org/TR/xpath/.
xsltproc

This is my tool of choice when testing out XSLT files on the command line.

It comes usually as part of libxslt and can be installed in Nix environments by running nix-env -iA nixpkgs.libxslt.

Salesforce Migration Tool
It comes as a JAR which can be used via Ant. Related documentation can be found via https://developer.salesforce.com/docs/.

Comments

comments powered by Disqus