def __init__(self): self.project = Project() self.project._snap_meta = Snap(name="project-name", base="core20", version="1.0", confinement="strict") self.parts = Parts()
def test_build_base_and_write_snap_yaml_type_base_with_build_base(self): snap_dict = OrderedDict( { "name": "core20", "version": "snap-version", "summary": "snap-summary", "description": "snap-description", "grade": "devel", "build-base": "core18", "type": "base", } ) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() # Write snap yaml. snap_yaml_path = os.path.join(self.path, "snap.yaml") snap.write_snap_yaml(path=snap_yaml_path) # Read snap yaml. written_snap_yaml = open(snap_yaml_path, "r").read() self.assertTrue("base" in written_snap_yaml) self.assertFalse("build-base" in written_snap_yaml) self.assertEqual(snap.get_build_base(), "core18")
def test_snapcraft_yaml_links(self): snap_dict = { "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "issues": "https://bug_url.org", "donation": [ "https://paypal.com", "https://cafecito.app/", "https://ko-fi.com/", ], "contact": ["mailto:[email protected]", "*****@*****.**"], "source-code": "https://github.com/org/source", "website": "https://webfront.org", } snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() self.assertEqual( { "issues": ["https://bug_url.org"], "donation": [ "https://paypal.com", "https://cafecito.app/", "https://ko-fi.com/", ], "contact": ["mailto:[email protected]", "*****@*****.**"], "source-code": ["https://github.com/org/source"], "website": ["https://webfront.org"], }, snap.to_snap_yaml_dict()["links"], )
def get_project(*, is_managed_host: bool = False, **kwargs): # We need to do this here until we can get_snapcraft_yaml as part of Project. if is_managed_host: try: os.chdir(os.path.expanduser(os.path.join("~", "project"))) except FileNotFoundError: # No project found (fresh environment). raise errors.ProjectNotFoundError() snapcraft_yaml_file_path = get_snapcraft_yaml() # This method may be called from a click.Command with no parent. ctx = click.get_current_context() if ctx.parent is not None: for key, value in ctx.parent.params.items(): if not kwargs.get(key): kwargs[key] = value project = Project( debug=kwargs.pop("debug", False), target_deb_arch=kwargs.pop("target_arch", None), snapcraft_yaml_file_path=snapcraft_yaml_file_path, is_managed_host=is_managed_host, ) # TODO: this should be automatic on get_project(). # This is not the complete meta parsed by the project loader. project._snap_meta = Snap.from_dict(project.info.get_raw_snapcraft()) return project
def get_project(base: str = "core20") -> Project: project = Project() project._snap_meta = Snap(name="project-name", base=base, version="1.0", confinement="strict") return project
def test_setup_environment_content_x86(tmp_work_path, monkeypatch, machine_platform, distro): snapcraft_project = Project() snapcraft_project._snap_meta = Snap(name="test-snap", base=distro[0]) monkeypatch.setattr(platform, "machine", lambda: machine_platform[0]) recorded_files = dict() @contextlib.contextmanager def fake_namedtempfile(*, suffix: str, **kwargs): # Usage hides the file basename in the suffix. tmp_path = os.path.join("tmpfile") with open(tmp_path, "wb") as f_write: yield f_write with open(tmp_path, "r") as f_read: recorded_files[suffix] = f_read.read() monkeypatch.setattr(tempfile, "NamedTemporaryFile", fake_namedtempfile) provider = ProviderImpl(project=snapcraft_project, echoer=Mock()) provider._setup_environment() assert recorded_files == { ".bashrc": '#!/bin/bash\nexport PS1="\\h \\$(/bin/_snapcraft_prompt)# "\n', "00-snapcraft": 'Apt::Install-Recommends "false";\n', "_snapcraft_prompt": dedent("""\ #!/bin/bash if [[ "$PWD" =~ ^$HOME.* ]]; then path="${PWD/#$HOME/\\ ..}" if [[ "$path" == " .." ]]; then ps1="" else ps1="$path" fi else ps1="$PWD" fi echo -n $ps1 """), "default.sources": dedent(f"""\ Types: deb URIs: {machine_platform[1]["main"]} Suites: {distro[1]} {distro[1]}-updates Components: main multiverse restricted universe """), "default-security.sources": dedent(f"""\ Types: deb URIs: {machine_platform[1]["security"]} Suites: {distro[1]}-security Components: main multiverse restricted universe """), "sources.list": "", }
def __init__( self, project_config: _config.Config, extracted_metadata: Optional[_metadata.ExtractedMetadata], ) -> None: self._project_config = project_config self._extracted_metadata = extracted_metadata self._snapcraft_yaml_path = project_config.project.info.snapcraft_yaml_file_path self._prime_dir = project_config.project.prime_dir self._parts_dir = project_config.project.parts_dir self._arch_triplet = project_config.project.arch_triplet self._is_host_compatible_with_base = ( project_config.project.is_host_compatible_with_base) self.meta_dir = os.path.join(self._prime_dir, "meta") self.meta_gui_dir = os.path.join(self.meta_dir, "gui") self._config_data = project_config.data.copy() self._original_snapcraft_yaml = project_config.project.info.get_raw_snapcraft( ) self._install_path_pattern = re.compile( r"{}/[a-z0-9][a-z0-9+-]*/install".format(re.escape( self._parts_dir))) os.makedirs(self.meta_dir, exist_ok=True) # TODO: create_snap_packaging managles config data, so we create # a new private instance of snap_meta. Longer term, this needs # to converge with project's snap_meta. self._snap_meta = Snap.from_dict(project_config.data)
def __init__(self, project: project.Project) -> None: self.build_snaps: Set[str] = set() self.project = project # raw_snapcraft_yaml is read only, create a new copy snapcraft_yaml = apply_extensions(project.info.get_raw_snapcraft()) self.validator = Validator(snapcraft_yaml) self.validator.validate() snapcraft_yaml = self._expand_filesets(snapcraft_yaml) self.data = self._expand_env(snapcraft_yaml) self.data["architectures"] = _process_architectures( self.data.get("architectures"), project.deb_arch) self._ensure_no_duplicate_app_aliases() self._global_grammar_processor = grammar_processing.GlobalGrammarProcessor( properties=self.data, project=project) # XXX: Resetting snap_meta due to above mangling of data. # Convergence to operating on snap_meta will remove this requirement... project._snap_meta = Snap.from_dict(self.data) self.parts = PartsConfig(parts=self.data, project=project, validator=self.validator)
def test_system_usernames_longform_scope(self): snap_dict = OrderedDict({ "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "system-usernames": { "snap_daemon": { "scope": "shared" }, "lxd": { "scope": "shared" }, }, }) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() self.assertThat(snap.system_usernames["snap_daemon"].name, Equals("snap_daemon")) self.assertThat(snap.system_usernames["snap_daemon"].scope, Equals(SystemUserScope.SHARED)) self.assertThat(snap.system_usernames["lxd"].name, Equals("lxd")) self.assertThat(snap.system_usernames["lxd"].scope, Equals(SystemUserScope.SHARED))
def test_missing_keys(self): snap_dict = OrderedDict({"name": "snap-test", "grade": "stable"}) snap = Snap.from_dict(snap_dict=snap_dict) self.assertEqual(snap_dict, snap.to_dict()) self.assertRaises(errors.MissingSnapcraftYamlKeysError, snap.validate)
def test_all_keys(self): snap_dict = { "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "adopt-info": "some-part", "apps": {"test-app": {"command": "test-app"}}, "architectures": ["all"], "assumes": ["command-chain"], "base": "core", "confinement": "strict", "compression": "lzo", "environment": {"TESTING": "1"}, "epoch": 0, "grade": "devel", "hooks": {"test-hook": {"command-chain": ["cmd1"], "plugs": ["network"]}}, "layout": {"/target": {"bind": "$SNAP/foo"}}, "license": "GPL", "passthrough": {"test": "value"}, "plugs": {"test-plug": {"interface": "some-value"}}, "slots": {"test-slot": {"interface": "some-value"}}, "system-usernames": {"snap_daemon": {"scope": "shared"}}, "title": "test-title", "type": "base", } snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() self.assertEqual(snap_dict, snap.to_dict()) self.assertEqual(True, snap.is_passthrough_enabled)
def test_passthrough(self): snap_dict = OrderedDict({ "name": "snap-test", "version": "snap-version", "summary": "snap-summary", "description": "snap-description", "passthrough": { "otherkey": "othervalue" }, "grade": "stable", }) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() transformed_dict = snap_dict.copy() passthrough = transformed_dict.pop("passthrough") transformed_dict.update(passthrough) self.assertEqual(transformed_dict, snap.to_dict()) self.assertEqual(True, snap.is_passthrough_enabled) self.assertEqual(passthrough, snap.passthrough) self.assertEqual(snap_dict["name"], snap.name) self.assertEqual(snap_dict["version"], snap.version) self.assertEqual(snap_dict["summary"], snap.summary) self.assertEqual(snap_dict["description"], snap.description)
def test_unsupported_base_raises(flutter_options): project = Project() project._snap_meta = Snap(name="test-snap", base="bad-base", confinement="strict") with pytest.raises(errors.PluginBaseError): flutter.FlutterPlugin("test-part", flutter_options, project)
def test_get_provider_content_directories_with_content_plugs(self): snap_dict = OrderedDict( { "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "plugs": { "test-plug": { "interface": "content", "content": "content", "target": "target", "default-provider": "gtk-common-themes:gtk-3-themes", } }, } ) meta_snap_yaml = dedent( """ name: test-content-snap-meta-snap-yaml version: "1.0" summary: test-summary description: test-description base: core18 architectures: - all confinement: strict grade: stable slots: test-slot-name: interface: content source: read: - $SNAP/dir1 - $SNAP/dir2 """ ) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() patcher = mock.patch("snapcraft.internal.common.get_installed_snap_path") mock_core_path = patcher.start() mock_core_path.return_value = self.path self.addCleanup(patcher.stop) meta_path = os.path.join(self.path, "meta") os.makedirs(meta_path) snap_yaml_path = os.path.join(meta_path, "snap.yaml") open(snap_yaml_path, "w").write(meta_snap_yaml) expected_content_dirs = set( [os.path.join(self.path, "dir1"), os.path.join(self.path, "dir2")] ) self.assertEqual(expected_content_dirs, snap.get_provider_content_directories())
def project(monkeypatch, tmp_work_path, request): """Return project variants for core and core18""" monkeypatch.setattr(Project, "parallel_build_count", 2) snapcraft_project = Project() snapcraft_project._snap_meta = Snap( name="test-snap", base=request.param, confinement="strict" ) return snapcraft_project
def project_core18(monkeypatch, tmp_work_path): """Return project for core18""" monkeypatch.setattr(Project, "parallel_build_count", 2) snapcraft_project = Project() snapcraft_project._snap_meta = Snap( name="test-snap", base="core18", confinement="strict" ) return snapcraft_project
def __init__(self, project: project.Project) -> None: self.build_snaps: Set[str] = set() self.project = project # raw_snapcraft_yaml is read only, create a new copy snapcraft_yaml = apply_extensions(project.info.get_raw_snapcraft()) self.validator = Validator(snapcraft_yaml) self.validator.validate() snapcraft_yaml = self._expand_filesets(snapcraft_yaml) self.data = self._expand_env(snapcraft_yaml) self.data["architectures"] = _process_architectures( self.data.get("architectures"), project.deb_arch) self._ensure_no_duplicate_app_aliases() grammar_processor = grammar_processing.GlobalGrammarProcessor( properties=self.data, project=project) self.build_tools = grammar_processor.get_build_packages() self.build_tools |= set(project.additional_build_packages) # If version: git is used we want to add "git" to build-packages if self.data.get("version") == "git": self.build_tools.add("git") # XXX: Resetting snap_meta due to above mangling of data. # Convergence to operating on snap_meta will remove this requirement... project._snap_meta = Snap.from_dict(self.data) # Always add the base for building for non os and base snaps if project.info.base is None and project.info.type in ("app", "gadget"): raise SnapcraftEnvironmentError( "A base is required for snaps of type {!r}.".format( project.info.type)) if project.info.base is not None: # If the base is already installed by other means, skip its installation. # But, we should always add it when in a docker environment so # the creator of said docker image is aware that it is required. if common.is_process_container( ) or not repo.snaps.SnapPackage.is_snap_installed( project.info.base): self.build_snaps.add(project.info.base) self.parts = PartsConfig( parts=self.data, project=project, validator=self.validator, build_snaps=self.build_snaps, build_tools=self.build_tools, )
def test_snap_yaml_all_keys(self): snap_dict = { "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "adopt-info": "some-part", "apps": {"test-app": {"command": "test-app"}}, "architectures": ["all"], "assumes": ["command-chain"], "base": "core", "confinement": "strict", "compression": "xz", "environment": {"TESTING": "1"}, "epoch": 0, "grade": "devel", "hooks": {"test-hook": {"command-chain": ["cmd1"], "plugs": ["network"]}}, "layout": {"/target": {"bind": "$SNAP/foo"}}, "license": "GPL", "package-repositories": [ {"type": "apt", "ppa": "test/ppa"}, { "type": "apt", "architectures": ["amd64", "i386"], "components": ["main"], "formats": ["deb"], "key-id": "test-key-id", "key-server": "test-key-server.com", "suites": ["xenial"], "url": "http://archive.ubuntu.com", }, ], "passthrough": {"test": "value"}, "plugs": {"test-plug": {"interface": "some-value"}}, "slots": {"test-slot": {"interface": "some-value"}}, "system-usernames": {"snap_daemon": {"scope": "shared"}}, "title": "test-title", "type": "base", } snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() expected_dict = snap_dict.copy() expected_dict.pop("adopt-info") expected_dict.pop("base") expected_dict.pop("compression") expected_dict.pop("package-repositories") expected_dict.update(expected_dict.pop("passthrough")) self.assertEqual(expected_dict, snap.to_snap_yaml_dict()) self.assertEqual(True, snap.is_passthrough_enabled)
def test_use_invalid_openjdk_version_fails(self, base, version, expected_message): class Options: gradle_options = [] gradle_output_dir = "build/libs" gradle_version = gradle._DEFAULT_GRADLE_VERSION gradle_version_checksum = gradle._DEFAULT_GRADLE_CHECKSUM gradle_openjdk_version = version project = Project() project._snap_meta = Snap(name="test-snap", base=base, confinement="strict") with pytest.raises(gradle.UnsupportedJDKVersionError) as error: gradle.GradlePlugin("test-part", Options(), project) assert str(error) == expected_message
def test_use_invalid_openjdk_version_fails(self, base, version, expected_message): class Options: maven_options = [] maven_targets = [""] maven_version = maven._DEFAULT_MAVEN_VERSION maven_version_checksum = maven._DEFAULT_MAVEN_CHECKSUM maven_openjdk_version = version project = Project() project._snap_meta = Snap(name="test-snap", base=base, confinement="strict") with pytest.raises(maven.UnsupportedJDKVersionError) as error: maven.MavenPlugin("test-part", Options(), project) assert str(error) == expected_message
def __init__( self, *, target_deb_arch=None, debug=False, snapcraft_yaml_file_path=None, work_dir: str = None, is_managed_host: bool = False ) -> None: project_dir = os.getcwd() if is_managed_host: work_dir = os.path.expanduser("~") else: work_dir = project_dir super().__init__(target_deb_arch, debug, work_dir=work_dir) # This here check is mostly for backwards compatibility with the # rest of the code base. if snapcraft_yaml_file_path is None: self.info: ProjectInfo = None # type: ignore else: self.info = ProjectInfo(snapcraft_yaml_file_path=snapcraft_yaml_file_path) self._is_managed_host = is_managed_host self._project_dir = project_dir self._work_dir = work_dir self.local_plugins_dir = self._get_local_plugins_dir() self._start_time = datetime.utcnow() # XXX: (Re)set by Config because it mangles source data. # Ideally everywhere wold converge to operating on snap_meta, and ww # would only need to initialize it once (properly). self._snap_meta = Snap()
def test_all_keys(self): snap_dict = OrderedDict( { "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "apps": {"test-app": {"command": "test-app"}}, "architectures": ["all"], "assumes": ["command-chain"], "base": "core", "confinement": "strict", "environment": {"TESTING": "1"}, "epoch": 0, "grade": "devel", "hooks": {"test-hook": {"plugs": ["network"]}}, "layout": {"/target": {"bind": "$SNAP/foo"}}, "license": "GPL", "plugs": {"test-plug": OrderedDict({"interface": "some-value"})}, "slots": {"test-slot": OrderedDict({"interface": "some-value"})}, "title": "test-title", "type": "base", } ) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() self.assertEqual(snap_dict, snap.to_dict()) self.assertEqual(False, snap.is_passthrough_enabled) self.assertEqual(snap_dict["name"], snap.name) self.assertEqual(snap_dict["version"], snap.version) self.assertEqual(snap_dict["summary"], snap.summary) self.assertEqual(snap_dict["description"], snap.description) self.assertEqual(snap_dict["apps"]["test-app"], snap.apps["test-app"].to_dict()) self.assertEqual(snap_dict["architectures"], snap.architectures) self.assertEqual(snap_dict["assumes"], snap.assumes) self.assertEqual(snap_dict["base"], snap.base) self.assertEqual(snap_dict["environment"], snap.environment) self.assertEqual(snap_dict["license"], snap.license) self.assertEqual( snap_dict["plugs"]["test-plug"], snap.plugs["test-plug"].to_dict() ) self.assertEqual( snap_dict["slots"]["test-slot"], snap.slots["test-slot"].to_dict() ) self.assertEqual(snap_dict["confinement"], snap.confinement) self.assertEqual(snap_dict["title"], snap.title) self.assertEqual(snap_dict["type"], snap.type)
def maven_plugin(tmp_work_path, request): """Return an instance of MavenPlugin setup with different bases and java versions.""" java_version, base = request.param class Options: maven_options = [] maven_targets = [""] maven_version = maven._DEFAULT_MAVEN_VERSION maven_version_checksum = maven._DEFAULT_MAVEN_CHECKSUM maven_openjdk_version = java_version project = Project() project._snap_meta = Snap(name="test-snap", base=base, confinement="strict") return maven.MavenPlugin("test-part", Options(), project)
def test_is_passthrough_enabled_hook(self): snap_dict = OrderedDict( { "name": "snap-test", "version": "test-version", "summary": "test-summary", "description": "test-description", "hooks": {"test-hook": {"passthrough": {"some-key": "some-value"}}}, } ) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() self.assertEqual(True, snap.is_passthrough_enabled)
def gradle_plugin(tmp_path, request): """Return an instance of GradlePlugin setup with different bases and java versions.""" java_version, base = request.param class Options: gradle_options = [] gradle_output_dir = "build/libs" gradle_version = gradle._DEFAULT_GRADLE_VERSION gradle_version_checksum = gradle._DEFAULT_GRADLE_CHECKSUM gradle_openjdk_version = java_version os.chdir(tmp_path) project = Project() project._snap_meta = Snap(name="test-snap", base=base, confinement="strict") return gradle.GradlePlugin("test-part", Options(), project)
def test_simple(self): snap_dict = OrderedDict({ "name": "snap-test", "version": "snap-version", "summary": "snap-summary", "description": "snap-description", "grade": "stable", }) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate() self.assertEqual(snap_dict, snap.to_dict()) self.assertEqual(False, snap.is_passthrough_enabled) self.assertEqual(snap_dict["name"], snap.name) self.assertEqual(snap_dict["version"], snap.version) self.assertEqual(snap_dict["summary"], snap.summary) self.assertEqual(snap_dict["description"], snap.description)
def test_use_invalid_openjdk_version_fails(self, base, version, expected_message): class Options: ant_properties = {} ant_build_targets = None ant_channel = None ant_version = "1.10.5" ant_version_checksum = "sha512/a7f1e0cec9d5ed1b3ab6cddbb9364f127305a997bbc88ecd734f9ef142ec0332375e01ace3592759bb5c3307cd9c1ac0a78a30053f304c7030ea459498e4ce4e" ant_openjdk_version = version project = Project() project._snap_meta = Snap(name="test-snap", base=base, confinement="strict") with pytest.raises(ant.UnsupportedJDKVersionError) as error: ant.AntPlugin("test-part", Options(), project) assert str(error) == expected_message
def test_from_file(self): snap_yaml = dedent(""" name: test-name version: "1.0" summary: test-summary description: test-description base: core18 architectures: - amd64 assumes: - snapd2.39 confinement: classic grade: devel apps: test-app: command: test-command completer: test-completer """) meta_path = os.path.join(self.path, "meta") os.makedirs(meta_path) snap_yaml_path = os.path.join(self.path, "meta", "snap.yaml") open(snap_yaml_path, "w").write(snap_yaml) snap = Snap.from_file(snap_yaml_path) snap.validate() self.assertEqual("test-name", snap.name) self.assertEqual("1.0", snap.version) self.assertEqual("test-summary", snap.summary) self.assertEqual("test-description", snap.description) self.assertEqual( OrderedDict({ "command": "test-command", "completer": "test-completer" }), snap.apps["test-app"].to_dict(), ) self.assertEqual(["amd64"], snap.architectures) self.assertEqual({"snapd2.39"}, snap.assumes) self.assertEqual("core18", snap.base) self.assertEqual("classic", snap.confinement) self.assertEqual("devel", snap.grade)
def test_conversions(self): # Ordering matters for verifying the YAML. snapcraft_yaml_path = os.path.join(self.path, "snapcraft.yaml") with open(snapcraft_yaml_path, "w") as f: f.write(self.snapcraft_yaml) snap = Snap.from_file(snapcraft_yaml_path) snap.validate() # Write snap yaml. snap_yaml_path = os.path.join(self.path, "snap.yaml") snap.write_snap_yaml(path=snap_yaml_path) # Read snap yaml. with open(snap_yaml_path, "r") as f: written_snap_yaml = f.read() # Compare stripped versions (to remove leading/trailing newlines). self.assertEqual(self.snap_yaml.strip(), written_snap_yaml.strip())
def test_grade_devel_statisfies_required_grade(self): self.fake_snapd.snaps_result = [{ "name": "fake-base", "channel": "edge", "revision": "fake-revision" }] snap_dict = OrderedDict({ "name": "snap-test", "base": "fake-base", "version": "snap-version", "summary": "snap-summary", "description": "snap-description", "grade": "devel", }) snap = Snap.from_dict(snap_dict=snap_dict) snap.validate()