| # Copyright 2020 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| """Build a GN target and upload to CIPD.""" |
| |
| from __future__ import annotations |
| from typing import TYPE_CHECKING |
| |
| from PB.recipes.pigweed.target_to_cipd import InputProperties |
| |
| if TYPE_CHECKING: # pragma: no cover |
| from typing import Generator |
| from recipe_engine import recipe_test_api |
| |
| DEPS = [ |
| 'fuchsia/buildbucket_util', |
| 'pigweed/build', |
| 'pigweed/checkout', |
| 'pigweed/cipd_upload', |
| 'pigweed/environment', |
| 'pigweed/pw_presubmit', |
| 'recipe_engine/buildbucket', |
| 'recipe_engine/file', |
| 'recipe_engine/path', |
| 'recipe_engine/properties', |
| 'recipe_engine/scheduler', |
| 'recipe_engine/step', |
| ] |
| |
| PROPERTIES = InputProperties |
| |
| |
| def RunSteps(api, props): |
| checkout = api.checkout(props.checkout_options) |
| env = api.environment.init(checkout, props.environment_options) |
| |
| with env(): |
| if props.artifacts: |
| build = api.build.create(checkout.root, props.build_options) |
| api.build(build) |
| export_dir = build.root / props.pw_presubmit_options.export_dir_name |
| |
| else: |
| presubmit = api.pw_presubmit.init( |
| checkout, props.pw_presubmit_options |
| ) |
| |
| # Presubmit steps from this recipe only make sense if there's only |
| # one, so complain if there's more than one. |
| assert len(presubmit.steps) == 1 |
| |
| # If using steps we use the entirety of export_dir_name instead of |
| # artifact globs. |
| assert not props.artifacts |
| |
| # OrderedDict.values() is not subscriptable, so iterate over the |
| # single value instead of using steps[0]. |
| for step in presubmit.steps: |
| assert step.export_dir |
| log_dir = api.path.start_dir / 'logs' |
| api.pw_presubmit.run(presubmit, step, log_dir=log_dir) |
| build_dir = step.dir |
| export_dir = step.export_dir |
| break # Not required but makes flow clearer at a glance. |
| |
| pkg_dir = api.path.start_dir / 'cipd-package' |
| |
| if props.artifacts: |
| api.file.ensure_directory('mkdir cipd-package', pkg_dir) |
| |
| for glob in props.artifacts: |
| with api.step.nest(glob): |
| sources = api.file.glob_paths( |
| 'glob', build.root, glob, test_data=(glob,) |
| ) |
| if not sources: # pragma: no cover |
| api.file.listdir('ls build', build.root, recursive=True) |
| raise api.step.StepFailure(f'no matches for {glob}') |
| for source in sources: |
| with api.step.nest('source') as pres: |
| pres.step_summary_text = '\n'.join( |
| (str(source), str(build.root)) |
| ) |
| relpath = api.path.relpath(source, build.root) |
| for replacement in props.replacements: |
| relpath = relpath.replace( |
| replacement.old, replacement.new |
| ) |
| dest = pkg_dir / relpath |
| pres.step_summary_text += f'\n{dest}' |
| dirname = api.path.dirname(dest) |
| api.file.ensure_directory(f'mkdir {dirname}', dirname) |
| api.file.copy(f'copy {source} {dest}', source, dest) |
| |
| else: |
| if api.path.isdir(export_dir): |
| api.file.copytree('copy', export_dir, pkg_dir) |
| |
| if checkout.options.use_repo: |
| api.file.write_text( |
| 'write manifest', |
| pkg_dir / 'manifest.xml', |
| checkout.manifest_snapshot(), |
| ) |
| |
| files = api.file.listdir('ls package-dir', pkg_dir, recursive=True) |
| if not files: # pragma: no cover |
| raise api.step.StepFailure('no files in package-dir') |
| |
| if not props.dry_run and not api.buildbucket_util.is_tryjob: |
| assert checkout.changes |
| change = checkout.changes[0] |
| search_tag = {'git_revision': change.ref} |
| |
| api.cipd_upload( |
| cipd_path=props.cipd_path, |
| package_root=pkg_dir, |
| search_tag=search_tag, |
| repository=checkout.options.remote, |
| add_platform=props.add_cipd_platform, |
| ) |
| |
| if props.roller_name: |
| api.scheduler.emit_trigger( |
| api.scheduler.GitilesTrigger( |
| change.remote, |
| f'refs/heads/{change.branch}', |
| change.ref, |
| ), |
| api.buildbucket.build.builder.project, |
| (props.roller_name,), |
| f'trigger {props.roller_name}', |
| ) |
| |
| |
| def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]: |
| def properties(**kwargs): |
| kwargs.setdefault('cipd_path', 'pigweed/cipd/path') |
| kwargs.setdefault('dry_run', False) |
| kwargs.setdefault('roller_name', 'ROLL') |
| props = InputProperties(**kwargs) |
| return api.properties(props) |
| |
| yield api.test( |
| 'success', |
| properties( |
| artifacts=['foo/bar/baz'], |
| replacements=[{'old': '/bar/', 'new': '/replacement/'}], |
| checkout_options=api.checkout.repo_options(), |
| build_options=api.build.options(ninja_targets=['foo', 'bar']), |
| ), |
| api.checkout.ci_test_data(api.checkout.manifest_repo), |
| api.checkout.manifest_test_data(name='pigweed'), |
| api.step_data('ls package-dir', api.file.listdir(('foo', 'bar'))), |
| ) |
| |
| yield api.test( |
| 'pw-presubmit', |
| properties( |
| checkout_options=api.checkout.git_options(), |
| pw_presubmit_options=api.pw_presubmit.options(step=['step']), |
| ), |
| api.step_data('ls package-dir', api.file.listdir(('foo', 'bar'))), |
| ) |