# Copyright 2019 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.

"""Recipe for updating flutter/infra with ci.yaml changes."""

from PB.go.chromium.org.luci.common.proto.gerrit import gerrit as gerrit_pb2

DEPS = [
    'flutter/repo_util',
    'fuchsia/auto_roller',
    'recipe_engine/buildbucket',
    'recipe_engine/cipd',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/step',
]


def _is_postsubmit(api):
  """Returns True if the current build is not in try, otherwise False."""
  return api.buildbucket.build.builder.bucket != 'try'


def _is_default_branch(branch):
  """Returns True if branch is master or main."""
  return branch in ("main", "master")


def RunSteps(api):
  """Steps to checkout infra, dependencies, and generate new config."""
  start_path = api.path['start_dir']
  cocoon_path = start_path.join('cocoon')
  flutter_path = start_path.join('flutter')
  infra_path = start_path.join('infra')

  # Checkout the stable version of Flutter.
  flutter_git_ref = 'refs/heads/master'
  api.repo_util.checkout('flutter', flutter_path, ref=flutter_git_ref)

  # Checkout latest version of flutter/cocoon.
  api.repo_util.checkout('cocoon', cocoon_path, ref='refs/heads/main')

  # Checkout latest version of flutter/infra
  api.repo_util.checkout('infra', infra_path, ref='refs/heads/main')

  # Install protoc to compile latest scheduler.proto
  protoc_path = start_path.join('protoc')
  api.cipd.ensure(
      protoc_path,
      api.cipd.EnsureFile().add_package(
          'infra/3pp/tools/protoc/${platform}', 'version:2@3.17.3'
      )
  )

  git_branch = api.properties.get('git_branch', 'main')
  repo = api.properties.get('git_repo')
  if _is_postsubmit(api):
    # Pulling from HEAD ensures out of order runs do not lead to inconsistencies.
    git_ref = git_branch
  else:
    # github pull request info
    git_ref = 'main'  # Default to master for LED runs
    for tag in api.buildbucket.build.tags:
      if 'sha/git/' in tag.value:
        git_ref = tag.value.replace('sha/git/', '')

  # The context adds dart-sdk tools to PATH and sets PUB_CACHE.
  env, env_prefixes = api.repo_util.flutter_environment(flutter_path)
  with api.context(env=env, env_prefixes=env_prefixes,
                   cwd=cocoon_path.join('app_dart')):
    api.step('flutter doctor', cmd=['flutter', 'doctor'])
    api.step('dart pub get', cmd=['dart', 'pub', 'get'])
    generate_jspb_path = cocoon_path.join(
        'app_dart', 'bin', 'generate_jspb.dart'
    )
    config_name = '%s_config.json' % repo
    if git_branch and not _is_default_branch(git_branch):
      config_name = '%s_%s_config.json' % (repo, git_branch)
    infra_config_path = infra_path.join(
        'config', 'generated', 'ci_yaml', config_name
    )
    # Generate_jspb
    jspb_step = api.step(
        'generate jspb',
        cmd=['dart', generate_jspb_path, repo, git_ref],
        stdout=api.raw_io.output_text(add_output_log=True),
        stderr=api.raw_io.output_text(add_output_log=True)
    )
    api.file.write_raw('write jspb', infra_config_path, jspb_step.stdout)

  # Roll scheduler.proto
  with api.context(env_prefixes={'PATH': [protoc_path.join('bin')]}):
    scheduler_proto_src = cocoon_path.join(
        'app_dart', 'lib', 'src', 'model', 'proto', 'internal',
        'scheduler.proto'
    )
    scheduler_proto_dst = infra_path.join('config', 'lib', 'ci_yaml')
    api.step(
        'Roll scheduler.proto',
        ['cp', scheduler_proto_src, scheduler_proto_dst]
    )
    api.step(
        'Compile scheduler.proto',
        ['bash', scheduler_proto_dst.join('compile_proto.sh')]
    )

  with api.context(cwd=infra_path):
    # Generate luci configs
    api.step('luci generate', cmd=['lucicfg', 'generate', 'config/main.star'])
    # Validate luci configs
    api.step('luci validate', cmd=['lucicfg', 'validate', 'config/main.star'])
    # Only send rolls on postsubmit
    if _is_postsubmit(api):
      api.auto_roller.attempt_roll(
          api.auto_roller.Options(
              remote='https://flutter.googlesource.com/infra',
              cc_on_failure_emails=['flutter-infra@grotations.appspotmail.com'],
              labels_to_set={'Commit-Queue': 2},
              bot_commit=True,
          ),
          repo_dir=infra_path,
          commit_message='Roll %s to %s' %
          (repo, api.buildbucket.gitiles_commit.id),
      )


def GenTests(api):
  yield api.test(
      'basic',
      api.buildbucket.ci_build(
          bucket='prod',
          git_repo='https://flutter.googlesource.com/mirrors/engine',
          revision='abc123'
      ), api.properties(git_branch='main', git_repo='engine'),
      api.repo_util.flutter_environment_data(
          api.path['start_dir'].join('flutter')
      ),
      api.step_data(
          'generate jspb', stdout=api.raw_io.output_text('{"hello": "world"}')
      ), api.auto_roller.success()
  )
  yield api.test(
      'release',
      api.buildbucket.ci_build(
          bucket='prod',
          git_repo='https://flutter.googlesource.com/mirrors/engine',
          revision='abc123'
      ), api.properties(git_branch='dev', git_repo='engine'),
      api.repo_util.flutter_environment_data(
          api.path['start_dir'].join('flutter')
      ),
      api.step_data(
          'generate jspb', stdout=api.raw_io.output_text('{"hello": "world"}')
      ), api.auto_roller.success()
  )
  yield api.test(
      'staging',
      api.buildbucket.ci_build(
          bucket='staging',
          git_repo='https://flutter.googlesource.com/mirrors/engine',
          revision='abc123'
      ), api.properties(git_branch='main', git_repo='engine'),
      api.repo_util.flutter_environment_data(
          api.path['start_dir'].join('flutter')
      ),
      api.step_data(
          'generate jspb', stdout=api.raw_io.output_text('{"hello": "world"}')
      ), api.auto_roller.success()
  )
  yield api.test(
      'presubmit',
      api.buildbucket.try_build(
          bucket='try',
          tags=api.buildbucket.tags(buildset=['sha/git/def123', 'sha/pr/1'])
      ),
      api.properties(git_repo='engine'),
      api.repo_util.flutter_environment_data(
          api.path['start_dir'].join('flutter')
      ),
  )
