diff --git a/cumulusci/salesforce_api/package_zip.py b/cumulusci/salesforce_api/package_zip.py index bf12bf1f84..c84aff4b4e 100644 --- a/cumulusci/salesforce_api/package_zip.py +++ b/cumulusci/salesforce_api/package_zip.py @@ -117,7 +117,8 @@ def from_zipfile(cls, zf, *, options=None, logger=None): def _convert_sfdx_format(self, path, name): orig_path = path with contextlib.ExitStack() as stack: - if not pathlib.Path(path, "package.xml").exists(): + # convert sfdx -> mdapi format if path exists but does not have package.xml + if len(os.listdir(path)) and not pathlib.Path(path, "package.xml").exists(): self.logger.info("Converting from sfdx to mdapi format") path = stack.enter_context(temporary_dir(chdir=False)) args = ["-r", str(orig_path), "-d", path] diff --git a/cumulusci/salesforce_api/tests/test_package_zip.py b/cumulusci/salesforce_api/tests/test_package_zip.py index ec799774fa..91c39cb9bf 100644 --- a/cumulusci/salesforce_api/tests/test_package_zip.py +++ b/cumulusci/salesforce_api/tests/test_package_zip.py @@ -317,12 +317,21 @@ def test_include_file(self): def test_convert_sfdx(self): with temporary_dir() as path: + touch("README.md") # make sure there's something in the directory with mock.patch("cumulusci.salesforce_api.package_zip.sfdx") as sfdx: builder = MetadataPackageZipBuilder() with builder._convert_sfdx_format(path, "Test Package"): pass sfdx.assert_called_once() + def test_convert_sfdx__skipped_if_directory_empty(self): + with temporary_dir() as path: + with mock.patch("cumulusci.salesforce_api.package_zip.sfdx") as sfdx: + builder = MetadataPackageZipBuilder() + with builder._convert_sfdx_format(path, "Test Package"): + pass + sfdx.assert_not_called() + def test_removes_feature_parameters_from_unlocked_package(self): with temporary_dir() as path: pathlib.Path(path, "package.xml").write_text( diff --git a/cumulusci/tasks/salesforce/Deploy.py b/cumulusci/tasks/salesforce/Deploy.py index 7af67eed5e..7f9e852705 100644 --- a/cumulusci/tasks/salesforce/Deploy.py +++ b/cumulusci/tasks/salesforce/Deploy.py @@ -79,7 +79,11 @@ def _get_api(self, path=None): path = self.options.get("path") package_zip = self._get_package_zip(path) - self.logger.info("Payload size: {} bytes".format(len(package_zip))) + if package_zip is not None: + self.logger.info("Payload size: {} bytes".format(len(package_zip))) + else: + self.logger.warning("Deployment package is empty; skipping deployment.") + return return self.api_class( self, @@ -113,9 +117,12 @@ def _get_package_zip(self, path): "namespaced_org": self._is_namespaced_org(namespace), } - return MetadataPackageZipBuilder( + package_zip = MetadataPackageZipBuilder( path=path, options=options, logger=self.logger - ).as_base64() + ) + if not package_zip.zf.namelist(): + return + return package_zip.as_base64() def freeze(self, step): steps = super(Deploy, self).freeze(step) diff --git a/cumulusci/tasks/salesforce/tests/test_Deploy.py b/cumulusci/tasks/salesforce/tests/test_Deploy.py index 72059b8c92..6a8b7e2043 100644 --- a/cumulusci/tasks/salesforce/tests/test_Deploy.py +++ b/cumulusci/tasks/salesforce/tests/test_Deploy.py @@ -114,6 +114,19 @@ def test_get_api__static_resources(self): self.assertIn("StaticResource", package_xml) self.assertIn("TestBundle", package_xml) + def test_get_api__empty_package_zip(self): + with temporary_dir() as path: + task = create_task( + Deploy, + { + "path": path, + "unmanaged": True, + }, + ) + + api = task._get_api() + assert api is None + def test_init_options(self): with self.assertRaises(TaskOptionsError): create_task(