- The file tree of the head of the OU branch should always (except temporarily while stuff is being committed to it) be identical (except for the sparse Minkata-specific customizations) to the file tree of some revision that exists on the Minkata branch and has been tested on the Minkata shard for some time.
This turns out to be a harder nut to crack. Are we willing to relax this requirement? I’m having a hard time reconciling it with a continuous process, because it directly contradicts the main goal we are trying to achieve with the continuous process, namely that we don’t want incoming contributions to have to wait for the testing cycle to end before they can be integrated into the Minkata branch.
Example: Features A and B are merged into the Minkata branch and published to the shard for testing. A week later, features C and D are merged and published to Minkata. Another two weeks later, it is decided that A and B are now tested enough and are ready for promotion to the OU branch. However, now the state that is committed to the OU branch, namely one that contains A and B, but not C and D, is one that has only existed on the shard for one week – we thought we had tested A and B for three weeks, but two of those were in combination with C and D, which is a different state than the one we’re promoting, strictly speaking (1). The only way to get the exact state we’re going to promote tested for three weeks is to make C and D wait for two weeks, which is exactly the essence of the cyclic process and what we’re trying to avoid here. Even worse, if we decide that A and C have been sufficiently tested, then the state that the OU branch ends up in, namely one containing A and C, but not B and D, has never existed in the Minkata branch and been tested on the shard (even though we considered A as having been tested for three weeks and C for two weeks) (2).
My current opinion is that we probably shouldn’t do (2), i.e. merge contributions to OU in a different order than to Minkata, but that (1) is permissible as a compromise, in exchange for the advantages we get from the continuous process. It just needs to be done carefully: the features that are tested (partially) concurrently but promoted separately should be ones that are considered unlikely to interact.
With that out of the way, here’s what I wanted to say about my experiments and the proposed process in general:
These experiments consisted of replaying past (and some tentative near-future) history of CWE-ou-minkata and MOULSCRIPT-ou-minkata as if the continuous process had already been in place at that time. Everything worked well, and you can see the resulting repositories here: CWE-ou-minkata-continuous, MOULSCRIPT-ou-minkata-continuous. Revisions whose commit messages start with “*” are recreations of past revisions, those that start with “* let's pretend” are possible future continuations. (Just to be clear, I’m not proposing that we do this history-rewriting if we decide to switch to the new process. I just did it to get more real-life material to work with. In reality, we’d just apply the new process going forward.) The deviation from history as it really happened starts with revision 02e11c6f0c62 in CWE-, which starts the “minkata” branch by applying the Minkata-specific customizations, and cab8cea2fbeb in MOULSCRIPT- (where there are no Minkata-specific customizations). The revisions graphs get a bit crowded, but if you specifically highlight the “default” and “minkata” branches, I think it’s still manageable, and the advantages are worth it.
As alluded to several times above, there are two important branches here: the OU branch and the Minkata branch (both in the current and in the proposed model – the difference is that in the current model the Minkata branch is periodically restarted from the OU branch, while in the new model it is long-lived). In the past, OU has simply been the “default” branch of the *-ou repository, and Minkata the “default” branch of the *-ou-minkata repository. Going forward, I propose naming them differently to better keep the overview, since the *-ou-minkata repository contains both of these branches (both in the current process and in the proposed one). The *-ou repository only contains the OU branch. In my experiments, I named the Minkata branch “minkata” and kept the OU branch at “default”. That made sense to me because the latter is the main branch of the OU repository that we’re publishing to the outside world, while the Minkata branch is more of an internal thing that we can name as we like. I’m open to other schemes though. In that scheme, I would also propose requiring that contributions come on named feature branches, not “default”, to keep “default” reserved to the main OU branch (which is generally good practice anyway). Contributions should still, as before, branch off a revision on the OU branch, preferably the latest at the time (or possibly another feature branch if they depend on that feature). Since the Minkata branch is now long-lived and not periodically discarded, it could be published on Bitbucket too, and contributors could be given the choice of whether to make their pull requests against the OU or Minkata branch. That wouldn’t affect how we maintainers treat it, but it would affect when Bitbucket considers the pull request closed – either when it is merged to Minkata (earlier) or when it is merged to OU (later).
On the left side of the following figure, I schematically explain the proposed continuous process again (also refer to the description in my previous post):
Contrast with the right side, which depicts the current cyclic process, and illustrates the main problem with it that we’re trying to overcome: In step 5, F3 cannot be accepted into the Minkata branch yet, but must wait for the testing cycle to complete. It can only be merged in step 8. This is because if we do accept it in step 5 (dotted), we have two choices, both of which are undesirable:
- We declare it to be part of the current testing cycle, i.e. part of the contributions that will be promoted to the OU branch at the end of the cycle. This will delay the end of the cycle, because testing requires time. During that delay, new contributions will come in, and if we declare them part of the current cycle as well, they delay it even more, and so on, and the cycle never completes.
- We declare it not part of the current testing cycle, as shown in the figure. Apart from (just like the continuous process) violating requirement 3, this means that it will be lost when the Minkata branch is restarted in step 7, and a new revision with the same file tree (thin gray line) will have to be recreated later (shown as part of step 8 here). This is unnecessary duplication of work and an opportunity for errors.
(If you take a close look at the example OU-to-Minkata merge in CWE-ou-minkata-continuous, you will notice that it doesn’t quite match what I said above – it does introduce small changes to AllClient.sln into the Minkata branch. This is because the Minkata history leading up to it wasn’t constructed entirely by merging feature branches, as it should have been. Some contributions were instead rebased onto it, and mistakes happened in that rebasing that I didn’t consider worth fixing specifically at the time, because the Minkata branch was destined to be discarded anyway.)
Whew! Wall of text – I hope anyone has read this far… If so, any thoughts?