Is your feature request related to a problem? Please describe.
The sfdx force:user:create command is great to create users on a Scratch Org.
However, as usernames need to be unique across all orgs, we can't set a specific username in the user file. It would be cool to have a way to create the user anyway, appending an org related string at the end to make it unique, like what's done for sandbox.
What are you trying to do
I have a repo with a user that needs to be created. A file that looks like this:
{
"Username": "[email protected]",
"FirstName": "Richard",
"LastName": "Hendricks",
"profileName": "Standard Platform User"
}
If 2 developers try to create a Scratch Org and create this user, only one of them will succeed, because of username uniqueness.
Describe the solution you'd like
I'd like a new flag on the sfdx force:user:create command to force username to be unique. It looks like Scratch Orgs don't have a "name" like a sandbox has, so this could be adding the org id to the username. So running the command with the new flag would end up creating the user in the Scratch Org (let's say Org Id 00DS0000003acEuMAI) with the username [email protected]. We would use 18 character case safe Id as username is lowercase.
The flag name could be something like --appendorgid or --forceuniqueness.
Describe alternatives you've considered
I thought about wrapping the existing command in one of mine, something like sfdx texei:user:create, but I think this would make sense to bring it to the official command.
Additional context
The idea behind this feature request is to be able to push metadata that contains usernames to a Scratch Orgs. Some are replaced on the fly with the scratch org user by the sfdx force commands, but not all of them. For instance Worfklow Field Update on Account Owner, or Approval Process on Account have to select a username at some point. It can't be replaced by a queue or a public group. Thus today it just can't be pushed to the Scratch Org.
With this, I could create the related users needed in the metadata, and just using the org id on the username while doing push/pull via a sfdx hook.
Thank you for filing this feature request. We appreciate your feedback and will review the feature at our next grooming or sprint planning session. We prioritize feature requests with more upvotes and comments.
This issue has been linked to a new work item: W-8825037
@FabienTaillon This is already possible. Simply remove the "username" attribute from the user's definition file. When you create the user, it will assign a completely random username based off the default scratch user's username.
@ImJohnMDaniel yes, that's not exactly what I want, I think I've been unclear.
Let's say I have a workflow field update that under some conditions will change the Account owner to "Richard Hendricks". If I want to push that metadata in the Scratch Org I can't because there is a username in the metadata, and this username doesn't exist in the Scratch Org. Plus this one has to be a username, it can't be replaced by a queue or a public group like it can be done for some other metadatas.
I could still replace on the fly the username in the metadata with the scratch org username, but then what happens if I have a user story that is something like "replace account owner in this workflow from Richard Hendricks to Erlich Bachman".
I wouldn't be able to do it in the Scratch Org. So what's the point of having it in the repo/scratch org if I can't really update it ?
Also, what if I change anything else in the workflow, and pull ? The metadata would then contain the scratch org user ?
Or worse, what if I have 5 different workflows or any metadata, that references 5 differents usernames. I can replace them on the fly, but then on the scratch org the metadata would reference the same username instead of 5 different ones. So even if on pull I replace on the fly the usernames the other way round, how do I know which username should be replaced and where ?
So what I would like to do is to create 2 usernames in the scratch org, [email protected] and [email protected], and see them created as [email protected] and [email protected].
Then I would be able to push the metadata as is, the same way as pushing this workflow in a sandbox will link it automatically to [email protected]. I'm working on a plugin using CLI hooks to achieve this, but that won't work until I can create a user with a specific username, not a random one.
What do you think ?
Also I think I can do the pull request myself here, but I was wondering if this would be a change that could be accepted.
@FabienTaillon you can solve this problem by creating a metadata renderer step on your pipeline to resolve the values for a particular environment. In summary, treat these specific values as env variables and use custom metadata to overwrite them during the env setup. In your example, I did not understand why would you have a hardcoded username in a workflow rule. Maybe the solution is to first remove all hardcoded references you could have. For workflow rules unfortunately you can't reference custom metadata values. So first you could stop using workflow rules and change them to triggers, or another automation type, where you can query the custom metadata values for the env you need if you are using sfdx packages, as it is definitely not good to have packages with hardcoded values that differ per environment. Then you package this metadata with the custom metadata with an entry record that is the default one, used by every scratch org. And for every environment, you would have a separate entry on this custom metadata that you would use to overwrite the default values during the deployment.
For the scenario where two developers need to create the user with that username appended with the org id to be unique, you can create an apex script and add it to your scratch org setup automation, and if you don't have it, create one, which is handy and you can later use on your pipeline. After that, you can render the custom metadata with the generated username and deploy it to your scratch org.
java
String email = '[email protected].' + UserInfo.getOrganizationId();
User user = new User();
user.email = email;
//fill in with all the other values needed for your user
insert user;
shipped!