def task_action_types(task, script_config): """Extract task actions as scope definitions. Args: task (dict): the task definition. script_config (dict): the script configuration Raises: TaskVerificationError: if the number of cert scopes is not 1. Returns: str: the cert type. """ actions = [ s.split(":")[-1] for s in task["scopes"] if s.startswith(script_config["taskcluster_scope_prefix"] + "action:") ] log.info("Action requests: %s", actions) if len(actions) < 1: raise TaskVerificationError( "Need at least one valid action specified in scopes") invalid_actions = set(actions) - set(VALID_ACTIONS) if len(invalid_actions) > 0: raise TaskVerificationError( "Task specified invalid actions: {}".format(invalid_actions)) return _sort_actions(actions)
def get_source_repo(task): """Get the source repo from the task metadata. Assumes task['metadata']['source'] exists and is a link to a mercurial file on hg.mozilla.org (over https) Args: task: the task definition. Returns: str: url, including https scheme, to mercurial repository of the source repo. Raises: TaskVerificationError: on unexpected input. """ source = task.get("metadata", {}).get("source", None) if not source: raise TaskVerificationError("No source, how did that happen") if not source.startswith("https://hg.mozilla.org/"): raise TaskVerificationError( "Unable to operate on sources not in hg.mozilla.org") parts = source.split('/file/') if len(parts) < 2: raise TaskVerificationError("Soure url is in unexpected format") return parts[0]
def task_action_types(task): """Extract task actions as scope definitions. Args: task (dict): the task definition. Raises: TaskVerificationError: if the number of cert scopes is not 1. Returns: str: the cert type. """ valid_action_scopes = tuple( "project:releng:treescript:action:{}".format(action) for action in VALID_ACTIONS) actions = tuple(s for s in task["scopes"] if s.startswith("project:releng:treescript:action:")) log.info("Action requests: %s", actions) if len(actions) < 1: raise TaskVerificationError( "Need at least one valid action specified in scopes") invalid_actions = set(actions) - set(valid_action_scopes) if len(invalid_actions) > 0: raise TaskVerificationError( "Task specified invalid actions: {}".format(invalid_actions)) return actions
async def bump_version(context): """Perform a version bump. This function takes its inputs from context.task by using the ``get_version_bump_info`` function from treescript.task. Using `next_version` and `files`. This function does nothing (but logs) if the current version and next version match, and nothing if the next_version is actually less than current_version. raises: TaskverificationError: if a file specified is not allowed, or if the file is not in the target repository. """ bump_info = get_version_bump_info(context.task) next_version = bump_info['next_version'] old_next_version = None files = bump_info['files'] changed = False for file in files: if old_next_version: next_version = old_next_version abs_file = os.path.join(context.repo, file) if file not in ALLOWED_BUMP_FILES: raise TaskVerificationError( "Specified file to version bump is not in whitelist") if not os.path.exists(abs_file): raise TaskVerificationError("Specified file is not in repo") curr_version = _get_version(abs_file) Comparator = StrictVersion if curr_version.endswith('esr') or next_version.endswith('esr'): # We use LooseVersion for ESR because StrictVersion can't parse the trailing # 'esr', but StrictVersion otherwise because it can sort X.0bN lower than X.0 Comparator = LooseVersion if Comparator(next_version) < Comparator(curr_version): log.warning("Version bumping skipped due to conflicting values: " "(next version {} is < current version {})".format( next_version, curr_version)) continue elif Comparator(next_version) == Comparator(curr_version): log.info("Version bumping skipped due to unchanged values") continue else: changed = True if curr_version.endswith('esr'): # Only support esr addition if already an esr string. if not next_version.endswith('esr'): old_next_version = next_version next_version = next_version + 'esr' replace_ver_in_file(file=abs_file, curr_version=curr_version, new_version=next_version) if changed: commit_msg = 'Automatic version bump CLOSED TREE NO BUG a=release' await run_hg_command(context, 'commit', '-m', commit_msg, local_repo=context.repo)
def task_action_types(config, task): """Extract task actions as scope definitions. Args: config (dict): the running config. task (dict): the task definition. Raises: TaskVerificationError: if the number of cert scopes is not 1. Returns: str: the cert type. """ if task.get("payload", {}).get("actions"): actions = task["payload"]["actions"] else: log.warning( "Scopes-based actions are deprecated! Use task.payload.actions instead." ) actions = [ s.split(":")[-1] for s in task["scopes"] if s.startswith(config["taskcluster_scope_prefix"] + "action:") ] if len(actions) < 1: raise TaskVerificationError( "Need at least one valid action specified in scopes") log.info("Action requests: %s", actions) invalid_actions = set(actions) - set(VALID_ACTIONS) if len(invalid_actions) > 0: raise TaskVerificationError( "Task specified invalid actions: {}".format(invalid_actions)) return _sort_actions(actions)
async def bump_version(context): """Perform a version bump. This function takes its inputs from context.task by using the ``get_version_bump_info`` function from treescript.task. Using `next_version` and `files`. This function does nothing (but logs) if the current version and next version match, and nothing if the next_version is actually less than current_version. raises: TaskverificationError: if a file specified is not allowed, or if the file is not in the target repository. """ bump_info = get_version_bump_info(context.task) next_version = bump_info['next_version'] files = bump_info['files'] changed = False for file in files: abs_file = os.path.join(context.repo, file) if file not in ALLOWED_BUMP_FILES: raise TaskVerificationError( "Specified file to version bump is not in whitelist") if not os.path.exists(abs_file): raise TaskVerificationError("Specified file is not in repo") curr_version = _get_version(abs_file) if StrictVersion(next_version) < StrictVersion(curr_version): log.warning("Version bumping skipped due to conflicting values: " "(next version {} is < current version {})".format( next_version, curr_version)) continue elif StrictVersion(next_version) == StrictVersion(curr_version): log.info("Version bumping skipped due to unchanged values") continue else: changed = True replace_ver_in_file(file=abs_file, curr_version=curr_version, new_version=next_version) if changed: commit_msg = 'Automatic version bump CLOSED TREE NO BUG a=release' await run_hg_command(context, 'commit', '-m', commit_msg, local_repo=context.repo)
def get_version_bump_info(task): """Get the version bump information from the task metadata. Args: task: the task definition. Returns: object: the tag info structure as passed to the task payload. Raises: TaskVerificationError: If run without tag_info in task definition. """ version_info = task.get("payload", {}).get("version_bump_info") if not version_info: raise TaskVerificationError( "Requested version bump but no version_bump_info in payload") return version_info
def get_l10n_bump_info(task, raise_on_empty=True): """Get the l10n bump information from the task metadata. Args: task: the task definition. Returns: object: the tag info structure as passed to the task payload. Raises: TaskVerificationError: If run without tag_info in task definition. """ l10n_bump_info = task.get("payload", {}).get("l10n_bump_info") if not l10n_bump_info and raise_on_empty: raise TaskVerificationError( "Requested l10n bump but no l10n_bump_info in payload") return l10n_bump_info
def get_tag_info(task): """Get the tag information from the task metadata. Assumes task['payload']['tag_info'] exists and is in the proper format. Args: task: the task definition. Returns: object: the tag info structure as passed to the task payload. Raises: TaskVerificationError: If run without tag_info in task definition. """ tag_info = task.get("payload", {}).get("tag_info") if not tag_info: raise TaskVerificationError( "Requested tagging but no tag_info in payload") return tag_info
def get_merge_config(task): """Get the payload's merge day configuration. Args: task (dict): the running task Returns: dict: The merge configuration. Raises: TaskVerificationError: on missing configuration. Invalid config is handled by the schema, which doesn't currently match up actions and required payload subsections. """ try: return task.get("payload", {})["merge_info"] except KeyError: raise TaskVerificationError( "Requested merge action with missing merge configuration.")
def task_action_types(config, task): """Extract task actions from task payload. Args: config (dict): the running config. task (dict): the task definition. Raises: TaskVerificationError: if unknown actions are specified. Returns: set: the set of specified actions """ actions = set(task["payload"].get("actions", [])) log.info("Action requests: %s", actions) invalid_actions = actions - VALID_ACTIONS if len(invalid_actions) > 0: raise TaskVerificationError( "Task specified invalid actions: {}".format(invalid_actions)) return actions
async def bump_version(context): """Perform a version bump. This function takes its inputs from context.task by using the ``get_version_bump_info`` function from treescript.task. Using `next_version` and `files`. This function does nothing (but logs) if the current version and next version match, and nothing if the next_version is actually less than current_version. raises: TaskverificationError: if a file specified is not allowed, or if the file is not in the target repository. """ bump_info = get_version_bump_info(context.task) files = bump_info['files'] changed = False for file in files: abs_file = os.path.join(context.repo, file) if file not in ALLOWED_BUMP_FILES: raise TaskVerificationError( "Specified file to version bump is not in whitelist") if not os.path.exists(abs_file): raise TaskVerificationError("Specified file is not in repo") VersionClass = _find_what_version_parser_to_use(file) curr_version = VersionClass.parse(_get_version(abs_file)) next_version = VersionClass.parse(bump_info['next_version']) # XXX In the case of ESR, some files (like version.txt) show version numbers without `esr` # at the end. next_version is usually provided without `esr` too. # That's why we do this late minute replacement and why we reset `next_version` at every # cycle of the loop if curr_version.is_esr and not any(( next_version.is_esr, # No need to append esr again # We don't want XX.Ya1esr nor XX.YbNesr next_version.is_aurora_or_devedition, next_version.is_beta, )): next_version = VersionClass.parse('{}esr'.format( bump_info['next_version'])) if next_version < curr_version: log.warning("Version bumping skipped due to conflicting values: " "(next version {} is < current version {})".format( next_version, curr_version)) continue elif next_version == curr_version: log.info("Version bumping skipped due to unchanged values") continue else: changed = True replace_ver_in_file(abs_file, curr_version, next_version) if changed: dontbuild = get_dontbuild(context.task) commit_msg = 'Automatic version bump CLOSED TREE NO BUG a=release' if dontbuild: commit_msg += DONTBUILD_MSG await run_hg_command(context, 'commit', '-m', commit_msg, local_repo=context.repo)
async def do_bump_version(config, repo_path, files, next_version): """Perform a version bump. This function takes its inputs from task by using the ``get_version_bump_info`` function from treescript.task. Using `next_version` and `files`. This function does nothing (but logs) if the current version and next version match, and nothing if the next_version is actually less than current_version. Args: config (dict): the running config task (dict): the running task repo_path (str): the source directory Raises: TaskverificationError: if a file specified is not allowed, or if the file is not in the target repository. Returns: int: the number of commits created. """ changed = False saved_next_version = next_version for file_ in files: abs_file = os.path.join(repo_path, file_) if file_ not in ALLOWED_BUMP_FILES: raise TaskVerificationError("{} is not in version bump whitelist".format(file_)) if not os.path.exists(abs_file): raise TaskVerificationError("{} is not in repo".format(abs_file)) VersionClass = _find_what_version_parser_to_use(file_) curr_version = get_version(file_, repo_path) next_version = VersionClass.parse(saved_next_version) try: is_esr = curr_version.is_esr except AttributeError: # Fenix does not expose the is_esr attribute is_esr = False # XXX In the case of ESR, some files (like version.txt) show version numbers without `esr` # at the end. next_version is usually provided without `esr` too. # That's why we do this late minute replacement and why we reset `next_version` at every # cycle of the loop if is_esr and not any( ( next_version.is_esr, # No need to append esr again # We don't want XX.Ya1esr nor XX.YbNesr next_version.is_aurora_or_devedition, next_version.is_beta, ) ): next_version = VersionClass.parse("{}esr".format(next_version)) if next_version < curr_version: log.warning("Version bumping skipped due to conflicting values: " "(next version {} is < current version {})".format(next_version, curr_version)) continue elif next_version == curr_version: log.info("Version bumping skipped due to unchanged values") continue else: changed = True replace_ver_in_file(abs_file, curr_version, next_version) return changed
async def bump_version(config, task, repo_path): """Perform a version bump. This function takes its inputs from task by using the ``get_version_bump_info`` function from treescript.task. Using `next_version` and `files`. This function does nothing (but logs) if the current version and next version match, and nothing if the next_version is actually less than current_version. Args: config (dict): the running config task (dict): the running task repo_path (str): the source directory Raises: TaskverificationError: if a file specified is not allowed, or if the file is not in the target repository. Returns: int: the number of commits created. """ bump_info = get_version_bump_info(task) files = bump_info["files"] changed = False num_commits = 0 for file_ in files: abs_file = os.path.join(repo_path, file_) if file_ not in ALLOWED_BUMP_FILES: raise TaskVerificationError( "{} is not in version bump whitelist".format(file_)) if not os.path.exists(abs_file): raise TaskVerificationError("{} is not in repo".format(abs_file)) VersionClass = _find_what_version_parser_to_use(file_) curr_version = get_version(file_, repo_path) next_version = VersionClass.parse(bump_info["next_version"]) # XXX In the case of ESR, some files (like version.txt) show version numbers without `esr` # at the end. next_version is usually provided without `esr` too. # That's why we do this late minute replacement and why we reset `next_version` at every # cycle of the loop if curr_version.is_esr and not any(( next_version.is_esr, # No need to append esr again # We don't want XX.Ya1esr nor XX.YbNesr next_version.is_aurora_or_devedition, next_version.is_beta, )): next_version = VersionClass.parse("{}esr".format( bump_info["next_version"])) if next_version < curr_version: log.warning("Version bumping skipped due to conflicting values: " "(next version {} is < current version {})".format( next_version, curr_version)) continue elif next_version == curr_version: log.info("Version bumping skipped due to unchanged values") continue else: changed = True replace_ver_in_file(abs_file, curr_version, next_version) if changed: dontbuild = get_dontbuild(task) commit_msg = "Automatic version bump CLOSED TREE NO BUG a=release" if dontbuild: commit_msg += DONTBUILD_MSG await run_hg_command(config, "commit", "-m", commit_msg, repo_path=repo_path) num_commits += 1 return num_commits