# Copyright 2020 The Dart Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A recipe that processes go/dart-cbuild results.

The cbuild uploads files to a GCS bucket (one per SDK commit). This recipe reads
those files and starts a synthethic build of the "google" builder with the same
outcome as the cbuild and a link to the cbuild results. Then it comments on the
gerrit change for the commit, if any. Finally, the result is deleted from the
GCS bucket so that it won't be processed again by the next run.
"""

import re

from google.protobuf import json_format
from recipe_engine import post_process

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
from PB.recipes.dart.dart.external_build import ExternalBuild

DEPS = [
    'depot_tools/gitiles',
    'depot_tools/gsutil',
    'fuchsia/gerrit',
    'recipe_engine/buildbucket',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/runtime',
    'recipe_engine/step',
]
BUILDER = 'google'
BUCKET = 'ci.sandbox'
CBUILD_BUCKET_URL = 'gs://dart-cbuild-test-results'
CBUILD_RESULT_URL = 'https://goto.google.com/dart-cbuild/find/%s'
CBUILD_MESSAGE = '''go/dart-cbuild result: %s

Details: %s
'''
HOST = 'dart.googlesource.com'
GERRIT_HOST_URL = 'dart-review.googlesource.com'
REF = 'refs/heads/master'
REPO = 'sdk'
REPO_URL = 'https://%s/%s' % (HOST, REPO)


def RunSteps(api):
  results = _find_cbuild_results(api)
  requests = []
  if not results:
    # Nothing to do
    return
  for result in results:
    requests.append(_create_schedule_build_request(api, result))
  api.buildbucket.schedule(requests)
  with api.step.defer_results():
    for result in results:
      commit_hash = result['commit_hash']
      change_id = _get_change_id(api, commit_hash)
      if not api.runtime.is_experimental and change_id:
        message = CBUILD_MESSAGE % (common_pb2.Status.Name(
            result['cbuild_result']), result['cbuild_url'])
        api.gerrit.set_review(
            'update gerrit for %s' % commit_hash,
            change_id,
            host=GERRIT_HOST_URL,
            message=message,
        )
      if not api.runtime.is_experimental:
        api.gsutil.remove_url(
            result['result_url'], name='delete result for %s' % commit_hash)


def _find_cbuild_results(api):
  listing = api.gsutil.list(
      CBUILD_BUCKET_URL, name='find cbuild results', stdout=api.raw_io.output())

  results = []
  result_urls = listing.stdout.splitlines()[:50]  # limit to 50 results per run
  for result_url in result_urls:
    if result_url.endswith('/'):
      # ignore subdirectories
      continue
    _, commit_hash = result_url.rsplit('/', 1)
    download = api.gsutil.download_url(
        result_url,
        api.raw_io.output_text(name='result', add_output_log=True),
        name='download cbuild result for %s' % commit_hash)
    cbuild_result_text = download.raw_io.output_texts.get('result').strip()
    assert cbuild_result_text in ('true', 'false'), 'Unexpected cbuild result'
    cbuild_success = cbuild_result_text == 'true'
    cbuild_result = common_pb2.SUCCESS if cbuild_success else common_pb2.FAILURE
    results.append({
        'result_url': result_url,
        'commit_hash': commit_hash,
        'cbuild_result': cbuild_result,
        'cbuild_url': CBUILD_RESULT_URL % commit_hash,
    })
  return results


def _create_schedule_build_request(api, result):
  return api.buildbucket.schedule_request(
      builder=BUILDER,
      bucket=BUCKET,
      properties=json_format.MessageToDict(
          ExternalBuild(
              result=result['cbuild_result'], url=result['cbuild_url'])),
      gitiles_commit=common_pb2.GitilesCommit(
          host=HOST,
          project=REPO,
          ref=REF,
          id=result['commit_hash'],
      ),
      inherit_buildsets=False,
  )


def _get_change_id(api, commit_hash):
  result = api.gitiles.commit_log(
      commit=commit_hash,
      step_name='download change-id for %s' % commit_hash,
      url=REPO_URL,
  )
  commit = result.get_result()
  match = re.search(r'^Change-Id: (.*)$', commit['message'], re.MULTILINE)
  change_id = match.group(1) if match else None
  return change_id


def GenTests(api):
  yield api.test(
      'no-results',
      api.post_process(post_process.DoesNotRunRE,
                       '.*(delete|download|schedule).*'),
      api.post_process(post_process.StatusSuccess),
      api.post_process(post_process.DropExpectation),
  )

  def _cbuild_results(commit_hash, cbuild_result):
    return sum([
        api.step_data('gsutil download cbuild result for %s' % commit_hash,
                      api.raw_io.output_text(cbuild_result, name='result')),
        api.step_data(
            'download change-id for %s' % commit_hash,
            api.gitiles.make_commit_test_data(
                commit_hash, 'Subject\n\nChange-Id: I%s\n' % commit_hash))
    ], api.empty_test_data())

  CBUILD_RESULT_URLS = '''gs://dart-cbuild-test-results/hash-of-success
gs://dart-cbuild-test-results/ignore-this-directory/
gs://dart-cbuild-test-results/hash-of-failure
'''
  yield api.test(
      'with-results',
      api.step_data(
          'gsutil find cbuild results',
          stdout=api.raw_io.output(CBUILD_RESULT_URLS)),
      _cbuild_results('hash-of-success', 'true'),
      _cbuild_results('hash-of-failure', 'false'),
      api.post_process(post_process.MustRun,
                       'update gerrit for hash-of-success'),
      api.post_process(post_process.MustRun,
                       'update gerrit for hash-of-failure'),
      api.post_process(post_process.MustRun,
                       'gsutil delete result for hash-of-success'),
      api.post_process(post_process.MustRun,
                       'gsutil delete result for hash-of-failure'),
      api.post_process(post_process.StatusSuccess),
  )

  yield api.test(
      'experimental-with-results',
      api.runtime(is_experimental=True),
      api.step_data(
          'gsutil find cbuild results',
          stdout=api.raw_io.output(CBUILD_RESULT_URLS)),
      _cbuild_results('hash-of-success', 'true'),
      _cbuild_results('hash-of-failure', 'false'),
      api.post_process(post_process.DoesNotRunRE, '.*(delete|update).*'),
      api.post_process(post_process.StatusSuccess),
  )

  yield api.test(
      'no-change-id',
      api.step_data(
          'gsutil find cbuild results',
          stdout=api.raw_io.output('gs://dart-cbuild-test-results/hash')),
      api.step_data('gsutil download cbuild result for hash',
                    api.raw_io.output_text('false', name='result')),
      api.step_data('download change-id for hash',
                    api.gitiles.make_commit_test_data('hash', 'Subject\n')),
      api.post_process(post_process.DoesNotRunRE, '.*update gerrit.*'),
      api.post_process(post_process.MustRun, 'gsutil delete result for hash'),
      api.post_process(post_process.StatusSuccess),
      api.post_process(post_process.DropExpectation),
  )
