Exemple #1
0
def create_task(task_class,
                options=None,
                project_config=None,
                org_config=None):
    "Older create_task helper which does not support orginfo cache."
    if project_config is None:
        project_config = create_project_config("TestRepo", "TestOwner")
    if org_config is None:
        org_config = OrgConfig(
            {
                "instance_url": "https://test.salesforce.com",
                "access_token": "TOKEN",
                "org_id": "ORG_ID",
                "username": "******",
            },
            "test",
            keychain=DummyKeychain(),
        )
        org_config.refresh_oauth_token = mock.Mock()
    if options is None:
        options = {}
    task_config = TaskConfig({"options": options})
    with mock.patch(
            "cumulusci.tasks.salesforce.BaseSalesforceTask._get_client_name",
            return_value="ccitests",
    ):
        return task_class(project_config, task_config, org_config)
Exemple #2
0
    def test_walk_releases__sfdx(self, extract_github):
        project_config = create_project_config()
        project_config.project__git__prefix_release = "rel/"
        project_config.project__name = "Project"

        task = create_task(
            GenerateDataDictionary,
            {
                "object_path": "object.csv",
                "field_path": "fields.csv",
                "release_prefix": "rel/",
            },
            project_config=project_config,
        )

        task.get_repo = Mock()
        release = Mock()
        release.draft = False
        release.prerelease = False
        release.tag_name = "rel/1.1"
        task.get_repo.return_value.releases.return_value = [release]
        task._process_sfdx_release = Mock()
        extract_github.return_value.namelist.return_value = [
            "force-app/main/default/objects/"
        ]

        task._walk_releases()

        task._process_sfdx_release.assert_called_once_with(
            extract_github.return_value, "1.1")
def test_init_options__general():
    project_config = create_project_config(namespace="ns")
    task = create_task(ProfileGrantAllAccess, {"managed": "true"},
                       project_config=project_config)
    assert task.options["managed"]
    assert not task.options["namespaced_org"]
    assert task.options["namespace_inject"] == "ns"
    assert task.namespace_prefixes == {"managed": "ns__", "namespaced_org": ""}

    task = create_task(
        ProfileGrantAllAccess,
        {
            "namespaced_org": "true",
            "managed": False
        },
        project_config=project_config,
    )
    assert not task.options["managed"]
    assert task.options["namespaced_org"]
    assert task.options["namespace_inject"] == "ns"
    assert task.namespace_prefixes == {"managed": "", "namespaced_org": "ns__"}

    task = create_task(ProfileGrantAllAccess, {})
    assert not task.options["managed"]
    assert not task.options["namespaced_org"]
    assert task.options["namespace_inject"] is None
    assert task.namespace_prefixes == {"managed": "", "namespaced_org": ""}
def test_init_options__general():
    pc = create_project_config()
    pc.project__package__namespace = "ns"
    task = create_task(ProfileGrantAllAccess, {"managed": "true"},
                       project_config=pc)
    assert task.options["managed"]
    assert not task.options["namespaced_org"]
    assert task.options["namespace_inject"] == "ns"
    assert task.namespace_prefixes == {"managed": "ns__", "namespaced_org": ""}

    task = create_task(ProfileGrantAllAccess, {"namespaced_org": "true"},
                       project_config=pc)
    assert task.options["managed"]
    assert task.options["namespaced_org"]
    assert task.options["namespace_inject"] == "ns"
    assert task.namespace_prefixes == {
        "managed": "ns__",
        "namespaced_org": "ns__"
    }

    task = create_task(ProfileGrantAllAccess, {}, project_config=pc)
    assert not task.options["managed"]
    assert not task.options["namespaced_org"]
    assert task.options["namespace_inject"] == "ns"
    assert task.namespace_prefixes == {"managed": "", "namespaced_org": ""}
Exemple #5
0
    def test_run_task(self, extract_github):
        # This is an integration test. We mock out `get_repo()` and the filesystem.
        xml_source = """<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <description>Description</description>
    <label>Test</label>
    <fields>
        <fullName>Type__c</fullName>
        <inlineHelpText>Type of field.</inlineHelpText>
        <label>Type</label>
        <type>Text</type>
    </fields>
</CustomObject>"""
        project_config = create_project_config()
        project_config.keychain.get_service = Mock()
        project_config.project__name = "Project"

        task = create_task(
            GenerateDataDictionary,
            {"release_prefix": "rel/"},
            project_config=project_config,
        )

        task.get_repo = Mock()
        release = Mock()
        release.draft = False
        release.prerelease = False
        release.tag_name = "rel/1.1"
        task.get_repo.return_value.releases.return_value = [release]

        extract_github.return_value.namelist.return_value = [
            "src/objects/",
            "src/objects/Test__c.object",
        ]
        extract_github.return_value.read.return_value = xml_source
        m = mock_open()

        with patch("builtins.open", m):
            task()

        m.assert_has_calls(
            [
                call("Project sObject Data Dictionary.csv", "w"),
                call("Project Field Data Dictionary.csv", "w"),
            ],
            any_order=True,
        )
        m.return_value.write.assert_has_calls(
            [
                call(
                    "Object Name,Object Label,Object Description,Version Introduced\r\n"
                ),
                call("Test__c,Test,Description,1.1\r\n"),
                call(
                    "Object Name,Field Name,Field Label,Type,Field Help Text,Picklist Values,Version Introduced\r\n"
                ),
                call("Test__c,Type__c,Type,Text,Type of field.,,1.1\r\n"),
            ],
            any_order=True,
        )
    def test_find_or_create_version__already_exists(self):
        responses.add(
            "GET",
            "https://metadeploy/versions?product=abcdef&label=1.0",
            json={"data": [{"url": "http://EXISTING_VERSION"}]},
        )

        project_config = create_project_config()
        project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
        project_config.config["plans"] = {
            "install": {
                "title": "Test Install",
                "slug": "install",
                "tier": "primary",
                "steps": {1: {"flow": "install_prod"}},
            }
        }
        project_config.keychain.set_service(
            "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
        )
        task_config = TaskConfig({"options": {"tag": "release/1.0"}})
        task = Publish(project_config, task_config)
        task._init_task()
        version = task._find_or_create_version(
            {"url": "http://EXISTING_PRODUCT", "id": "abcdef"}
        )
        self.assertEqual("http://EXISTING_VERSION", version["url"])
Exemple #7
0
    def test_run_task_downgrade_unneeded(self, ApiRetrieveInstalledPackages):
        project_config = create_project_config()
        project_config.get_github_api = mock.Mock()
        project_config.config["project"]["dependencies"] = ({
            "namespace": "package",
            "version": "1.0"
        }, )

        task = create_task(
            UpdateDependencies,
            {
                "allow_newer": True,
                "allow_uninstalls": True
            },
            project_config=project_config,
        )
        ApiRetrieveInstalledPackages.return_value = {"package": "1.1"}

        task.api_class = mock.Mock()
        zf = zipfile.ZipFile(io.BytesIO(), "w")
        task._download_extract_github = mock.Mock(return_value=zf)
        task._download_extract_zip = mock.Mock(return_value=zf)
        task()
        self.assertEqual([], task.install_queue)
        self.assertEqual([], task.uninstall_queue)
    def test_walk_releases__draft(self, extract_github):
        project_config = create_project_config()
        project_config.project__git__prefix_release = "rel/"
        project_config.project__name = "Project"
        task = create_task(GenerateDataDictionary, {},
                           project_config=project_config)
        task._init_schema()

        repo = Mock()
        release_draft = Mock()
        release_draft.draft = False
        release_draft.prerelease = True
        release_draft.tag_name = "rel/1.1_Beta_1"
        release_real = Mock()
        release_real.draft = False
        release_real.prerelease = False
        release_real.tag_name = "rel/1.1"

        repo.releases.return_value = [release_draft, release_real]
        task._process_mdapi_release = Mock()
        extract_github.return_value.namelist.return_value = ["src/objects/"]
        p = Package(repo, "Test", "test__", "rel/")

        task._walk_releases(p)

        task._process_mdapi_release.assert_called_once()
 def test_init_task__named_plan(self):
     project_config = create_project_config()
     project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
     expected_plans = {
         "install": {
             "title": "Test Install",
             "slug": "install",
             "tier": "primary",
             "steps": {
                 1: {
                     "flow": "install_prod"
                 }
             },
         }
     }
     project_config.config["plans"] = expected_plans
     project_config.keychain.set_service(
         "metadeploy",
         ServiceConfig({
             "url": "https://metadeploy",
             "token": "TOKEN"
         }))
     task_config = TaskConfig(
         {"options": {
             "tag": "release/1.0",
             "plan": "install"
         }})
     task = Publish(project_config, task_config)
     task._init_task()
     self.assertEqual(expected_plans, task.plan_configs)
Exemple #10
0
    def test_default_path(self):
        """Verify that if no path is provided, we search robot/<project>"""

        project_config = create_project_config()
        project_config.config["project"]["name"] = "TestPackage"
        task = create_task(RobotLint, {}, project_config=project_config)
        assert task.options["path"] == ["robot/TestPackage"]
Exemple #11
0
    def test_find_or_create_version__commit(self):
        responses.add(
            "GET",
            "https://metadeploy/versions?product=abcdef&label=abcdef",
            json={"data": [{"url": "http://EXISTING_VERSION"}]},
        )

        project_config = create_project_config()
        project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
        project_config.config["plans"] = {
            "install": {
                "title": "Test Install",
                "slug": "install",
                "tier": "primary",
                "steps": {1: {"flow": "install_prod"}},
            }
        }
        project_config.keychain.set_service(
            "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
        )
        task_config = TaskConfig({"options": {"commit": "abcdef"}})
        task = Publish(project_config, task_config)
        task._init_task()
        version = task._find_or_create_version(
            {"url": "http://EXISTING_PRODUCT", "id": "abcdef"}
        )
        self.assertEqual("http://EXISTING_VERSION", version["url"])
    def test_find_or_create_version__already_exists(self):
        responses.add(
            "GET",
            "https://metadeploy/versions?product=abcdef&label=1.0",
            json={"data": [{
                "url": "http://EXISTING_VERSION"
            }]},
        )

        project_config = create_project_config()
        project_config.keychain.set_service(
            "metadeploy",
            ServiceConfig({
                "url": "https://metadeploy",
                "token": "TOKEN"
            }))
        task_config = TaskConfig({
            "options": {
                "flow": "install_prod",
                "product_id": "abcdef",
                "tag": "release/1.0",
                "title": "Test Product",
                "slug": "test",
                "tier": "primary",
            }
        })
        task = Publish(project_config, task_config)
        task._init_task()
        version = task._find_or_create_version()
        self.assertEqual("http://EXISTING_VERSION", version["url"])
def test_install_package_version__error():
    responses.add(
        "POST",
        "https://salesforce/services/data/v50.0/tooling/sobjects/PackageInstallRequest/",
        json={"id": "0Hf"},
    )
    responses.add(
        "GET",
        "https://salesforce/services/data/v50.0/tooling/query/",
        json={
            "records": [
                {
                    "Status": "ERROR",
                    "Errors": {"errors": [{"message": "We have a problem."}]},
                }
            ]
        },
    )

    project_config = create_project_config()
    org_config = OrgConfig(
        {"instance_url": "https://salesforce", "access_token": "TOKEN"}, "test"
    )
    with pytest.raises(PackageInstallError, match="We have a problem."):
        install_package_version(project_config, org_config, {"version_id": "04t"})
def test_install_package_version__not_propagated(caplog):
    caplog.set_level(logging.INFO)
    responses.add(
        "POST",
        "https://salesforce/services/data/v50.0/tooling/sobjects/PackageInstallRequest/",
        json={"id": "0Hf"},
    )
    responses.add(
        "GET",
        "https://salesforce/services/data/v50.0/tooling/query/",
        status=400,
        body="invalid cross reference id",
    )
    responses.add(
        "GET",
        "https://salesforce/services/data/v50.0/tooling/query/",
        json={"records": [{"Status": "SUCCESS"}]},
    )

    project_config = create_project_config()
    org_config = OrgConfig(
        {"instance_url": "https://salesforce", "access_token": "TOKEN"}, "test"
    )
    install_package_version(project_config, org_config, {"version_id": "04t"})
    assert "Retrying" in caplog.text
    assert "Success" in caplog.text
    def test_run_task__commit_not_found(self):
        self.init_github()
        responses.add(
            method=responses.GET,
            url=self.repo_api_url,
            json=self._get_expected_repo("TestOwner", "TestRepo"),
        )
        responses.add(method=responses.GET,
                      url=f"{self.repo_api_url}/commits/abcdef",
                      status=404)

        project_config = create_project_config(repo_commit="abcdef")
        project_config.keychain.set_service(
            "github",
            ServiceConfig({
                "username": "******",
                "token": "TestPass",
                "email": "*****@*****.**",
            }),
        )
        task_config = TaskConfig({"options": {"context": "2gp"}})
        org_config = OrgConfig(
            {
                "instance_url": "https://salesforce",
                "access_token": "TOKEN"
            }, "test")
        task = GetPackageDataFromCommitStatus(project_config, task_config,
                                              org_config)
        task._init_task()
        with pytest.raises(DependencyLookupError,
                           match="Could not find commit abcdef on github"):
            task._run_task()
Exemple #16
0
 def test_run_task__metadata_bundle(self):
     project_config = create_project_config()
     project_config.get_github_api = mock.Mock()
     task = create_task(
         UpdateDependencies,
         {
             "dependencies": [{
                 "repo_owner": "SFDO-Tooling",
                 "repo_name": "CumulusCI-Test",
                 "ref": "abcdef",
                 "subfolder": "src",
                 "namespace_tokenize": "ns",
             }]
         },
         project_config=project_config,
     )
     task._download_extract_github = make_fake_zipfile
     api = mock.Mock()
     task.api_class = mock.Mock(return_value=api)
     task()
     self.assertEqual(
         [{
             "repo_owner": "SFDO-Tooling",
             "repo_name": "CumulusCI-Test",
             "ref": "abcdef",
             "subfolder": "src",
             "namespace_tokenize": "ns",
         }],
         task.install_queue,
     )
     api.assert_called_once()
    def test_get_dependencies__version_not_found(self):
        responses.add(
            "GET",
            "https://salesforce/services/data/v50.0/tooling/query/",
            json={"records": []},
        )

        project_config = create_project_config(repo_commit="abcdef")
        project_config.keychain.set_service(
            "github",
            ServiceConfig({
                "username": "******",
                "token": "TestPass",
                "email": "*****@*****.**",
            }),
        )
        task_config = TaskConfig({"options": {"context": "2gp"}})
        org_config = OrgConfig(
            {
                "instance_url": "https://salesforce",
                "access_token": "TOKEN"
            }, "test")
        task = GetPackageDataFromCommitStatus(project_config, task_config,
                                              org_config)
        task._init_task()
        with pytest.raises(DependencyLookupError,
                           match="Could not look up dependencies of 04t"):
            task._get_dependencies("04t")
    def test_walk_releases__sfdx(self, extract_github):
        project_config = create_project_config()
        project_config.project__git__prefix_release = "rel/"
        project_config.project__name = "Project"

        task = create_task(GenerateDataDictionary, {},
                           project_config=project_config)
        task._init_schema()

        repo = Mock()
        release = Mock()
        release.draft = False
        release.prerelease = False
        release.tag_name = "rel/1.1"
        repo.releases.return_value = [release]
        task._process_sfdx_release = Mock()
        extract_github.return_value.namelist.return_value = [
            "force-app/main/default/objects/"
        ]
        p = Package(repo, "Test", "test__", "rel/")

        task._walk_releases(p)

        task._process_sfdx_release.assert_called_once_with(
            extract_github.return_value,
            PackageVersion(p, StrictVersion("1.1")))
Exemple #19
0
    def test_call_api__collect_pages(self):
        responses.add(
            "GET",
            "https://metadeploy/rest",
            json={
                "data": [1],
                "links": {
                    "next": "https://metadeploy/rest?page=2"
                }
            },
        )
        responses.add(
            "GET",
            "https://metadeploy/rest",
            json={
                "data": [2],
                "links": {
                    "next": None
                }
            },
        )

        project_config = create_project_config()
        project_config.keychain.set_service(
            "metadeploy",
            ServiceConfig({
                "url": "https://metadeploy",
                "token": "TOKEN"
            }))
        task_config = TaskConfig()
        task = BaseMetaDeployTask(project_config, task_config)
        task._init_task()
        results = task._call_api("GET", "/rest", collect_pages=True)
        self.assertEqual([1, 2], results)
Exemple #20
0
 def test_get_destructive_changes(self, UninstallPackageZipBuilder):
     project_config = create_project_config()
     project_config.config["project"]["package"]["namespace"] = "ns"
     task = create_task(UninstallPackage, {}, project_config)
     task.api_class = mock.Mock()
     task._get_api()
     UninstallPackageZipBuilder.assert_called_once()
    def test_init_options__defaults(self):
        project_config = create_project_config()
        project_config.project__name = "Project"

        task = create_task(GenerateDataDictionary, {}, project_config)

        assert task.options["object_path"] == "Project Objects.csv"
        assert task.options["field_path"] == "Project Fields.csv"
Exemple #22
0
 def setUp(self):
     self.project_config = create_project_config()
     self.project_config.keychain = mock.Mock()
     self.project_config.keychain.get_service.side_effect = ServiceNotConfigured
     self.task_config = TaskConfig()
     self.org_config = OrgConfig({},
                                 "test",
                                 keychain=self.project_config.keychain)
    def test_update_dependency_latest_option_err(self):
        project_config = create_project_config()
        project_config.config["project"]["dependencies"] = [{"namespace": "foo"}]
        task = create_task(UpdateDependencies, project_config=project_config)
        task.options["include_beta"] = True
        task.org_config = mock.Mock()

        with self.assertRaises(TaskOptionsError):
            task()
Exemple #24
0
    def setUp(self):
        self.project_config = create_project_config('TestOwner', 'TestRepo')
        self.project_config.config['tasks'] = {
            'pass_name': {
                'description': 'Pass the name',
                'class_path':
                'cumulusci.core.tests.test_flows._TaskReturnsStuff',
            },
            'name_response': {
                'description': 'Pass the name',
                'class_path':
                'cumulusci.core.tests.test_flows._TaskResponseName',
            },
            'raise_exception': {
                'description': 'Raises an exception',
                'class_path':
                'cumulusci.core.tests.test_flows._TaskRaisesException',
                'options': {
                    'exception': Exception,
                    'message': 'Test raised exception as expected',
                }
            },
            'sfdc_task': {
                'description': 'An sfdc task',
                'class_path': 'cumulusci.core.tests.test_flows._SfdcTask'
            },
        }
        self.project_config.config['flows'] = {
            'nested_flow': {
                'description': 'A flow that runs inside another flow',
                'steps': {
                    1: {
                        'task': 'pass_name'
                    },
                },
            },
            'nested_flow_2': {
                'description':
                'A flow that runs inside another flow, and calls another flow',
                'steps': {
                    1: {
                        'task': 'pass_name'
                    },
                    2: {
                        'flow': 'nested_flow'
                    },
                },
            },
        }
        self.org_config = OrgConfig(
            {
                'username': '******',
                'org_id': ORG_ID
            }, 'test')

        self._flow_log_handler.reset()
        self.flow_log = self._flow_log_handler.messages
Exemple #25
0
    def setUp(self):
        self.project_config = create_project_config("TestOwner", "TestRepo")
        self.project_config.config["tasks"] = {
            "pass_name": {
                "description": "Pass the name",
                "class_path":
                "cumulusci.core.tests.test_flows._TaskReturnsStuff",
            },
            "name_response": {
                "description": "Pass the name",
                "class_path":
                "cumulusci.core.tests.test_flows._TaskResponseName",
            },
            "raise_exception": {
                "description": "Raises an exception",
                "class_path":
                "cumulusci.core.tests.test_flows._TaskRaisesException",
                "options": {
                    "exception": Exception,
                    "message": "Test raised exception as expected",
                },
            },
            "sfdc_task": {
                "description": "An sfdc task",
                "class_path": "cumulusci.core.tests.test_flows._SfdcTask",
            },
        }
        self.project_config.config["flows"] = {
            "nested_flow": {
                "description": "A flow that runs inside another flow",
                "steps": {
                    1: {
                        "task": "pass_name"
                    }
                },
            },
            "nested_flow_2": {
                "description":
                "A flow that runs inside another flow, and calls another flow",
                "steps": {
                    1: {
                        "task": "pass_name"
                    },
                    2: {
                        "flow": "nested_flow"
                    }
                },
            },
        }
        self.org_config = OrgConfig(
            {
                "username": "******",
                "org_id": ORG_ID
            }, "test")

        self._flow_log_handler.reset()
        self.flow_log = self._flow_log_handler.messages
    def test_update_dependency_latest_option_err(self):
        project_config = create_project_config()
        project_config.config["project"]["dependencies"] = [{"namespace": "foo"}]
        task = create_task(UpdateDependencies, project_config=project_config)
        task.options["include_beta"] = True
        task.org_config = mock.Mock()

        with self.assertRaises(TaskOptionsError):
            task()
Exemple #27
0
 def test_init_task__no_tag_or_commit(self):
     project_config = create_project_config()
     project_config.keychain.set_service(
         "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
     )
     task_config = TaskConfig({"options": {}})
     task = Publish(project_config, task_config)
     with self.assertRaises(TaskOptionsError):
         task._init_task()
def test_init_options__namespace_injection():
    pc = create_project_config(namespace="ns")
    org_config = DummyOrgConfig({"namespace": "ns"})
    org_config._installed_packages = {"ns": None}
    task = create_task(ProfileGrantAllAccess, {},
                       project_config=pc,
                       org_config=org_config)
    assert task.options["namespace_inject"] == "ns"
    assert task.options["namespaced_org"]
    assert task.options["managed"]
 def test_run_task_with_retry(self):
     project_config = create_project_config()
     project_config.get_latest_version = mock.Mock(return_value="1.0")
     project_config.config["project"]["package"]["namespace"] = "ns"
     task = create_task(InstallPackageVersion, {"version": "latest"}, project_config)
     not_yet = MetadataApiError("This package is not yet available", None)
     api = mock.Mock(side_effect=[not_yet, None])
     task.api_class = mock.Mock(return_value=api)
     task()
     self.assertEqual(2, api.call_count)
Exemple #30
0
 def test_run_task__bad_security_type(self):
     project_config = create_project_config()
     project_config.config["project"]["dependencies"] = PROJECT_DEPENDENCIES
     with self.assertRaises(TaskOptionsError):
         create_task(
             UpdateDependencies,
             {"security_type": "BOGUS"},
             project_config,
             mock.Mock(),
         )
Exemple #31
0
 def test_run_task__bad_security_type(self):
     project_config = create_project_config()
     project_config.get_latest_version = mock.Mock(return_value="1.0")
     project_config.config["project"]["package"]["namespace"] = "ns"
     with self.assertRaises(TaskOptionsError):
         create_task(
             InstallPackageVersion,
             {"version": "latest", "security_type": "BOGUS"},
             project_config,
         )
    def setUp(self):
        self.project_config = create_project_config("TestOwner", "TestRepo")
        self.org_config = OrgConfig(
            {"username": "******", "org_id": ORG_ID}, "test"
        )
        self.org_config.refresh_oauth_token = mock.Mock()

        self._flow_log_handler.reset()
        self.flow_log = self._flow_log_handler.messages
        self._setup_project_config()
 def test_run_task(self):
     with temporary_dir() as path:
         project_config = create_project_config()
         project_config.config["project"]["package"]["name"] = "TestPackage"
         task = create_task(RetrievePackaged, {"path": path}, project_config)
         zf = zipfile.ZipFile(io.BytesIO(), "w")
         zf.writestr("TestPackage/testfile", "test")
         task.api_class = mock.Mock(return_value=mock.Mock(return_value=zf))
         task()
         self.assertTrue(os.path.exists(os.path.join(path, "testfile")))
    def test_call_api__400(self):
        responses.add("GET", "https://metadeploy/rest", status=400, body=b"message")

        project_config = create_project_config()
        project_config.keychain.set_service(
            "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
        )
        task_config = TaskConfig()
        task = BaseMetaDeployTask(project_config, task_config)
        task._init_task()
        with self.assertRaises(requests.exceptions.HTTPError):
            task._call_api("GET", "/rest")
 def test_run_task__options(self):
     project_config = create_project_config()
     project_config.get_latest_version = mock.Mock(return_value="1.0 (Beta 1)")
     project_config.config["project"]["package"]["namespace"] = "ns"
     task = create_task(
         InstallPackageVersion,
         {"version": "latest_beta", "activateRSS": True, "password": "******"},
         project_config,
     )
     api = task._get_api()
     zf = zipfile.ZipFile(io.BytesIO(base64.b64decode(api.package_zip)), "r")
     package_xml = zf.read("installedPackages/ns.installedPackage")
     self.assertIn(b"<activateRSS>true</activateRSS", package_xml)
     self.assertIn(b"<password>astro</password>", package_xml)
    def setUp(self):

        # Set up the mock values
        self.repo_name = "TestRepo"
        self.repo_owner = "TestOwner"
        self.repo_api_url = "https://api.github.com/repos/{}/{}".format(
            self.repo_owner, self.repo_name
        )
        self.branch = "master"

        # Create the project config
        self.project_config = create_project_config(self.repo_name, self.repo_owner)

        if not self.envelope_start:
            self.envelope_start = self.api_class.soap_envelope_start
 def test_find_product__not_found(self):
     responses.add(
         "GET",
         "https://metadeploy/products?repo_url=EXISTING_REPO",
         json={"data": []},
     )
     project_config = create_project_config()
     project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
     project_config.keychain.set_service(
         "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
     )
     task_config = TaskConfig({"options": {"tag": "release/1.0"}})
     task = Publish(project_config, task_config)
     task._init_task()
     with self.assertRaises(Exception):
         task._find_product()
 def setUp(self):
     self.repo_owner = "TestOwner"
     self.repo_name = "TestRepo"
     self.repo_api_url = "https://api.github.com/repos/{}/{}".format(
         self.repo_owner, self.repo_name
     )
     self.project_config = create_project_config(self.repo_name, self.repo_owner)
     self.project_config.keychain.set_service(
         "github",
         ServiceConfig(
             {
                 "username": "******",
                 "password": "******",
                 "email": "*****@*****.**",
             }
         ),
     )
 def setUp(self):
     self.project_config = create_project_config()
     self.project_config.config["project"]["apexdoc"] = {
         "branch": "master",
         "dir": "docs",
         "repo_dir": "docs",
     }
     self.project_config.keychain.set_service(
         "github",
         ServiceConfig(
             {
                 "username": "******",
                 "password": "******",
                 "email": "*****@*****.**",
             }
         ),
     )
 def test_init_task__named_plan(self):
     project_config = create_project_config()
     project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
     expected_plans = {
         "install": {
             "title": "Test Install",
             "slug": "install",
             "tier": "primary",
             "steps": {1: {"flow": "install_prod"}},
         }
     }
     project_config.config["plans"] = expected_plans
     project_config.keychain.set_service(
         "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
     )
     task_config = TaskConfig({"options": {"tag": "release/1.0", "plan": "install"}})
     task = Publish(project_config, task_config)
     task._init_task()
     self.assertEqual(expected_plans, task.plan_configs)
 def test_run_task(self, GithubReleaseNotesGenerator):
     generator = mock.Mock(return_value="notes")
     GithubReleaseNotesGenerator.return_value = generator
     project_config = create_project_config()
     project_config.keychain.set_service(
         "github",
         ServiceConfig(
             {
                 "username": "******",
                 "password": "******",
                 "email": "*****@*****.**",
             }
         ),
     )
     task_config = TaskConfig({"options": {"tag": "release/1.0"}})
     task = GithubReleaseNotes(project_config, task_config)
     task.github = mock.Mock()
     task.get_repo = mock.Mock()
     task()
     generator.assert_called_once()
    def test_call_api__collect_pages(self):
        responses.add(
            "GET",
            "https://metadeploy/rest",
            json={"data": [1], "links": {"next": "https://metadeploy/rest?page=2"}},
        )
        responses.add(
            "GET",
            "https://metadeploy/rest",
            json={"data": [2], "links": {"next": None}},
        )

        project_config = create_project_config()
        project_config.keychain.set_service(
            "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
        )
        task_config = TaskConfig()
        task = BaseMetaDeployTask(project_config, task_config)
        task._init_task()
        results = task._call_api("GET", "/rest", collect_pages=True)
        self.assertEqual([1, 2], results)
def create_task(task_class, options=None, project_config=None, org_config=None):
    if project_config is None:
        project_config = create_project_config("TestRepo", "TestOwner")
    if org_config is None:
        org_config = OrgConfig(
            {
                "instance_url": "https://test.salesforce.com",
                "access_token": "TOKEN",
                "org_id": "ORG_ID",
                "username": "******",
            },
            "test",
        )
        org_config.refresh_oauth_token = mock.Mock()
    if options is None:
        options = {}
    task_config = TaskConfig({"options": options})
    with mock.patch(
        "cumulusci.tasks.salesforce.BaseSalesforceTask._get_client_name",
        return_value="ccitests",
    ):
        return task_class(project_config, task_config, org_config)
    def test_find_or_create_plan_template__not_found(self):
        responses.add(
            "GET",
            "https://metadeploy/plantemplates?product=abcdef&name=install",
            json={"data": []},
        )
        responses.add(
            "POST",
            "https://metadeploy/plantemplates",
            json={"url": "https://NEW_PLANTEMPLATE"},
        )
        responses.add(
            "POST", "https://metadeploy/planslug", json={"url": "http://NEW_PLANSLUG"}
        )

        project_config = create_project_config()
        project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
        expected_plans = {
            "install": {
                "title": "Test Install",
                "slug": "install",
                "tier": "primary",
                "steps": {1: {"flow": "install_prod"}},
            }
        }
        project_config.config["plans"] = expected_plans
        project_config.keychain.set_service(
            "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
        )
        task_config = TaskConfig({"options": {"tag": "release/1.0"}})
        task = Publish(project_config, task_config)
        task._init_task()
        plantemplate = task._find_or_create_plan_template(
            {"url": "https://EXISTING_PRODUCT", "id": "abcdef"},
            "install",
            {"slug": "install"},
        )
        self.assertEqual("https://NEW_PLANTEMPLATE", plantemplate["url"])
    def test_get_destructive_changes(self, ApiRetrievePackaged):
        project_config = create_project_config()
        project_config.config["project"]["package"]["name"] = "TestPackage"
        project_config.config["project"]["package"]["api_version"] = "43.0"
        task = create_task(UninstallPackaged, {}, project_config)
        zf = zipfile.ZipFile(io.BytesIO(), "w")
        zf.writestr(
            "TestPackage/objects/Test__c.object",
            '<?xml version="1.0" encoding="UTF-8"?><root />',
        )
        ApiRetrievePackaged.return_value = zf
        result = task._get_destructive_changes()
        self.assertEqual(
            """<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Test__c</members>
        <name>CustomObject</name>
    </types>
    <version>43.0</version>
</Package>""",
            result,
        )
 def test_run_task__metadata_bundle(self):
     project_config = create_project_config()
     project_config.get_github_api = mock.Mock()
     task = create_task(
         UpdateDependencies,
         {
             "dependencies": [
                 {
                     "repo_owner": "SFDO-Tooling",
                     "repo_name": "CumulusCI-Test",
                     "ref": "abcdef",
                     "subfolder": "src",
                     "namespace_tokenize": "ns",
                 }
             ]
         },
         project_config=project_config,
     )
     zf = zipfile.ZipFile(io.BytesIO(), "w")
     task._download_extract_github = mock.Mock(return_value=zf)
     api = mock.Mock()
     task.api_class = mock.Mock(return_value=api)
     task()
     self.assertEqual(
         [
             {
                 "repo_owner": "SFDO-Tooling",
                 "repo_name": "CumulusCI-Test",
                 "ref": "abcdef",
                 "subfolder": "src",
                 "namespace_tokenize": "ns",
             }
         ],
         task.install_queue,
     )
     api.assert_called_once()
    def test_get_destructive_changes(self):
        with temporary_dir():
            os.mkdir("src")
            with open(os.path.join("src", "package.xml"), "w") as f:
                f.write(
                    """<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Class1</members>
        <members>Class2</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Page1</members>
        <name>ApexPage</name>
    </types>
    <types>
        <name>Empty</name>
    </types>
    <version>43.0</version>
</Package>"""
                )
            project_config = create_project_config()
            project_config.config["project"]["package"]["name"] = "TestPackage"
            project_config.config["project"]["package"]["api_version"] = "43.0"
            task = create_task(
                UninstallPackagedIncremental,
                {"ignore": {"ApexClass": ["Ignored"]}},
                project_config,
            )
            zf = zipfile.ZipFile(io.BytesIO(), "w")
            zf.writestr(
                "package.xml",
                """<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Test__c</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>Class1</members>
        <members>Class2</members>
        <members>Class3</members>
        <members>Ignored</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Page1</members>
        <name>ApexPage</name>
    </types>
    <types>
        <name>Empty</name>
    </types>
    <version>43.0</version>
</Package>""",
            )
            task._retrieve_packaged = mock.Mock(return_value=zf)
            result = task._get_destructive_changes()
            self.assertEqual(
                """<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Class3</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Test__c</members>
        <name>CustomObject</name>
    </types>
    <version>43.0</version>
</Package>""",
                result,
            )
 def setUp(self):
     self.project_config = create_project_config()
     self.project_config.keychain = mock.Mock()
     self.project_config.keychain.get_service.side_effect = ServiceNotConfigured
     self.task_config = TaskConfig()
     self.org_config = OrgConfig({}, "test")
 def test_run_task(self, ApiRetrieveInstalledPackages):
     project_config = create_project_config()
     project_config.get_github_api = mock.Mock()
     project_config.config["project"]["dependencies"] = [
         {
             "zip_url": "http://zipurl",
             "subfolder": "src",
             "namespace_tokenize": "ns",
             "namespace_inject": "ns",
             "namespace_strip": "ns",
             "dependencies": [
                 {"namespace": "upgradeddep", "version": "1.1"},
                 {"namespace": "samedep", "version": "1.0"},
                 {"namespace": "downgradeddep", "version": "1.0"},
                 {"namespace": "newdep", "version": "1.0"},
                 {
                     "repo_owner": "TestOwner",
                     "repo_name": "TestRepo",
                     "subfolder": "subfolder",
                     "ref": "ref",
                 },
             ],
         },
         {
             "namespace": "dependsonupgradedbeta",
             "version": "1.0",
             "dependencies": [
                 {"namespace": "upgradedbeta", "version": "1.0 (Beta 2)"}
             ],
         },
     ]
     task = create_task(UpdateDependencies, project_config=project_config)
     ApiRetrieveInstalledPackages.return_value = {
         "upgradeddep": "1.0",
         "samedep": "1.0",
         "downgradeddep": "1.1",
         "removeddep": "1.0",
         "upgradedbeta": "1.0 (Beta 1)",
         "dependsonupgradedbeta": "1.0",
     }
     task.api_class = mock.Mock()
     zf = zipfile.ZipFile(io.BytesIO(), "w")
     task._download_extract_github = mock.Mock(return_value=zf)
     task._download_extract_zip = mock.Mock(return_value=zf)
     task()
     self.assertEqual(
         [
             {"version": "1.1", "namespace": "upgradeddep"},
             {"version": "1.0", "namespace": "downgradeddep"},
             {"version": "1.0", "namespace": "newdep"},
             {
                 "repo_owner": "TestOwner",
                 "repo_name": "TestRepo",
                 "subfolder": "subfolder",
                 "ref": "ref",
             },
             {
                 "dependencies": [
                     {"version": "1.1", "namespace": "upgradeddep"},
                     {"version": "1.0", "namespace": "samedep"},
                     {"version": "1.0", "namespace": "downgradeddep"},
                     {"version": "1.0", "namespace": "newdep"},
                     {
                         "repo_owner": "TestOwner",
                         "repo_name": "TestRepo",
                         "subfolder": "subfolder",
                         "ref": "ref",
                     },
                 ],
                 "zip_url": "http://zipurl",
                 "subfolder": "src",
                 "namespace_tokenize": "ns",
                 "namespace_inject": "ns",
                 "namespace_strip": "ns",
             },
             {"version": "1.0 (Beta 2)", "namespace": "upgradedbeta"},
             {
                 "version": "1.0",
                 "namespace": "dependsonupgradedbeta",
                 "dependencies": [
                     {"version": "1.0 (Beta 2)", "namespace": "upgradedbeta"}
                 ],
             },
         ],
         task.install_queue,
     )
     self.assertEqual(
         [
             {
                 "version": "1.0",
                 "namespace": "dependsonupgradedbeta",
                 "dependencies": [
                     {"version": "1.0 (Beta 2)", "namespace": "upgradedbeta"}
                 ],
             },
             {"version": "1.0 (Beta 2)", "namespace": "upgradedbeta"},
             {"version": "1.0", "namespace": "downgradeddep"},
         ],
         task.uninstall_queue,
     )
     self.assertEqual(10, task.api_class.call_count)
    def test_run_task(self):
        project_config = create_project_config()
        project_config.config["project"]["git"]["repo_url"] = "EXISTING_REPO"
        project_config.config["plans"] = {
            "install": {
                "title": "Test Install",
                "slug": "install",
                "tier": "primary",
                "steps": {1: {"flow": "install_prod"}},
            }
        }
        project_config.keychain.set_service(
            "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
        )
        project_config.keychain.set_service(
            "github",
            ServiceConfig(
                {"username": "******", "password": "******", "email": "*****@*****.**"}
            ),
        )

        responses.add(
            "GET",
            "https://metadeploy/products?repo_url=EXISTING_REPO",
            json={"data": [{"id": "abcdef", "url": "https://EXISTING_PRODUCT"}]},
        )
        responses.add(
            "GET",
            "https://api.github.com/repos/TestOwner/TestRepo",
            json=self._get_expected_repo("TestOwner", "TestRepo"),
        )
        responses.add(
            "GET",
            "https://api.github.com/repos/TestOwner/TestRepo/git/refs/tags/release/1.0",
            json=self._get_expected_tag_ref("release/1.0", "tag_sha"),
        )
        responses.add(
            "GET",
            "https://api.github.com/repos/TestOwner/TestRepo/git/tags/tag_sha",
            json=self._get_expected_tag("release/1.0", "commit_sha"),
        )
        f = io.BytesIO()
        zf = zipfile.ZipFile(f, "w")
        zfi = zipfile.ZipInfo("toplevel/")
        zf.writestr(zfi, "")
        zf.writestr(
            "toplevel/cumulusci.yml",
            yaml.dump(
                {
                    "project": {
                        "package": {"name_managed": "Test Product", "namespace": "ns"}
                    }
                }
            ),
        )
        zf.close()
        responses.add(
            "GET",
            "https://api.github.com/repos/TestOwner/TestRepo/zipball/commit_sha",
            body=f.getvalue(),
            content_type="application/zip",
        )
        responses.add(
            "GET",
            "https://api.github.com/repos/TestOwner/TestRepo/releases/latest",
            json=self._get_expected_release("release/1.0"),
        )
        responses.add(
            "GET",
            "https://metadeploy/versions?product=abcdef&label=1.0",
            json={"data": []},
        )
        responses.add(
            "POST",
            "https://metadeploy/versions",
            json={"url": "https:/metadeploy/versions/1", "id": 1},
        )
        responses.add(
            "GET",
            "https://metadeploy/plantemplates?product=abcdef&name=install",
            json={"data": [{"url": "https://metadeploy/plantemplates/1"}]},
        )
        responses.add(
            "POST",
            "https://metadeploy/plans",
            json={"url": "https://metadeploy/plans/1"},
        )
        responses.add("PATCH", "https://metadeploy/versions/1", json={})

        task_config = TaskConfig({"options": {"tag": "release/1.0"}})
        task = Publish(project_config, task_config)
        task()

        steps = json.loads(responses.calls[-2].request.body)["steps"]
        self.assertEqual(
            [
                {
                    "is_required": True,
                    "kind": "managed",
                    "name": "Install Test Product 1.0",
                    "path": "install_prod.install_managed",
                    "step_num": "1.2",
                    "task_class": "cumulusci.tasks.salesforce.InstallPackageVersion",
                    "task_config": {
                        "options": {
                            "activateRSS": True,
                            "namespace": "ns",
                            "retries": 5,
                            "retry_interval": 5,
                            "retry_interval_add": 30,
                            "version": "1.0",
                        }
                    },
                },
                {
                    "is_required": True,
                    "kind": "metadata",
                    "name": "Update Admin Profile",
                    "path": "install_prod.config_managed.update_admin_profile",
                    "step_num": "1.3.2",
                    "task_class": "cumulusci.tasks.salesforce.UpdateAdminProfile",
                    "task_config": {
                        "options": {"managed": True, "namespaced_org": False}
                    },
                },
            ],
            steps,
        )