def _run_in_provider(project: Project, command_name: str, parsed_args: "argparse.Namespace") -> None: """Pack image in provider instance.""" emit.debug("Checking build provider availability") provider_name = "lxd" if parsed_args.use_lxd else None provider = providers.get_provider(provider_name) provider.ensure_provider_is_available() cmd = ["snapcraft", command_name] if hasattr(parsed_args, "parts"): cmd.extend(parsed_args.parts) if getattr(parsed_args, "output", None): cmd.extend(["--output", parsed_args.output]) if emit.get_mode() == EmitterMode.VERBOSE: cmd.append("--verbose") elif emit.get_mode() == EmitterMode.QUIET: cmd.append("--quiet") elif emit.get_mode() == EmitterMode.DEBUG: cmd.append("--verbosity=debug") elif emit.get_mode() == EmitterMode.TRACE: cmd.append("--verbosity=trace") if parsed_args.debug: cmd.append("--debug") if getattr(parsed_args, "shell", False): cmd.append("--shell") if getattr(parsed_args, "shell_after", False): cmd.append("--shell-after") if getattr(parsed_args, "enable_manifest", False): cmd.append("--enable-manifest") build_information = getattr(parsed_args, "manifest_build_information", None) if build_information: cmd.append("--manifest-build-information") cmd.append(build_information) output_dir = utils.get_managed_environment_project_path() emit.progress("Launching instance...") with provider.launched_environment( project_name=project.name, project_path=Path().absolute(), base=project.get_effective_base(), bind_ssh=parsed_args.bind_ssh, build_on=get_host_architecture(), build_for=get_host_architecture(), ) as instance: try: with emit.pause(): instance.execute_run(cmd, check=True, cwd=output_dir) capture_logs_from_instance(instance) except subprocess.CalledProcessError as err: capture_logs_from_instance(instance) raise providers.ProviderError( f"Failed to execute {command_name} in instance.") from err
def _run_command( command_name: str, *, project: Project, parse_info: Dict[str, List[str]], assets_dir: Path, start_time: datetime, parallel_build_count: int, parsed_args: "argparse.Namespace", ) -> None: managed_mode = utils.is_managed_mode() part_names = getattr(parsed_args, "parts", None) if not managed_mode: run_project_checks(project, assets_dir=assets_dir) if command_name == "snap": emit.progress( "The 'snap' command is deprecated, use 'pack' instead.", permanent=True, ) if parsed_args.use_lxd and providers.get_platform_default_provider( ) == "lxd": emit.progress("LXD is used by default on this platform.", permanent=True) if (not managed_mode and not parsed_args.destructive_mode and not os.getenv("SNAPCRAFT_BUILD_ENVIRONMENT") == "host"): if command_name == "clean" and not part_names: _clean_provider(project, parsed_args) else: _run_in_provider(project, command_name, parsed_args) return if managed_mode: work_dir = utils.get_managed_environment_home_path() project_dir = utils.get_managed_environment_project_path() else: work_dir = Path.cwd() project_dir = Path.cwd() step_name = "prime" if command_name in ("pack", "snap") else command_name lifecycle = PartsLifecycle( project.parts, work_dir=work_dir, assets_dir=assets_dir, base=project.get_effective_base(), package_repositories=project.package_repositories, parallel_build_count=parallel_build_count, part_names=part_names, adopt_info=project.adopt_info, project_name=project.name, parse_info=parse_info, project_vars={ "version": project.version or "", "grade": project.grade or "", }, extra_build_snaps=project.get_extra_build_snaps(), ) if command_name == "clean": lifecycle.clean(part_names=part_names) return lifecycle.run( step_name, debug=parsed_args.debug, shell=getattr(parsed_args, "shell", False), shell_after=getattr(parsed_args, "shell_after", False), ) # Extract metadata and generate snap.yaml project_vars = lifecycle.project_vars if step_name == "prime" and not part_names: emit.progress("Extracting and updating metadata...") metadata_list = lifecycle.extract_metadata() update_project_metadata( project, project_vars=project_vars, metadata_list=metadata_list, assets_dir=assets_dir, prime_dir=lifecycle.prime_dir, ) emit.progress("Copying snap assets...") setup_assets( project, assets_dir=assets_dir, project_dir=project_dir, prime_dir=lifecycle.prime_dir, ) emit.progress("Generating snap metadata...") snap_yaml.write( project, lifecycle.prime_dir, arch=lifecycle.target_arch, arch_triplet=lifecycle.target_arch_triplet, ) emit.progress("Generated snap metadata", permanent=True) if parsed_args.enable_manifest: _generate_manifest( project, lifecycle=lifecycle, start_time=start_time, parsed_args=parsed_args, ) if command_name in ("pack", "snap"): snap_filename = pack.pack_snap( lifecycle.prime_dir, output=parsed_args.output, compression=project.compression, name=project.name, version=process_version(project.version), target_arch=lifecycle.target_arch, ) emit.message(f"Created snap package {snap_filename}")
def launched_environment( self, *, project_name: str, project_path: pathlib.Path, base: str, bind_ssh: bool, build_on: str, build_for: str, ) -> Generator[Executor, None, None]: """Launch environment for specified base. :param project_name: Name of project. :param project_path: Path to project. :param base: Base to create. """ alias = BASE_TO_BUILDD_IMAGE_ALIAS[base] instance_name = self.get_instance_name( project_name=project_name, project_path=project_path, build_on=build_on, build_for=build_for, ) alias = BASE_TO_BUILDD_IMAGE_ALIAS[base] try: image_remote = lxd.configure_buildd_image_remote() except lxd.LXDError as error: raise ProviderError(str(error)) from error environment = self.get_command_environment() base_configuration = SnapcraftBuilddBaseConfiguration( alias=alias, environment=environment, hostname=instance_name, ) try: instance = lxd.launch( name=instance_name, base_configuration=base_configuration, image_name=base, image_remote=image_remote, auto_clean=True, auto_create_project=True, map_user_uid=True, uid=os.stat(project_path).st_uid, use_snapshots=True, project=self.lxd_project, remote=self.lxd_remote, ) except (bases.BaseConfigurationError, lxd.LXDError) as error: raise ProviderError(str(error)) from error # Mount project. instance.mount( host_source=project_path, target=utils.get_managed_environment_project_path(), ) # Mount ssh directory. if bind_ssh: instance.mount( host_source=pathlib.Path.home() / ".ssh", target=utils.get_managed_environment_home_path() / ".ssh", ) try: yield instance finally: # Ensure to unmount everything and stop instance upon completion. try: instance.unmount_all() instance.stop() except lxd.LXDError as error: raise ProviderError(str(error)) from error
def launched_environment( self, *, project_name: str, project_path: pathlib.Path, base: str, bind_ssh: bool, build_on: str, build_for: str, ) -> Generator[Executor, None, None]: """Launch environment for specified base. :param project_name: Name of the project. :param project_path: Path to project. :param base: Base to create. """ alias = BASE_TO_BUILDD_IMAGE_ALIAS[base] instance_name = self.get_instance_name( project_name=project_name, project_path=project_path, build_on=build_on, build_for=build_for, ) environment = self.get_command_environment() base_configuration = SnapcraftBuilddBaseConfiguration( alias=alias, # type: ignore environment=environment, hostname=instance_name, ) try: instance = multipass.launch( name=instance_name, base_configuration=base_configuration, image_name=f"snapcraft:{base}", cpus=2, disk_gb=64, mem_gb=2, auto_clean=True, ) except (bases.BaseConfigurationError, MultipassError) as error: raise ProviderError(str(error)) from error try: # Mount project. instance.mount( host_source=project_path, target=utils.get_managed_environment_project_path(), ) # Mount ssh directory. if bind_ssh: instance.mount( host_source=pathlib.Path.home() / ".ssh", target=utils.get_managed_environment_home_path() / ".ssh", ) except MultipassError as error: raise ProviderError(str(error)) from error try: yield instance finally: # Ensure to unmount everything and stop instance upon completion. try: instance.unmount_all() instance.stop() except MultipassError as error: raise ProviderError(str(error)) from error
def _run_command( command_name: str, *, project: Project, parse_info: Dict[str, List[str]], assets_dir: Path, start_time: datetime, parallel_build_count: int, parsed_args: "argparse.Namespace", ) -> None: managed_mode = utils.is_managed_mode() part_names = getattr(parsed_args, "parts", None) if not managed_mode: run_project_checks(project, assets_dir=assets_dir) if command_name == "snap": emit.progress( "The 'snap' command is deprecated, use 'pack' instead.", permanent=True, ) if parsed_args.use_lxd and providers.get_platform_default_provider( ) == "lxd": emit.progress("LXD is used by default on this platform.", permanent=True) if (not managed_mode and not parsed_args.destructive_mode and not os.getenv("SNAPCRAFT_BUILD_ENVIRONMENT") == "host"): if command_name == "clean" and not part_names: _clean_provider(project, parsed_args) else: _run_in_provider(project, command_name, parsed_args) return if managed_mode: work_dir = utils.get_managed_environment_home_path() project_dir = utils.get_managed_environment_project_path() else: work_dir = project_dir = Path.cwd() step_name = "prime" if command_name in ("pack", "snap") else command_name lifecycle = PartsLifecycle( project.parts, work_dir=work_dir, assets_dir=assets_dir, base=project.get_effective_base(), package_repositories=project.package_repositories, parallel_build_count=parallel_build_count, part_names=part_names, adopt_info=project.adopt_info, project_name=project.name, parse_info=parse_info, project_vars={ "version": project.version or "", "grade": project.grade or "", }, extra_build_snaps=project.get_extra_build_snaps(), target_arch=project.get_build_for(), ) if command_name == "clean": lifecycle.clean(part_names=part_names) return lifecycle.run( step_name, debug=parsed_args.debug, shell=getattr(parsed_args, "shell", False), shell_after=getattr(parsed_args, "shell_after", False), ) # Extract metadata and generate snap.yaml if step_name == "prime" and not part_names: _generate_metadata( project=project, lifecycle=lifecycle, project_dir=project_dir, assets_dir=assets_dir, start_time=start_time, parsed_args=parsed_args, ) if command_name in ("pack", "snap"): issues = linters.run_linters(lifecycle.prime_dir, lint=project.lint) status = linters.report(issues, intermediate=True) # In case of linter errors, stop execution and return the error code. if status in (LinterStatus.ERRORS, LinterStatus.FATAL): raise errors.LinterError("Linter errors found", exit_code=status) snap_filename = pack.pack_snap( lifecycle.prime_dir, output=parsed_args.output, compression=project.compression, name=project.name, version=process_version(project.version), target_arch=project.get_build_for(), ) emit.message(f"Created snap package {snap_filename}")