Exemplo n.º 1
0
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"
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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}")
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
def test_process_version_dirty(mocker):
    """A version string should be returned unmodified."""
    assert utils.process_version("1.2.3") == "1.2.3"
Exemplo n.º 6
0
def test_process_version_empty(mocker):
    """``version:None`` raises an error."""
    with pytest.raises(ValueError):
        utils.process_version(None)
Exemplo n.º 7
0
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}")