Repository: oppia/oppia

Issue:
[Dependency Flake]: ConnectionResetError [Errno 104] Connection reset by peer
### Describe the bug

Occurrences:
6 September 2023: https://github.com/oppia/oppia/actions/runs/6098791669/job/16552295256#step:5:4924
log: 
```
Successfully installed astroid-2.15.6 beautifulsoup4-4.12.2 certifi-2022.12.7 cffi-1.15.1 charset-normalizer-3.2.0 coverage-7.2.3 cryptography-41.0.2 deprecated-1.2.14 dill-0.3.6 esprima-4.0.1 future-0.18.3 grpcio-1.54.0 idna-3.4 isort-5.12.0 lazy-object-proxy-1.9.0 mccabe-0.7.0 pillow-9.5.0 platformdirs-3.9.1 protobuf-3.13.0 psutil-5.9.5 pycodestyle-2.10.0 pycparser-2.21 pygithub-1.58.1 pyjwt-2.7.0 pylint-2.17.2 pylint-quotes-0.2.3 pynacl-1.5.0 pyyaml-6.0 rcssmin-1.1.1 requests-2.31.0 six-1.16.0 soupsieve-2.4.1 tomlkit-0.11.8 typing-extensions-4.5.0 urllib3-2.0.3 waitress-2.1.2 webob-1.8.7 webtest-3.0.0 wrapt-1.15.0 xmltodict-0.13.0

Notice:  A new release of pip is available: 23.1.2 -> 23.2.1
Notice:  To update, run: pip install --upgrade pip
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/runner/work/oppia/oppia/scripts/install_third_party_libs.py", line 249, in <module>
    main()
  File "/home/runner/work/oppia/oppia/scripts/install_third_party_libs.py", line 167, in main
    setup.main(args=[])
  File "/home/runner/work/oppia/oppia/scripts/setup.py", line 200, in main
    download_and_install_node()
  File "/home/runner/work/oppia/oppia/scripts/setup.py", line 152, in download_and_install_node
    download_and_install_package(
  File "/home/runner/work/oppia/oppia/scripts/setup.py", line 98, in download_and_install_package
    common.url_retrieve(url_to_retrieve, filename)
  File "/home/runner/work/oppia/oppia/scripts/common.py", line 882, in url_retrieve
    output_file.write(response.read())
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/http/client.py", line 472, in read
    s = self._safe_read(self.length)
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/http/client.py", line 613, in _safe_read
    data = self.fp.read(amt)
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/socket.py", line 669, in readinto
    return self._sock.recv_into(b)
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/ssl.py", line 1241, in recv_into
    return self.read(nbytes, buffer)
  File "/opt/hostedtoolcache/Python/3.8.15/x64/lib/python3.8/ssl.py", line 1099, in read
    return self._sslobj.read(len, buffer)
ConnectionResetError: [Errno 104] Connection reset by peer
Checking if node.js is installed in /home/runner/work/oppia/oppia/../oppia_tools
Installing Node.js
Error: Process completed with exit code 1.
```
### Tips for developers

Before tackling the bug, please use `git bisect` (see https://git-scm.com/docs/git-bisect) to investigate which PR caused it (you only need to go back as far as commit https://github.com/oppia/oppia/commits/9a334e9). If you find the PR, leave a comment on this issue pointing to it, or just say that it happened before commit 9a334e9 if you could reproduce it there. This will help us fix the issue by reverting the faulty PR.

Also, if this is your first issue, please make sure to follow https://github.com/oppia/oppia/wiki/Contributing-code-to-Oppia#choosing-a-good-first-issue and https://github.com/oppia/oppia/wiki/Contributing-code-to-Oppia#setting-things-up before claiming it. Thanks!



Discussion:
I think we can solve this by adding the ConnectionResetError to the list of errors we can rerun on:

https://github.com/oppia/oppia/blob/bac842bf82071784ee90a744cb273b33600cd68f/scripts/common.py#L876-L894

Resolving patch:
diff --git a/scripts/common.py b/scripts/common.py
--- a/scripts/common.py
+++ b/scripts/common.py
@@ -881,7 +881,8 @@ def url_retrieve(
                 with open(output_path, 'wb') as output_file:
                     output_file.write(response.read())
         except (
-            urlerror.URLError, ssl.SSLError, client.IncompleteRead
+            urlerror.URLError, ssl.SSLError,
+            client.IncompleteRead, ConnectionResetError
         ) as exception:
             failures += 1
             print('Attempt %d of %d failed when downloading %s.' % (


Test patch: