# Copyright 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Orchestrator recipe that runs subbuilds required to release engine.
#
# This recipe reads <engine_checkout>/.ci_yaml, and for every target
# marked with release_build: true, and spawens a subbuild.

import json
from contextlib import contextmanager

from PB.recipes.flutter.release.release import InputProperties
from PB.recipes.flutter.release.release import EnvProperties

from RECIPE_MODULES.flutter.repo_util.api import REPOS

from google.protobuf import struct_pb2

DEPS = [
    'flutter/yaml',
    'flutter/display_util',
    'flutter/repo_util',
    'flutter/shard_util_v2',
    'recipe_engine/buildbucket',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties
ENV_PROPERTIES = EnvProperties

RELEASE_CHANNELS = ('refs/heads/beta', 'refs/heads/stable')


def ShouldRun(api, git_ref, target):
  """Validates if a target should run based on platform, channel and repo."""
  release_build = target.get('properties', {}).get('release_build', False)
  for_this_platform = target['name'].lower().startswith(api.platform.name)
  # Postsubmit for engine and flutter repositories.
  if (release_build and for_this_platform and
      (git_ref not in RELEASE_CHANNELS)):
    return True
  # Packaging for the flutter repository.
  if (target.get('scheduler') == 'release' and for_this_platform and
      (git_ref in RELEASE_CHANNELS) and
      git_ref.replace('refs/heads/', '') in target.get('enabled_branches', [])):
    return True
  return False


def RunSteps(api, properties, env_properties):
  repository = api.properties.get(
      'git_repo'
  ) or api.buildbucket.gitiles_commit.project
  repository_parts = repository.split('/')
  checkout_path = api.path['start_dir'].join(*repository_parts)
  git_ref = api.properties.get('git_ref') or api.buildbucket.gitiles_commit.ref
  git_url = api.properties.get('git_url') or REPOS[repository]
  api.repo_util.checkout(
      repository, checkout_path=checkout_path, url=git_url, ref=git_ref
  )

  ci_yaml_path = checkout_path.join('.ci.yaml')
  ci_yaml = api.yaml.read('read ci yaml', ci_yaml_path, api.json.output())

  # Get release branch.
  branches = api.repo_util.current_commit_branches(checkout_path)
  branches = [b for b in branches if b.startswith('flutter')]
  release_branch = branches[0] if branches else 'main'

  # Foreach target defined in .ci.yaml, if it contains
  # release_build: True, then spawn a subbuild.
  tasks = {}
  build_results = []
  with api.step.nest('launch builds') as presentation:
    for target in ci_yaml.json.output['targets']:
      if ShouldRun(api, git_ref, target):
        target = api.shard_util_v2.pre_process_properties(target)
        tasks.update(
            api.shard_util_v2.schedule([
                target,
            ],
                                       presentation,
                                       branch=release_branch)
        )
  with api.step.nest('collect builds') as presentation:
    build_results = api.shard_util_v2.collect(tasks)

  api.display_util.display_subbuilds(
      step_name='display builds',
      subbuilds=build_results,
      raise_on_failure=True,
  )


def GenTests(api):
  try_subbuild1 = api.shard_util_v2.try_build_message(
      build_id=8945511751514863186,
      builder="builder-subbuild1",
      output_props={"test_orchestration_inputs_hash": "abc"},
      status="SUCCESS",
  )
  tasks_dict = {
      'targets': [{
          'name': 'linux one', 'recipe': 'engine/something', 'properties': {
              'release_build': True,
              '$flutter/osx_sdk': '{"sdk_version": "14a5294e"}'
          }, 'drone_dimensions': ['os=Linux']
      }, {
          'name': 'linux packaging one', 'recipe': 'release/something',
          'scheduler': 'release',
          'properties': {'$flutter/osx_sdk': '{"sdk_version": "14a5294e"}'},
          'enabled_branches': ['beta',
                               'main'], 'drone_dimensions': ['os=Linux']
      }]
  }
  for git_ref in ['main', 'beta']:
    yield api.test(
        'basic_linux_%s' % git_ref, api.platform.name('linux'),
        api.properties(environment='Staging', repository='engine'),
        api.buildbucket.try_build(
            project='prod',
            builder='try-builder',
            git_repo='https://flutter.googlesource.com/mirrors/engine',
            revision='a' * 40,
            build_number=123,
            git_ref='refs/heads/%s' % git_ref,
        ),
        api.shard_util_v2.child_build_steps(
            subbuilds=[try_subbuild1],
            launch_step="launch builds.schedule",
            collect_step="collect builds",
        ), api.step_data('read ci yaml.parse', api.json.output(tasks_dict))
    )
