def test_load_project_config_no_config(self, mock_class): mock_class.return_value = self.tempdir_home os.mkdir(os.path.join(self.tempdir_project, ".git")) with cd(self.tempdir_project): universal_config = UniversalConfig() with self.assertRaises(ProjectConfigNotFound): BaseProjectConfig(universal_config)
def _run_task(self): chdir = self.options.get("chdir") if chdir: self.logger.info("Changing directory to {}".format(chdir)) with cd(chdir): for element in self.options["elements"]: self._process_element(element)
def _process_static_resources(self, zip_src): relpath = self.options.get("static_resource_path") if not relpath or not os.path.exists(relpath): return zip_src path = os.path.realpath(relpath) # We need to build a new zip file so that we can replace package.xml zip_dest = zipfile.ZipFile(io.BytesIO(), "w", zipfile.ZIP_DEFLATED) for name in zip_src.namelist(): if name == "package.xml": package_xml = zip_src.open(name) else: content = zip_src.read(name) zip_dest.writestr(name, content) # Build static resource bundles and add to package zip with temporary_dir(): os.mkdir("staticresources") bundles = [] for name in os.listdir(path): bundle_relpath = os.path.join(relpath, name) bundle_path = os.path.join(path, name) if not os.path.isdir(bundle_path): continue self.logger.info( "Zipping {} to add to staticresources".format(bundle_relpath) ) # Add resource-meta.xml file meta_name = "{}.resource-meta.xml".format(name) meta_path = os.path.join(path, meta_name) with open(meta_path, "rb") as f: zip_dest.writestr("staticresources/{}".format(meta_name), f.read()) # Add bundle zip_path = os.path.join("staticresources", "{}.resource".format(name)) with open(zip_path, "wb") as bundle_fp: bundle_zip = zipfile.ZipFile(bundle_fp, "w", zipfile.ZIP_DEFLATED) with cd(bundle_path): for resource_file in self._get_static_resource_files(): bundle_zip.write(resource_file) bundle_zip.close() zip_dest.write(zip_path) bundles.append(name) # Update package.xml Package = metadata_tree.parse(package_xml) sections = Package.findall("types", name="StaticResource") section = sections[0] if sections else None if not section: section = Package.append("types") section.append("name", text="StaticResource") for name in bundles: section.insert_before(section.find("name"), tag="members", text=name) package_xml = Package.tostring(xml_declaration=True) zip_dest.writestr("package.xml", package_xml) return zip_dest
def test_repo_commit(self, mock_class): mock_class.return_value = self.tempdir_home os.mkdir(os.path.join(self.tempdir_project, ".git")) self._create_git_config() # create valid project config file self._create_project_config() with cd(self.tempdir_project): universal_config = UniversalConfig() config = BaseProjectConfig(universal_config) self.assertEqual(config.repo_commit, self.current_commit)
def test_load_project_config_empty_config(self, mock_class): mock_class.return_value = self.tempdir_home os.mkdir(os.path.join(self.tempdir_project, ".git")) self._create_git_config() # create empty project config file filename = os.path.join(self.tempdir_project, BaseProjectConfig.config_filename) content = "" self._write_file(filename, content) with cd(self.tempdir_project): universal_config = UniversalConfig() config = BaseProjectConfig(universal_config) self.assertEqual(config.config_project, {})
def _get_package_zip(self, path): # Build the zip file zip_bytes = io.BytesIO() zipf = zipfile.ZipFile(zip_bytes, "w", zipfile.ZIP_DEFLATED) with cd(path): for root, dirs, files in os.walk("."): for f in files: self._write_zip_file(zipf, root, f) zipf.close() zipf_processed = self._process_zip_file(zipfile.ZipFile(zip_bytes)) fp = zipf_processed.fp zipf_processed.close() return bytes_to_native_str(base64.b64encode(fp.getvalue()))
def _get_package_zip(self, path): # Build the zip file zip_bytes = io.BytesIO() zipf = zipfile.ZipFile(zip_bytes, "w", zipfile.ZIP_DEFLATED) with cd(path): for file_to_package in self._get_files_to_package(path): zipf.write(file_to_package) zipf.close() zipf_processed = self._process_zip_file(zipfile.ZipFile(zip_bytes)) fp = zipf_processed.fp zipf_processed.close() return bytes_to_native_str(base64.b64encode(fp.getvalue()))
def __call__(self): if self.salesforce_task and not self.org_config: raise TaskRequiresSalesforceOrg( "This task requires a salesforce org. " "Use org default <name> to set a default org " "or pass the org name with the --org option") self._update_credentials() self._init_task() with stacked_task(self): self.working_path = os.getcwd() with cd(self.project_config.repo_root): self._log_begin() self.result = self._run_task() return self.return_values
def test_load_project_config_valid_config(self, mock_class): mock_class.return_value = self.tempdir_home os.mkdir(os.path.join(self.tempdir_project, ".git")) self._create_git_config() local_yaml = "tasks:\n newtesttask:\n description: test description" self._create_universal_config_local(local_yaml) # create valid project config file self._create_project_config() with cd(self.tempdir_project): universal_config = UniversalConfig() config = BaseProjectConfig(universal_config) self.assertEqual(config.project__package__name, "TestProject") self.assertEqual(config.project__package__namespace, "testproject")
def _get_package_zip(self, path): # Build the zip file zip_bytes = io.BytesIO() zipf = zipfile.ZipFile(zip_bytes, "w", zipfile.ZIP_DEFLATED) with cd(path): for file_to_package in self._get_files_to_package(): zipf.write(file_to_package) zipf.close() zipf_processed = self._process_zip_file(zipfile.ZipFile(zip_bytes)) fp = zipf_processed.fp zipf_processed.close() return bytes_to_native_str(base64.b64encode(fp.getvalue()))
def test_load_additional_yaml(self, mock_class): mock_class.return_value = self.tempdir_home os.mkdir(os.path.join(self.tempdir_project, ".git")) self._create_git_config() # create valid project config file self._create_project_config() # create local project config file content = "project:\n" + " package:\n" + " api_version: 45.0\n" with cd(self.tempdir_project): universal_config = UniversalConfig() config = BaseProjectConfig(universal_config, additional_yaml=content) self.assertNotEqual(config.config_additional_yaml, {}) self.assertEqual(config.project__package__api_version, 45.0)
def _freeze_steps(self, project_config, plan_config): steps = plan_config["steps"] flow_config = FlowConfig(plan_config) flow_config.project_config = project_config flow = FlowCoordinator(project_config, flow_config) steps = [] for step in flow.steps: if step.skip: continue with cd(step.project_config.repo_root): task = step.task_class( step.project_config, TaskConfig(step.task_config), name=step.task_name, ) steps.extend(task.freeze(step)) return steps
def __call__(self): # If sentry is configured, initialize sentry for error capture self.project_config.init_sentry() if self.salesforce_task and not self.org_config: raise TaskRequiresSalesforceOrg( "This task requires a salesforce org. " "Use org default <name> to set a default org " "or pass the org name with the --org option") self._update_credentials() self._init_task() with stacked_task(self): self.working_path = os.getcwd() with cd(self.project_config.repo_root): try: self._log_begin() self.result = self._run_task() return self.return_values except Exception as e: self._process_exception(e) raise
def test_cd__no_path(self): cwd = os.getcwd() with utils.cd(None): self.assertEqual(cwd, os.getcwd())
def _run_task(self): if self.chdir: self.logger.info("Changing directory to {}".format(self.chdir)) with cd(self.chdir): for element in self.elements: self._process_element(element)
def _process_static_resources(self, zip_src): relpath = self.options.get("static_resource_path") if not relpath or not os.path.exists(relpath): return zip_src path = os.path.realpath(relpath) # We need to build a new zip file so that we can replace package.xml zip_dest = zipfile.ZipFile(io.BytesIO(), "w", zipfile.ZIP_DEFLATED) for name in zip_src.namelist(): content = zip_src.read(name) if name == "package.xml": package_xml = content else: zip_dest.writestr(name, content) # Build static resource bundles and add to package zip with temporary_dir(): os.mkdir("staticresources") bundles = [] for name in os.listdir(path): bundle_relpath = os.path.join(relpath, name) bundle_path = os.path.join(path, name) if not os.path.isdir(bundle_path): continue self.logger.info( "Zipping {} to add to staticresources".format(bundle_relpath) ) # Add resource-meta.xml file meta_name = "{}.resource-meta.xml".format(name) meta_path = os.path.join(path, meta_name) with open(meta_path, "rb") as f: zip_dest.writestr("staticresources/{}".format(meta_name), f.read()) # Add bundle zip_path = os.path.join("staticresources", "{}.resource".format(name)) with open(zip_path, "wb") as bundle_fp: bundle_zip = zipfile.ZipFile(bundle_fp, "w", zipfile.ZIP_DEFLATED) with cd(bundle_path): for resource_file in self._get_static_resource_files(): bundle_zip.write(resource_file) bundle_zip.close() zip_dest.write(zip_path) bundles.append(name) # Update package.xml tree = ET.fromstring(package_xml) section = tree.find(".//sf:types[sf:name='StaticResource']", self.namespaces) if section is None: section = ET.Element("{{{}}}types".format(self.namespaces["sf"])) name = ET.Element("{{{}}}name".format(self.namespaces["sf"])) section.append(name) name.text = "StaticResource" tree.find(".//sf:types[last()]", self.namespaces).addnext(section) for name in bundles: member = ET.Element("{{{}}}members".format(self.namespaces["sf"])) member.text = name section.find(".//sf:name", self.namespaces).addprevious(member) package_xml = ET.tostring(tree) zip_dest.writestr("package.xml", package_xml) return zip_dest
def test_get_package_zip(self): with temporary_dir() as path: # add package.xml with open(os.path.join(path, "package.xml"), "w") as f: f.write( """<?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <version>45.0</version> </Package>""" ) # add lwc lwc_path = os.path.join(path, "lwc") os.mkdir(lwc_path) # add lwc linting files (not included in zip) lwc_ignored_files = [".eslintrc.json", "jsconfig.json"] for lwc_ignored_file in lwc_ignored_files: touch(os.path.join(lwc_path, lwc_ignored_file)) # add lwc component lwc_component_path = os.path.join(lwc_path, "myComponent") os.mkdir(lwc_component_path) # add lwc component files included in zip (in alphabetical order) lwc_component_files = [ {"name": "myComponent.html"}, {"name": "myComponent.js"}, { "name": "myComponent.js-meta.xml", "body:": """<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="myComponent"> <apiVersion>45.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle>""", }, {"name": "myComponent.svg"}, {"name": "myComponent.css"}, ] for lwc_component_file in lwc_component_files: with open( os.path.join(lwc_component_path, lwc_component_file.get("name")), "w", ) as f: if lwc_component_file.get("body") is not None: f.write(lwc_component_file.get("body")) # add lwc component files not included in zip for lwc_ignored_file in lwc_ignored_files: touch(os.path.join(lwc_component_path, lwc_ignored_file)) # add lwc component sub-directory and files not included in zip lwc_component_test_path = os.path.join(lwc_component_path, "__tests__") os.mkdir(lwc_component_test_path) touch(os.path.join(lwc_component_test_path, "test.js")) # add classes classes_path = os.path.join(path, "classes") os.mkdir(classes_path) class_files = [ { "name": "MyClass.cls-meta.xml", "body": """<?xml version="1.0" encoding="UTF-8"?> <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>45.0</apiVersion> <status>Active</status> </ApexClass> """, }, {"name": "MyClass.cls"}, ] for class_file in class_files: with open(os.path.join(classes_path, class_file.get("name")), "w") as f: if class_file.get("body") is not None: f.write(class_file.get("body")) # add objects objects_path = os.path.join(path, "objects") os.mkdir(objects_path) object_file_names = ["Account.object", "Contact.object", "CustomObject__c"] object_file_names.sort() for object_file_name in object_file_names: touch(os.path.join(objects_path, object_file_name)) # add sub-directory of objects (that doesn't really exist) objects_sub_path = os.path.join(objects_path, "does-not-exist-in-schema") os.mkdir(objects_sub_path) touch(os.path.join(objects_sub_path, "some.file")) # test task = create_task( Deploy, { "path": path, "namespace_tokenize": "ns", "namespace_inject": "ns", "namespace_strip": "ns", }, ) zip_bytes = io.BytesIO() zipf = zipfile.ZipFile(zip_bytes, "w", zipfile.ZIP_DEFLATED) with cd(path): for file_to_package in task._get_files_to_package(): zipf.write(file_to_package) zipf.close() zipf_processed = task._process_zip_file(zipfile.ZipFile(zip_bytes)) fp = zipf_processed.fp zipf_processed.close() expected = bytes_to_native_str(base64.b64encode(fp.getvalue())) actual = task._get_package_zip(path) self.assertEqual(expected, actual)
def test_load_project_config_not_repo(self, mock_class): mock_class.return_value = self.tempdir_home with cd(self.tempdir_project): universal_config = UniversalConfig() with self.assertRaises(NotInProject): BaseProjectConfig(universal_config)
def _process_static_resources(self, zip_src): relpath = self.options.get("static_resource_path") if not relpath or not os.path.exists(relpath): return zip_src path = os.path.realpath(relpath) # We need to build a new zip file so that we can replace package.xml zip_dest = zipfile.ZipFile(io.BytesIO(), "w", zipfile.ZIP_DEFLATED) for name in zip_src.namelist(): content = zip_src.read(name) if name == "package.xml": package_xml = content else: zip_dest.writestr(name, content) # Build static resource bundles and add to package zip with temporary_dir(): os.mkdir("staticresources") bundles = [] for name in os.listdir(path): bundle_relpath = os.path.join(relpath, name) bundle_path = os.path.join(path, name) if not os.path.isdir(bundle_path): continue self.logger.info("Zipping {} to add to staticresources".format( bundle_relpath)) # Add resource-meta.xml file meta_name = "{}.resource-meta.xml".format(name) meta_path = os.path.join(path, meta_name) with open(meta_path, "rb") as f: zip_dest.writestr("staticresources/{}".format(meta_name), f.read()) # Add bundle zip_path = os.path.join("staticresources", "{}.resource".format(name)) with open(zip_path, "wb") as bundle_fp: bundle_zip = zipfile.ZipFile(bundle_fp, "w", zipfile.ZIP_DEFLATED) with cd(bundle_path): for resource_file in self._get_static_resource_files(): bundle_zip.write(resource_file) bundle_zip.close() zip_dest.write(zip_path) bundles.append(name) # Update package.xml tree = ET.fromstring(package_xml) section = tree.find(".//sf:types[sf:name='StaticResource']", self.namespaces) if section is None: section = ET.Element("{{{}}}types".format(self.namespaces["sf"])) name = ET.Element("{{{}}}name".format(self.namespaces["sf"])) section.append(name) name.text = "StaticResource" tree.find(".//sf:types[last()]", self.namespaces).addnext(section) for name in bundles: member = ET.Element("{{{}}}members".format(self.namespaces["sf"])) member.text = name section.find(".//sf:name", self.namespaces).addprevious(member) package_xml = ET.tostring(tree) zip_dest.writestr("package.xml", package_xml) return zip_dest
def test_cd__no_path(self): cwd = os.getcwd() with utils.cd(None): assert cwd == os.getcwd()
def test_get_package_zip(self): with temporary_dir() as path: # add package.xml with open(os.path.join(path, "package.xml"), "w") as f: f.write("""<?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <version>45.0</version> </Package>""") # add lwc lwc_path = os.path.join(path, "lwc") os.mkdir(lwc_path) # add lwc linting files (not included in zip) lwc_ignored_files = [".eslintrc.json", "jsconfig.json"] for lwc_ignored_file in lwc_ignored_files: with open(os.path.join(lwc_path, lwc_ignored_file), "w"): pass # add lwc component lwc_component_path = os.path.join(lwc_path, "myComponent") os.mkdir(lwc_component_path) # add lwc component files included in zip (in alphabetical order) lwc_component_files = [ { "name": "myComponent.html" }, { "name": "myComponent.js" }, { "name": "myComponent.js-meta.xml", "body:": """<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="myComponent"> <apiVersion>45.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle>""", }, { "name": "myComponent.svg" }, { "name": "myComponent.css" }, ] for lwc_component_file in lwc_component_files: with open( os.path.join(lwc_component_path, lwc_component_file.get("name")), "w", ) as f: if lwc_component_file.get("body") is not None: f.write(lwc_component_file.get("body")) # add lwc component files not included in zip for lwc_ignored_file in lwc_ignored_files: with open(os.path.join(lwc_component_path, lwc_ignored_file), "w"): pass # add lwc component sub-directory and files not included in zip lwc_component_test_path = os.path.join(lwc_component_path, "__tests__") os.mkdir(lwc_component_test_path) with open(os.path.join(lwc_component_test_path, "test.js"), "w"): pass # add classes classes_path = os.path.join(path, "classes") os.mkdir(classes_path) class_files = [ { "name": "MyClass.cls-meta.xml", "body": """<?xml version="1.0" encoding="UTF-8"?> <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>45.0</apiVersion> <status>Active</status> </ApexClass> """, }, { "name": "MyClass.cls" }, ] for class_file in class_files: with open(os.path.join(classes_path, class_file.get("name")), "w") as f: if class_file.get("body") is not None: f.write(class_file.get("body")) # add objects objects_path = os.path.join(path, "objects") os.mkdir(objects_path) object_file_names = [ "Account.object", "Contact.object", "CustomObject__c" ] object_file_names.sort() for object_file_name in object_file_names: with open(os.path.join(objects_path, object_file_name), "w"): pass # add sub-directory of objects (that doesn't really exist) objects_sub_path = os.path.join(objects_path, "does-not-exist-in-schema") os.mkdir(objects_sub_path) with open(os.path.join(objects_sub_path, "some.file"), "w"): pass # test task = create_task( Deploy, { "path": path, "namespace_tokenize": "ns", "namespace_inject": "ns", "namespace_strip": "ns", }, ) zip_bytes = io.BytesIO() zipf = zipfile.ZipFile(zip_bytes, "w", zipfile.ZIP_DEFLATED) with cd(path): for file_to_package in task._get_files_to_package(path): zipf.write(file_to_package) zipf.close() zipf_processed = task._process_zip_file(zipfile.ZipFile(zip_bytes)) fp = zipf_processed.fp zipf_processed.close() expected = bytes_to_native_str(base64.b64encode(fp.getvalue())) actual = task._get_package_zip(path) self.assertEqual(expected, actual)