cypress 9.2.0 → 9.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ const is = require('check-more-types');
8
8
 
9
9
  const os = require('os');
10
10
 
11
- const url = require('url');
11
+ const Url = require('url');
12
12
 
13
13
  const path = require('path');
14
14
 
@@ -36,6 +36,7 @@ const fs = require('../fs');
36
36
  const util = require('../util');
37
37
 
38
38
  const defaultBaseUrl = 'https://download.cypress.io/';
39
+ const defaultMaxRedirects = 10;
39
40
 
40
41
  const getProxyForUrlWithNpmConfig = url => {
41
42
  return getProxyForUrl(url) || process.env.npm_config_https_proxy || process.env.npm_config_proxy || null;
@@ -76,7 +77,7 @@ const getCA = () => {
76
77
  };
77
78
 
78
79
  const prepend = urlPath => {
79
- const endpoint = url.resolve(getBaseUrl(), urlPath);
80
+ const endpoint = Url.resolve(getBaseUrl(), urlPath);
80
81
  const platform = os.platform();
81
82
  return `${endpoint}?platform=${platform}&arch=${arch()}`;
82
83
  };
@@ -183,8 +184,18 @@ const downloadFromUrl = ({
183
184
  url,
184
185
  downloadDestination,
185
186
  progress,
186
- ca
187
+ ca,
188
+ version,
189
+ redirectTTL = defaultMaxRedirects
187
190
  }) => {
191
+ if (redirectTTL <= 0) {
192
+ return Promise.reject(new Error(stripIndent`
193
+ Failed downloading the Cypress binary.
194
+ There were too many redirects. The default allowance is ${defaultMaxRedirects}.
195
+ Maybe you got stuck in a redirect loop?
196
+ `));
197
+ }
198
+
188
199
  return new Promise((resolve, reject) => {
189
200
  const proxy = getProxyForUrlWithNpmConfig(url);
190
201
  debug('Downloading package', {
@@ -192,35 +203,24 @@ const downloadFromUrl = ({
192
203
  proxy,
193
204
  downloadDestination
194
205
  });
195
- let redirectVersion;
196
- const reqOptions = {
197
- url,
198
- proxy,
199
-
200
- followRedirect(response) {
201
- const version = response.headers['x-version'];
202
- debug('redirect version:', version);
203
-
204
- if (version) {
205
- // set the version in options if we have one.
206
- // this insulates us from potential redirect
207
- // problems where version would be set to undefined.
208
- redirectVersion = version;
209
- } // yes redirect
210
-
211
-
212
- return true;
213
- }
214
-
215
- };
216
206
 
217
207
  if (ca) {
218
208
  debug('using custom CA details from npm config');
219
- reqOptions.agentOptions = {
220
- ca
221
- };
222
209
  }
223
210
 
211
+ const reqOptions = {
212
+ uri: url,
213
+ ...(proxy ? {
214
+ proxy
215
+ } : {}),
216
+ ...(ca ? {
217
+ agentOptions: {
218
+ ca
219
+ }
220
+ } : {}),
221
+ method: 'GET',
222
+ followRedirect: false
223
+ };
224
224
  const req = request(reqOptions); // closure
225
225
 
226
226
  let started = null;
@@ -248,18 +248,46 @@ const downloadFromUrl = ({
248
248
  // response headers
249
249
 
250
250
 
251
- started = new Date(); // if our status code does not start with 200
252
-
253
- if (!/^2/.test(response.statusCode)) {
251
+ started = new Date();
252
+
253
+ if (/^3/.test(response.statusCode)) {
254
+ const redirectVersion = response.headers['x-version'];
255
+ const redirectUrl = response.headers.location;
256
+ debug('redirect version:', redirectVersion);
257
+ debug('redirect url:', redirectUrl);
258
+ downloadFromUrl({
259
+ url: redirectUrl,
260
+ progress,
261
+ ca,
262
+ downloadDestination,
263
+ version: redirectVersion,
264
+ redirectTTL: redirectTTL - 1
265
+ }).then(resolve).catch(reject); // if our status code does not start with 200
266
+ } else if (!/^2/.test(response.statusCode)) {
254
267
  debug('response code %d', response.statusCode);
255
268
  const err = new Error(stripIndent`
256
269
  Failed downloading the Cypress binary.
257
270
  Response code: ${response.statusCode}
258
271
  Response message: ${response.statusMessage}
259
272
  `);
260
- reject(err);
273
+ reject(err); // status codes here are all 2xx
274
+ } else {
275
+ // We only enable this pipe connection when we know we've got a successful return
276
+ // and handle the completion with verify and resolve
277
+ // there was a possible race condition between end of request and close of writeStream
278
+ // that is made ordered with this Promise.all
279
+ Promise.all([new Promise(r => {
280
+ return response.pipe(fs.createWriteStream(downloadDestination).on('close', r));
281
+ }), new Promise(r => response.on('end', r))]).then(() => {
282
+ debug('downloading finished');
283
+ verifyDownloadedFile(downloadDestination, expectedSize, expectedChecksum).then(() => debug('verified')).then(() => resolve(version)).catch(reject);
284
+ });
261
285
  }
262
- }).on('error', reject).on('progress', state => {
286
+ }).on('error', e => {
287
+ if (e.code === 'ECONNRESET') return; // sometimes proxies give ECONNRESET but we don't care
288
+
289
+ reject(e);
290
+ }).on('progress', state => {
263
291
  // total time we've elapsed
264
292
  // starting on our first progress notification
265
293
  const elapsed = new Date() - started; // request-progress sends a value between 0 and 1
@@ -268,12 +296,6 @@ const downloadFromUrl = ({
268
296
  const eta = util.calculateEta(percentage, elapsed); // send up our percent and seconds remaining
269
297
 
270
298
  progress.onProgress(percentage, util.secsRemaining(eta));
271
- }) // save this download here
272
- .pipe(fs.createWriteStream(downloadDestination)).on('finish', () => {
273
- debug('downloading finished');
274
- verifyDownloadedFile(downloadDestination, expectedSize, expectedChecksum).then(() => {
275
- return resolve(redirectVersion);
276
- }, reject);
277
299
  });
278
300
  });
279
301
  };
@@ -288,7 +310,8 @@ const start = opts => {
288
310
  let {
289
311
  version,
290
312
  downloadDestination,
291
- progress
313
+ progress,
314
+ redirectTTL
292
315
  } = opts;
293
316
 
294
317
  if (!downloadDestination) {
@@ -316,7 +339,11 @@ const start = opts => {
316
339
  url,
317
340
  downloadDestination,
318
341
  progress,
319
- ca
342
+ ca,
343
+ version,
344
+ ...(redirectTTL ? {
345
+ redirectTTL
346
+ } : {})
320
347
  });
321
348
  }).catch(err => {
322
349
  return prettyDownloadErr(err, version);
@@ -37,7 +37,7 @@ const xvfb = require('../exec/xvfb');
37
37
 
38
38
  const state = require('./state');
39
39
 
40
- const VERIFY_TEST_RUNNER_TIMEOUT_MS = process.env.CYPRESS_VERIFY_TIMEOUT || 30000;
40
+ const VERIFY_TEST_RUNNER_TIMEOUT_MS = +process.env.CYPRESS_VERIFY_TIMEOUT || 30000;
41
41
 
42
42
  const checkExecutable = binaryDir => {
43
43
  const executable = state.getPathToExecutable(binaryDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress",
3
- "version": "9.2.0",
3
+ "version": "9.2.1",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "postinstall": "node index.js --exec install",
@@ -19,7 +19,7 @@
19
19
  "chalk": "^4.1.0",
20
20
  "check-more-types": "^2.24.0",
21
21
  "cli-cursor": "^3.1.0",
22
- "cli-table3": "~0.6.0",
22
+ "cli-table3": "~0.6.1",
23
23
  "commander": "^5.1.0",
24
24
  "common-tags": "^1.8.0",
25
25
  "dayjs": "^1.10.4",