mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Bazel installer: Retry ripunzip step.
Ripunzip is great, but occasionally bugs out due to a parallelism issue. As we don't want this to fail CI, retry the entire ripunzip/installation step up to 3 times. We need to clean up the working directory as ripunzip doesn't support overwriting files. I've not been able to test this with the original issue (it doesn't seem to reproduce locally for me), but I injected another error and got 3 retries of installation.
This commit is contained in:
@@ -13,24 +13,41 @@ import shutil
|
||||
import subprocess
|
||||
import platform
|
||||
import time
|
||||
import sys
|
||||
from python.runfiles import runfiles
|
||||
|
||||
runfiles = runfiles.Create()
|
||||
assert runfiles, "Installer should be run with `bazel run`"
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--destdir", type=pathlib.Path, required=True,
|
||||
help="Desination directory, relative to `--build-file`")
|
||||
parser.add_argument("--pkg-install-script", required=True,
|
||||
help="The wrapped `pkg_install` installation script rlocation")
|
||||
parser.add_argument("--build-file",
|
||||
help="BUILD.bazel rlocation relative to which the installation should take place")
|
||||
parser.add_argument("--ripunzip",
|
||||
help="ripunzip executable rlocation. Must be provided if `--zip-manifest` is.")
|
||||
parser.add_argument("--zip-manifest",
|
||||
help="The rlocation of a file containing newline-separated `prefix:zip_file` entries")
|
||||
parser.add_argument("--cleanup", action=argparse.BooleanOptionalAction, default=True,
|
||||
help="Whether to wipe the destination directory before installing (true by default)")
|
||||
parser.add_argument(
|
||||
"--destdir",
|
||||
type=pathlib.Path,
|
||||
required=True,
|
||||
help="Desination directory, relative to `--build-file`",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pkg-install-script",
|
||||
required=True,
|
||||
help="The wrapped `pkg_install` installation script rlocation",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--build-file",
|
||||
help="BUILD.bazel rlocation relative to which the installation should take place",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ripunzip", help="ripunzip executable rlocation. Must be provided if `--zip-manifest` is."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--zip-manifest",
|
||||
help="The rlocation of a file containing newline-separated `prefix:zip_file` entries",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cleanup",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=True,
|
||||
help="Whether to wipe the destination directory before installing (true by default)",
|
||||
)
|
||||
opts = parser.parse_args()
|
||||
if opts.zip_manifest and not opts.ripunzip:
|
||||
parser.error("Provide `--ripunzip` when specifying `--zip-manifest`")
|
||||
@@ -45,13 +62,14 @@ script = runfiles.Rlocation(opts.pkg_install_script)
|
||||
|
||||
_WIN_FILE_IN_USE_ERROR_CODE = 32
|
||||
|
||||
if destdir.exists() and opts.cleanup:
|
||||
if platform.system() == 'Windows':
|
||||
|
||||
def rmdir(dir: pathlib.Path):
|
||||
if platform.system() == "Windows":
|
||||
# On Windows we might have virus scanner still looking at the path so
|
||||
# attempt removal a couple of times sleeping between each attempt.
|
||||
for retry_delay in [1, 2, 2]:
|
||||
try:
|
||||
shutil.rmtree(destdir)
|
||||
shutil.rmtree(dir)
|
||||
break
|
||||
except OSError as e:
|
||||
if e.winerror == _WIN_FILE_IN_USE_ERROR_CODE:
|
||||
@@ -59,21 +77,41 @@ if destdir.exists() and opts.cleanup:
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
shutil.rmtree(destdir)
|
||||
shutil.rmtree(dir)
|
||||
else:
|
||||
shutil.rmtree(destdir)
|
||||
shutil.rmtree(dir)
|
||||
|
||||
destdir.mkdir(parents=True, exist_ok=True)
|
||||
subprocess.run([script, "--destdir", destdir], check=True)
|
||||
|
||||
if opts.zip_manifest:
|
||||
ripunzip = runfiles.Rlocation(opts.ripunzip)
|
||||
zip_manifest = runfiles.Rlocation(opts.zip_manifest)
|
||||
with open(zip_manifest) as manifest:
|
||||
for line in manifest:
|
||||
prefix, _, zip = line.partition(":")
|
||||
assert zip, f"missing prefix for {prefix}, you should use prefix:zip format"
|
||||
zip = zip.strip()
|
||||
dest = destdir / prefix
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
subprocess.run([ripunzip, "unzip-file", zip, "-d", dest], check=True)
|
||||
if destdir.exists() and opts.cleanup:
|
||||
rmdir(destdir)
|
||||
|
||||
class RetryException(Exception):
|
||||
pass
|
||||
|
||||
attempts = 0
|
||||
success = False
|
||||
while attempts < 3 and success is False:
|
||||
destdir.mkdir(parents=True, exist_ok=True)
|
||||
subprocess.run([script, "--destdir", destdir], check=True)
|
||||
|
||||
if opts.zip_manifest:
|
||||
ripunzip = runfiles.Rlocation(opts.ripunzip)
|
||||
zip_manifest = runfiles.Rlocation(opts.zip_manifest)
|
||||
with open(zip_manifest) as manifest:
|
||||
for line in manifest:
|
||||
prefix, _, zip = line.partition(":")
|
||||
assert zip, f"missing prefix for {prefix}, you should use prefix:zip format"
|
||||
zip = zip.strip()
|
||||
dest = destdir / prefix
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
command = [ripunzip, "unzip-file", zip, "-d", dest]
|
||||
print(f"Running ", *command)
|
||||
ret = subprocess.run(command)
|
||||
success = ret.returncode == 0
|
||||
if not success:
|
||||
print(f"Failed to unzip {zip} to {dest}, retrying installation...")
|
||||
attempts += 1
|
||||
rmdir(destdir)
|
||||
break
|
||||
|
||||
sys.exit(ret.returncode)
|
||||
|
||||
Reference in New Issue
Block a user