# Buggy code
def do_yarn_install(
    target_path: str,
    yarn_args: List[str],
    success_stamp: str,
    stdout: Optional[IO[Any]] = None,
    stderr: Optional[IO[Any]] = None,
) -> None:
    os.makedirs(target_path, exist_ok=True)
    shutil.copy("package.json", target_path)
    shutil.copy("yarn.lock", target_path)
    shutil.copy(".yarnrc", target_path)
    cached_node_modules = os.path.join(target_path, "node_modules")
    print("Cached version not found! Installing node modules.")

    # Copy the existing node_modules to speed up install
    if os.path.exists("node_modules") and not os.path.exists(cached_node_modules):
        shutil.copytree("node_modules/", cached_node_modules, symlinks=True)
    if os.environ.get("CUSTOM_CA_CERTIFICATES"):
        run(
            [YARN_BIN, "config", "set", "cafile", os.environ["CUSTOM_CA_CERTIFICATES"]],
            stdout=stdout,
            stderr=stderr,
        )
    run(
        [YARN_BIN, "install", "--non-interactive", "--frozen-lockfile"] + yarn_args,
        cwd=target_path,
        stdout=stdout,
        stderr=stderr,
    )
    with open(success_stamp, "w"):
        pass


# Traceback (subprocess.CalledProcessError)
2020-04-17 21:23:41,590 upgrade-zulip-stage-2: Building static assets...
Cached version not found! Installing node modules.
+ /srv/zulip-yarn/bin/yarn install --non-interactive --frozen-lockfile --prod

Error running a subcommand of ./tools/update-prod-static: /srv/zulip-yarn/bin/yarn install --non-interactive --frozen-lockfile --prod
Actual error output for the subcommand is just above this.

Traceback (most recent call last):
File "./tools/update-prod-static", line 37, in <module>
setup_node_modules(production=True, stdout=fp, stderr=fp)
File "./tools/../scripts/lib/node_cache.py", line 66, in setup_node_modules
stderr=stderr)
File "./tools/../scripts/lib/node_cache.py", line 91, in do_yarn_install
cwd=target_path, stdout=stdout, stderr=stderr)
File "./tools/../scripts/lib/zulip_tools.py", line 200, in run
subprocess.check_call(args, **kwargs)
File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/srv/zulip-yarn/bin/yarn', 'install', '--non-interactive', '--frozen-lockfile', '--prod']' returned non-zero exit status 1
Traceback (most recent call last):
File "/home/zulip/deployments/2020-04-18-01-53-13/scripts/lib/upgrade-zulip-stage-2", line 122, in <module>
preexec_fn=su_to_zulip)
File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['./tools/update-prod-static', '--authors-not-required', '--prev-deploy', '/home/zulip/deployments/current']' returned non-zero exit status 1
Traceback (most recent call last):
File "/home/zulip/deployments/current/scripts/lib/upgrade-zulip-from-git", line 69, in <module>
deploy_path, "--from-git"] + deploy_options)
File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/home/zulip/deployments/2020-04-18-01-53-13/scripts/lib/upgrade-zulip-stage-2', '/home/zulip/deployments/2020-04-18-01-53-13', '--from-git']' returned non-zero exit status 1

# Fixed code
def do_yarn_install(target_path: str, yarn_args: List[str], success_stamp: str) -> None:
    os.makedirs(target_path, exist_ok=True)
    shutil.copy("package.json", target_path)
    shutil.copy("yarn.lock", target_path)
    shutil.copy(".yarnrc", target_path)
    cached_node_modules = os.path.join(target_path, "node_modules")
    print("Cached version not found! Installing node modules.")

    # Copy the existing node_modules to speed up install
    if os.path.exists("node_modules") and not os.path.exists(cached_node_modules):
        shutil.copytree("node_modules/", cached_node_modules, symlinks=True)
    if os.environ.get("CUSTOM_CA_CERTIFICATES"):
        run([YARN_BIN, "config", "set", "cafile", os.environ["CUSTOM_CA_CERTIFICATES"]])
    run(
        [YARN_BIN, "install", "--non-interactive", "--frozen-lockfile"] + yarn_args,
        cwd=target_path,
    )
    with open(success_stamp, "w"):
        pass