blob: 4ce135c968f6456593ede7e641c3ca7368318881 [file]
# Copyright 2026 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
import textwrap
from recipe_engine.post_process import (
DropExpectation,
StepCommandContains,
StatusFailure,
StatusSuccess,
)
from packaging.version import parse
from dataclasses import dataclass
from recipe_engine.recipe_api import RecipeScriptApi
from recipe_engine.recipe_test_api import RecipeTestApi
from RECIPE_MODULES.build import chromium
from RECIPE_MODULES.infra import codesearch
from RECIPE_MODULES.depot_tools import (
bot_update,
gclient,
git,
gsutil,
)
from RECIPE_MODULES.recipe_engine import (
buildbucket,
cipd,
context,
file,
golang,
path,
platform,
properties,
step,
)
@dataclass
class DEPS(RecipeScriptApi):
bot_update: bot_update.API
buildbucket: buildbucket.API
chromium: chromium.API
codesearch: codesearch.API
context: context.API
cipd: cipd.API
file: file.API
gclient: gclient.API
git: git.API
golang: golang.API
gsutil: gsutil.API
path: path.API
platform: platform.API
properties: properties.API
step: step.API
@dataclass
class TEST_DEPS(RecipeTestApi):
buildbucket: buildbucket.TEST_API
file: file.TEST_API
path: path.TEST_API
platform: platform.TEST_API
MODULE_RE = re.compile(r'^module\s+([^\s#]+)', re.MULTILINE)
GO_VERSION_RE = re.compile(r'^go (\d+\.\d+(?:\.\d+)?)$', re.MULTILINE)
def RunSteps(api: DEPS):
kythe_bin = api.codesearch.ensure_kythe().joinpath(
'extractors', 'go_extractor'
)
c = api.gclient.make_config()
soln = c.solutions.add()
soln.name = 'build'
soln.url = 'https://chromium.googlesource.com/build.git'
soln.revision = 'HEAD'
api.gclient.c = c
with api.context(cwd=api.path.cache_dir):
result = api.bot_update.ensure_checkout()
kzip_name = '%s.kzip' % result.properties['got_revision']
build_dir = api.path.cache_dir / 'build'
kzip_loc = api.path.cache_dir / kzip_name
go_mod_files = api.file.glob_paths(
'find go.mod files',
build_dir,
'*/go.mod',
)
if not go_mod_files:
raise api.step.StepFailure('No go.mod files found in the repository.')
targets = []
targets_dir = []
go_version = '1.26'
for mod_file in go_mod_files:
mod_text = api.file.read_text('read %s' % mod_file, mod_file)
match = MODULE_RE.search(mod_text)
if not match:
raise api.step.StepFailure('Did not detect Modules for %s' % mod_file)
targets.append(match.group(1) + '/...')
targets_dir.append(api.path.basename(api.path.dirname(mod_file)))
match = GO_VERSION_RE.search(mod_text)
if not match:
raise api.step.StepFailure('Did not detect Go version for %s' % mod_file)
go_version = max(go_version, match.group(1), key=parse)
# Download pre-built 3pp static libseccomp for linux-amd64,
# needed for siso-tap
seccomp_dir = api.path.mkdtemp('libseccomp')
ensure_file = api.cipd.EnsureFile()
ensure_file.add_package(
'infra/3pp/static_libs/libseccomp/${platform}', 'latest'
)
api.cipd.ensure(seccomp_dir, ensure_file)
base_env = {
'KYTHE_ROOT_DIRECTORY': build_dir,
'CGO_ENABLED': '1',
'CGO_CFLAGS': f'-I{seccomp_dir}/include',
'CGO_LDFLAGS': f'-L{seccomp_dir}/lib -lseccomp',
}
env_prefixes = {
'PKG_CONFIG_PATH': [seccomp_dir / 'lib' / 'pkgconfig'],
}
# KYTHE_ROOT_DIRECTORY makes sub modules relpath to build repo root.
with (
api.golang(version=go_version),
api.context(cwd=build_dir, env=base_env, env_prefixes=env_prefixes),
):
# Without go.work we have to loop multiple directories and merge kzips.
api.step('init go modules', ['go', 'work', 'init'] + targets_dir)
api.step(
'override broken go modules',
[
'go',
'work',
'edit',
'-replace',
'go.opentelemetry.io/collector/exporter/exportertest=go.opentelemetry.io/collector/exporter/exportertest@v0.157.0',
],
)
api.step(
'generate go kzip',
[
kythe_bin,
'--corpus',
'chromium.googlesource.com/build//main',
'--use_default_corpus_for_stdlib=true',
'--use_default_corpus_for_deps=true',
'--output',
kzip_loc,
]
+ targets,
)
api.gsutil.upload(
name='upload kythe index pack',
source=kzip_loc,
bucket='chrome-codesearch',
dest='build/%s' % kzip_name,
)
def GenTests(api: TEST_DEPS):
yield api.test(
'basic',
api.buildbucket.try_build(
project='infra',
builder='generic tester',
git_repo='https://chromium.googlesource.com/build',
),
api.platform('linux', 64),
api.path.exists(api.path.cache_dir / 'build'),
api.step_data(
'find go.mod files',
api.file.glob_paths(['siso/go.mod', 'kajiya/go.mod', 'bench/go.mod']),
),
api.step_data(
'read [CACHE]/build/bench/go.mod',
api.file.read_text(
textwrap.dedent('''
module go.chromium.org/build/bench
go 1.25.9
tool (
google.golang.org/a/foo
google.golang.org/b/bar
)''')
),
),
api.step_data(
'read [CACHE]/build/siso/go.mod',
api.file.read_text(
textwrap.dedent('''
module go.chromium.org/build/siso
go 1.26.2
tool (
google.golang.org/a/foo
google.golang.org/b/bar
)''')
),
),
api.step_data(
'read [CACHE]/build/kajiya/go.mod',
api.file.read_text(
textwrap.dedent('''
module go.chromium.org/build/kajiya
go 1.26.1
tool (
google.golang.org/a/foo
google.golang.org/b/bar
)''')
),
),
api.post_process(
StepCommandContains,
'ensure_installed (3)',
['infra/3pp/tools/go/${platform} version:3@1.26.2'],
),
api.post_process(
StepCommandContains,
'init go modules',
['go', 'work', 'init', 'bench', 'kajiya', 'siso'],
),
api.post_process(
StepCommandContains,
'generate go kzip',
['go.chromium.org/build/kajiya/...', 'go.chromium.org/build/siso/...'],
),
api.post_process(StatusSuccess),
api.post_process(DropExpectation),
)
yield api.test(
'no_mod_files',
api.buildbucket.try_build(
project='infra',
builder='generic tester',
git_repo='https://chromium.googlesource.com/build',
),
api.platform('linux', 64),
api.post_process(StatusFailure),
api.expect_status('FAILURE'),
api.post_process(DropExpectation),
)
yield api.test(
'malformed_mod_files',
api.buildbucket.try_build(
project='infra',
builder='generic tester',
git_repo='https://chromium.googlesource.com/build',
),
api.platform('linux', 64),
api.path.exists(api.path.cache_dir / 'build'),
api.step_data(
'find go.mod files',
api.file.glob_paths(
[
'siso/go.mod',
]
),
),
api.step_data(
'read [CACHE]/build/siso/go.mod',
api.file.read_text(
textwrap.dedent('''
go 1.26.1
tool (
google.golang.org/a/foo
google.golang.org/b/bar
)''')
),
),
api.post_process(StatusFailure),
api.expect_status('FAILURE'),
api.post_process(DropExpectation),
)
yield api.test(
'malformed_mod_version',
api.buildbucket.try_build(
project='infra',
builder='generic tester',
git_repo='https://chromium.googlesource.com/build',
),
api.platform('linux', 64),
api.path.exists(api.path.cache_dir / 'build'),
api.step_data(
'find go.mod files',
api.file.glob_paths(
[
'siso/go.mod',
]
),
),
api.step_data(
'read [CACHE]/build/siso/go.mod',
api.file.read_text(
textwrap.dedent('''
module go.chromium.org/build/kajiya
tool (
google.golang.org/a/foo
google.golang.org/b/bar
)''')
),
),
api.post_process(StatusFailure),
api.expect_status('FAILURE'),
api.post_process(DropExpectation),
)