1
1
package build
2
2
3
3
import (
4
+ "encoding/json"
4
5
"errors"
5
6
"fmt"
7
+ hv "github.com/hashicorp/go-version"
8
+ "net/http"
6
9
"os"
7
10
"path/filepath"
11
+ "sort"
8
12
"strconv"
13
+ "strings"
9
14
)
10
15
11
16
const (
12
- chromeDriverBinary = "chromedriver"
17
+ chromeDriverBinary = "chromedriver"
18
+ newChromeDriverBinary = "chromedriver-linux64/chromedriver"
13
19
)
14
20
15
21
type Chrome struct {
@@ -25,7 +31,12 @@ func (c *Chrome) Build() error {
25
31
26
32
pkgTagVersion := extractVersion (pkgVersion )
27
33
28
- driverVersion , err := c .parseChromeDriverVersion (pkgTagVersion )
34
+ chromeDriverVersions , err := fetchChromeDriverVersions ()
35
+ if err != nil {
36
+ return fmt .Errorf ("fetch chromedriver versions: %v" , err )
37
+ }
38
+
39
+ driverVersion , err := c .parseChromeDriverVersion (pkgTagVersion , chromeDriverVersions )
29
40
if err != nil {
30
41
return fmt .Errorf ("parse chromedriver version: %v" , err )
31
42
}
@@ -82,7 +93,7 @@ func (c *Chrome) Build() error {
82
93
}
83
94
image .BuildArgs = append (image .BuildArgs , fmt .Sprintf ("VERSION=%s" , pkgTagVersion ))
84
95
85
- err = c .downloadChromeDriver (image .Dir , driverVersion )
96
+ err = c .downloadChromeDriver (image .Dir , driverVersion , chromeDriverVersions )
86
97
if err != nil {
87
98
return fmt .Errorf ("failed to download chromedriver: %v" , err )
88
99
}
@@ -117,25 +128,60 @@ func (c *Chrome) channelToBuildArgs() []string {
117
128
}
118
129
}
119
130
120
- func (c * Chrome ) parseChromeDriverVersion (pkgVersion string ) (string , error ) {
131
+ func (c * Chrome ) parseChromeDriverVersion (pkgVersion string , chromeDriverVersions map [ string ] string ) (string , error ) {
121
132
version := c .DriverVersion
122
133
if version == LatestVersion {
134
+
135
+ var matchingVersions []string
136
+ for mv := range chromeDriverVersions {
137
+ if strings .Contains (mv , pkgVersion ) {
138
+ matchingVersions = append (matchingVersions , mv )
139
+ }
140
+ }
141
+ if len (matchingVersions ) > 0 {
142
+ sort .SliceStable (matchingVersions , func (i , j int ) bool {
143
+ l := matchingVersions [i ]
144
+ r := matchingVersions [j ]
145
+ lv , err := hv .NewVersion (l )
146
+ if err != nil {
147
+ return false
148
+ }
149
+ rv , err := hv .NewVersion (r )
150
+ if err != nil {
151
+ return false
152
+ }
153
+ return lv .LessThan (rv )
154
+ })
155
+ return matchingVersions [0 ], nil
156
+ }
157
+
123
158
const baseUrl = "https://chromedriver.storage.googleapis.com/"
124
159
v , err := c .getLatestChromeDriver (baseUrl , pkgVersion )
125
160
if err != nil {
126
161
return "" , err
127
162
}
128
- version = v
163
+ return v , nil
129
164
}
130
165
return version , nil
131
166
}
132
167
133
- func (c * Chrome ) downloadChromeDriver (dir string , version string ) error {
134
- u := fmt .Sprintf ("http://chromedriver.storage.googleapis.com/%s/chromedriver_linux64.zip" , version )
135
- _ , err := downloadDriver (u , chromeDriverBinary , dir )
168
+ func (c * Chrome ) downloadChromeDriver (dir string , version string , chromeDriverVersions map [string ]string ) error {
169
+ u := fmt .Sprintf ("https://chromedriver.storage.googleapis.com/%s/chromedriver_linux64.zip" , version )
170
+ fn := chromeDriverBinary
171
+ if cdu , ok := chromeDriverVersions [version ]; ok {
172
+ u = cdu
173
+ fn = newChromeDriverBinary
174
+ }
175
+ outputPath , err := downloadDriver (u , fn , dir )
136
176
if err != nil {
137
177
return fmt .Errorf ("download chromedriver: %v" , err )
138
178
}
179
+ if fn == newChromeDriverBinary {
180
+ err = os .Rename (outputPath , filepath .Join (dir , chromeDriverBinary ))
181
+ if err != nil {
182
+ return fmt .Errorf ("rename chromedriver: %v" , err )
183
+ }
184
+ }
139
185
return nil
140
186
}
141
187
@@ -176,3 +222,46 @@ func (c *Chrome) getLatestChromeDriver(baseUrl string, pkgVersion string) (strin
176
222
}
177
223
}
178
224
}
225
+
226
+ func fetchChromeDriverVersions () (map [string ]string , error ) {
227
+ const versionsURL = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"
228
+ resp , err := http .Get (versionsURL )
229
+ if err != nil {
230
+ return nil , fmt .Errorf ("fetch chrome versions: %v" , err )
231
+ }
232
+ defer resp .Body .Close ()
233
+ var cv ChromeVersions
234
+ err = json .NewDecoder (resp .Body ).Decode (& cv )
235
+ if err != nil {
236
+ return nil , fmt .Errorf ("decode json: %v" , err )
237
+ }
238
+ ret := make (map [string ]string )
239
+ const platformLinux64 = "linux64"
240
+ const chromeDriver = "chromedriver"
241
+ for _ , v := range cv .Versions {
242
+ version := v .Version
243
+ if cd , ok := v .Downloads [chromeDriver ]; ok {
244
+ for _ , d := range cd {
245
+ u := d .URL
246
+ if u != "" && d .Platform == platformLinux64 {
247
+ ret [version ] = u
248
+ }
249
+ }
250
+ }
251
+ }
252
+ return ret , nil
253
+ }
254
+
255
+ type ChromeVersions struct {
256
+ Versions []ChromeVersion `json:"versions"`
257
+ }
258
+
259
+ type ChromeVersion struct {
260
+ Version string `json:"version"`
261
+ Downloads map [string ][]ChromeDownload `json:"downloads"`
262
+ }
263
+
264
+ type ChromeDownload struct {
265
+ Platform string `json:"platform"`
266
+ URL string `json:"url"`
267
+ }
0 commit comments