# 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'):
    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 = 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
