0

This is a best practices question for release management of an app. But this scenario is a bit different than what I've been able to find myself.

Essentially my company maintains a fork of its own app. There are two versions of the app that will have different configurations of bug fixes / features. These fixes and features come from a common pool of what's completed. The reason for the two configurations is that there are two main testing environments with different goals.

Let me explain that a bit more with a scenario:

  1. We have features 1, 2, & 3 and bug fixes 1, 3, & 3 being worked on at the same time by different devs.
  2. For the upcomming releases to QC, Config-1 of the app wants to include feature 1, and bug fixes 1 & 2, and Config-2 wants to include features 2 & 4.
  3. For subsequent releases to QC, certain features may get rejected as being incomplete, buggy, no longer needed, etc. And same with the bug fixes.

#3 is important because not all features get removed or synced between the two configurations. This means that the two configurations diverge slightly over time. But only in the short term for what's in active development. Over the long term, the code base is in sync with what's in production.

So, as a diagram, the builds could look like this over time (with some added features / bugs from the bulleted scenario above):

Builds Over Time of Two Related but Different Configurations

Basically a normal development life cycle, but with twin timelines. There's the main app, and a fork of it that's derived merely by a different combination of the available patches. Patch queues would work well but we use a build server to produce the builds which requires us to publicly push committed changes (as far as I can figure out) to a remote repo.

My question is really about what the easiest way to manage this is, at the actual source control level. What we've done in the past is (using Mercurial) maintain two repositories (one per configuration) and all features / bugs would get imported as needed as patches. Removing items would be done using a variety of ways, backouts probably being the most common. The problem with this is that the two repos ended up wildly different from each other with different items being applied at different times. So the entire changeset stack would be a different order.

What we're thinking about doing, is still maintain two separate repos, but every effort (features, bugs) would be developed as a branch and that branch gets pushed to the repo it's needed in. Within a given repo, if the branch is wanted in the upcoming build, it gets merged in the build branch which is monitored by our Jenkins server and produces the builds.

Is there a better way? An ironed out best practice that prevents messy build branches as a result of backing out items, and possibly even other issues that we don't know about yet?

4
  • 2
    If I were you, at this point I would try to move away from managing features on the repository level and instead incorporate selective feature management in the app itself - something like martinfowler.com/bliki/CanaryRelease.html (and then of course maintain a single code base) Jan 8, 2019 at 10:12
  • 3
    @PawelGorczynski: I guess you meant Feature Toggles?
    – Doc Brown
    Jan 8, 2019 at 21:33
  • @DocBrown yeah, seems so, thanks for the wording :) Jan 9, 2019 at 15:43
  • 1
    Version control systems are good for managing project history, but not as good for managing different editions of your software. It might be better to select features during the build process, but have all features present in the source code. Otherwise you're massively increasing the probability of conflicting changes.
    – amon
    Feb 3, 2020 at 8:26

2 Answers 2

0

Short answer

Single repo with Mercurial Queues for any amount of "configurations"

Longer answer

If all features are just patches on top of common clean code-base, MQ is your best friend: you can have every feature (even as WIP) in separate MQ-patch and apply|unapply when it needed. Because MQ-patches aren't part of repository (FIXME!) and if feature can be developed|used more than one developer, you can also be interested in MQCollab extension in order to share MQ-patches in easy and natural way between different locations

More longer answer

If all your future MQ-patches are independent of others (by design and idea - by code is the responsibility of the end developer), you can use single queue and just change order of patches in it before applying to code

If your patches will have internal dependences (bad idea, but... shit happens), you can separate dependent patches into separate queues with own stack of patches (main+dependent) in each and apply patches not "by patch", but "by full queue"


What we're thinking about doing, is still maintain two separate repos, but every effort (features, bugs) would be developed as a branch and that branch gets pushed to the repo it's needed in.

Congrats, you rediscover "Release Branch" strategy in 2019. And yes, it works in a lot of cases and can work for you too

  1. You can use single repo with "branch per task" workflow
  2. Release Branch is permanent branch with merge-only commits in it (by policy) - no backouts, no hotfixes
2
  • Since Patch Queues aren't a part of the repository, our build server wouldn't be able to see it to make the build. Also, for a little self defense, we have been using a release branch strategy for a few years elsewhere, but it's been an issue of migrating and this project, with it's bizarre multi-config testing requirements has been left until last. Jan 8, 2019 at 14:29
  • I took a look at MqCollab as that sounded interesting, but it needs to be updated to work with the newer versions of Mercurial. As an example, it's using cmdutil.command which was dropped back in May 2018 Jan 8, 2019 at 15:15
0

The problem with removing a feature by changing the source code is that you have no guarantee you haven't broken some other feature due to some shared code.

If you need to switch features on and off then I would suggest "Feature Flags" ie. some config you application reads and uses to know whether a feature, which will still be in the code base should be exposed to the user or not.

There are various tools you can use to help with feature flags such as https://launchdarkly.com/

However, over all I would recommend changing your work practices so that rejecting a feature in QA is something that doesn't happen frequently enough that you need to worry about it.

Any back and forth between dev and test is a time sink and rejected a "done" feature from a release is going to mean a lot of work remerging it with the next set of changes. Its just inefficient.

  • Do your features and releases in branches rather than forks
  • Have a better "definition of done"
  • More testing in dev
  • Better specifications for features
  • Automated regression tests
  • Testers and Devs work on features together, no "throwing over the wall"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.