Make a post about how debbugs versions are merged
authorDon Armstrong <don@donarmstrong.com>
Tue, 9 Jan 2018 01:27:03 +0000 (17:27 -0800)
committerDon Armstrong <don@donarmstrong.com>
Tue, 9 Jan 2018 05:21:18 +0000 (21:21 -0800)
posts/debbugs_merge_versions.mdwn [new file with mode: 0644]

diff --git a/posts/debbugs_merge_versions.mdwn b/posts/debbugs_merge_versions.mdwn
new file mode 100644 (file)
index 0000000..b64c139
--- /dev/null
@@ -0,0 +1,186 @@
+[[!meta title="Debbugs Versioning: Merging"]] 
+
+One of the key features of Debbugs,
+the [bug tracking system Debian uses](https://bugs.debian.org), is its
+ability to figure out which bugs apply to which versions of a package
+by tracking package uploads. This system generally works well, but
+when a package maintainer's workflow doesn't match the assumptions of
+Debbugs, unexpected things can happen. In this post, I'm going to:
+
+1. introduce how Debbugs tracks versions
+2. provide an example of a merge-based workflow which Debbugs doesn't handle well
+3. provide some suggestions on what to do in this case
+
+# Debbugs Versioning
+
+Debbugs tracks versions using a set of one or
+more
+[rooted trees](https://en.wikipedia.org/wiki/Tree_%28graph_theory%29#Forest) which
+it builds from the ordering of debian/changelog entries. In the
+simplist case, every upload of a Debian package has changelogs in the
+same order, and each upload adds just one version. For example, in the
+case of [dgit](https://packages.debian.org/dgit), to start with the
+package has this (abridged) version tree:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"""]]
+
+the next upload, *3.13*, has a changelog with this version ordering:
+`3.13 3.12 3.11 3.10`, which causes the *3.13* version to be added as
+a descendant of *3.12*, and the version tree now looks like this:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"3.12"
+"""]]
+
+dgit is being developed while also being used, so new versions with
+potentially disruptive changes are uploaded to experimental while
+production versions are uploaded to unstable. For example, the *4.0*
+experimental upload was based on the *3.10* version, with the
+changelog ordering `4.0 3.10`. The tree now has two branches, but
+everything seems as you would expect:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"3.12"
+"4.0"->"3.10"
+"""]]
+
+# Merge based workflows
+
+Bugfixes in the maintenance version of dgit also are made to the
+experimental package by merging changes from the production version
+using git. In this case, some changes which were present in the *3.12*
+and *3.11* versions are merged using git, corresponds to a git merge
+flow like this:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"3.12"
+"4.0"->"3.10"
+"4.1"->"4.0"
+"4.1"->"3.12"
+"""]]
+
+If an upload is prepared with changelog ordering `4.1 4.0 3.12 3.11
+3.10`, Debbugs combines this new changelog ordering with the
+previously known tree, to produce this version tree:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"3.12"
+"4.0"->"3.12"
+"4.1"->"4.0"
+"""]]
+
+This looks a bit odd; what happened? Debbugs walks through the new
+changelog, connecting each of the new versions to the previous version
+if and only if that version is not already an ancestor of the new
+version. Because the changelog says that *3.12* is the ancestor of
+*4.0*, that's where the `4.1 4.0` version tree is connected.
+
+Now, when *4.2* is uploaded, it has the changelog ordering (based on
+time) `4.2 3.13 4.1 4.0 3.12 3.11 3.10`, which corresponds to this git
+merge flow:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"3.12"
+"4.0"->"3.10"
+"4.1"->"4.0"
+"4.1"->"3.12"
+"4.2"->"4.1"
+"4.2"->"3.13"
+"""]]
+
+Debbugs adds in *3.13* as an ancestor of *4.2*, and because *4.1* was
+not an ancestor of *3.13* in the previous tree, *4.1* is added as an
+ancestor of *3.13*. This results in the following graph:
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"4.1"
+"4.0"->"3.12"
+"4.1"->"4.0"
+"4.2"->"3.13"
+"""]]
+
+Which doesn't seem particularly helpful, because
+
+[[!graph src="""
+ranksep = 0.2;
+rankdir = "LR";
+node [fontsize=12,shape=box,margin=0.05,width=0.3,height=0.1];
+edge [dir="back"];
+"3.11"->"3.10"
+"3.12"->"3.11"
+"3.13"->"3.12"
+"4.0"->"3.10"
+"4.1"->"4.0"
+"4.2"->"4.1"
+"""]]
+
+is probably the tree that more closely resembles reality.
+
+
+# Suggestions on what to do
+
+*Why does this even matter?* Bugs which are found in *3.11*, and fixed
+in *3.12* now show up as being found in *4.0* after the *4.1* release,
+though they weren't found in *4.0* before that release. It also means
+that *3.13* now shows up as having all of the bugs fixed in *4.2*,
+which might not be what is meant.
+
+To avoid this, my suggestion is to order the entries in changelogs in
+the same order that the version graph should be traversed from the
+leaf version you are releasing to the root. So if the previous version
+tree is what is wanted, *3.13* should have a changelog with ordering
+`3.13 3.12 3.11 3.10`, and *4.2* should have a changelog with ordering
+`4.2 4.1 4.0 3.10`.
+
+*What about making the BTS support DAGs which are not trees?* I think
+something like this would be useful, but I don't personally have a
+good idea on how this could be specified using the changelog or how
+bug fixed/found/absent should be propagated in the DAG. If you have
+better ideas, email me!
+
+
+
+[[!tag debian tech debbugs]]