# 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

PYTHON_VERSION_COMPATIBILITY = 'PY2+3'

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/stable'
  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')
  repo = api.properties.get('git_repo')
  if _is_postsubmit(api):
    # gitiles commit info
    git_ref = api.buildbucket.gitiles_commit.id
  else:
    # github pull request info
    git_ref = 'master' # 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('pub get', cmd=['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(), stderr=api.raw_io.output_text())
    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(
            gerrit_host = 'flutter-review.googlesource.com',
            gerrit_project = 'infra',
            repo_dir = infra_path,
            commit_message = 'Roll %s to %s' % (repo, git_ref),
            cc_on_failure = ['flutter-infra@grotations.appspotmail.com'],
            labels_to_set = {'Commit-Queue': 2},
            bot_commit = True,
        )


def GenTests(api):
  yield api.test(
      'basic',
      api.buildbucket.ci_build(
          bucket='prod',
          git_repo='https://chromium.googlesource.com/external/github.com/flutter/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://chromium.googlesource.com/external/github.com/flutter/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://chromium.googlesource.com/external/github.com/flutter/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')
      ),
  )
