def abandon_release(name): session = flask.g.db.session try: release = session.query(Release).filter(Release.name == name).one() # Cancel all submitted task groups first for phase in filter(lambda x: x.submitted, release.phases): actions = fetch_actions_json(phase.task_id) hook = generate_action_hook( decision_task_id=phase.task_id, action_name='cancel-all', actions=actions, ) # some parameters contain a lot of entries, so we hit the payload # size limit. We don't use this parameter in any case, safe to # remove for long_param in ('existing_tasks', 'release_history', 'release_partner_config'): del hook['context']['parameters'][long_param] log.info('Cancel phase %s by hook %s', phase.name, hook) res = _hooks().triggerHook(hook['hook_group_id'], hook['hook_id'], hook['hook_payload']) log.debug('Done: %s', res) release.status = 'aborted' session.commit() return release.json except NoResultFound: flask.abort(404)
def abandon_release(name): session = current_app.db.session try: release = session.query(Release).filter(Release.name == name).one() # we must require scope which depends on product required_permission = f"{SCOPE_PREFIX}/abandon_release/{release.product}" if not current_user.has_permissions(required_permission): user_permissions = ", ".join(current_user.get_permissions()) abort( 401, f"required permission: {required_permission}, user permissions: {user_permissions}" ) # Cancel all submitted task groups first for phase in filter(lambda x: x.submitted and not x.skipped, release.phases): try: actions = fetch_artifact(phase.task_id, "public/actions.json") parameters = fetch_artifact(phase.task_id, "public/parameters.yml") except ArtifactNotFound: logger.info("Ignoring not completed action task %s", phase.task_id) continue hook = generate_action_hook(task_group_id=phase.task_id, action_name="cancel-all", actions=actions, parameters=parameters, input_={}) hooks = get_service("hooks") client_id = hooks.options["credentials"]["clientId"].decode( "utf-8") hook["context"]["clientId"] = client_id hook_payload_rendered = render_action_hook( payload=hook["hook_payload"], context=hook["context"], delete_params=[ "existing_tasks", "release_history", "release_partner_config" ]) logger.info("Cancel phase %s by hook %s with payload: %s", phase.name, hook["hook_id"], hook_payload_rendered) res = hooks.triggerHook(hook["hook_group_id"], hook["hook_id"], hook_payload_rendered) logger.debug("Done: %s", res) release.status = "aborted" session.commit() release_json = release.json except NoResultFound: abort(404) notify_via_irc( release.product, f"Release {release.product} {release.version} build{release.build_number} was just canceled." ) return release_json
def abandon_release(name): session = current_app.db.session try: release = session.query(Release).filter(Release.name == name).one() # we must require scope which depends on product required_permission = f'{SCOPE_PREFIX}/abandon_release/{release.product}' if not current_user.has_permissions(required_permission): user_permissions = ', '.join(current_user.get_permissions()) abort( 401, f'required permission: {required_permission}, user permissions: {user_permissions}' ) # Cancel all submitted task groups first for phase in filter(lambda x: x.submitted, release.phases): try: actions = fetch_actions_json(phase.task_id) except ActionsJsonNotFound: logger.info('Ignoring not completed action task %s', phase.task_id) continue hook = generate_action_hook( task_group_id=phase.task_id, action_name='cancel-all', actions=actions, input_={}, ) hooks = get_service('hooks') client_id = hooks.options['credentials']['clientId'].decode( 'utf-8') hook['context']['clientId'] = client_id hook_payload_rendered = render_action_hook( payload=hook['hook_payload'], context=hook['context'], delete_params=[ 'existing_tasks', 'release_history', 'release_partner_config' ], ) logger.info('Cancel phase %s by hook %s with payload: %s', phase.name, hook['hook_id'], hook_payload_rendered) res = hooks.triggerHook(hook['hook_group_id'], hook['hook_id'], hook_payload_rendered) logger.debug('Done: %s', res) release.status = 'aborted' session.commit() release_json = release.json except NoResultFound: abort(404) notify_via_irc( release.product, f'Release {release.product} {release.version} build{release.build_number} was just canceled.' ) return release_json
def generate_phases(self, partner_urls=None, github_token=None): phases = [] previous_graph_ids = [self.decision_task_id] next_version = bump_version(self.version.replace('esr', '')) input_common = { 'build_number': self.build_number, 'next_version': next_version, # specify version rather than relying on in-tree version, # so if a version bump happens between the build and an action task # revision, we still use the correct version. 'version': self.version, 'release_eta': self.release_eta } if not is_partner_enabled(self.product, self.version): input_common['release_enable_partners'] = False if not is_eme_free_enabled(self.product, self.version): input_common['release_enable_emefree'] = False if self.partial_updates: input_common['partial_updates'] = {} for partial_version, info in self.partial_updates.items(): input_common['partial_updates'][partial_version] = { 'buildNumber': info['buildNumber'], 'locales': info['locales'] } target_action = find_action('release-promotion', self.actions) kind = target_action['kind'] if kind != 'hook': raise ValueError(f'Unsupported kind: {kind}') for phase in self.release_promotion_flavors(): input_ = copy.deepcopy(input_common) input_['release_promotion_flavor'] = phase['name'] input_['previous_graph_ids'] = list(previous_graph_ids) hook = generate_action_hook( task_group_id=self.decision_task_id, action_name='release-promotion', actions=self.actions, parameters=self.parameters, input_=input_, ) hook_no_context = {k: v for k, v in hook.items() if k != 'context'} phase_obj = Phase( name=phase['name'], task_id='', task=json.dumps(hook_no_context), context=json.dumps(hook['context']), ) # we need to update input_['previous_graph_ids'] later, because # the task IDs cannot be set for hooks in advance if phase['in_previous_graph_ids']: previous_graph_ids.append(phase['name']) phase_obj.signoffs = self.phase_signoffs(self.branch, self.product, phase['name']) phases.append(phase_obj) self.phases = phases
def generate_phases(self, partner_urls=None, github_token=None): phases = [] previous_graph_ids = [self.decision_task_id] next_version = bump_version(self.version.replace("esr", "")) input_common = { "build_number": self.build_number, "next_version": next_version, # specify version rather than relying on in-tree version, # so if a version bump happens between the build and an action task # revision, we still use the correct version. "version": self.version, "release_eta": self.release_eta, } if not is_partner_enabled(self.product, self.version): input_common["release_enable_partners"] = False if not is_eme_free_enabled(self.product, self.version): input_common["release_enable_emefree"] = False if self.partial_updates: input_common["partial_updates"] = {} for partial_version, info in self.partial_updates.items(): input_common["partial_updates"][partial_version] = { "buildNumber": info["buildNumber"], "locales": info["locales"] } target_action = find_action("release-promotion", self.actions) kind = target_action["kind"] if kind != "hook": raise ValueError(f"Unsupported kind: {kind}") for phase in self.release_promotion_flavors(): input_ = copy.deepcopy(input_common) input_["release_promotion_flavor"] = phase["name"] input_["previous_graph_ids"] = list(previous_graph_ids) hook = generate_action_hook(task_group_id=self.decision_task_id, action_name="release-promotion", actions=self.actions, parameters=self.parameters, input_=input_) hook_no_context = {k: v for k, v in hook.items() if k != "context"} phase_obj = Phase(name=phase["name"], task_id="", task=json.dumps(hook_no_context), context=json.dumps(hook["context"])) # we need to update input_['previous_graph_ids'] later, because # the task IDs cannot be set for hooks in advance if phase["in_previous_graph_ids"]: previous_graph_ids.append(phase["name"]) phase_obj.signoffs = self.phase_signoffs(self.branch, self.product, phase["name"]) phases.append(phase_obj) self.phases = phases
def abandon_release(name): session = g.db.session try: r = session.query(Release).filter(Release.name == name).one() # Cancel all submitted task groups first for phase in filter(lambda x: x.submitted, r.phases): try: actions = fetch_actions_json(phase.task_id) except ActionsJsonNotFound: logger.info('Ignoring not completed action task %s', phase.task_id) continue hook = generate_action_hook( task_group_id=phase.task_id, action_name='cancel-all', actions=actions, input_={}, ) hooks = get_service('hooks') client_id = hooks.options['credentials']['clientId'].decode( 'utf-8') hook['context']['clientId'] = client_id hook_payload_rendered = render_action_hook( payload=hook['hook_payload'], context=hook['context'], delete_params=[ 'existing_tasks', 'release_history', 'release_partner_config' ], ) logger.info('Cancel phase %s by hook %s with payload: %s', phase.name, hook['hook_id'], hook_payload_rendered) res = hooks.triggerHook(hook['hook_group_id'], hook['hook_id'], hook_payload_rendered) logger.debug('Done: %s', res) r.status = 'aborted' session.commit() release = r.json except NoResultFound: abort(404) notify_via_irc( f'Release {r.product} {r.version} build{r.build_number} was just canceled.' ) return release
def abandon_release(name): session = g.db.session try: r = session.query(Release).filter(Release.name == name).one() # Cancel all submitted task groups first for phase in filter(lambda x: x.submitted, r.phases): try: actions = fetch_actions_json(phase.task_id) except ActionsJsonNotFound: logger.info('Ignoring not completed action task %s', phase.task_id) continue hook = generate_action_hook( decision_task_id=phase.task_id, action_name='cancel-all', actions=actions, ) # some parameters contain a lot of entries, so we hit the payload # size limit. We don't use this parameter in any case, safe to # remove for long_param in ('existing_tasks', 'release_history', 'release_partner_config'): del hook['context']['parameters'][long_param] logger.info('Cancel phase %s by hook %s', phase.name, hook) hooks = get_service('hooks') res = hooks.triggerHook(hook['hook_group_id'], hook['hook_id'], hook['hook_payload']) logger.debug('Done: %s', res) r.status = 'aborted' session.commit() release = r.json except NoResultFound: abort(404) notify_via_irc( f'Release {r.product} {r.version} build{r.build_number} was just canceled.' ) return release
def generate_phases(self): phases = [] previous_graph_ids = [self.decision_task_id] for phase in self.release_promotion_flavors(): input_ = copy.deepcopy(self.common_input) input_["release_promotion_flavor"] = phase["name"] input_["previous_graph_ids"] = list(previous_graph_ids) hook = generate_action_hook( task_group_id=self.decision_task_id, action_name="release-promotion", actions=self.actions, parameters=self.parameters, input_=input_ ) hook_no_context = {k: v for k, v in hook.items() if k != "context"} phase_obj = self.phase_class(name=phase["name"], task_id="", task=json.dumps(hook_no_context), context=json.dumps(hook["context"])) # we need to update input_['previous_graph_ids'] later, because # the task IDs cannot be set for hooks in advance if phase["in_previous_graph_ids"]: previous_graph_ids.append(phase["name"]) phase_obj.signoffs = self.phase_signoffs(phase["name"]) phases.append(phase_obj) self.phases = phases
def generate_phases(self, partner_urls=None, github_token=None): phases = [] previous_graph_ids = [self.decision_task_id] next_version = bump_version(self.version.replace('esr', '')) input_common = { 'build_number': self.build_number, 'next_version': next_version, # specify version rather than relying on in-tree version, # so if a version bump happens between the build and an action task # revision, we still use the correct version. 'version': self.version, 'release_eta': self.release_eta } if not is_partner_enabled(self.product, self.version): input_common['release_enable_partners'] = False if not is_eme_free_enabled(self.product, self.version): input_common['release_enable_emefree'] = False if self.partial_updates: input_common['partial_updates'] = {} for partial_version, info in self.partial_updates.items(): input_common['partial_updates'][partial_version] = { 'buildNumber': info['buildNumber'], 'locales': info['locales'] } target_action = find_action('release-promotion', self.actions) kind = target_action['kind'] for phase in self.release_promotion_flavors(): input_ = copy.deepcopy(input_common) input_['release_promotion_flavor'] = phase['name'] input_['previous_graph_ids'] = list(previous_graph_ids) if kind == 'task': action_task_id, action_task, context = generate_action_task( decision_task_id=self.decision_task_id, action_name='release-promotion', input_=input_, actions=self.actions, ) if phase['in_previous_graph_ids']: previous_graph_ids.append(action_task_id) phase_obj = Phase( phase['name'], action_task_id, json.dumps(action_task), json.dumps(context)) elif kind == 'hook': hook = generate_action_hook( task_group_id=self.decision_task_id, action_name='release-promotion', actions=self.actions, input_=input_, ) hook_no_context = {k: v for k, v in hook.items() if k != 'context'} phase_obj = Phase( name=phase['name'], task_id='', task=json.dumps(hook_no_context), context=json.dumps(hook['context']), ) # we need to update input_['previous_graph_ids'] later, because # the task IDs cannot be set for hooks in advance if phase['in_previous_graph_ids']: previous_graph_ids.append(phase['name']) else: raise ValueError(f'Unsupported kind: {kind}') phase_obj.signoffs = self.phase_signoffs(self.branch, self.product, phase['name']) phases.append(phase_obj) self.phases = phases