def test_check_if_bases_matches_host_matches(mock_get_os_platform, mock_get_host_architecture): base = Base(name="host-os", channel="host-CHANNEL", architectures=["host-ARCH"]) assert check_if_base_matches_host(base) == (True, None) base = Base( name="host-os", channel="host-CHANNEL", architectures=["other-ARCH", "host-ARCH"], ) assert check_if_base_matches_host(base) == (True, None)
def test_check_if_bases_matches_host_channel_mismatch( mock_get_os_platform, mock_get_host_architecture): base = Base(name="host-os", channel="other-CHANNEL", architectures=["host-ARCH"]) assert check_if_base_matches_host(base) == ( False, "channel 'other-CHANNEL' does not match host 'host-CHANNEL'", )
def test_check_if_bases_matches_host_arch_mismatch(mock_get_os_platform, mock_get_host_architecture): base = Base( name="host-os", channel="host-CHANNEL", architectures=["other-ARCH", "other-ARCH2"], ) assert check_if_base_matches_host(base) == ( False, "host architecture 'host-ARCH' not in base architectures ['other-ARCH', 'other-ARCH2']", )
def plan( self, *, bases_indices: Optional[List[int]], destructive_mode: bool, managed_mode: bool ) -> List[Tuple[BasesConfiguration, Base, int, int]]: """Determine the build plan based on user inputs and host environment. Provide a list of bases that are buildable and scoped according to user configuration. Provide all relevant details including the applicable bases configuration and the indices of the entries to build for. :returns: List of Tuples (bases_config, build_on, bases_index, build_on_index). """ build_plan: List[Tuple[BasesConfiguration, Base, int, int]] = [] for bases_index, bases_config in enumerate(self.config.bases): if bases_indices and bases_index not in bases_indices: emit.trace( f"Skipping 'bases[{bases_index:d}]' due to --base-index usage." ) continue for build_on_index, build_on in enumerate(bases_config.build_on): if managed_mode or destructive_mode: matches, reason = check_if_base_matches_host(build_on) else: matches, reason = self.provider.is_base_available(build_on) if matches: emit.trace( f"Building for 'bases[{bases_index:d}]' " f"as host matches 'build-on[{build_on_index:d}]'.", ) build_plan.append( (bases_config, build_on, bases_index, build_on_index)) break else: emit.progress( f"Skipping 'bases[{bases_index:d}].build-on[{build_on_index:d}]': " f"{reason}.", ) else: emit.message( "No suitable 'build-on' environment found " f"in 'bases[{bases_index:d}]' configuration.", intermediate=True, ) return build_plan
def run(self, bases_indices: Optional[List[int]] = None, destructive_mode: bool = False) -> List[str]: """Run build process. In managed-mode or destructive-mode, build for each bases configuration which has a matching build-on to the host we are executing on. Warn for each base configuration that is incompatible. Error if unable to produce any builds for any bases configuration. :returns: List of charm files created. """ charms: List[str] = [] managed_mode = is_charmcraft_running_in_managed_mode() if not managed_mode and not destructive_mode: ensure_provider_is_available() if self.entrypoint: notify_deprecation("dn04") if self.requirement_paths: notify_deprecation("dn05") if not (self.charmdir / "charmcraft.yaml").exists(): notify_deprecation("dn02") for bases_index, bases_config in enumerate(self.config.bases): if bases_indices and bases_index not in bases_indices: logger.debug( "Skipping 'bases[%d]' due to --base-index usage.", bases_index, ) continue for build_on_index, build_on in enumerate(bases_config.build_on): if managed_mode or destructive_mode: matches, reason = check_if_base_matches_host(build_on) else: matches, reason = is_base_providable(build_on) if matches: logger.debug( "Building for 'bases[%d]' as host matches 'build-on[%d]'.", bases_index, build_on_index, ) if managed_mode or destructive_mode: charm_name = self.build_charm(bases_config) else: charm_name = self.pack_charm_in_instance( bases_index=bases_index, build_on=build_on, build_on_index=build_on_index, ) charms.append(charm_name) break else: logger.info( "Skipping 'bases[%d].build-on[%d]': %s.", bases_index, build_on_index, reason, ) else: logger.warning( "No suitable 'build-on' environment found in 'bases[%d]' configuration.", bases_index, ) if not charms: raise CommandError( "No suitable 'build-on' environment found in any 'bases' configuration." ) return charms