TL;DR: never change the functionality of upgrade tasks that have been released – create new fixer tasks instead. Keep your upgrade tasks independent of other services. From time to time we get bugs in our products that are caused by changes to upgrade tasks. In general, changing the functionality of upgrade tasks is a bad idea. A year-old example OnDemand uses a suite of plugins on top of our regular on-premises applications to provide the integration between the apps. Two of the services provided are Subversion hosting (or were – we no longer offer the Subversion service) and Bamboo (Bamboo is our CI offering – we don’t provide build agents as part of OnDemand; people need to use Amazon’s EC2 platform for that). The integration in this case is that Bamboo builds in OnDemand automatically know about Subversion and can check out from there without extra setup. The ability to do this is implemented by having a special user in the system that Subversion knows about and Bamboo has credentials for. About a year ago, we needed to change the way this user was created so we moved it into the upgrade task code. There was already an upgrade task which did the initial setup in Bamboo, so it seemed logical to add the new user creation code there. Our functional tests start with a clean slate so, in the functional tests, the upgrade task was run and the user created successfully – but manual upgrade testing showed that Bamboo agents could no longer check out from Subversion. The code worked well on new instances, but the users were not created on old instances! The reason was that the upgrade task had already run and was not re-run. The effect was that old instances couldn’t use Bamboo. It took us a lot of time to diagnose the problem because the upgrade task looked like it was creating the user and debugging showed that it did create the user. If we hadn’t changed the upgrade task, and instead written a new one, we’d have saved a fair bit of time. The problem Making alterations to upgrade tasks is a high-risk area. It’s high-risk because it’s code that only runs once and then is never run again. This means that if an upgrade task has had its functionality changed at some stage then different versions of that plugin will run with upgrade tasks that do different things. This means that if you get a fresh checkout of the plugin source, you will not be looking at the code that has run everywhere the plugin is used. After a few changes to upgrade tasks between plugin versions, you approach a situation where what has been run (such as workflows being put in a certain state at some time* or, in the case of the above example, a user existing in a certain state at a certain time**) differ significantly between instances, which means you can no longer make assumptions about what has happened in your upgrade tasks. Discovering what version has been [...]