-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvendoring.slide
270 lines (139 loc) · 6.25 KB
/
vendoring.slide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#+theme=black
Vendoring in Go
Or, How I stopped worrying and learned to love dependency management
J. Gregory
jay@johngregory.me.uk
http://github.com/necrophonic
@n3crophonic
# -----------------------------------------------
* First, a diversion
# -----------------------------------------------
* Dependency management is hard
Almost no software is every built without some kind of external dependency
There are many tools dedicated to the problem
- *Maven* for Java
- *Bundler* for Ruby
- *Pip* for Python
- *Bower* for Javascript, CSS
- etc ..
Those may be the main go-to tools for each language, but they are far from the only tools. It's a problem that is constantly being re-solved.
# -----------------------------------------------
* Dependency management in Go
For Go, we have the built in package manager
$ go get
"*get* _downloads_the_packages_named_by_the_import_paths,_along_with_their_dependencies._It_then_installs_the_named_packages,_like_ *go*install* "
.caption -- [[https://golang.org/cmd/go/#hdr-Download_and_install_packages_and_dependencies][go get docs]]
But that just pulls the most up to date code from the default branch
# -----------------------------------------------
* What if we want a specific version?
# -----------------------------------------------
* Could use a service like gopkg.in
http://gopkg.in
A service which provides versioned URLs for redirecting the *go*get* tool onto well defined Github repositories
$ go get gopkg.in/user/pkg.v3
Which would reference
$ github.com/user/pkg
On branch/tag *v3*, *v3.N* or *v3.N.M*
package main
import github.com/user/pkg.v3
func main() {
...
}
# -----------------------------------------------
* However
There are limitations
- Only works on Github hosted repos
- Only works if branches/tags are named as expected
- Makes you rely on another 3rd party to be available and secure
And, as with any third party code:
- There's no guarantee that version v2.0.0 yesterday is v2.0.0 today
Although you _should_ never change a public release there is nothing to stop someone changing something, deleting and then retagging a release
(which is a problem if you require audited code!)
# -----------------------------------------------
* So what to do?
# -----------------------------------------------
* Vendor!
# -----------------------------------------------
* What is vendoring?
Vendoring is defined in Go as:
"_Vendoring_is_the_act_of_making_your_own_copy_of_the_3rd_party_packages_your_project_is_using._Those_copies_are_traditionally_placed_inside_each_project_and_then_saved_in_the_project_repository._"
.caption -- [[https://www.goinggo.net/2013/10/manage-dependencies-with-godep.html]]
By convention, vendored code is placed in the */vendor* folder under you repo root in $GOPATH:
.
├── main.go
└── vendor
├── github.com
├── ...
└── k8s.io
*nb* Most third party tools before this was formalised would generate their own proprietary structure but now support or defautly use */vendor*
# -----------------------------------------------
* How did we get here?
*Go*1.5*
Vendor support added (off by deafult) and enabled with:
$ export GO15VENDOREXPERIMENT=1
*Go*1.6*
Vendoring was enabled by default, but could be disabled by using:
$ export GO15VENDOREXPERIMENT=0
*Go*1.7*
Vendoring now standard and support for *GO15VENDOREXPERIMENT* removed
*Go*1.8+*
Yup, it's still there :)
# -----------------------------------------------
* There are tools
Many third party tools exist to support vendoring in Go
- [[https://github.com/tools/godep][Godep]] - _4635_github_stars,_413_forks_
- [[https://github.com/kardianos/govendor][govendor]] - _1990_github_stars,_154_forks_
- [[https://github.com/Masterminds/glide][Glide]] - _4606_github_stars,_281_forks_
- ... and [[https://github.com/golang/go/wiki/PackageManagementTools][many more]]
Each take a slightly different approach, but ultimately achieve the same aim
with similar characteristics:
- Discovers *import* dependencies in the current project
- Copies dependency code locally into the project
- Creates some kind of manifest to manage vendored code
# -----------------------------------------------
* But the Go toolchain is generally awesome ...
# -----------------------------------------------
* ... so why do I need a third party tool!?
# -----------------------------------------------
* The Go way
The plan is that the official tool for vendoring in Go will be *dep*
Currently in _alpha_
$ dep init
$ dep ensure github.com/pkg/errors@^0.8.0
Example project
.
├── Gopkg.lock
├── Gopkg.toml
├── main.go
└── vendor
├── github.com
├── golang.org
├── google.golang.org
├── gopkg.in
└── k8s.io
# -----------------------------------------------
* The dep roadmap
The roadmap has three basic phases:
- Get *dep* in shape ready to be merged into the toolchain (ideally at the beginning of a Go development cycle)
- Once merged, finished essential features and make robust
- The "future" - changes that can be made once the tool is well established
The goal is to have phase 1 wrapped up be the end of the *1.9* cycle and `dep`
merged into the toolchain when *1.10* development begins
_Though_none_of_this_is_guaranteed!_
.caption -- Read more at the [[https://github.com/golang/dep/wiki/Roadmap][roadmap wiki]]
# -----------------------------------------------
* Some Caveats
- *Vendor*projects,*not*libaries*
Avoid vendoring in code that will itself likely be vendored inside other code
- *Do*not*touch*vendor/*
Vendored code must _only_ be updated via your dep tool. Treat it otherwise as
immutable and do not edit
- *Dependencies*must*behave*
As Go does not use a formal package registry (as _perl_ users *CPAN* and _python_ uses *PyPI* for example), *dep* and other tools rely on code branches/releases being
correctly named and versioned in their respective repositories
# -----------------------------------------------
* Some References
- [[blog.gopheracademy.com/advent-2016/saga-go-dependency-management/]]
- [[github.com/golang/go/wiki/PackageManagementTools]]
- [[github.com/golang/dep/wiki/Roadmap]]
- [[www.goinggo.net/2013/10/manage-dependencies-with-godep.html]]