It would be useful if you provided callbacks that could be registered which get fired the moment the user clicks one of the Build & Test or Build & Publish buttons. There are many things that I'd like to do with my U# compiler that I can't reasonably do because I can't tell when a user is about to upload their world. And there are utilities that I've made in the past that would have benefited from being able to know when a build is starting. There are many potential optimization tools that could be made to take advantage of the build callbacks as well.
The callbacks should be able to differentiate between Build & Test and Build & Publish.
The callbacks should also be capable of canceling a build in the case that some problem was found by the callback. Being able to do this is very important for U# because Unity has a great bug; where if any serialized fields on any C# script type have changed between a build and the last script compile, Unity will throw an out of bounds exception internally while doing the assetbundle build. This hard crashes Unity and corrupts the project’s assemblies, so the next time you start Unity, you will be left with a bunch of broken scripts. In order to fix this, you need to reimport a script and force Unity to rebuild the assemblies, then restart your editor. Sometimes you need to do this multiple times for the assemblies to repair fully. This could be prevented by refreshing the asset database and canceling a build if any scripts are compiling when the build has been requested.
Implementing a callback execution order where each script callback can register itself with an integer priority would be useful if people happened to make utilities that interfered with one another when executed in the wrong order. For a workable system I don’t think it’s necessary to provide a UI for the execution order, in the unlikely chance that two people make different utilities that interfere with each other, execution order may not help there and it should probably be left up to the utility authors to make sure their utilities do not clash.
The callbacks could be implemented as a list of a tuple of integer and Func<bool> that’s sorted by the integer for the priority. Callbacks could then be registered and unregistered through static methods on the VRCSdkControlPanelBuilder.