blob: f29928cc96186e5d6ddebf0327dc89e36860910e [file] [log] [blame]
# 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$'
ENGINE_VERSION_FILE = '/bin/internal/engine.version'
def isValidTag(tag, release_channel):
stable = re.search(stableTagRegex, tag)
beta = re.search(betaTagRegex, tag)
if release_channel == 'stable':
return stable
return beta
"""
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 in ('stable', 'beta')
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, release_channel)
# This recipe is only able to be triggered on linux, and the other platforms
# are not necessary
assert api.platform.is_linux
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'):
engine_tot = 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,
)
engine_version = GetEngineVersion(api, flutter_checkout)
engine_tot = '' if api.repo_util._test_data.enabled else engine_tot
if engine_tot != engine_version: # pragma: no cover
api.step(
'(Warning) engine.version in flutter sdk does not match engine ToT', []
)
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 engine_version
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' 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) + ENGINE_VERSION_FILE
).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'):
if ((tag == '1.2.3-4.5.pre' and release_channel == 'stable') or
(tag == '1.2.3' and release_channel == 'beta')):
# These are invalid combinations of tag and release_channel.
# Expect assertion errors for these combinations
post_processing = [api.expect_exception('AssertionError')]
else:
# Remaining tag combinations of tag and release channel are valid.
post_processing = [
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)
]
test = api.test(
'%s_%s_%s%s' % (
'flutter-2.8-candidate.9', tag, release_channel,
'_force' if force == 'True' else 'False'
), api.platform('linux', 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),
*post_processing
)
yield test