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

import re
from recipe_engine import post_process

DEPS = [
    'flutter/flutter_deps',
    'flutter/kms',
    'flutter/repo_util',
    'fuchsia/git',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/runtime',
    'recipe_engine/step',
]

stableTagRegex = r'^(\d+)\.(\d+)\.(\d+)$'
betaTagRegex = r'^(\d+)\.(\d+)\.(\d+)-(\d+)\.(\d+)\.pre$'

def isValidTag(tag):
  stable = re.search(stableTagRegex, tag)
  development = re.search(betaTagRegex, tag)
  return stable or development

"""
This recipe executes the tag and publishing stages of a flutter release.
To trigger this recipe, tool proxy must be invoked with multi-party approval.
Tool proxy information can be found at go/tool-proxy.
Because of this configuration, the recipe is triggered manually during the
release process.

It is expected that a valid release git branch, tag, and release_channel are passed
to the recipe.

The recipe will tag and push to github unless triggered
from an experimental run.
"""
def RunSteps(api):
  git_branch = api.properties.get('git_branch')
  tag = api.properties.get('tag')
  release_channel = api.properties.get('release_channel')
  # default to False force push
  force = False if api.runtime.is_experimental else api.properties.get('force', False)
  assert git_branch and tag and release_channel

  flutter_checkout = api.path['start_dir'].join('flutter')
  engine_checkout = api.path['start_dir'].join('engine')
  flutter_git_url = 'https://github.com/flutter/flutter'
  engine_git_url = 'https://github.com/flutter/engine'

  # Validate the given tag is correctly formatted for either stable or latest
  assert isValidTag(tag)

  # This recipe should only be executed on linux or mac machines to
  # guard against Windows git issues
  assert api.platform.is_linux or api.platform.is_mac

  with api.step.nest('checkout flutter release branch'):
    flutter_rel_hash = api.repo_util.checkout(
      'flutter',
      flutter_checkout,
      url=flutter_git_url,
      ref="refs/heads/%s" % git_branch,
    )
  with api.step.nest('checkout engine release branch'):
    api.repo_util.checkout(
      'engine',
      api.path['start_dir'].join('engine'),
      url=engine_git_url,
      ref='refs/heads/%s' % git_branch,
    )

  env_flutter, env_flutter_prefixes = api.repo_util.flutter_environment(flutter_checkout)
  env_engine, env_engine_prefixes = api.repo_util.engine_environment(engine_checkout)
  api.flutter_deps.required_deps(
      env_flutter,
      env_flutter_prefixes,
      api.properties.get('dependencies', []),
  )
  api.flutter_deps.required_deps(
      env_engine,
      env_engine_prefixes,
      api.properties.get('dependencies', []),
  )

  resource_name = api.resource('push_release.sh')
  api.step(
      'Set execute permission',
      ['chmod', '755', resource_name],
      infra_step=True,
  )

  for repo in ('flutter', 'engine'):
    env = env_flutter if repo=='flutter' else env_engine
    env_prefixes = env_flutter_prefixes if repo=='flutter' else env_engine_prefixes
    checkout = flutter_checkout if repo=='flutter' else engine_checkout
    rel_hash = flutter_rel_hash if repo=='flutter' else GetEngineVersion(api, flutter_checkout)
    with api.context(env=env, env_prefixes=env_prefixes, cwd=checkout):
      token_decrypted = api.path['cleanup'].join('token.txt')
      api.kms.get_secret('flutter-release-github-token.encrypted', token_decrypted)

      env['FORCE_FLAG'] = '--force-with-lease=%s:%s' % (release_channel, rel_hash) if force else ''
      env['TOKEN_PATH'] = token_decrypted
      env['TAG'] = tag
      env['REL_HASH'] = rel_hash
      env['RELEASE_CHANNEL'] = release_channel
      env['GIT_BRANCH'] = git_branch
      env['GITHUB_USER'] = 'fluttergithubbot'
      env['REPO'] = 'flutter' if repo=='flutter' else 'engine'

      # Run script within a new context to use the new env variables.
      # Tag and push flutter/flutter first, then use hash found in
      # bin/internal/engine.version to tag and push engine next
      with api.context(env=env, env_prefixes=env_prefixes):
        api.step('Tag and push release on flutter/%s' % repo, [resource_name])

def GetEngineVersion(api, flutter_checkout):
  return api.file.read_text('read engine hash', str(flutter_checkout)+'/bin/internal/engine.version').strip()

def GenTests(api):
    checkout_path = api.path['start_dir'].join('flutter')
    for tag in ('1.2.3-4.5.pre', '1.2.3'):
      for release_channel in ('stable', 'beta'):
        for force in ('True', 'False'):
          test = api.test(
              '%s_%s_%s%s' % (
                  'flutter-2.8-candidate.9',
                  tag,
                  release_channel,
                  '_force' if force=='True' else 'False'
              ), api.platform('mac', 64),
              api.properties(
                  git_branch='flutter-2.8-candidate.9',
                  tag=tag,
                  release_channel=release_channel,
                  force=force
              ),
              api.repo_util.flutter_environment_data(checkout_dir=checkout_path),
              api.post_process(post_process.MustRun,
                'Tag and push release on flutter/flutter'),
              api.post_process(post_process.MustRun,
                'Tag and push release on flutter/engine'),
              api.post_process(post_process.StatusSuccess),
          )
          yield test
