def make_decision_task(params, root, symbol, arguments=[]): """Generate a basic decision task, based on the root .taskcluster.yml""" with open(os.path.join(root, '.taskcluster.yml'), 'rb') as f: taskcluster_yml = yaml.safe_load(f) push_info = find_hg_revision_push_info(params['repository_url'], params['head_rev']) slugids = {} def as_slugid(name): # https://github.com/taskcluster/json-e/issues/164 name = name[0] if name not in slugids: slugids[name] = slugid.nice() return slugids[name] # provide a similar JSON-e context to what mozilla-taskcluster provides: # https://docs.taskcluster.net/reference/integrations/mozilla-taskcluster/docs/taskcluster-yml # but with a different tasks_for and an extra `cron` section context = { 'tasks_for': 'cron', 'repository': { 'url': params['repository_url'], 'project': params['project'], 'level': params['level'], }, 'push': { 'revision': params['head_rev'], # remainder are fake values, but the decision task expects them anyway 'pushlog_id': push_info['pushid'], 'pushdate': push_info['pushdate'], 'owner': 'cron', 'comment': '', }, 'cron': { 'task_id': os.environ.get('TASK_ID', '<cron task id>'), 'job_name': params['job_name'], 'job_symbol': symbol, # args are shell-quoted since they are given to `bash -c` 'quoted_args': ' '.join(pipes.quote(a) for a in arguments), }, 'now': current_json_time(), 'as_slugid': as_slugid, } rendered = jsone.render(taskcluster_yml, context) if len(rendered['tasks']) != 1: raise Exception( "Expected .taskcluster.yml to only produce one cron task") task = rendered['tasks'][0] task_id = task.pop('taskId') return (task_id, task)
def release_promotion_action(parameters, graph_config, input, task_group_id, task_id): release_promotion_flavor = input['release_promotion_flavor'] promotion_config = graph_config['release-promotion']['flavors'][ release_promotion_flavor] release_history = {} product = promotion_config['product'] next_version = str(input.get('next_version') or '') if promotion_config.get('version-bump', False): # We force str() the input, hence the 'None' if next_version in ['', 'None']: raise Exception( "`next_version` property needs to be provided for `{}` " "target.".format(release_promotion_flavor)) if promotion_config.get('partial-updates', False): partial_updates = input.get('partial_updates', {}) if not partial_updates and release_level( parameters['project']) == 'production': raise Exception( "`partial_updates` property needs to be provided for `{}`" "target.".format(release_promotion_flavor)) balrog_prefix = product.title() os.environ['PARTIAL_UPDATES'] = json.dumps(partial_updates) release_history = populate_release_history( balrog_prefix, parameters['project'], partial_updates=partial_updates) target_tasks_method = promotion_config['target-tasks-method'].format( project=parameters['project']) rebuild_kinds = input.get('rebuild_kinds', promotion_config.get('rebuild-kinds', [])) do_not_optimize = input.get('do_not_optimize', promotion_config.get('do-not-optimize', [])) # make parameters read-write parameters = dict(parameters) # Build previous_graph_ids from ``previous_graph_ids``, ``pushlog_id``, # or ``revision``. previous_graph_ids = input.get('previous_graph_ids') if not previous_graph_ids: revision = input.get('revision') if not parameters['pushlog_id']: repo_param = '{}head_repository'.format( graph_config['project-repo-param-prefix']) push_info = find_hg_revision_push_info( repository=parameters[repo_param], revision=revision) parameters['pushlog_id'] = push_info['pushid'] previous_graph_ids = [find_decision_task(parameters, graph_config)] # Download parameters from the first decision task parameters = get_artifact(previous_graph_ids[0], "public/parameters.yml") # Download and combine full task graphs from each of the previous_graph_ids. # Sometimes previous relpro action tasks will add tasks, like partials, # that didn't exist in the first full_task_graph, so combining them is # important. The rightmost graph should take precedence in the case of # conflicts. combined_full_task_graph = {} for graph_id in previous_graph_ids: full_task_graph = get_artifact(graph_id, "public/full-task-graph.json") combined_full_task_graph.update(full_task_graph) _, combined_full_task_graph = TaskGraph.from_json(combined_full_task_graph) parameters['existing_tasks'] = find_existing_tasks_from_previous_kinds( combined_full_task_graph, previous_graph_ids, rebuild_kinds) parameters['do_not_optimize'] = do_not_optimize parameters['target_tasks_method'] = target_tasks_method parameters['build_number'] = int(input['build_number']) parameters['next_version'] = next_version parameters['release_history'] = release_history if promotion_config.get('is-rc'): parameters['release_type'] += '-rc' parameters['release_eta'] = input.get('release_eta', '') parameters['release_product'] = product # When doing staging releases on try, we still want to re-use tasks from # previous graphs. parameters['optimize_target_tasks'] = True # Partner/EMEfree are enabled by default when get_partner_url_config() returns a non-null url # The action input may override by sending False. It's an error to send True with no url found partner_url_config = get_partner_url_config(parameters, graph_config) release_enable_partners = partner_url_config[ 'release-partner-repack'] is not None release_enable_emefree = partner_url_config[ 'release-eme-free-repack'] is not None if input.get('release_enable_partners') is False: release_enable_partners = False elif input.get( 'release_enable_partners') is True and not release_enable_partners: raise Exception( "Can't enable partner repacks when no config url found") if input.get('release_enable_emefree') is False: release_enable_emefree = False elif input.get( 'release_enable_emefree') is True and not release_enable_emefree: raise Exception("Can't enable EMEfree when no config url found") parameters['release_enable_partners'] = release_enable_partners parameters['release_enable_emefree'] = release_enable_emefree partner_config = input.get('release_partner_config') if not partner_config and (release_enable_emefree or release_enable_partners): github_token = get_token(parameters) partner_config = get_partner_config(partner_url_config, github_token) if partner_config: parameters['release_partner_config'] = fix_partner_config( partner_config) parameters['release_partners'] = input.get('release_partners') if input.get('release_partner_build_number'): parameters['release_partner_build_number'] = input[ 'release_partner_build_number'] if input['version']: parameters['version'] = input['version'] parameters['required_signoffs'] = get_required_signoffs(input, parameters) parameters['signoff_urls'] = get_signoff_urls(input, parameters) # make parameters read-only parameters = Parameters(**parameters) taskgraph_decision({'root': graph_config.root_dir}, parameters=parameters)