def test_dsc_include_missing_file_no_fail_mode(self): ''' This tests whether includes work properly if no fail mode is on''' workspace = tempfile.mkdtemp() file1_name = "file1.dsc" file1_path = os.path.join(workspace, file1_name) file1_data = "!include BAD_FILE.dsc" TestDscParserIncludes.write_to_file(file1_path, file1_data) parser = DscParser() parser.SetNoFailMode() parser.SetBaseAbsPath(workspace) parser.ParseFile(file1_path)
def get_packages_to_build(self, possible_packages: list) -> dict: self.parsed_dec_cache = {} (rc, files) = self._get_files_that_changed_in_this_pr(self.pr_target) if rc != 0: return {} remaining_packages = possible_packages.copy() # start with all possible packages and remove each # package once it is determined to be build. This optimization # avoids checking packages that already will be built. packages_to_build = {} # packages to build. Key = pkg name, Value = 1st reason for build # # Policy 1 - CI Settings file defined # after = self.PlatformSettings.FilterPackagesToTest(files, remaining_packages) for a in after: if a not in remaining_packages: raise ValueError(f"PlatformSettings.FilterPackagesToTest returned package not allowed {a}") packages_to_build[a] = "Policy 1 - PlatformSettings - Filter Packages" remaining_packages.remove(a) # No more packages to eval - return the results if len(remaining_packages) == 0: return packages_to_build # # Policy 2: Build any package that has changed # for f in files: try: pkg = self.edk2_path_obj.GetContainingPackage(os.path.abspath(f)) except Exception as e: self.logger.warning(f"Failed to get package for file {f}. Exception {e}") # Ignore a file in which we fail to get the package continue if(pkg not in packages_to_build.keys() and pkg in remaining_packages): packages_to_build[pkg] = "Policy 2 - Build any package that has changed" remaining_packages.remove(pkg) # No more packages to eval - return the results if len(remaining_packages) == 0: return packages_to_build # # Policy 3: If a file change is a public file then build all packages that # are dependent on that package. # # list of packages with public files that have changed public_package_changes = [] # Get all public files in packages for f in files: try: pkg = self.edk2_path_obj.GetContainingPackage(os.path.abspath(f)) except Exception as e: self.logger.warning(f"Failed to get package for file {f}. Exception {e}") # Ignore a file in which we fail to get the package continue if self._is_public_file(f): public_package_changes.append(pkg) # de-duplicate list public_package_changes = list(set(public_package_changes)) # Now check all remaining packages to see if they depend on the set of packages # with public file changes. # NOTE: future enhancement could be to check actual file dependencies for a in public_package_changes: for p in remaining_packages[:]: # slice so we can delete as we go if(self._does_pkg_depend_on_package(p, a)): packages_to_build[p] = f"Policy 3 - Package depends on {a}" remaining_packages.remove(p) # remove from remaining packages # No more packages to eval - return the results if len(remaining_packages) == 0: return packages_to_build # # Policy 4: If a file changed in a module and that module is used in the provided dsc file # then the package of the dSC file must be built # PlatformDscInfo = self.PlatformSettings.GetPlatformDscAndConfig() if PlatformDscInfo is not None and len(remaining_packages) > 0: if len(remaining_packages) != 1: raise Exception("Policy 4 can only be used by builds for a single package") # files are all the files changed edk2 workspace root relative path changed_modules = self._get_unique_module_infs_changed(files) # now check DSC dsc = DscParser() dsc.SetBaseAbsPath(self.edk2_path_obj.WorkspacePath) dsc.SetPackagePaths(self.edk2_path_obj.PackagePathList) # given that PR eval runs before dependencies are downloaded we must tolerate errors dsc.SetNoFailMode() dsc.SetInputVars(PlatformDscInfo[1]) dsc.ParseFile(PlatformDscInfo[0]) allinfs = dsc.OtherMods + dsc.ThreeMods + dsc.SixMods + dsc.Libs # get list of all INF files # # Note: for now we assume that remaining_packages has only 1 package and that it corresponds # to the DSC file provided. # for p in remaining_packages[:]: # slice so we can delete as we go for cm in changed_modules: if cm in allinfs: # is the changed module listed in the DSC file? packages_to_build[p] = f"Policy 4 - Package Dsc depends on {cm}" remaining_packages.remove(p) # remove from remaining packages break # All done now return result return packages_to_build