def test_process_version_git(mocker): """``version:git`` must be correctly handled.""" mocker.patch( "craft_parts.sources.git_source.GitSource.generate_version", return_value="1.2.3-dirty", ) assert utils.process_version("git") == "1.2.3-dirty"
def write(project: Project, prime_dir: Path, *, arch: str, arch_triplet: str): """Create a snap.yaml file. :param project: Snapcraft project. :param prime_dir: The directory containing the content to be snapped. :param arch: Target architecture the snap project is built to. :param arch_triplet: Architecture triplet of the platform. """ meta_dir = prime_dir / "meta" meta_dir.mkdir(parents=True, exist_ok=True) assumes: Set[str] = set() snap_apps: Dict[str, SnapApp] = {} if project.apps: for name, app in project.apps.items(): app_sockets: Dict[str, Socket] = {} if app.sockets: for socket_name, socket in app.sockets.items(): app_sockets[socket_name] = Socket( listen_stream=socket.listen_stream, socket_mode=socket.socket_mode, ) if app.command_chain: assumes.add("command-chain") snap_apps[name] = SnapApp( command=app.command, autostart=app.autostart, common_id=app.common_id, bus_name=app.bus_name, completer=app.completer, stop_command=app.stop_command, post_stop_command=app.post_stop_command, start_timeout=app.start_timeout, stop_timeout=app.stop_timeout, watchdog_timeout=app.watchdog_timeout, reload_command=app.reload_command, restart_delay=app.restart_delay, timer=app.timer, daemon=app.daemon, after=app.after if app.after else None, before=app.before if app.before else None, refresh_mode=app.refresh_mode, stop_mode=app.stop_mode, restart_condition=app.restart_condition, install_mode=app.install_mode, plugs=app.plugs, aliases=app.aliases, environment=app.environment, command_chain=app.command_chain if app.command_chain else None, sockets=app_sockets if app_sockets else None, ) if project.hooks and any( h for h in project.hooks.values() if h.command_chain): assumes.add("command-chain") environment = _populate_environment(project.environment, prime_dir, arch_triplet) version = process_version(project.version) snap_metadata = SnapMetadata( name=project.name, title=project.title, version=version, summary=project.summary, description=project.description, # type: ignore license=project.license, type=project.type, architectures=[arch], base=cast(str, project.base), assumes=list(assumes) if assumes else None, epoch=project.epoch, apps=snap_apps or None, confinement=project.confinement, grade=project.grade or "stable", environment=environment, plugs=project.plugs, slots=project.slots, hooks=project.hooks, layout=project.layout, system_usernames=project.system_usernames, ) yaml.add_representer(str, _repr_str, Dumper=yaml.SafeDumper) yaml_data = snap_metadata.yaml( by_alias=True, exclude_none=True, allow_unicode=True, sort_keys=False, width=1000, ) snap_yaml = meta_dir / "snap.yaml" snap_yaml.write_text(yaml_data)
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 write( project: Project, prime_dir: Path, *, arch: str, parts: Dict[str, Any], image_information: str, start_time: datetime, primed_stage_packages: List[str], ): """Create a manifest.yaml file.""" snap_dir = prime_dir / "snap" snap_dir.mkdir(parents=True, exist_ok=True) osrel = os_release.OsRelease() version = utils.process_version(project.version) try: image_info = json.loads(image_information) except json.decoder.JSONDecodeError as err: raise errors.SnapcraftError( f"Image information decode error at {err.lineno}:{err.colno}: " f"{err.doc!r}: {err.msg}") from err manifest = Manifest( # Snapcraft annotations snapcraft_version=__version__, snapcraft_started_at=start_time.isoformat("T") + "Z", snapcraft_os_release_id=osrel.name().lower(), snapcraft_os_release_version_id=osrel.version_id().lower(), # Project fields name=project.name, version=version, summary=project.summary, # type: ignore description=project.description, # type: ignore base=project.base, grade=project.grade or "stable", confinement=project.confinement, apps=project.apps, parts=parts, # Architecture architectures=[arch], # Image info image_info=image_info, # Build environment build_packages=[], build_snaps=[], primed_stage_packages=primed_stage_packages, ) yaml_data = manifest.yaml( by_alias=True, exclude_none=True, exclude_unset=True, allow_unicode=True, sort_keys=False, width=1000, ) manifest_yaml = snap_dir / "manifest.yaml" manifest_yaml.write_text(yaml_data)
def test_process_version_dirty(mocker): """A version string should be returned unmodified.""" assert utils.process_version("1.2.3") == "1.2.3"
def test_process_version_empty(mocker): """``version:None`` raises an error.""" with pytest.raises(ValueError): utils.process_version(None)
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}")