>It doesn't seem like the idea of full TO API SemVer was ever fully discussed and voted on
>Since it seems like we never truly committed to SemVer with minor versions for the TO API There was consensus: https://lists.apache.org/thread.html/8f8a850c68424021a0fe06967894383a24e463f1b0cee4d652d04590@%3Cdev.trafficcontrol.apache.org%3E https://lists.apache.org/thread.html/1a42a2192a81fc4d76639ccd10761b6b73c31345a63715bb8aa86e4e@%3Cdev.trafficcontrol.apache.org%3E We didn't do an official [VOTE], but we rarely do that as a project, unless there's difficulty reaching unofficial consensus. That said, there's nothing stopping another discussion or vote, if we want to change things. >as long as we set the expectations for the user That's precisely my point. We can always say "we set the expectations, it's the user's fault for misreading, or misunderstanding, or not noticing a changelog." It's not about fault, it's about providing a better user experience. >that support has to be baked into traffic_ops_golang such that it's easy and maintainable to support tons of minor versions. If we keep heading down our current path we are going to be left with a giant mess. I don't think anyone disagrees. Traffic Ops versioning has had considerable technical debt for some time now. We just haven't been willing to spend the time to fix it. I agree, that needs to change. I'd also like to note, there's another option: code generation. We can keep the structs and handlers largely the same, and generate the "duplicate" code when a new minor version is added. There's a strong argument that this is the "idomatic" way to solve this problem, for the Go language. I personally feel Reflection is better here. But, I wanted everyone to be aware that's an option, if the consensus is that it's the best option. In a nutshell, we could generate code with a script (with a spectrum of precision and complexity, from `cp && sed` to parsing the AST), and `routes.go` would have a `//go:generate` header. For examples, see: https://blog.golang.org/generate https://godoc.org/golang.org/x/tools/cmd/stringer I did some prototyping of that approach, if anyone is interested, just let me know and I can provide examples of what that would look like. On Wed, Feb 13, 2019 at 5:09 PM Rawlin Peters <rawlin.pet...@gmail.com> wrote: > On Wed, Feb 13, 2019 at 1:20 PM Gray, Jonathan > <jonathan_g...@comcast.com> wrote: > > > > I'm +1 on keeping full API SemVer. > > > On 2/13/19, 12:16 PM, "Robert Butts" <r...@apache.org> wrote: > > > > We would be abandoning Semantic Versioning. > > This is why I wanted to open this up for broader discussion within the > community. It doesn't seem like the idea of full TO API SemVer was > ever fully discussed and voted on (at least not to my knowledge), > which is why I haven't been abiding by it myself or enforcing it upon > other TO API devs either. If we're going to truly commit to SemVer > with minor versions for TO API then we should fully understand the > cost vs utility of doing so. Also, SemVer doesn't have to be an "all > or nothing" thing, as we currently choose to ignore the "patch" > version for the TO API. We could also choose to ignore the minor > version and just focus on the most important aspect of SemVer which is > not introducing backwards-incompatible changes in the same major > version. > > Since it seems like we never truly committed to SemVer with minor > versions for the TO API, traffic_ops_golang wasn't designed to easily > support minor versions. So if we're going to truly commit to SemVer > with minor versions for TO API, then that support has to be baked into > traffic_ops_golang such that it's easy and maintainable to support > tons of minor versions. If we keep heading down our current path we > are going to be left with a giant mess. > > The only way I can get behind supporting the "minor version promise" > is if we have a way to basically just tag fields as introduced in a > specific API version, with just a single struct per resource and a > single handler per major version of an endpoint. We should only > require a single implementation of an endpoint per major version. If a > custom JSON parser allows us to do that, then that's great. Without > that, I don't think supporting the "minor version promise" is even a > viable option. > > A lot of those scenarios around user confusion due to supporting just > a major version are not really an issue as long as we set the > expectations for the user. I.e.: > - clients should request v1 > - as the v1 API is enhanced in a backwards-compatible manner, clients > will begin to see new fields in the server responses > - if a client wants to modify a resource, they will typically do a GET > on the resource, modify the resource, then do a PUT back to the > server. > - in the GET response, if the client sees new fields, they can expect > to modify those fields and see it reflected on the server. > - if the client does NOT see new fields, then they cannot add fields > and expect to see that reflected on the server > - null values in optional fields will be interpreted by the server as > whatever the default for that optional field is. So if the default for > new optional field "foo" is 5, then a client sending `"foo": null` > will be interpreted by the server as `"foo": 5`, and `"foo": null` > should never have a different meaning than `"foo": 5` on the server. > > The advantage of just supporting the "major version promise": > - jives better with Go's lack of metaprogramming > - no custom JSON parser in Go required > - less general overhead in development > - only have to worry about breaking changes > - no worrying about which fields belong to which minor versions > - no extra API testing to make sure fields introduced in API v1.N > aren't returned to v1.N-1 clients > - don't have to update every single client in the repo with the new > minor version every time a minor version is incremented (since clients > would just specify the major version) > > So, as a community, we need to weigh these options and decide whether > or not we want to take the "major version only" route or the "major > plus minor version" route. Personally, I prefer the "major version > only" route because it means less code, less overhead, less > coordination, and less things to potentially go wrong. However, if a > relatively small custom JSON parser is all we really need to > reasonably support the "minor version promise", then I can't say I'm > completely against that route either (just that I wouldn't prefer it). > > - Rawlin >