def test_pull_is_dirty_if_target_arch_changes( self, mock_install_build_snaps, mock_install_build_packages, mock_enable_cross_compilation, ): # Set the option to error on dirty/outdated steps with snapcraft_legacy.config.CLIConfig() as cli_config: cli_config.set_outdated_step_action( snapcraft_legacy.config.OutdatedStepAction.ERROR) mock_install_build_packages.return_value = [] project_config = self.make_snapcraft_project( textwrap.dedent("""\ parts: part1: plugin: nil """)) project = Project( snapcraft_yaml_file_path=self.snapcraft_yaml_file_path, target_deb_arch="amd64", ) project_config = project_loader.load_config(project) # Pull it with amd64 lifecycle.execute(steps.PULL, project_config) # Reset logging since we only care about the following self.fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(self.fake_logger) project = Project( snapcraft_yaml_file_path=self.snapcraft_yaml_file_path, target_deb_arch="armhf", ) project_config = project_loader.load_config(project) # Pull it again with armhf. Should catch that the part needs to be # re-pulled due to the change in target architecture and raise an # error. raised = self.assertRaises(errors.StepOutdatedError, lifecycle.execute, steps.PULL, project_config) self.assertThat(self.fake_logger.output, Contains("Setting target machine to 'armhf'")) self.assertThat(raised.step, Equals(steps.PULL)) self.assertThat(raised.part, Equals("part1")) self.assertThat( raised.report, Equals("The 'deb_arch' project option appears to have changed.\n"), )
def clean(project: "Project", parts, step=None): # step defaults to None because that's how it comes from docopt when it's # not set. if not step: step = steps.PULL if not parts and step == steps.PULL: _cleanup_common_directories_for_step(step, project) return config = project_loader.load_config(project) if not parts and step <= steps.PRIME: # If we've been asked to clean stage or prime without being given # specific parts, just blow away those directories instead of # doing it per part (it would just be a waste of time). _cleanup_common_directories_for_step(step, project, parts=config.all_parts) # No need to continue if that's all that was required if step >= steps.STAGE: return if parts: config.parts.validate(parts) else: parts = [part.name for part in config.all_parts] staged_state = config.get_project_state(steps.STAGE) primed_state = config.get_project_state(steps.PRIME) _clean_parts(parts, step, config, staged_state, primed_state) _cleanup_common_directories(config, project)
def get_project_config(snapcraft_yaml_content): snapcraft_yaml_path = pathlib.Path("snapcraft.yaml") with snapcraft_yaml_path.open("w") as snapcraft_yaml_file: print(snapcraft_yaml_content, file=snapcraft_yaml_file) project = Project(snapcraft_yaml_file_path=snapcraft_yaml_path.as_posix()) return project_loader.load_config(project)
def make_snapcraft_project(self, snapcraft_yaml, project_kwargs=None): snapcraft_yaml_file_path = self.make_snapcraft_yaml(snapcraft_yaml) if project_kwargs is None: project_kwargs = dict() project = _Project(snapcraft_yaml_file_path=snapcraft_yaml_file_path, **project_kwargs) return project_loader.load_config(project)
def make_snapcraft_project(self, parts): snapcraft_yaml = fixture_setup.SnapcraftYaml(self.path) snapcraft_yaml.update_part("part1", dict(plugin="nil")) for part_name, part in parts: snapcraft_yaml.update_part(part_name, part) self.useFixture(snapcraft_yaml) project = Project( snapcraft_yaml_file_path=snapcraft_yaml.snapcraft_yaml_file_path) return project_loader.load_config(project)
def get_project_config(snapcraft_yaml_content, target_deb_arch=None): snapcraft_yaml_path = pathlib.Path("Snapcraft.yaml") with snapcraft_yaml_path.open("w") as snapcraft_yaml_file: print(snapcraft_yaml_content, file=snapcraft_yaml_file) snapcraft_project = project.Project( snapcraft_yaml_file_path=snapcraft_yaml_path.as_posix(), target_deb_arch=target_deb_arch, ) return load_config(snapcraft_project)
def make_snapcraft_project(self, apps): snapcraft_yaml = fixture_setup.SnapcraftYaml(self.path) snapcraft_yaml.update_part("part1", dict(plugin="nil")) for app_name, app in apps: snapcraft_yaml.update_app(app_name, app) self.useFixture(snapcraft_yaml) p = project.Project( snapcraft_yaml_file_path=snapcraft_yaml.snapcraft_yaml_file_path) return load_config(p)
def _get_snap_packaging(self, **yaml_args): if "parts" not in yaml_args: yaml_args["parts"] = dict(part1=dict(plugin="nil")) snapcraft_yaml = fixture_setup.SnapcraftYaml(self.path, **yaml_args) self.useFixture(snapcraft_yaml) project = Project( snapcraft_yaml_file_path=snapcraft_yaml.snapcraft_yaml_file_path) config = load_config(project) return _SnapPackaging(project_config=config, extracted_metadata=None)
def test_non_prime_and_no_version(self): snapcraft_yaml = fixture_setup.SnapcraftYaml(self.path, version=None) snapcraft_yaml.data["adopt-info"] = "test-part" snapcraft_yaml.update_part( "test-part", { "plugin": "nil", "override-build": "snapcraftctl set-version 1.0" }, ) self.useFixture(snapcraft_yaml) project = Project( snapcraft_yaml_file_path=snapcraft_yaml.snapcraft_yaml_file_path) project_config = project_loader.load_config(project) # This should not fail lifecycle.execute(steps.PULL, project_config)
def make_snapcraft_project(self, parts, snap_type=""): yaml = textwrap.dedent("""\ name: test base: core18 version: "1.0" summary: test description: test confinement: strict grade: stable {type} {parts} """) self.snapcraft_yaml_file_path = self.make_snapcraft_yaml( yaml.format(parts=parts, type=snap_type)) project = snapcraft_legacy.project.Project( snapcraft_yaml_file_path=self.snapcraft_yaml_file_path) return project_loader.load_config(project)
def _execute( # noqa: C901 step: steps.Step, parts: Sequence[str], pack_project: bool = False, output: Optional[str] = None, shell: bool = False, shell_after: bool = False, setup_prime_try: bool = False, ua_token: Optional[str] = None, **kwargs, ) -> "Project": # Cleanup any previous errors. _clean_provider_error() build_provider = get_build_provider(**kwargs) build_provider_flags = get_build_provider_flags( build_provider, ua_token=ua_token, **kwargs ) apply_host_provider_flags(build_provider_flags) is_managed_host = build_provider == "managed-host" # Temporary fix to ignore target_arch. if kwargs.get("target_arch") is not None and build_provider in ["multipass", "lxd"]: echo.warning( "Ignoring '--target-arch' flag. This flag requires --destructive-mode and is unsupported with Multipass and LXD build providers." ) kwargs.pop("target_arch") project = get_project(is_managed_host=is_managed_host, **kwargs) conduct_project_sanity_check(project, **kwargs) project_path = pathlib.Path(project._project_dir) if project_path.name in ["build-aux", "snap"]: echo.warning( f"Snapcraft is running in directory {project_path.name!r}. If this is the snap assets directory, please run snapcraft from {project_path.parent}." ) if build_provider in ["host", "managed-host"]: with ua_manager.ua_manager(ua_token): project_config = project_loader.load_config(project) lifecycle.execute(step, project_config, parts) if pack_project: _pack( project.prime_dir, compression=project._snap_meta.compression, output=output, ) else: build_provider_class = build_providers.get_provider_for(build_provider) try: build_provider_class.ensure_provider() except build_providers.errors.ProviderNotFound as provider_error: if provider_error.prompt_installable: if echo.is_tty_connected() and echo.confirm( "Support for {!r} needs to be set up. " "Would you like to do it now?".format(provider_error.provider) ): build_provider_class.setup_provider(echoer=echo) else: raise provider_error else: raise provider_error with build_provider_class( project=project, echoer=echo, build_provider_flags=build_provider_flags ) as instance: try: if shell: # shell means we want to do everything right up to the previous # step and then go into a shell instead of the requested step. # the "snap" target is a special snowflake that has not made its # way to be a proper step. previous_step = None if pack_project: previous_step = steps.PRIME elif step > steps.PULL: previous_step = step.previous_step() # steps.PULL is the first step, so we would directly shell into it. if previous_step: instance.execute_step(previous_step, part_names=parts) elif pack_project: instance.pack_project(output=output) elif setup_prime_try: instance.expose_prime() instance.execute_step(step, part_names=parts) else: instance.execute_step(step, part_names=parts) except Exception: _retrieve_provider_error(instance) if project.debug: instance.shell() else: echo.warning( "Run the same command again with --debug to shell into the environment " "if you wish to introspect this failure." ) raise else: if shell or shell_after: instance.shell() return project
def setUp(self): super().setUp() self.useFixture(fixtures.FakeLogger(level=logging.ERROR)) temp_cwd = fixture_setup.TempCWD() self.useFixture(temp_cwd) snapcraft_yaml = fixture_setup.SnapcraftYaml( temp_cwd.path, base="core18", parts={"test-part": { "plugin": "nil" }}) self.useFixture(snapcraft_yaml) project = Project( snapcraft_yaml_file_path=snapcraft_yaml.snapcraft_yaml_file_path) self.global_state_filepath = project._get_global_state_file_path() self.project_config = project_loader.load_config(project) self.useFixture( fixtures.MockPatchObject(self.project_config, "get_build_snaps", return_value={"core18"})) self.useFixture( fixtures.MockPatch( "snapcraft_legacy.internal.lifecycle._runner._Executor.run")) self.useFixture( fixtures.MockPatch( "snapcraft_legacy.internal.repo.snaps.install_snaps")) # Avoid unnecessary calls to info. channel_map = [] for arch in ("amd64", "i386", "s390x", "arm64", "armhf", "ppc64el"): channel_map.append({ "channel": { "architecture": arch, "name": "stable", "released-at": "2019-10-15T13:54:06.800280+00:00", "risk": "stable", "track": "latest", }, "confinement": "strict", "download": { "deltas": [], "sha3-384": "64d232d6bfa65be14d7f8d84e952d4e372e12021e2c3dbaf70cf2af5e78bf51c4baf9c9107dd6db815064636b781bda6", "size": 57151488, "url": "https://api.snapcraft.io/api/v1/snaps/download/CSO04Jhav2yK0uz97cr0ipQRyqg0qQL6_1223.snap", }, "revision": 1223, }) info = { "channel-map": channel_map, "default-track": None, "name": "core18", "snap": { "name": "core18", "publisher": { "display-name": "Canonical", "id": "canonical", "username": "******", "validation": "verified", }, "snap-id": "CSO04Jhav2yK0uz97cr0ipQRyqg0qQL6", }, "snap-id": "CSO04Jhav2yK0uz97cr0ipQRyqg0qQL6", } self.fake_storeapi_get_info = fixtures.MockPatch( "snapcraft_legacy.storeapi._snap_api.SnapAPI.get_info", return_value=SnapInfo(info), ) self.useFixture(self.fake_storeapi_get_info)