When deploying new custom profiles between orgs with Gearset, there's some slightly unintuitive behavior in how the profiles are applied in the target org which can catch some people out. This article explains what the behavior is, and how to work around it.
What's the scenario?
You're deploying a new custom profile from a source org to a target org. The custom object permission is set to unticked/false in the source org, and to ticked/true in the Standard User
profile in the target org.
(Note: standard objects are considered custom objects
in the metadata API, so custom object permission can include permissions to standard objects.)
What happens?
After the deployment completes, you'll find that the custom object permission on the new profile in your target org is set to ticked/true, when you would expect it to be unticked/false.
Apex class access, app permissions and system permissions are similarly affected.
You may also find that some user permissions on the new profile in your target org are set to ticked/true, when you would expect them to be unticked/false.
Why does this happen?
It comes down to how readable and editable permissions are represented by the Salesforce metadata API, and how Gearset interprets them:
A permission which is ticked/true is represented as
<permission>true</permission>
A permission which is unticked/false can be not returned at all in the XML
A permission which is unticked/false can be represented as
<permission>false</permission>
When deploying permissions through the metadata API, if the permission is not explicitly set, Salesforce will set it to the default (taken from the Standard User
profile) in the target org. The default can be either true or false.
As a result, when Gearset queries an org before a profile exists it's hard to tell if a specific permission is explicitly set to false (in which case nothing is returned), or if it's in the default state (which could be true or false, but is also not returned), as both generate the same XML from Salesforce.
In this scenario, Gearset will assume the profile should be set to the org default instead of forcing it to be unticked/false.
What's the workaround?
Once you've run the first deployment, run a second comparison between the same source and target.
You should now see the appropriate custom object permission (as well as apex class access, app permissions and system permissions) as a deleted item in the result grid, and be able to deploy those permissions to correctly set it in the target org.
You may also want to vote on this suggestion in Salesforce IdeaExchange.