|
1 | 1 | # Versioning and Branching in controller-runtime
|
2 | 2 |
|
3 |
| -*NB*: this also applies to controller-tools. |
| 3 | +We follow the [common KubeBuilder versioning guidelines][guidelines], and |
| 4 | +use the corresponding tooling. |
4 | 5 |
|
5 |
| -## TL;DR: |
| 6 | +For the purposes of the aforementioned guidelines, controller-runtime |
| 7 | +counts as a "library project", but otherwise follows the guidelines |
| 8 | +exactly. |
6 | 9 |
|
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 recommended) |
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 |
25 |
| - upgrading?"), and make life hard for maintainers and contributors |
26 |
| - (dealing with 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 recommend 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. If some cases, it may |
69 |
| -be necessary open PRs for bugfixes directly against stable branches, but |
70 |
| -this should generally not be the case. |
71 |
| - |
72 |
| -The maintainers are responsible for updating the contents of this branch; |
73 |
| -generally, this is done just before a release using release tooling that |
74 |
| -filters and checks for changes tagged as breaking (see below). |
75 |
| - |
76 |
| -### Tooling |
77 |
| - |
78 |
| -Tooling for releases lives in the [kubebuilder-release-tools |
79 |
| -repository][rel-tools]. |
80 |
| - |
81 |
| -* `go run sigs.k8s.io/kubebuilder-release-tools/notes` from a `release-X` |
82 |
| - (or `release-0.Y`) branch will generate release notes based on the emoji |
83 |
| - described below. |
84 |
| - |
85 |
| - You can generally paste the stdout output directly into the release, |
86 |
| - unless the tool mentions needing manual edits. |
87 |
| - |
88 |
| -* the [GitHub actions workflow][actions-wf] in this repo will verify PRs |
89 |
| - using the verifier action from the [release-tools][rel-tools] mentioned |
90 |
| - above. If you want to add new checks, you can do it there. |
91 |
| - |
92 |
| -[rel-tools]: https://sigs.k8s.io/kubebuilder-release-tools |
93 |
| - |
94 |
| -[actions-wf]: /.github/workflows/verify.yml |
95 |
| - |
96 |
| -## PR Process |
97 |
| - |
98 |
| -Every PR should be annotated with an icon indicating whether it's |
99 |
| -a: |
100 |
| - |
101 |
| -- Breaking change: :warning: (`:warning:`) |
102 |
| -- Non-breaking feature: :sparkles: (`:sparkles:`) |
103 |
| -- Patch fix: :bug: (`:bug:`) |
104 |
| -- Docs: :book: (`:book:`) |
105 |
| -- Infra/Tests/Other: :seedling: (`:seedling:`) |
106 |
| -- No release note: :ghost: (`:ghost:`) |
107 |
| - |
108 |
| -Use :ghost: (no release note) only for the PRs that change or revert unreleased |
109 |
| -changes, which don't deserve a release note. Please don't abuse it. |
110 |
| - |
111 |
| -You can also use the equivalent emoji directly, since GitHub doesn't |
112 |
| -render the `:xyz:` aliases in PR titles. |
113 |
| - |
114 |
| -Individual commits should not be tagged separately, but will generally be |
115 |
| -assumed to match the PR. For instance, if you have a bugfix in with |
116 |
| -a breaking change, it's generally encouraged to submit the bugfix |
117 |
| -separately, but if you must put them in one PR, mark the commit |
118 |
| -separately. |
119 |
| - |
120 |
| -### Commands and Workflow |
121 |
| - |
122 |
| -controller-runtime follows the standard Kubernetes workflow: any PR needs |
123 |
| -`lgtm` and `approved` labels, PRs authors must have signed the CNCF CLA, |
124 |
| -and PRs must pass the tests before being merged. See [the contributor |
125 |
| -docs](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#the-testing-and-merge-workflow) |
126 |
| -for more info. |
127 |
| - |
128 |
| -We use the same priority and kind labels as Kubernetes. See the labels |
129 |
| -tab in GitHub for the full list. |
130 |
| - |
131 |
| -The standard Kubernetes comment commands should work in |
132 |
| -controller-runtime. See [Prow](https://prow.k8s.io/command-help) for |
133 |
| -a command reference. |
134 |
| - |
135 |
| -## Release Process |
136 |
| - |
137 |
| -Minor and patch releases are generally done immediately after a feature or |
138 |
| -bugfix is landed, or sometimes a series of features tied together. |
139 |
| - |
140 |
| -Minor releases will only be tagged on the *most recent* major release |
141 |
| -branch, except in exceptional circumstances. Patches will be backported |
142 |
| -to maintained stable versions, as needed. |
143 |
| - |
144 |
| -Major releases are done shortly after a breaking change is merged -- once |
145 |
| -a breaking change is merged, the next release *must* be a major revision. |
146 |
| -We don't intend to have a lot of these, so we may put off merging breaking |
147 |
| -PRs until a later date. |
148 |
| - |
149 |
| -### Exact Steps |
150 |
| - |
151 |
| -Follow the release-specific steps below, then follow the general steps |
152 |
| -after that. |
153 |
| - |
154 |
| -#### Minor and patch releases |
155 |
| - |
156 |
| -1. Update the release-X branch with the latest set of changes by calling |
157 |
| - `git rebase master` from the release branch. |
158 |
| - |
159 |
| -#### Major releases |
160 |
| - |
161 |
| -1. Create a new release branch named `release-X` (where `X` is the new |
162 |
| - version) off of master. |
163 |
| - |
164 |
| -#### General |
165 |
| - |
166 |
| -2. Generate release notes using the release note tooling. |
167 |
| - |
168 |
| -3. Add a release for controller-runtime on GitHub, using those release |
169 |
| - notes, with a title of `vX.Y.Z`. |
170 |
| - |
171 |
| -4. Do a similar process for |
172 |
| - [controller-tools](https://github.com/kubernetes-sigs/controller-tools) |
173 |
| - |
174 |
| -5. Announce the release in `#kubebuilder` on Slack with a pinned message. |
175 |
| - |
176 |
| -6. Potentially update |
177 |
| - [kubebuilder](https://github.com/kubernetes-sigs/kubebuilder) as well. |
178 |
| - |
179 |
| -### Breaking Changes |
180 |
| - |
181 |
| -Try to avoid breaking changes. They make life difficult for users, who |
182 |
| -have to rewrite their code when they eventually upgrade, and for |
183 |
| -maintainers/contributors, who have to deal with differences between master |
184 |
| -and stable branches. |
185 |
| - |
186 |
| -That being said, we'll occasionally want to make breaking changes. They'll |
187 |
| -be merged onto master, and will then trigger a major release (see [Release |
188 |
| -Process](#release-process)). Because breaking changes induce a major |
189 |
| -revision, the maintainers may delay a particular breaking change until |
190 |
| -a later date when they are ready to make a major revision with a few |
191 |
| -breaking changes. |
192 |
| - |
193 |
| -If you're going to make a breaking change, please make sure to explain in |
194 |
| -detail why it's helpful. Is it necessary to cleanly resolve an issue? |
195 |
| -Does it improve API ergonomics? |
196 |
| - |
197 |
| -Maintainers should treat breaking changes with caution, and evaluate |
198 |
| -potential non-breaking solutions (see below). |
199 |
| - |
200 |
| -Note that API breakage in public APIs due to dependencies will trigger |
201 |
| -a major revision, so you may occasionally need to have a major release |
202 |
| -anyway, due to changes in libraries like `k8s.io/client-go` or |
203 |
| -`k8s.io/apimachinery`. |
204 |
| - |
205 |
| -*NB*: Pre-1.0 releases treat breaking changes a bit more lightly. We'll |
206 |
| -still consider carefully, but the pre-1.0 timeframe is useful for |
207 |
| -converging on a ergonomic API. |
208 |
| - |
209 |
| -#### Avoiding breaking changes |
210 |
| - |
211 |
| -##### Solutions to avoid |
212 |
| - |
213 |
| -- **Confusingly duplicate methods, functions, or variables.** |
214 |
| - |
215 |
| - For instance, suppose we have an interface method `List(ctx |
216 |
| - context.Context, options *ListOptions, obj runtime.Object) error`, and |
217 |
| - we decide to switch it so that options come at the end, parametrically. |
218 |
| - Adding a new interface method `ListParametric(ctx context.Context, obj |
219 |
| - runtime.Object, options... ListOption)` is probably not the right |
220 |
| - solution: |
221 |
| - |
222 |
| - - Users will intuitively see `List`, and use that in new projects, even |
223 |
| - if it's marked as deprecated. |
224 |
| - |
225 |
| - - Users who don't notice the deprecation may be confused as to the |
226 |
| - difference between `List` and `ListParametric`. |
227 |
| - |
228 |
| - - It's not immediately obvious in isolation (e.g. in surrounding code) |
229 |
| - why the method is called `ListParametric`, and may cause confusion |
230 |
| - when reading code that makes use of that method. |
231 |
| - |
232 |
| - In this case, it may be better to make the breaking change, and then |
233 |
| - eventually do a major release. |
234 |
| - |
235 |
| -## Why don't we... |
236 |
| - |
237 |
| -### Use "next"-style branches |
238 |
| - |
239 |
| -Development branches: |
240 |
| - |
241 |
| -- don't win us much in terms of maintenance in the case of breaking |
242 |
| - changes (we still have to merge/manage multiple branches for development |
243 |
| - and stable) |
244 |
| - |
245 |
| -- can be confusing to contributors, who often expect master to have the |
246 |
| - latest changes. |
247 |
| - |
248 |
| -### Never break compatibility |
249 |
| - |
250 |
| -Never doing a new major release could be an admirable goal, but gradually |
251 |
| -leads to API cruft. |
252 |
| - |
253 |
| -Since one of the goals of controller-runtime is to be a friendly and |
254 |
| -intuitive API, we want to avoid too much API cruft over time, and |
255 |
| -occasional breaking changes in major releases help accomplish that goal. |
256 |
| - |
257 |
| -Furthermore, our dependency on Kubernetes libraries makes this difficult |
258 |
| -(see below) |
259 |
| - |
260 |
| -### Always assume we've broken compatibility |
261 |
| - |
262 |
| -*a.k.a. k8s.io/client-go style* |
263 |
| - |
264 |
| -While this makes life easier (a bit) for maintainers, it's problematic for |
265 |
| -users. While breaking changes arrive sooner, upgrading becomes very |
266 |
| -painful. |
267 |
| - |
268 |
| -Furthermore, we still have to maintain stable branches for bugfixes, so |
269 |
| -the maintenance burden isn't lessened by a ton. |
270 |
| - |
271 |
| -### Extend compatibility guarantees to all dependencies |
272 |
| - |
273 |
| -This is very difficult with the number of Kubernetes dependencies we have. |
274 |
| -Kubernetes dependencies tend to either break compatibility every major |
275 |
| -release (e.g. k8s.io/client-go, which loosely follows semver), or at |
276 |
| -a whim (many other Kubernetes libraries). |
277 |
| - |
278 |
| -If we limit to the few objects we expose, we can better inform users about |
279 |
| -how *controller-runtime itself* has changed in a given release. Then, |
280 |
| -users can make informed decisions about how to proceed with any direct |
281 |
| -uses of Kubernetes dependencies their controller-runtime-based application |
282 |
| -may have. |
| 10 | +[guidelines]: https://sigs.k8s.io/kubebuilder-release-tools/VERSIONING.md |
0 commit comments