@cypress/github-action 7.4.4 → 7.4.5

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.
Files changed (3) hide show
  1. package/README.md +63 -57
  2. package/dist/index.js +293 -159
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -97,7 +97,7 @@ name: End-to-end tests
97
97
  on: push
98
98
  jobs:
99
99
  cypress-run:
100
- runs-on: ubuntu-24.04
100
+ runs-on: ubuntu-26.04
101
101
  steps:
102
102
  - name: Checkout
103
103
  uses: actions/checkout@v7
@@ -122,7 +122,7 @@ name: Component tests
122
122
  on: push
123
123
  jobs:
124
124
  cypress-run:
125
- runs-on: ubuntu-24.04
125
+ runs-on: ubuntu-26.04
126
126
  steps:
127
127
  - name: Checkout
128
128
  uses: actions/checkout@v7
@@ -166,7 +166,15 @@ The workflows in the [examples](./examples/) directory use the latest commit fro
166
166
 
167
167
  ### Browser
168
168
 
169
- Specify the browser name or path with the `browser` parameter. The default browser, if none is specified, is the built-in [Electron browser](https://on.cypress.io/guides/guides/launching-browsers#Electron-Browser).
169
+ Specify the browser name or path with the `browser` parameter.
170
+
171
+ The default browser can be set as a [Browser](https://docs.cypress.io/app/references/configuration#Browser) configuration option `defaultBrowser`.
172
+ If no `browser` parameter is specified and `defaultBrowser` is also undefined,
173
+ the built-in [Electron browser](https://on.cypress.io/guides/guides/launching-browsers#Electron-Browser) is used.
174
+
175
+ [cypress@16.0.0](https://docs.cypress.io/app/references/changelog#16-0-0) deprecated the Electron browser and describes the plan to remove it in a future major version of Cypress.
176
+
177
+ Each of the [examples](./examples/) directories in this repo sets `defaultBrowser` to `chrome`.
170
178
 
171
179
  ### Chrome
172
180
 
@@ -175,7 +183,7 @@ name: Chrome
175
183
  on: push
176
184
  jobs:
177
185
  chrome:
178
- runs-on: ubuntu-24.04
186
+ runs-on: ubuntu-26.04
179
187
  name: E2E on Chrome
180
188
  steps:
181
189
  - uses: actions/checkout@v7
@@ -199,7 +207,7 @@ name: Chrome for Testing
199
207
  on: push
200
208
  jobs:
201
209
  chrome:
202
- runs-on: ubuntu-24.04
210
+ runs-on: ubuntu-26.04
203
211
  name: E2E on Chrome for Testing
204
212
  steps:
205
213
  - uses: actions/checkout@v7
@@ -218,7 +226,7 @@ name: Firefox
218
226
  on: push
219
227
  jobs:
220
228
  firefox:
221
- runs-on: ubuntu-24.04
229
+ runs-on: ubuntu-26.04
222
230
  name: E2E on Firefox
223
231
  steps:
224
232
  - uses: actions/checkout@v7
@@ -236,7 +244,7 @@ name: Edge
236
244
  on: push
237
245
  jobs:
238
246
  edge:
239
- runs-on: ubuntu-24.04
247
+ runs-on: ubuntu-26.04
240
248
  name: E2E on Edge
241
249
  steps:
242
250
  - uses: actions/checkout@v7
@@ -256,7 +264,7 @@ name: Chrome headed
256
264
  on: push
257
265
  jobs:
258
266
  cypress-run:
259
- runs-on: ubuntu-24.04
267
+ runs-on: ubuntu-26.04
260
268
  steps:
261
269
  - uses: actions/checkout@v7
262
270
  - uses: cypress-io/github-action@v7
@@ -274,7 +282,7 @@ name: Test in Docker
274
282
  on: push
275
283
  jobs:
276
284
  cypress-run:
277
- runs-on: ubuntu-24.04
285
+ runs-on: ubuntu-26.04
278
286
  # Cypress Docker image from https://hub.docker.com/r/cypress
279
287
  # with browsers pre-installed
280
288
  container:
@@ -298,7 +306,7 @@ name: Test with Docker cypress/included
298
306
  on: push
299
307
  jobs:
300
308
  cypress-run:
301
- runs-on: ubuntu-24.04
309
+ runs-on: ubuntu-26.04
302
310
  container:
303
311
  # Cypress Docker image from https://hub.docker.com/r/cypress/included
304
312
  # with Cypress globally pre-installed
@@ -328,7 +336,7 @@ name: Cypress tests
328
336
  on: push
329
337
  jobs:
330
338
  cypress-run:
331
- runs-on: ubuntu-24.04
339
+ runs-on: ubuntu-26.04
332
340
  steps:
333
341
  - name: Checkout
334
342
  uses: actions/checkout@v7
@@ -346,7 +354,7 @@ name: Cypress tests
346
354
  on: push
347
355
  jobs:
348
356
  cypress-run:
349
- runs-on: ubuntu-24.04
357
+ runs-on: ubuntu-26.04
350
358
  steps:
351
359
  - name: Checkout
352
360
  uses: actions/checkout@v7
@@ -371,7 +379,7 @@ name: Cypress tests
371
379
  on: push
372
380
  jobs:
373
381
  cypress-run:
374
- runs-on: ubuntu-24.04
382
+ runs-on: ubuntu-26.04
375
383
  steps:
376
384
  - name: Checkout
377
385
  uses: actions/checkout@v7
@@ -396,7 +404,7 @@ on: push
396
404
  jobs:
397
405
  cypress-run:
398
406
  name: Cypress run
399
- runs-on: ubuntu-24.04
407
+ runs-on: ubuntu-26.04
400
408
  steps:
401
409
  - name: Checkout
402
410
  uses: actions/checkout@v7
@@ -427,7 +435,7 @@ on: push
427
435
  jobs:
428
436
  cypress-run:
429
437
  name: Cypress run
430
- runs-on: ubuntu-24.04
438
+ runs-on: ubuntu-26.04
431
439
  steps:
432
440
  - name: Checkout
433
441
  uses: actions/checkout@v7
@@ -459,7 +467,7 @@ on: push
459
467
  jobs:
460
468
  cypress-run:
461
469
  name: Cypress run
462
- runs-on: ubuntu-24.04
470
+ runs-on: ubuntu-26.04
463
471
  steps:
464
472
  - name: Checkout
465
473
  uses: actions/checkout@v7
@@ -489,7 +497,7 @@ on: push
489
497
  jobs:
490
498
  cypress-run:
491
499
  name: Cypress run
492
- runs-on: ubuntu-24.04
500
+ runs-on: ubuntu-26.04
493
501
  steps:
494
502
  - name: Checkout
495
503
  uses: actions/checkout@v7
@@ -522,7 +530,7 @@ name: Example echo PR number and URL
522
530
  on: push
523
531
  jobs:
524
532
  cypress-run:
525
- runs-on: ubuntu-24.04
533
+ runs-on: ubuntu-26.04
526
534
  steps:
527
535
  - name: Checkout
528
536
  uses: actions/checkout@v7
@@ -560,7 +568,7 @@ on: push
560
568
  jobs:
561
569
  cypress-run:
562
570
  name: Cypress run
563
- runs-on: ubuntu-24.04
571
+ runs-on: ubuntu-26.04
564
572
  steps:
565
573
  - name: Checkout
566
574
  uses: actions/checkout@v7
@@ -588,7 +596,7 @@ name: tags
588
596
  on: push
589
597
  jobs:
590
598
  cypress-run:
591
- runs-on: ubuntu-24.04
599
+ runs-on: ubuntu-26.04
592
600
  # let's make sure our "app" works on several versions of Node
593
601
  strategy:
594
602
  matrix:
@@ -633,7 +641,7 @@ name: Cypress E2E Tests
633
641
  on: push
634
642
  jobs:
635
643
  cypress-run:
636
- runs-on: ubuntu-24.04
644
+ runs-on: ubuntu-26.04
637
645
  name: E2E
638
646
  steps:
639
647
  - name: Checkout
@@ -661,7 +669,7 @@ name: Artifacts
661
669
  on: push
662
670
  jobs:
663
671
  cypress-run:
664
- runs-on: ubuntu-24.04
672
+ runs-on: ubuntu-26.04
665
673
  name: Artifacts
666
674
  steps:
667
675
  - uses: actions/checkout@v7
@@ -690,7 +698,7 @@ name: example-quiet
690
698
  on: push
691
699
  jobs:
692
700
  cypress-run:
693
- runs-on: ubuntu-24.04
701
+ runs-on: ubuntu-26.04
694
702
  steps:
695
703
  - name: Checkout
696
704
  uses: actions/checkout@v7
@@ -715,7 +723,7 @@ on: push
715
723
  jobs:
716
724
  cypress-run:
717
725
  name: Cypress run
718
- runs-on: ubuntu-24.04
726
+ runs-on: ubuntu-26.04
719
727
  steps:
720
728
  - name: Checkout
721
729
  uses: actions/checkout@v7
@@ -738,7 +746,7 @@ on: push
738
746
  jobs:
739
747
  cypress-run:
740
748
  name: Cypress run
741
- runs-on: ubuntu-24.04
749
+ runs-on: ubuntu-26.04
742
750
  steps:
743
751
  - name: Checkout
744
752
  uses: actions/checkout@v7
@@ -765,7 +773,7 @@ on: push
765
773
  jobs:
766
774
  test:
767
775
  name: Cypress run
768
- runs-on: ubuntu-24.04
776
+ runs-on: ubuntu-26.04
769
777
  strategy:
770
778
  # when one test fails, DO NOT cancel the other
771
779
  # containers, because this will kill Cypress processes
@@ -852,7 +860,7 @@ name: Build
852
860
  on: push
853
861
  jobs:
854
862
  cypress-run:
855
- runs-on: ubuntu-24.04
863
+ runs-on: ubuntu-26.04
856
864
  steps:
857
865
  - name: Checkout
858
866
  uses: actions/checkout@v7
@@ -871,7 +879,7 @@ name: With server
871
879
  on: push
872
880
  jobs:
873
881
  cypress-run:
874
- runs-on: ubuntu-24.04
882
+ runs-on: ubuntu-26.04
875
883
  steps:
876
884
  - name: Checkout
877
885
  uses: actions/checkout@v7
@@ -890,7 +898,7 @@ name: With server
890
898
  on: push
891
899
  jobs:
892
900
  cypress-run:
893
- runs-on: ubuntu-24.04
901
+ runs-on: ubuntu-26.04
894
902
  steps:
895
903
  - name: Checkout
896
904
  uses: actions/checkout@v7
@@ -916,7 +924,7 @@ name: With servers
916
924
  on: push
917
925
  jobs:
918
926
  cypress-run:
919
- runs-on: ubuntu-24.04
927
+ runs-on: ubuntu-26.04
920
928
  steps:
921
929
  - name: Checkout
922
930
  uses: actions/checkout@v7
@@ -946,7 +954,7 @@ name: After server responds
946
954
  on: push
947
955
  jobs:
948
956
  cypress-run:
949
- runs-on: ubuntu-24.04
957
+ runs-on: ubuntu-26.04
950
958
  steps:
951
959
  - name: Checkout
952
960
  uses: actions/checkout@v7
@@ -1035,7 +1043,7 @@ name: Visual
1035
1043
  on: push
1036
1044
  jobs:
1037
1045
  e2e:
1038
- runs-on: ubuntu-24.04
1046
+ runs-on: ubuntu-26.04
1039
1047
  steps:
1040
1048
  - name: Checkout
1041
1049
  uses: actions/checkout@v7
@@ -1082,7 +1090,7 @@ name: Parallel
1082
1090
  on: push
1083
1091
  jobs:
1084
1092
  test:
1085
- runs-on: ubuntu-24.04
1093
+ runs-on: ubuntu-26.04
1086
1094
  strategy:
1087
1095
  matrix:
1088
1096
  # run 3 copies of the current job in parallel
@@ -1167,7 +1175,7 @@ We use `working-directory: app-test` to match the above example directory struct
1167
1175
  on: push
1168
1176
  jobs:
1169
1177
  cypress-run:
1170
- runs-on: ubuntu-24.04
1178
+ runs-on: ubuntu-26.04
1171
1179
  steps:
1172
1180
  - uses: actions/checkout@v7
1173
1181
  - uses: cypress-io/github-action@v7
@@ -1205,7 +1213,7 @@ name: E2E
1205
1213
  on: push
1206
1214
  jobs:
1207
1215
  test:
1208
- runs-on: ubuntu-24.04
1216
+ runs-on: ubuntu-26.04
1209
1217
  steps:
1210
1218
  - uses: actions/checkout@v7
1211
1219
  - name: Install root dependencies
@@ -1237,14 +1245,14 @@ name: example-basic-pnpm
1237
1245
  on: push
1238
1246
  jobs:
1239
1247
  basic-pnpm:
1240
- runs-on: ubuntu-24.04
1248
+ runs-on: ubuntu-26.04
1241
1249
  steps:
1242
1250
  - name: Checkout
1243
1251
  uses: actions/checkout@v7
1244
1252
  - name: Install pnpm
1245
1253
  uses: pnpm/action-setup@v6
1246
1254
  with:
1247
- version: 11
1255
+ version: 12
1248
1256
  - name: Install Node.js
1249
1257
  uses: actions/setup-node@v7
1250
1258
  with:
@@ -1297,7 +1305,7 @@ name: example-yarn-classic
1297
1305
  on: push
1298
1306
  jobs:
1299
1307
  yarn-classic:
1300
- runs-on: ubuntu-24.04
1308
+ runs-on: ubuntu-26.04
1301
1309
  steps:
1302
1310
  - name: Checkout
1303
1311
  uses: actions/checkout@v7
@@ -1320,7 +1328,7 @@ name: example-yarn-modern
1320
1328
  on: push
1321
1329
  jobs:
1322
1330
  yarn-modern:
1323
- runs-on: ubuntu-24.04
1331
+ runs-on: ubuntu-26.04
1324
1332
  steps:
1325
1333
  - name: Checkout
1326
1334
  uses: actions/checkout@v7
@@ -1354,7 +1362,7 @@ name: example-yarn-modern-pnp
1354
1362
  on: push
1355
1363
  jobs:
1356
1364
  yarn-classic:
1357
- runs-on: ubuntu-24.04
1365
+ runs-on: ubuntu-26.04
1358
1366
  steps:
1359
1367
  - name: Checkout
1360
1368
  uses: actions/checkout@v7
@@ -1384,7 +1392,7 @@ jobs:
1384
1392
  # the example has Yarn workspace in its "root" folder
1385
1393
  # examples/start-and-yarn-workspaces
1386
1394
  # and tests in a subfolder like "workspace-1"
1387
- runs-on: ubuntu-24.04
1395
+ runs-on: ubuntu-26.04
1388
1396
  steps:
1389
1397
  - uses: actions/checkout@v7
1390
1398
  - uses: cypress-io/github-action@v7
@@ -1415,7 +1423,7 @@ name: Package manager caching
1415
1423
  on: push
1416
1424
  jobs:
1417
1425
  cypress-run:
1418
- runs-on: ubuntu-24.04
1426
+ runs-on: ubuntu-26.04
1419
1427
  name:
1420
1428
  steps:
1421
1429
  - uses: actions/checkout@v7
@@ -1438,7 +1446,7 @@ name: End-to-end tests
1438
1446
  on: push
1439
1447
  jobs:
1440
1448
  cypress-run:
1441
- runs-on: ubuntu-24.04
1449
+ runs-on: ubuntu-26.04
1442
1450
  # let's make sure our "app" works on several versions of Node
1443
1451
  strategy:
1444
1452
  matrix:
@@ -1476,7 +1484,7 @@ name: Node versions
1476
1484
  on: push
1477
1485
  jobs:
1478
1486
  cypress-run:
1479
- runs-on: ubuntu-24.04
1487
+ runs-on: ubuntu-26.04
1480
1488
  strategy:
1481
1489
  matrix:
1482
1490
  node:
@@ -1505,7 +1513,7 @@ name: E2E
1505
1513
  on: push
1506
1514
  jobs:
1507
1515
  test:
1508
- runs-on: ubuntu-24.04
1516
+ runs-on: ubuntu-26.04
1509
1517
  steps:
1510
1518
  - uses: actions/checkout@v7
1511
1519
  - name: Install dependencies
@@ -1538,7 +1546,7 @@ name: Split build and test
1538
1546
  on: push
1539
1547
  jobs:
1540
1548
  build:
1541
- runs-on: ubuntu-24.04
1549
+ runs-on: ubuntu-26.04
1542
1550
  steps:
1543
1551
  - uses: actions/checkout@v7
1544
1552
  - name: Build app
@@ -1556,7 +1564,7 @@ jobs:
1556
1564
 
1557
1565
  test:
1558
1566
  needs: build
1559
- runs-on: ubuntu-24.04
1567
+ runs-on: ubuntu-26.04
1560
1568
  steps:
1561
1569
  - uses: actions/checkout@v7
1562
1570
  - name: Restore build artifacts
@@ -1584,7 +1592,7 @@ You can tell the CI to stop the job or the individual step if it runs for longer
1584
1592
  ```yml
1585
1593
  jobs:
1586
1594
  cypress-run:
1587
- runs-on: ubuntu-24.04
1595
+ runs-on: ubuntu-26.04
1588
1596
  # stop the job if it runs over 10 minutes
1589
1597
  # to prevent a hanging process from using all your CI minutes
1590
1598
  timeout-minutes: 10
@@ -1629,7 +1637,7 @@ name: CLI migration example
1629
1637
  on: push
1630
1638
  jobs:
1631
1639
  cypress-run:
1632
- runs-on: ubuntu-24.04
1640
+ runs-on: ubuntu-26.04
1633
1641
  steps:
1634
1642
  - name: Check out repo
1635
1643
  uses: actions/checkout@v7
@@ -1817,7 +1825,7 @@ name: info
1817
1825
  on: push
1818
1826
  jobs:
1819
1827
  cypress-run:
1820
- runs-on: ubuntu-24.04
1828
+ runs-on: ubuntu-26.04
1821
1829
  steps:
1822
1830
  - name: Checkout
1823
1831
  uses: actions/checkout@v7
@@ -1834,7 +1842,7 @@ name: info
1834
1842
  on: push
1835
1843
  jobs:
1836
1844
  cypress-run:
1837
- runs-on: ubuntu-24.04
1845
+ runs-on: ubuntu-26.04
1838
1846
  steps:
1839
1847
  - name: Checkout
1840
1848
  uses: actions/checkout@v7
@@ -1865,7 +1873,7 @@ on:
1865
1873
  - cron: '0 4 * * *'
1866
1874
  jobs:
1867
1875
  nightly:
1868
- runs-on: ubuntu-24.04
1876
+ runs-on: ubuntu-26.04
1869
1877
  steps:
1870
1878
  - name: Checkout
1871
1879
  uses: actions/checkout@v7
@@ -1886,7 +1894,7 @@ name: Summary titles
1886
1894
  on: push
1887
1895
  jobs:
1888
1896
  tests:
1889
- runs-on: ubuntu-24.04
1897
+ runs-on: ubuntu-26.04
1890
1898
  steps:
1891
1899
  - uses: actions/checkout@v7
1892
1900
  - name: Cypress headless tests
@@ -1914,7 +1922,7 @@ name: Example no summary
1914
1922
  on: push
1915
1923
  jobs:
1916
1924
  cypress-run:
1917
- runs-on: ubuntu-24.04
1925
+ runs-on: ubuntu-26.04
1918
1926
  steps:
1919
1927
  - name: Checkout
1920
1928
  uses: actions/checkout@v7
@@ -1949,9 +1957,7 @@ View the [CHANGELOG](./CHANGELOG.md) document for an overview of version changes
1949
1957
  ## Compatibility
1950
1958
 
1951
1959
  - `github-action@v7` is the current recommended version, uses `node24` and is compatible with Cypress `10` and above.
1952
- - `github-action@v6` is deprecated. It uses `node20` which has reached its end of life - see [Deprecation of Node 20 on GitHub Actions runners](https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/).
1953
- - `github-action@v6.7.9` is the minimum version required to use GitHub Actions caching services. The legacy caching service used by lower versions of the action is no longer available.
1954
- - `github-action` versions `v1` to `v5` are unsupported: they rely on Node.js `12` and `16` in End-of-life status.
1960
+ - `github-action` versions `v1` to `v6` are unsupported: they rely on Node.js `12`, `16` or `20` in End-of-life status.
1955
1961
 
1956
1962
  Cypress lists browser compatibility information under [System Requirements](https://docs.cypress.io/app/get-started/install-cypress#Browsers).
1957
1963
 
package/dist/index.js CHANGED
@@ -29789,7 +29789,7 @@ async function connectH1 (client, socket) {
29789
29789
 
29790
29790
  function clearIdleSocketValidation (socket) {
29791
29791
  if (socket[kIdleSocketValidationTimeout]) {
29792
- clearTimeout(socket[kIdleSocketValidationTimeout])
29792
+ clearImmediate(socket[kIdleSocketValidationTimeout])
29793
29793
  socket[kIdleSocketValidationTimeout] = null
29794
29794
  }
29795
29795
 
@@ -29798,15 +29798,23 @@ function clearIdleSocketValidation (socket) {
29798
29798
 
29799
29799
  function scheduleIdleSocketValidation (client, socket) {
29800
29800
  socket[kIdleSocketValidation] = 1
29801
- socket[kIdleSocketValidationTimeout] = setTimeout(() => {
29801
+ // Yield to the check phase (after poll) so unsolicited bytes / FIN / RST
29802
+ // already pending on this idle keep-alive socket are processed before the
29803
+ // next request is written (GHSA-35p6-xmwp-9g52).
29804
+ //
29805
+ // setTimeout(0) pays Node's ~1ms timer floor on every sequential reuse
29806
+ // (#5493). setImmediate avoids that, but an *unref'd* Immediate lets poll
29807
+ // block for ~500ms when the event loop is otherwise idle (#5600 / #5606).
29808
+ // A ref'd Immediate both keeps the pending request alive and makes poll
29809
+ // return immediately — the hybrid those issues asked for.
29810
+ socket[kIdleSocketValidationTimeout] = setImmediate(() => {
29802
29811
  socket[kIdleSocketValidationTimeout] = null
29803
29812
  socket[kIdleSocketValidation] = 2
29804
29813
 
29805
29814
  if (client[kSocket] === socket && !socket.destroyed) {
29806
29815
  client[kResume]()
29807
29816
  }
29808
- }, 0)
29809
- socket[kIdleSocketValidationTimeout].unref?.()
29817
+ })
29810
29818
  }
29811
29819
 
29812
29820
  /**
@@ -33478,6 +33486,7 @@ class RetryHandler {
33478
33486
  this.end = null
33479
33487
  this.etag = null
33480
33488
  this.resume = null
33489
+ this.headersSent = false
33481
33490
 
33482
33491
  // Handle possible onConnect duplication
33483
33492
  this.handler.onConnect(reason => {
@@ -33490,6 +33499,20 @@ class RetryHandler {
33490
33499
  })
33491
33500
  }
33492
33501
 
33502
+ checkpointResponseEnd (headers, resume) {
33503
+ if (this.end == null && this.opts.method !== 'HEAD') {
33504
+ const contentLength = headers['content-length']
33505
+ this.end = contentLength != null ? Number(contentLength) - 1 : null
33506
+
33507
+ assert(
33508
+ this.end == null || Number.isFinite(this.end),
33509
+ 'invalid content-length'
33510
+ )
33511
+ }
33512
+
33513
+ this.resume = this.end != null ? resume : null
33514
+ }
33515
+
33493
33516
  onRequestSent () {
33494
33517
  if (this.handler.onRequestSent) {
33495
33518
  this.handler.onRequestSent()
@@ -33579,6 +33602,8 @@ class RetryHandler {
33579
33602
 
33580
33603
  if (statusCode >= 300) {
33581
33604
  if (this.retryOpts.statusCodes.includes(statusCode) === false) {
33605
+ this.headersSent = true
33606
+ this.checkpointResponseEnd(headers, resume)
33582
33607
  return this.handler.onHeaders(
33583
33608
  statusCode,
33584
33609
  rawHeaders,
@@ -33647,8 +33672,15 @@ class RetryHandler {
33647
33672
 
33648
33673
  const { start, size, end = size - 1 } = contentRange
33649
33674
 
33650
- assert(this.start === start, 'content-range mismatch')
33651
- assert(this.end == null || this.end === end, 'content-range mismatch')
33675
+ if (this.start !== start || (this.end != null && this.end !== end)) {
33676
+ this.abort(
33677
+ new RequestRetryError('Content-Range mismatch', statusCode, {
33678
+ headers,
33679
+ data: { count: this.retryCount }
33680
+ })
33681
+ )
33682
+ return false
33683
+ }
33652
33684
 
33653
33685
  this.resume = resume
33654
33686
  return true
@@ -33660,6 +33692,7 @@ class RetryHandler {
33660
33692
  const range = parseRangeHeader(headers['content-range'])
33661
33693
 
33662
33694
  if (range == null) {
33695
+ this.headersSent = true
33663
33696
  return this.handler.onHeaders(
33664
33697
  statusCode,
33665
33698
  rawHeaders,
@@ -33698,6 +33731,7 @@ class RetryHandler {
33698
33731
  )
33699
33732
 
33700
33733
  this.resume = resume
33734
+ this.headersSent = true
33701
33735
  this.etag = headers.etag != null ? headers.etag : null
33702
33736
 
33703
33737
  // Weak etags are not useful for comparison nor cache
@@ -33737,7 +33771,7 @@ class RetryHandler {
33737
33771
  }
33738
33772
 
33739
33773
  onError (err) {
33740
- if (this.aborted || isDisturbed(this.opts.body)) {
33774
+ if (this.aborted || isDisturbed(this.opts.body) || (this.headersSent && this.resume == null)) {
33741
33775
  return this.handler.onError(err)
33742
33776
  }
33743
33777
 
@@ -38223,6 +38257,49 @@ const COLON = 0x3A
38223
38257
  */
38224
38258
  const SPACE = 0x20
38225
38259
 
38260
+ const DATA = Buffer.from('data')
38261
+ const EVENT = Buffer.from('event')
38262
+ const ID = Buffer.from('id')
38263
+ const RETRY = Buffer.from('retry')
38264
+
38265
+ function isASCIINumberBytes (buffer, start) {
38266
+ if (start >= buffer.length) {
38267
+ return false
38268
+ }
38269
+
38270
+ for (let i = start; i < buffer.length; i++) {
38271
+ if (buffer[i] < 0x30 || buffer[i] > 0x39) {
38272
+ return false
38273
+ }
38274
+ }
38275
+
38276
+ return true
38277
+ }
38278
+
38279
+ function isValidLastEventIdBytes (buffer, start) {
38280
+ for (let i = start; i < buffer.length; i++) {
38281
+ if (buffer[i] === 0x00) {
38282
+ return false
38283
+ }
38284
+ }
38285
+
38286
+ return true
38287
+ }
38288
+
38289
+ function isFieldName (line, length, field) {
38290
+ if (length !== field.length) {
38291
+ return false
38292
+ }
38293
+
38294
+ for (let i = 0; i < length; i++) {
38295
+ if (line[i] !== field[i]) {
38296
+ return false
38297
+ }
38298
+ }
38299
+
38300
+ return true
38301
+ }
38302
+
38226
38303
  /**
38227
38304
  * @typedef {object} EventSourceStreamEvent
38228
38305
  * @type {object}
@@ -38263,11 +38340,14 @@ class EventSourceStream extends Transform {
38263
38340
  eventEndCheck = false
38264
38341
 
38265
38342
  /**
38266
- * @type {Buffer}
38343
+ * @type {Buffer[]}
38267
38344
  */
38268
- buffer = null
38345
+ chunks = []
38269
38346
 
38347
+ chunkIndex = 0
38270
38348
  pos = 0
38349
+ lineChunkIndex = 0
38350
+ linePos = 0
38271
38351
 
38272
38352
  event = {
38273
38353
  data: undefined,
@@ -38306,92 +38386,20 @@ class EventSourceStream extends Transform {
38306
38386
  return
38307
38387
  }
38308
38388
 
38309
- // Cache the chunk in the buffer, as the data might not be complete while
38310
- // processing it
38311
- // TODO: Investigate if there is a more performant way to handle
38312
- // incoming chunks
38313
- // see: https://github.com/nodejs/undici/issues/2630
38314
- if (this.buffer) {
38315
- this.buffer = Buffer.concat([this.buffer, chunk])
38316
- } else {
38317
- this.buffer = chunk
38318
- }
38389
+ this.chunks.push(chunk)
38319
38390
 
38320
38391
  // Strip leading byte-order-mark if we opened the stream and started
38321
38392
  // the processing of the incoming data
38322
38393
  if (this.checkBOM) {
38323
- switch (this.buffer.length) {
38324
- case 1:
38325
- // Check if the first byte is the same as the first byte of the BOM
38326
- if (this.buffer[0] === BOM[0]) {
38327
- // If it is, we need to wait for more data
38328
- callback()
38329
- return
38330
- }
38331
- // Set the checkBOM flag to false as we don't need to check for the
38332
- // BOM anymore
38333
- this.checkBOM = false
38334
-
38335
- // The buffer only contains one byte so we need to wait for more data
38336
- callback()
38337
- return
38338
- case 2:
38339
- // Check if the first two bytes are the same as the first two bytes
38340
- // of the BOM
38341
- if (
38342
- this.buffer[0] === BOM[0] &&
38343
- this.buffer[1] === BOM[1]
38344
- ) {
38345
- // If it is, we need to wait for more data, because the third byte
38346
- // is needed to determine if it is the BOM or not
38347
- callback()
38348
- return
38349
- }
38350
-
38351
- // Set the checkBOM flag to false as we don't need to check for the
38352
- // BOM anymore
38353
- this.checkBOM = false
38354
- break
38355
- case 3:
38356
- // Check if the first three bytes are the same as the first three
38357
- // bytes of the BOM
38358
- if (
38359
- this.buffer[0] === BOM[0] &&
38360
- this.buffer[1] === BOM[1] &&
38361
- this.buffer[2] === BOM[2]
38362
- ) {
38363
- // If it is, we can drop the buffered data, as it is only the BOM
38364
- this.buffer = Buffer.alloc(0)
38365
- // Set the checkBOM flag to false as we don't need to check for the
38366
- // BOM anymore
38367
- this.checkBOM = false
38368
-
38369
- // Await more data
38370
- callback()
38371
- return
38372
- }
38373
- // If it is not the BOM, we can start processing the data
38374
- this.checkBOM = false
38375
- break
38376
- default:
38377
- // The buffer is longer than 3 bytes, so we can drop the BOM if it is
38378
- // present
38379
- if (
38380
- this.buffer[0] === BOM[0] &&
38381
- this.buffer[1] === BOM[1] &&
38382
- this.buffer[2] === BOM[2]
38383
- ) {
38384
- // Remove the BOM from the buffer
38385
- this.buffer = this.buffer.subarray(3)
38386
- }
38387
-
38388
- // Set the checkBOM flag to false as we don't need to check for the
38389
- this.checkBOM = false
38390
- break
38394
+ if (this.handleBOM()) {
38395
+ callback()
38396
+ return
38391
38397
  }
38392
38398
  }
38393
38399
 
38394
- while (this.pos < this.buffer.length) {
38400
+ while (this.hasCurrentByte()) {
38401
+ const byte = this.currentByte()
38402
+
38395
38403
  // If the previous line ended with an end-of-line, we need to check
38396
38404
  // if the next character is also an end-of-line.
38397
38405
  if (this.eventEndCheck) {
@@ -38404,10 +38412,9 @@ class EventSourceStream extends Transform {
38404
38412
  if (this.crlfCheck) {
38405
38413
  // If the current character is a line feed, we can remove it
38406
38414
  // from the buffer and reset the crlfCheck flag
38407
- if (this.buffer[this.pos] === LF) {
38408
- this.buffer = this.buffer.subarray(this.pos + 1)
38409
- this.pos = 0
38415
+ if (byte === LF) {
38410
38416
  this.crlfCheck = false
38417
+ this.consumeCurrentByte()
38411
38418
 
38412
38419
  // It is possible that the line feed is not the end of the
38413
38420
  // event. We need to check if the next character is an
@@ -38423,19 +38430,17 @@ class EventSourceStream extends Transform {
38423
38430
  this.crlfCheck = false
38424
38431
  }
38425
38432
 
38426
- if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
38433
+ if (byte === LF || byte === CR) {
38427
38434
  // If the current character is a carriage return, we need to
38428
38435
  // set the crlfCheck flag to true, as we need to check if the
38429
38436
  // next character is a line feed so we can remove it from the
38430
38437
  // buffer
38431
- if (this.buffer[this.pos] === CR) {
38438
+ if (byte === CR) {
38432
38439
  this.crlfCheck = true
38433
38440
  }
38434
38441
 
38435
- this.buffer = this.buffer.subarray(this.pos + 1)
38436
- this.pos = 0
38437
- if (
38438
- this.event.data !== undefined || this.event.event || this.event.id || this.event.retry) {
38442
+ this.consumeCurrentByte()
38443
+ if (this.hasPendingEvent()) {
38439
38444
  this.processEvent(this.event)
38440
38445
  }
38441
38446
  this.clearEvent()
@@ -38449,22 +38454,18 @@ class EventSourceStream extends Transform {
38449
38454
 
38450
38455
  // If the current character is an end-of-line, we can process the
38451
38456
  // line
38452
- if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
38457
+ if (byte === LF || byte === CR) {
38453
38458
  // If the current character is a carriage return, we need to
38454
38459
  // set the crlfCheck flag to true, as we need to check if the
38455
38460
  // next character is a line feed
38456
- if (this.buffer[this.pos] === CR) {
38461
+ if (byte === CR) {
38457
38462
  this.crlfCheck = true
38458
38463
  }
38459
38464
 
38460
38465
  // In any case, we can process the line as we reached an
38461
38466
  // end-of-line character
38462
- this.parseLine(this.buffer.subarray(0, this.pos), this.event)
38463
-
38464
- // Remove the processed line from the buffer
38465
- this.buffer = this.buffer.subarray(this.pos + 1)
38466
- // Reset the position as we removed the processed line from the buffer
38467
- this.pos = 0
38467
+ this.parseLine(this.readLine(), this.event)
38468
+ this.consumeCurrentByte()
38468
38469
  // A line was processed and this could be the end of the event. We need
38469
38470
  // to check if the next line is empty to determine if the event is
38470
38471
  // finished.
@@ -38472,7 +38473,7 @@ class EventSourceStream extends Transform {
38472
38473
  continue
38473
38474
  }
38474
38475
 
38475
- this.pos++
38476
+ this.advanceCursor()
38476
38477
  }
38477
38478
 
38478
38479
  callback()
@@ -38497,64 +38498,53 @@ class EventSourceStream extends Transform {
38497
38498
  return
38498
38499
  }
38499
38500
 
38500
- let field = ''
38501
- let value = ''
38501
+ let fieldLength = line.length
38502
+ let valueStart = line.length
38502
38503
 
38503
38504
  // If the line contains a U+003A COLON character (:)
38504
38505
  if (colonPosition !== -1) {
38505
- // Collect the characters on the line before the first U+003A COLON
38506
- // character (:), and let field be that string.
38507
- // TODO: Investigate if there is a more performant way to extract the
38508
- // field
38509
- // see: https://github.com/nodejs/undici/issues/2630
38510
- field = line.subarray(0, colonPosition).toString('utf8')
38506
+ fieldLength = colonPosition
38511
38507
 
38512
38508
  // Collect the characters on the line after the first U+003A COLON
38513
38509
  // character (:), and let value be that string.
38514
38510
  // If value starts with a U+0020 SPACE character, remove it from value.
38515
- let valueStart = colonPosition + 1
38511
+ valueStart = colonPosition + 1
38516
38512
  if (line[valueStart] === SPACE) {
38517
38513
  ++valueStart
38518
38514
  }
38519
- // TODO: Investigate if there is a more performant way to extract the
38520
- // value
38521
- // see: https://github.com/nodejs/undici/issues/2630
38522
- value = line.subarray(valueStart).toString('utf8')
38515
+ }
38523
38516
 
38524
- // Otherwise, the string is not empty but does not contain a U+003A COLON
38525
- // character (:)
38526
- } else {
38527
- // Process the field using the steps described below, using the whole
38528
- // line as the field name, and the empty string as the field value.
38529
- field = line.toString('utf8')
38530
- value = ''
38531
- }
38532
-
38533
- // Modify the event with the field name and value. The value is also
38534
- // decoded as UTF-8
38535
- switch (field) {
38536
- case 'data':
38537
- if (event[field] === undefined) {
38538
- event[field] = value
38539
- } else {
38540
- event[field] += `\n${value}`
38541
- }
38542
- break
38543
- case 'retry':
38544
- if (isASCIINumber(value)) {
38545
- event[field] = value
38546
- }
38547
- break
38548
- case 'id':
38549
- if (isValidLastEventId(value)) {
38550
- event[field] = value
38551
- }
38552
- break
38553
- case 'event':
38554
- if (value.length > 0) {
38555
- event[field] = value
38556
- }
38557
- break
38517
+ if (isFieldName(line, fieldLength, DATA)) {
38518
+ const value = line.toString('utf8', valueStart)
38519
+
38520
+ if (event.data === undefined) {
38521
+ event.data = value
38522
+ } else {
38523
+ event.data += `\n${value}`
38524
+ }
38525
+ return
38526
+ }
38527
+
38528
+ if (isFieldName(line, fieldLength, RETRY)) {
38529
+ if (isASCIINumberBytes(line, valueStart)) {
38530
+ event.retry = line.toString('utf8', valueStart)
38531
+ }
38532
+ return
38533
+ }
38534
+
38535
+ if (isFieldName(line, fieldLength, ID)) {
38536
+ if (isValidLastEventIdBytes(line, valueStart)) {
38537
+ event.id = line.toString('utf8', valueStart)
38538
+ }
38539
+ return
38540
+ }
38541
+
38542
+ if (isFieldName(line, fieldLength, EVENT)) {
38543
+ const value = line.toString('utf8', valueStart)
38544
+
38545
+ if (value.length > 0) {
38546
+ event.event = value
38547
+ }
38558
38548
  }
38559
38549
  }
38560
38550
 
@@ -38584,12 +38574,151 @@ class EventSourceStream extends Transform {
38584
38574
  }
38585
38575
 
38586
38576
  clearEvent () {
38587
- this.event = {
38588
- data: undefined,
38589
- event: undefined,
38590
- id: undefined,
38591
- retry: undefined
38577
+ this.event.data = undefined
38578
+ this.event.event = undefined
38579
+ this.event.id = undefined
38580
+ this.event.retry = undefined
38581
+ }
38582
+
38583
+ hasPendingEvent () {
38584
+ return this.event.data !== undefined ||
38585
+ this.event.event !== undefined ||
38586
+ this.event.id !== undefined ||
38587
+ this.event.retry !== undefined
38588
+ }
38589
+
38590
+ hasCurrentByte () {
38591
+ return this.chunkIndex < this.chunks.length &&
38592
+ this.pos < this.chunks[this.chunkIndex].length
38593
+ }
38594
+
38595
+ currentByte () {
38596
+ return this.chunks[this.chunkIndex][this.pos]
38597
+ }
38598
+
38599
+ consumeCurrentByte () {
38600
+ this.advanceCursor()
38601
+ this.syncLineStartToCursor()
38602
+ }
38603
+
38604
+ advanceCursor () {
38605
+ this.pos++
38606
+
38607
+ while (this.chunkIndex < this.chunks.length && this.pos >= this.chunks[this.chunkIndex].length) {
38608
+ this.chunkIndex++
38609
+ this.pos = 0
38610
+ }
38611
+ }
38612
+
38613
+ syncLineStartToCursor () {
38614
+ this.lineChunkIndex = this.chunkIndex
38615
+ this.linePos = this.pos
38616
+ this.dropConsumedChunks()
38617
+ }
38618
+
38619
+ dropConsumedChunks () {
38620
+ while (this.lineChunkIndex > 0) {
38621
+ this.chunks.shift()
38622
+ this.lineChunkIndex--
38623
+ this.chunkIndex--
38592
38624
  }
38625
+
38626
+ if (this.chunkIndex === this.chunks.length) {
38627
+ this.chunks.length = 0
38628
+ this.chunkIndex = 0
38629
+ this.pos = 0
38630
+ this.lineChunkIndex = 0
38631
+ this.linePos = 0
38632
+ }
38633
+ }
38634
+
38635
+ readLine () {
38636
+ if (this.lineChunkIndex === this.chunkIndex) {
38637
+ return this.chunks[this.chunkIndex].subarray(this.linePos, this.pos)
38638
+ }
38639
+
38640
+ const chunks = []
38641
+ let length = 0
38642
+
38643
+ for (let i = this.lineChunkIndex; i <= this.chunkIndex; i++) {
38644
+ const chunk = this.chunks[i]
38645
+ const start = i === this.lineChunkIndex ? this.linePos : 0
38646
+ const end = i === this.chunkIndex ? this.pos : chunk.length
38647
+ const slice = chunk.subarray(start, end)
38648
+ length += slice.length
38649
+ chunks.push(slice)
38650
+ }
38651
+
38652
+ return Buffer.concat(chunks, length)
38653
+ }
38654
+
38655
+ peekBufferedByte (offset) {
38656
+ let chunkIndex = this.lineChunkIndex
38657
+ let pos = this.linePos
38658
+
38659
+ while (chunkIndex < this.chunks.length) {
38660
+ const chunk = this.chunks[chunkIndex]
38661
+ const remaining = chunk.length - pos
38662
+
38663
+ if (offset < remaining) {
38664
+ return chunk[pos + offset]
38665
+ }
38666
+
38667
+ offset -= remaining
38668
+ chunkIndex++
38669
+ pos = 0
38670
+ }
38671
+ }
38672
+
38673
+ discardLeadingBytes (count) {
38674
+ while (count > 0 && this.lineChunkIndex < this.chunks.length) {
38675
+ const chunk = this.chunks[this.lineChunkIndex]
38676
+ const remaining = chunk.length - this.linePos
38677
+
38678
+ if (count < remaining) {
38679
+ this.linePos += count
38680
+ count = 0
38681
+ } else {
38682
+ count -= remaining
38683
+ this.lineChunkIndex++
38684
+ this.linePos = 0
38685
+ }
38686
+ }
38687
+
38688
+ this.chunkIndex = this.lineChunkIndex
38689
+ this.pos = this.linePos
38690
+ this.dropConsumedChunks()
38691
+ }
38692
+
38693
+ handleBOM () {
38694
+ const first = this.peekBufferedByte(0)
38695
+ const second = this.peekBufferedByte(1)
38696
+ const third = this.peekBufferedByte(2)
38697
+
38698
+ if (second === undefined) {
38699
+ if (first === BOM[0]) {
38700
+ return true
38701
+ }
38702
+
38703
+ this.checkBOM = false
38704
+ return true
38705
+ }
38706
+
38707
+ if (third === undefined) {
38708
+ if (first === BOM[0] && second === BOM[1]) {
38709
+ return true
38710
+ }
38711
+
38712
+ this.checkBOM = false
38713
+ return false
38714
+ }
38715
+
38716
+ if (first === BOM[0] && second === BOM[1] && third === BOM[2]) {
38717
+ this.discardLeadingBytes(3)
38718
+ }
38719
+
38720
+ this.checkBOM = false
38721
+ return !this.hasCurrentByte()
38593
38722
  }
38594
38723
  }
38595
38724
 
@@ -49881,7 +50010,7 @@ function establishWebSocketConnection (url, protocols, client, ws, onEstablish,
49881
50010
  // is specified, the server needs to include the same field and one of
49882
50011
  // the selected subprotocol values in its response for the connection to
49883
50012
  // be established.
49884
- if (!requestProtocols.includes(secProtocol)) {
50013
+ if (requestProtocols === null || !requestProtocols.includes(secProtocol)) {
49885
50014
  failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.')
49886
50015
  return
49887
50016
  }
@@ -50646,7 +50775,12 @@ class PerMessageDeflate {
50646
50775
 
50647
50776
  if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) {
50648
50777
  callback(new MessageSizeExceededError())
50778
+ // The inflater may still hold buffered input that can emit a late
50779
+ // zlib error. Remove the data listener, then deterministically stop
50780
+ // the stream so a subsequent 'error' cannot fire without a listener
50781
+ // (which would terminate the process as an unhandled error event).
50649
50782
  this.#inflate.removeAllListeners()
50783
+ this.#inflate.destroy()
50650
50784
  this.#inflate = null
50651
50785
  return
50652
50786
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cypress/github-action",
3
- "version": "7.4.4",
3
+ "version": "7.4.5",
4
4
  "description": "GitHub Action for running Cypress end-to-end and component tests",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -62,7 +62,7 @@
62
62
  "globals": "17.11.0",
63
63
  "husky": "9.1.7",
64
64
  "markdown-link-check": "3.15.0",
65
- "prettier": "3.9.6"
65
+ "prettier": "3.9.8"
66
66
  },
67
67
  "publishConfig": {
68
68
  "access": "public"