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)
Exemple #3
0
 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)
Exemple #4
0
    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, {})
Exemple #7
0
    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()))
Exemple #8
0
    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()))
Exemple #9
0
    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)
Exemple #13
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
Exemple #14
0
    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
Exemple #15
0
 def test_cd__no_path(self):
     cwd = os.getcwd()
     with utils.cd(None):
         self.assertEqual(cwd, os.getcwd())
Exemple #16
0
 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)
Exemple #20
0
    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
Exemple #21
0
 def test_cd__no_path(self):
     cwd = os.getcwd()
     with utils.cd(None):
         assert cwd == os.getcwd()
 def test_cd__no_path(self):
     cwd = os.getcwd()
     with utils.cd(None):
         self.assertEqual(cwd, os.getcwd())
Exemple #23
0
    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)