getnelson / nelson

Automated, multi-region container deployment
https://getnelson.io
Apache License 2.0
395 stars 40 forks source link

Support for multi-branch deployment #223

Open timperrett opened 5 years ago

timperrett commented 5 years ago

For the longest time, Nelson has followed the notion of an unstable master branch and encouraged users to ship code as fast as possible, leveraging supporting tools for experiemtantion and comparative analysis to see if there changes were better or worse than previous revisions - this was the environment and vision which spawned Nelson. However, as the adoption of Nelson has grown, it has become clear that this free-form fast moving environment is not present everywhere, and the notion of a so-called golden master exists in many organizations: changes merged to master should be functional and work "as expected". To continue to drive adoption, Nelson needs to provide improved support for this workflow which means supporting what the author is terming “branch deployments”.

Revisioning

Historically, Nelson has embraced Semantic versioning from the early days of that open specification and the semantics are fundamental in how Nelson's garbage collection subsystems operate. Branch deployments have the potential to explode this complexity as assumptions about increasing patch versions (as one example) would not hold if there are multiple streams of deployment into a given namespace: how do you lexicographically sort these arbitrary versions?

One approach would be to have Nelson support multiple revisioning schemes, for example, all branch deployments could be monotonically revisioned either with user-supplied input (dangerous) or some Nelson-provided epoch. The following revisioning strategies are most common in industry:

  1. Semantic versioning (version 1.x): Many ecosystems - for example, NodeJS, Java etc - use traditional semantic versioning. For example, 1.20.3, 2.5.1 etc. Whilst these revisions can sort such that Nelson know’s total order, semantic challenges abound when we consider non-master (trunk) releases… what would it mean to have different semantic revisions from different branches, which may or may not be intersecting? This could cause havoc with users.

  2. Monotonic versioning: Some users rely on their CI system to globally and monotonically increment the version number over time, regardless of package, compatibility or otherwise.

  3. SCM revisioning: while less common, some organizations use the identifier from their SCM system, for example, Git SHA or revision counts. The challenge with these kinds of revisioning schemes is that they typically do not lexicographically sort, leaving Nelson no way to know which revision came before another (sort order is partial, not total).

The impedance miss-match between these different revisioning strategies causes a fundamental problem: Nelson cannot support them all and retain cogent, accurate garbage collection. With this frame, we need a solution that can satisfy most users, whilst also making a system that is maintainable. With this frame, the author proposes that Nelson adopt Semantic versioning 2.x, which would allow versions to be qualified however users wish. Consider the following examples:

1.0.1 1.0.1-newfeature.1 1.2.3+20130313144700

All of these versions are valid and sortable pertaining to one another. The author proposes that all versions going forward take a branch qualifier; whilst this makes the versioning a little noisier, it has the benefit that any given organization using Nelson can determine for themselves what their branching strategy is, and Nelson becomes less prescriptive overall.

Default Repository Branch

With this change, we are considering adding the notion of a default repository branch for a given repo, such that when an end user enables Nelson on a given repository, they can optionally supply a default branch. This would allow Nelson to retain a notion of root namespaces, whilst doing any per-branch deployments to a subordinate branch-based namespace. For example:

Such a scheme would be useful, as it would potentially assist in cleaning up these ephemeral namespaces.

Affected System Components

Implementing this change would sweep throughout the whole codebase, and touch the following systems:

Open Questions

Nelson Administrator Considerations

okoye commented 5 years ago

👀

adelbertc commented 5 years ago

Overall this looks good to me.

Revisioning I like the adoption of Semantic Versioning 2.x since SemVer seems to be the predominant versioning scheme used. One concern I have that we brought up during our meeting was how we treat the master branch with respect to versioning. With multi-branch deploys we now expect multiple branches to be triggering deployments. However I assume, perhaps incorrectly, that we will have some sort of master branch which are the quasi-stable deployments. We would then need a way to signal to Nelson/Slipway what the master branch for a repo is so that it can ensure branches are treated accordingly. I realize now as I'm typing this the next section is about this so..

Default branches There are some ergonomics and usability questions here that we would need to figure out like "are we going to require users specify a default branch for every repo?" This seems like a reasonable requirement.. but what happens if users want to change the default branch (this has happened on my team a couple times).

Open questions Namespace cleanup: I think tying it to the lifetime of the branch makes sense. IDK if GitHub has a "branch deleted" event but if so maybe we could tie a webhook to it. Alternatively we can add another background job that periodically scans the repo branches we've deployed off of.. though for a large org that might get really large. Also agree regarding the ergonomics of nelson datacenters list.. time to rewrite in Rust 😛

H2: I'd imagine it depends on the org size.. I can see it bogging down if the org is large enough. Perhaps time to add a Postgres backend or something..

Template linting: I think this goes back to whether we make default branches a requirement or not.

I could've sworn I had a couple other questions but for the life of me cannot remember now. In any case this feature would be useful for us as we already have a couple situations where we've had to work around this problem like creating "dummy" repos which exist purely to cut releases.