async def _check_final_state_of_release(existing_release, release_config): if _does_release_need_to_be_updated(existing_release, release_config): raise TaskError("Release still needs to be updated!") existing_artifacts = list(existing_release.assets()) for artifact in release_config["artifacts"]: existing_artifact = _get_existing_artifact(existing_artifacts, artifact) if await _does_existing_artifact_need_to_be_reuploaded(existing_artifact, artifact, retry_on_404=True): raise TaskError(f'Artifact "{artifact["name"]}" needs to be reuploaded')
async def async_main(config, task): prefix = extract_common_scope_prefix(config, task) project = get_github_project(task, prefix) projects = config["github_projects"].keys() if project in projects: project_config = config["github_projects"][project] else: project_config = {} for p in projects: if not p.endswith("*"): continue cleaned = p.rstrip("*") if project.startswith(cleaned): if project_config != {}: raise TaskError( f'project "{project}" matches multiple configs in "{projects}"' ) project_config = config["github_projects"][p] release_config = get_release_config(project_config, task["payload"], config) contact_github = bool(release_config.get("contact_github")) _warn_contact_github(contact_github) action = get_action(task, prefix) check_action_is_allowed(project_config, action) if action == "release": await release(release_config) else: raise NotImplementedError(f'Action "{action}" is not supported') log.info("Done!")
async def run_task(self): """Run the task, creating a task-specific log file.""" self.status = 0 username = self.config["notarization_username"] password = self.config["notarization_password"] await self.download_uuids() self.pending_uuids = list(self.uuids) while True: self.task_log("pending uuids: %s", self.pending_uuids) for uuid in sorted(self.pending_uuids): self.task_log("Polling %s", uuid) base_cmd = list(self.config["xcrun_cmd"]) + [ "altool", "--notarization-info", uuid, "-u", username, "--password" ] log_cmd = base_cmd + ["********"] rm(self.poll_log_path) status = await retry_async( run_command, args=[base_cmd + [password]], kwargs={ "log_path": self.poll_log_path, "log_cmd": log_cmd, "exception": RetryError }, retry_exceptions=(RetryError, ), attempts=10, ) with open(self.poll_log_path, "r") as fh: contents = fh.read() self.task_log("Polling response (status %d)", status, worker_log=False) for line in contents.splitlines(): self.task_log(" %s", line, worker_log=False) if status == STATUSES["success"]: m = NOTARIZATION_POLL_REGEX.search(contents) if m is not None: if m["status"] == "invalid": self.status = STATUSES["failure"] self.task_log("Apple believes UUID %s is invalid!", uuid, level=logging.CRITICAL) raise TaskError( "Apple believes UUID %s is invalid!" % uuid) # There are only two possible matches with the regex # Adding `pragma: no branch` to be explicit in our # checks, but still avoid testing an unreachable code # branch if m["status"] == "success": # pragma: no branch self.task_log("UUID %s is successful", uuid) self.pending_uuids.remove(uuid) if len(self.pending_uuids) == 0: self.task_log("All UUIDs are successfully notarized: %s", self.uuids) break else: await asyncio.sleep(self.config["poll_sleep_time"])
async def request_helper(): async with session.request(method, url, **kwargs) as resp: log.debug("Status {}".format(resp.status)) message = "Bad status {}".format(resp.status) if resp.status in retry_statuses: raise RetryError(message) if resp.status not in good: raise TaskError(message) if return_type == "text": return await resp.text() elif return_type == "json": return await resp.json() else: return resp
def makedirs(path): """Equivalent to mkdir -p. Args: path (str): the path to mkdir -p Raises: TaskError: if path exists already and the realpath is not a dir. """ if path: try: log.debug("makedirs({})".format(path)) realpath = os.path.realpath(path) os.makedirs(realpath, exist_ok=True) except OSError as e: raise TaskError("makedirs: error creating {}: {}".format(path, e)) from e
async def async_error(*args, **kwargs): exception = TaskError("async_error!") exception.exit_code = 42 raise exception
async def die_async(*args, **kwargs): raise TaskError("Expected exception.")
async def always_fail(*args, **kwargs): global retry_count retry_count.setdefault("always_fail", 0) retry_count["always_fail"] += 1 raise TaskError("fail")
async def fail_first(*args, **kwargs): global retry_count retry_count["fail_first"] += 1 if retry_count["fail_first"] < 2: raise TaskError("first") return "yay"