Skip to content

Commit 657d0aa

Browse files
committed
[WIP] 📖 Versioning and Branching Strategy
1 parent 902ff11 commit 657d0aa

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ Documentation:
1313
- [Creating a controller](https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/controller#example-New)
1414
- [Example `main.go`](https://github.com/kubernetes-sigs/controller-runtime/blob/master/example/main.go)
1515

16+
# Versioning, Maintenance, and Compatibility
17+
18+
The full documentation can be found at [VERSIONING.md](VERSIONING.md), but TL;DR:
19+
20+
Users:
21+
22+
- We follow [Semantic Versioning (semver)](https://semver.org)
23+
- Use releases with your dependency management to ensure that you get compatible code
24+
- The master branch contains all the latest code, some of which may break compatibility (so "normal" `go get` is not reccomended)
25+
26+
Contributors:
27+
28+
- All code PR must be labeled with :bug: (patch fixes), :sparkles: (backwards-compatible features), or :warning: (breaking changes)
29+
- Breaking changes will find their way into the next major release, other changes will go into an semi-immediate patch or minor release
30+
1631
## Community, discussion, contribution, and support
1732

1833
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).

VERSIONING.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# Versioning and Branching in controller-runtime
2+
3+
*NB*: this also applies to controller-tools.
4+
5+
## TL;DR:
6+
7+
### Users
8+
9+
- We follow [Semantic Versioning (semver)](https://semver.org)
10+
- Use releases with your dependency management to ensure that you get
11+
compatible code
12+
- The master branch contains all the latest code, some of which may break
13+
compatibility (so "normal" `go get` is not reccomended)
14+
15+
### Contributors
16+
17+
- All code PR must be labeled with :bug: (patch fixes), :sparkles:
18+
(backwards-compatible features), or :warning: (breaking changes)
19+
20+
- Breaking changes will find their way into the next major release, other
21+
changes will go into an semi-immediate patch or minor release
22+
23+
- Please *try* to avoid breaking changes when you can. They make users
24+
face difficult decisions (when do I go through the pain of upgrading),
25+
and make life hard for maintainers and contributors (dealing with
26+
differences on stable branches).
27+
28+
### Mantainers
29+
30+
Don't be lazy, read the rest of this doc :-)
31+
32+
## Overview
33+
34+
controller-runtime (and friends) follow [Semantic
35+
Versioning](https://semver.org). I'd reccomend reading the aforementioned
36+
link if you're not familiar, but essentially, for any given release X.Y.Z:
37+
38+
- an X (*major*) release indicates a set of backwards-compatible code.
39+
Changing X means there's a breaking change.
40+
41+
- a Y (*minor*) release indicates a minimum feature set. Changing Y means
42+
the addition of a backwards-compatible feature.
43+
44+
- a Z (*patch*) release indicates minimum set of bugfixes. Changing
45+
Z means a backwards-compatible change that doesn't add functionality.
46+
47+
*NB*: If the major release is `0`, any minor release may contain breaking
48+
changes.
49+
50+
These guarantees extend to all code exposed in public APIs of
51+
controller-runtime. This includes code both in controller-runtime itself,
52+
*plus types from dependencies in public APIs*. Types and functions not in
53+
public APIs are not considered part of the guarantee.
54+
55+
In order to easily maintain the guarantees, we have a couple of processes
56+
that we follow.
57+
58+
## Branches
59+
60+
controller-runtime contains two types of branches: the *master* branch and
61+
*release-X* branches.
62+
63+
The *master* branch is where development happens. All the latest and
64+
greatest code, including breaking changes, happens on master.
65+
66+
The *release-X* branches contain stable, backwards compatible code. Every
67+
major (X) release, a new such branch is created. It is from these
68+
branches that minor and patch releases are tagged.
69+
70+
The maintainers are responsible for updating the contents of this branch;
71+
generally, this is done just before a release using release tooling that
72+
filters and checks for changes tagged as breaking (see below).
73+
74+
### Tooling
75+
76+
***TODO***
77+
78+
## PR Process
79+
80+
Every PR should be annotated with an icon indicating whether it's
81+
a:
82+
83+
- Breaking change: :warning: (`:warning:`)
84+
- Non-breaking feature: :sparkles: (`:sparkles:`)
85+
- Patch fix: :bug: (`:bug:`)
86+
- Docs: :book: (`:book:`)
87+
- Infra/Tests/Other: :running: (`:running:`)
88+
89+
Individual commits may be tagged separately, but will generally be assumed
90+
to match the PR. For instance, if you have a bugfix in with a breaking
91+
change, it's generally encouraged to submit the bugfix separately, but if
92+
you must put them in one PR, mark the commit separately.
93+
94+
## Release Process
95+
96+
Minor and patch releases are generally done immediately after a feature or
97+
bugfix is landed, or sometimes a series of features tied together.
98+
99+
Major releases are done once a sufficient amount of breaking changes are
100+
accrued. Since we don't intend to have a ton of these, the maintainers
101+
will evaluate when to do a major release as it comes up.
102+
103+
### Exact Steps
104+
105+
***TODO***
106+
107+
### Breaking Changes
108+
109+
Try to avoid breaking changes. They make life difficult for users, who
110+
have to rewrite their code when they eventually upgrade, and for
111+
maintainers/contributors, who have to deal with differences between master
112+
and stable branches.
113+
114+
That being said, we'll occaisonally want to make breaking changes. They'll
115+
be merged onto master, but won't make it into a release immediately (see
116+
[Release Proccess](#release-process)).
117+
118+
If you're going to make a breaking change, please make sure to explain in
119+
detail why it's helpful. Is it necessary to cleanly resolve an issue?
120+
Does it improve API ergonomics?
121+
122+
Maintainers should treat breaking changes with caution, and evaluate
123+
potential non-breaking solutions (see below).
124+
125+
*NB*: Pre-1.0 releases treat breaking changes a bit more lightly. We'll
126+
still consider carefully, but the pre-1.0 timeframe is useful for
127+
converging on a ergonomic API.
128+
129+
#### Avoiding breaking changes
130+
131+
***TODO***
132+
133+
##### Solutions to avoid
134+
135+
- **Confusingly duplicate methods, functions, or variables.**
136+
137+
For instance, suppose we have an interface method `List(ctx
138+
context.Context, options *ListOptions, obj runtime.Object) error`, and
139+
we decide to switch it so that options come at the end, parametrically.
140+
Adding a new interface method `ListParametric(ctx context.Context, obj
141+
runtime.Object, options... ListOption)` is probably not the right
142+
solution:
143+
144+
- Users will intuitively see `List`, and use that in new projects, even
145+
if it's marked as deprecated.
146+
147+
- Users who don't notice the deprecation may be confused as to the
148+
difference between `List` and `ListParametric`.
149+
150+
- It's not immediately obvious in isolation (e.g. in surrounding code)
151+
why the method is called `ListParametric`, and may cause confusion
152+
when reading code that makes use of that method.
153+
154+
In this case, it may be better to make the breaking change, and then
155+
eventually do a major release.
156+
157+
***TODO***: make a better suggestion
158+
159+
## Why don't we...
160+
161+
### Use "next"-style branches
162+
163+
Development branches:
164+
165+
- don't win us much in terms of maintenance in the case of breaking
166+
changes (we still have to merge/manage multiple branches for development
167+
and stable)
168+
169+
- can be confusing to contributors, who often expect master to have the
170+
latest changes.
171+
172+
### Never break compatibility
173+
174+
Never doing a new major release could be an admirable goal, but gradually
175+
leads to API cruft.
176+
177+
Since one of the goals of controller-runtime is to be a friendly and
178+
intuitive API, we want to avoid too much API cruft over time, and
179+
occaisonal breaking changes in major releases help accomplish that goal.
180+
181+
Furthermore, our dependency on Kubernetes libraries makes this difficult
182+
(see below)
183+
184+
### Always assume we've broken compatibility
185+
186+
*a.k.a. k8s.io/client-go style*
187+
188+
While this makes life easier (a bit) for maintainers, it's problematic for
189+
users. While breaking changes arrive sooner, upgrading becomes very
190+
painful.
191+
192+
Furthermore, we still have to maintain stable branches for bugfixes, so
193+
the maintenance burden isn't lessened by a ton.
194+
195+
### Extend compatibility guarantees to all dependencies
196+
197+
This is very difficult with the number of Kubernetes dependencies we have.
198+
Kubernetes dependencies tend to either break compatibility every major
199+
release (e.g. k8s.io/client-go, which loosely follows semver), or at
200+
a whim (many other Kubernetes libraries).
201+
202+
If we limit to the few objects we expose, we can better inform users about
203+
how *controller-runtime itself* has changed in a given release. Then,
204+
users can make informed decisions about how to proceed with any direct
205+
uses of Kubernetes dependencies their controller-runtime-based application
206+
may have.

0 commit comments

Comments
 (0)