@@ -9,6 +9,43 @@ Bitwarden uses [Renovate](https://www.mend.io/renovate/) for automating dependen
9
9
will automatically create pull requests for dependencies on a weekly cadence. Security updates will
10
10
generate pull requests immediately.
11
11
12
+ ## Renovate configuration
13
+
14
+ Renovate is configured by a ` .github/renovate.json ` (or ` .github/renovate.json5 ` ) file in each
15
+ repository. We follow an internal template for consistency. The template is available in the
16
+ [ template repository] ( https://github.com/bitwarden/template/blob/main/.github/renovate.json ) .
17
+
18
+ It is recommended that all repositories extend the
19
+ [ default] ( https://github.com/bitwarden/renovate-config/blob/main/default.json ) configuration from
20
+ our [ shared configuration repository] ( https://github.com/bitwarden/renovate-config ) that is included
21
+ when a new repository is created from the template.
22
+
23
+ The default configuration:
24
+
25
+ - Combines minor and patch changes into one rollup pull request, per package manager.
26
+ - Uses a dependency dashboard so we can see what pull requests are not yet created but still manage
27
+ the workload.
28
+ - Manages updates with semantic versioning and lock file updates. Rebases are disabled.
29
+ - Allows an unlimited number of pull requests to be created.
30
+ - Includes major updates (the latest) as individual pull requests. Monorepo updates are also
31
+ grouped.
32
+ - Schedules runs to happen on the weekend when more Actions workers are likely available for the
33
+ organization, but also on a two-week basis to better align with the release schedule.
34
+ - Certain build pipeline dependencies are pinned to specific versions.
35
+
36
+ See [ Management Strategies] ( #management-strategies ) below for more detail on why we have chosen
37
+ these configuration options.
38
+
39
+ All package managers are recommended to be left enabled should a repository expand over time to
40
+ include new ones, within reason for what might be in the scope of the repository. Update schedules
41
+ and how many pull requests are up to the individual repository. Exceptions, other package managers,
42
+ and dependency-specific configuration may be needed.
43
+
44
+ Consider [ best practices] ( https://docs.renovatebot.com/dependency-pinning/#so-whats-best ) with
45
+ pinning dependencies, especially at the root. Development dependencies such as formatters and
46
+ linters deserve communication and coordinated rollout across all teams so that code style is
47
+ consistent per our standards and the editor configurations seen in the template repository itself.
48
+
12
49
## Ownership
13
50
14
51
Bitwarden's repositories fall under two categories: team-owned and shared.
@@ -20,8 +57,7 @@ is responsible for reviewing, approving, and merging dependency updates. Some re
20
57
might be team-owned are that it's primarily developed by that team, or to balance out the number of
21
58
dependencies teams have to manage.
22
59
23
- Some examples of team-owned repositories are [ ` directory-connector ` ] [ dc ] , which is owned by the
24
- _ Admin Console_ team, and [ ` key-connector ` ] [ kc ] , which is owned by the Auth team.
60
+ Some examples of team-owned repositories are [ ` directory-connector ` ] [ dc ] and [ ` key-connector ` ] [ kc ] .
25
61
26
62
### Shared repositories
27
63
@@ -35,8 +71,9 @@ Examples of shared repositories are [`server`][server] and [`clients`][clients].
35
71
36
72
When adding a new dependency to a shared repository it ** must** be owned by a team. It's up to the
37
73
engineer adding the dependency to determine the appropriate team and get their approval for the
38
- addition before merging the PR. Please check [ Renovate configuration] ( #renovate-configuration ) for
39
- more information on how to assign ownership.
74
+ addition before merging the PR. Please check
75
+ [ Renovate configuration] ( #assigning-reviewers-through-renovate ) for more information on how to
76
+ assign ownership.
40
77
41
78
## Example PR
42
79
@@ -55,11 +92,163 @@ version is **13 days**, and **13%** of repositories have adopted this version. R
55
92
change. For more details read
56
93
[ Renovate documentation about Merge Confidence] ( https://docs.renovatebot.com/merge-confidence/ ) .
57
94
58
- ## Workflow
95
+ ## Management strategies
96
+
97
+ :::success Our Goal: A sustainable review cadence
98
+
99
+ The overarching purpose behind our use of these strategies is ensuring that our dependencies are as
100
+ up-to-date as possible, while opening PRs for review at a frequency and level of complexity that is
101
+ sustainable for all responsible teams.
59
102
60
103
Renovate is currently scheduled to automatically create pull requests every 2 weeks. The goal of our
61
104
dependency management process is for the teams to review and merge the opened pull requests in the
62
- same 2-week cadence. To avoid a large backlog of PRs and out-of-date packages accumulating.
105
+ same 2-week cadence -- to avoid a large backlog of PRs and out-of-date packages accumulating.
106
+
107
+ :::
108
+
109
+ ### Dependency pinning strategies
110
+
111
+ #### Pinned dependencies
112
+
113
+ :::info Why do we pin dependencies?
114
+
115
+ For background on why we pin, see [ Renovate's] ( https://docs.renovatebot.com/dependency-pinning/ )
116
+ documentation.
117
+
118
+ :::
119
+
120
+ For our client projects that are not intended to be consumed as libraries our strategy is to pin all
121
+ dependencies. In addition, we use ` package-lock.json ` and ` Cargo.lock ` lock files, as recommended by
122
+ Renovate.
123
+
124
+ #### Unpinned dependencies
125
+
126
+ For projects that are intended to be consumed as libraries (e.g. our SDKs) our strategy is not to
127
+ pin dependencies so that consumers are not locked in to a particular version. As Renovate
128
+ [ recommends] ( https://docs.renovatebot.com/dependency-pinning/ ) :
129
+
130
+ > It is usually a bad idea to pin all your dependencies because it will introduce an unnecessarily
131
+ > narrow range (one release!) and cause most users of your package to bloat their ` node_modules `
132
+ > with duplicates.
133
+
134
+ Instead, the [ recommended configuration] ( https://docs.renovatebot.com/presets-config/#configjs-lib )
135
+ for libraries is to pin only ` devDependencies ` and leave the others as ranges.
136
+
137
+ ### Dependency grouping strategies
138
+
139
+ We use grouping in Renovate to group related dependencies into a single PR.
140
+
141
+ There are two different levels at which our grouped dependencies are configured:
142
+
143
+ 1 . Our Renovate configuration uses the “monorepo presets” that Renovate
144
+ [ defines] ( https://docs.renovatebot.com/noise-reduction/#package-grouping ) . These are groups of
145
+ dependencies that Renovate has grouped together through the ` group:monorepos ` configuration,
146
+ which we have enabled. If we use any of these pre-grouped dependencies, Renovate will
147
+ automatically group them together into a single PR.
148
+ 2 . Grouping that we have put in place in our Renovate configuration. We have several different ways
149
+ that we configure to do this, which we’ll detail below.
150
+
151
+ #### Why we group dependencies in our configuration
152
+
153
+ If a group of dependencies are closely related, we may decide that they should move as a unit
154
+ through the review and QA process. We’ll do this if we want to:
155
+
156
+ - Group by ** domain** to avoid errors resulting in inter-dependency version requirements
157
+ - If a dependency relies on other related dependencies to have been updated along with it, we need
158
+ to group these together to avoid errors when building. Sometimes we do this for all update
159
+ types, and sometimes we only do this for major updates, depending on when we feel like
160
+ inter-version dependencies exist.
161
+ - Group by ** domain** or by ** package manager** to reduce the noise of too many PRs
162
+ - This is a [ trade-off] ( https://docs.renovatebot.com/noise-reduction/#noise-reduction ) , and we
163
+ acknowledge that doing so will make identification of any issues stemming from the update
164
+ harder.
165
+ - Sometimes we only do this for minor or patch updates, as we acknowledge the trade-off with
166
+ identifying breaking changes and want to have separate PRs for major updates.
167
+
168
+ :::info Grouping and team ownership
169
+
170
+ Grouping does not equal team ownership. In other words, a PR that has dependencies owned by multiple
171
+ teams would have multiple reviewers on it. As a matter of practice, we try to assign all grouped
172
+ dependencies to a single team, so that only a single team is responsible for the review.
173
+
174
+ :::
175
+
176
+ ### Dependency update type strategies
177
+
178
+ :::info What are update types?
179
+
180
+ “Update type” refers to the classification of a version as major, minor, or patch.
181
+
182
+ :::
183
+
184
+ ### Combining update types
185
+
186
+ For all of our dependencies, we default to:
187
+
188
+ - Combining minor and patch updates into a single PR for a given dependency, and
189
+ - _ Not_ combining major updates with any minor or patch updates for a given dependency
190
+
191
+ We do this because we want to reduce the noise of separate minor and patch updates, but we also
192
+ don’t want to miss out on incremental minor/patch updates while we do the larger body of work for a
193
+ major update. For example, if we’re updating Angular to version 20, we would want to receive minor
194
+ and patch updates for version 19 while the PR for the version 20 update is open and being evaluated.
195
+
196
+ This combination of updates is for an individual dependency. This is distinct from grouping multiple
197
+ dependencies into a single PR, which is covered in
198
+ [ Dependency grouping strategies] ( #dependency-grouping-strategies ) .
199
+
200
+ ### Managing patch updates
201
+
202
+ In order to maintain a sustainable number of update PRs for our teams to review, we have elected to
203
+ send most patch updates through Renovate's
204
+ [ Dependency Dashboard Approval] ( https://docs.renovatebot.com/configuration-options/#dependencydashboardapproval )
205
+ flow. This means that Renovate will _ not_ automatically generate a PR for these updates; rather, it
206
+ will list them in a "Pending Approval" section of the Dependency Dashboard. If a team desires to
207
+ update the dependency to pull in a bug fix that affects our code, they can trigger the pull request
208
+ to be created from the dashboard.
209
+
210
+ ### Dependency reviewer assignment strategies
211
+
212
+ In order for a dependency update PR to successfully move through the review process, it must be
213
+ assigned a reviewer. We do this one of two ways:
214
+
215
+ - Through GitHub ` CODEOWNERS `
216
+ - Through reviewer assignment in Renovate
217
+
218
+ #### Assigning reviewers through ` CODEOWNERS `
219
+
220
+ When a team owns the file updated by a dependency update (e.g. ` package.json ` and
221
+ ` package-lock.json ` ), they will be added as reviewers on the pull request without any configuration
222
+ in Renovate.
223
+
224
+ This will be the case for:
225
+
226
+ - Repositories owned by a single team, and
227
+ - GitHub Action workflows on shared repositories
228
+ - In this case, the workflow files themselves are updated by Renovate, meaning that the team who
229
+ owns the workflow will be added to the PR.
230
+
231
+ #### Assigning reviewers through Renovate
232
+
233
+ When the package and lock files are not owned by ` CODEOWNERS ` (as is the case for any of our shared
234
+ repositories), we explicitly assign ownership of each dependency by specifying the responsible team
235
+ in Renovate configuration in the repository.
236
+
237
+ Renovate uses a concept called
238
+ [ ` PackageRules ` ] ( https://docs.renovatebot.com/configuration-options/#packagerules ) that allows us to
239
+ specify ownership of dependencies and ensure the appropriate team is added as reviewers. Below is an
240
+ example assigning ` @angular/core ` to the Platform team.
241
+
242
+ ``` json
243
+ {
244
+ "matchPackageNames" : [" @angular/core" ],
245
+ "description" : " Platform owned dependencies" ,
246
+ "commitMessagePrefix" : " [deps] Platform:" ,
247
+ "reviewers" : [" team:team-platform-dev" ]
248
+ }
249
+ ```
250
+
251
+ ## Dependency review workflow
63
252
64
253
:::info Major upgrades
65
254
@@ -95,9 +284,13 @@ A typical dependency workflow involves the following steps:
95
284
2 . For ** deprecations** , create high priority Jira tickets on the affected teams' backlogs with a
96
285
due date at least one sprint before the next scheduled major release of the dependency.
97
286
4 . Verify CI status.
287
+
288
+ - This may also include re-running any failed workflows due to insufficient permissions when
289
+ Renovate created the pull request.
290
+
98
291
5 . If test coverage is lacking, check out locally and manually confirm a few key areas.
99
292
6 . Review the proposed code changes and approve the PR.
100
- 7 . Write a Jira ticket containing testing notes for QA.
293
+ 7 . Update the ticket to include testing notes for QA.
101
294
- Testing notes should include:
102
295
- What areas of the codebase are affected by the dependency to help isolate future problems.
103
296
- Recommendation for manual QA testing ** only** if the developer identifies this as a high-risk
@@ -159,29 +352,6 @@ In those cases the team can comment on the PR with a reason for not yet upgradin
159
352
or defer it until a later date. If a team closes a PR it is expected that its members monitor the
160
353
dependency and revisiting the upgrade in the future.
161
354
162
- ## Renovate configuration
163
-
164
- Renovate is configured by a ` .github/renovate.json ` (or ` .github/renovate.json5 ` ) file in each
165
- repository. We follow an internal template for consistency. The template is available at the
166
- [ template repository] ( https://github.com/bitwarden/template/blob/main/.github/renovate.json ) .
167
-
168
- Renovate uses a concept called
169
- [ ` PackageRules ` ] ( https://docs.renovatebot.com/configuration-options/#packagerules ) that allows us to
170
- specify ownership of dependencies and ensure the appropriate team is added as reviewers. Below is an
171
- example assigning ` @angular/core ` to the Platform team.
172
-
173
- ``` json
174
- {
175
- "matchPackageNames" : [" @angular/core" ],
176
- "description" : " Platform owned dependencies" ,
177
- "commitMessagePrefix" : " [deps] Platform:" ,
178
- "reviewers" : [" team:team-platform-dev" ]
179
- }
180
- ```
181
-
182
- For repositories maintained by a single team there is no need to use ` packageRules ` to assign
183
- ownership. Instead ensure appropriate code owners are set up.
184
-
185
355
[ dc ] : https://github.com/bitwarden/directory-connector
186
356
[ kc ] : https://github.com/bitwarden/key-connector/
187
357
[ server ] : https://github.com/bitwarden/server/
0 commit comments