blob: 151bdefc5e620bd4b5290e2b4e65039e2b10b83a [file]
# Copyright 2023 The Chromium Authors
# 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.post_process import (
DoesNotRun,
DropExpectation,
StepCommandContains,
StepTextEquals,
)
from RECIPE_MODULES.build.v8.v8version import choose_revision_to_roll
from dataclasses import dataclass
from recipe_engine.recipe_api import RecipeScriptApi
from recipe_engine.recipe_test_api import RecipeTestApi
from RECIPE_MODULES.build import v8
from RECIPE_MODULES.depot_tools import (
bot_update,
gclient,
git,
gitiles,
)
from RECIPE_MODULES.recipe_engine import (
context,
file,
path,
raw_io,
step,
)
@dataclass
class DEPS(RecipeScriptApi):
bot_update: bot_update.API
context: context.API
file: file.API
gclient: gclient.API
git: git.API
gitiles: gitiles.API
path: path.API
raw_io: raw_io.API
step: step.API
v8: v8.API
@dataclass
class TEST_DEPS(RecipeTestApi):
file: file.TEST_API
gclient: gclient.TEST_API
git: git.TEST_API
gitiles: gitiles.TEST_API
path: path.TEST_API
raw_io: raw_io.TEST_API
step: step.TEST_API
v8: v8.TEST_API
TEST_DEPS_FILE = """
vars = {
'chromium_git': 'https://chromium.googlesource.com',
'v8_revision': '%s',
}
deps = {
'src/v8':
Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'),
}
"""
V8_VERSION_RE = re.compile(r'^\d+\.\d+\.\d+(?:\.\d+)?$')
def get_last_v8_revision(api: DEPS):
"""Retrieve the last V8 revision in Chromium from gitiles."""
deps = api.gitiles.download_file(
'https://chromium.googlesource.com/chromium/src',
'DEPS',
branch='refs/heads/main',
step_test_data=lambda: api.gitiles.test_api.make_encoded_file(
TEST_DEPS_FILE % 'deadbeef'
),
)
deps_file = api.path.mkdtemp('gitiles') / 'DEPS'
api.file.write_text('gitiles', deps_file, deps)
revision = api.gclient(
'get gitiles deps',
['getdep', '--var=v8_revision', f'--deps-file={deps_file}'],
stdout=api.raw_io.output_text(),
).stdout.strip()
api.step.active_result.presentation.logs['revision'] = [revision]
return revision
def get_v8_tag(api: DEPS, revision):
"""Returns the V8 version tag associated with a revision or None."""
tags = api.v8.git_output('tag', '--points-at', revision).split('\n')
return next((tag for tag in tags if V8_VERSION_RE.match(tag)), None)
def get_next_v8_revision(api: DEPS, last_v8_revision):
"""Choose the next newest viable V8 revision to roll.
We override with the last if the algorithm determined that a new
version isn't ready yet. If, e.g., a new patched version is in the
works, but not ready, this ensures that we won't roll to anything
else in the meantime.
Args:
last_v8_revision: The previously rolled revision.
"""
with api.step.nest('Choose revision') as parent:
api.git('fetch', 'origin', '+refs/tags/*:refs/tags/*')
last_version = get_v8_tag(api, last_v8_revision)
assert last_version, 'The last rolled v8 revision is not tagged.'
ref_lines = api.v8.git_output(
'for-each-ref',
'--count=160',
'--sort=-committerdate',
'--format',
'%(refname) %(objectname) %(committerdate)',
'refs/tags/*',
).split('\n')
revision, reason = choose_revision_to_roll(ref_lines, last_version)
parent.step_text = reason
return revision or last_v8_revision
def RunSteps(api: DEPS):
api.gclient.set_config('v8_bare')
update_result = api.v8.checkout()
source_dir = update_result.source_root.path
last_v8_revision = get_last_v8_revision(api)
with api.context(
cwd=source_dir,
env={'DEPOT_TOOLS_UPDATE': '0'},
env_prefixes={'PATH': [api.v8.depot_tools_path(source_dir)]},
):
next_v8_revision = get_next_v8_revision(api, last_v8_revision)
api.git(
'fetch',
'https://chromium.googlesource.com/v8/v8',
'refs/heads/roll',
next_v8_revision,
)
api.git(
'push',
'https://chromium.googlesource.com/v8/v8',
f'+{next_v8_revision}:refs/heads/roll',
)
TEST_REF_DATA = """
refs/tags/11.7.10-pgo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2 Fri Jul 7 11:32:02 2023 +0000
refs/tags/11.7.10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2 Fri Jul 7 11:32:02 2023 +0000
refs/tags/11.7.9-pgo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1 Fri Jul 7 10:32:02 2023 +0000
refs/tags/11.7.9 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1 Fri Jul 7 10:32:02 2023 +0000
"""
def GenTests(api: TEST_DEPS):
def last_v8_revision():
return api.override_step_data(
'gclient get gitiles deps',
api.raw_io.stream_output_text('deadbeef', stream='stdout'),
)
def v8_tag(tag):
return api.override_step_data(
'Choose revision.git tag',
api.raw_io.stream_output_text(f'{tag}-pgo\n{tag}', stream='stdout'),
)
def v8_ref_data():
return api.override_step_data(
'Choose revision.git for-each-ref',
api.raw_io.stream_output_text(TEST_REF_DATA, stream='stdout'),
)
yield api.test(
'standard',
last_v8_revision(),
v8_tag('11.7.8'),
v8_ref_data(),
api.post_process(
StepTextEquals,
'Choose revision',
'found revision to roll: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2',
),
api.post_process(
StepCommandContains,
'git push',
['+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2:refs/heads/roll'],
),
api.post_process(DropExpectation),
status='SUCCESS',
)
yield api.test(
'nothing_new',
last_v8_revision(),
v8_tag('11.7.11'),
v8_ref_data(),
api.post_process(
StepTextEquals, 'Choose revision', 'found no newer revision than: 11.7.11'
),
api.post_process(
StepCommandContains, 'git push', ['+deadbeef:refs/heads/roll']
),
api.post_process(DropExpectation),
status='SUCCESS',
)