示例#1
0
    def _run_task(self, flow_task_config):
        task_config = self.project_config.get_task(flow_task_config['task'])
        task_config = copy.deepcopy(task_config.config)

        task_config = TaskConfig(task_config)

        if flow_task_config:
            if 'options' not in task_config.config:
                task_config.config['options'] = {}
            task_config.config['options'].update(flow_task_config.get('options', {}))

            # Handle dynamic value lookups in the format ^^task_name.attr1.attr2
            for option, value in task_config.options.items():
                if unicode(value).startswith('^^'):
                    value_parts = value[2:].split('.')
                    task_name = value_parts[0]
                    parent = self._find_task_by_name(task_name)
                    for attr in value_parts[1:]:
                        parent = getattr(parent, attr)
                    task_config.config['options'][option] = parent


        task_class = import_class(task_config.class_path)

        self.logger.info('')
        self.logger.info(
            'Running task: {}'.format(
                flow_task_config['task'],
            )
        )

        task = task_class(
            self.project_config,
            task_config,
            org_config = self.org_config,
        )
        self.tasks.append(task)

        for line in self._render_task_config(task):
            self.logger.info(line)

        try:
            response = task()
            self.logger.info('Task complete: {}'.format(flow_task_config['task']))
            self.responses.append(response)
            return response
        except:
            self.logger.error('Task failed: {}'.format(flow_task_config['task']))
            if not flow_task_config.get('ignore_failure'):
                self.logger.info('Aborting flow')
                raise
            self.logger.info('Continuing flow')
示例#2
0
    def test_run_task__failed_class_level_no_symboltable__spring20_managed(self):
        self._mock_apex_class_query(name="ns__Test_TEST", namespace="ns")
        self._mock_run_tests()
        self._mock_get_failed_test_classes_failure()
        self._mock_tests_complete()
        self._mock_get_test_results()
        self._mock_get_symboltable_failure()
        task_config = TaskConfig()
        task_config.config["options"] = {
            "junit_output": "results_junit.xml",
            "poll_interval": 1,
            "test_name_match": "%_TEST",
            "managed": True,
            "namespace": "ns",
        }

        task = RunApexTests(self.project_config, task_config, self.org_config)
        task._get_test_methods_for_class = Mock()

        task()

        task._get_test_methods_for_class.assert_not_called()
示例#3
0
def task_doc(config):
    config_src = config.global_config

    click.echo("==========================================")
    click.echo("Tasks Reference")
    click.echo("==========================================")
    click.echo("")

    for name, options in list(config_src.tasks.items()):
        task_config = TaskConfig(options)
        doc = doc_task(name, task_config)
        click.echo(doc)
        click.echo("")
示例#4
0
def _make_task(task_class, task_config):
    task_config = TaskConfig(task_config)
    universal_config = UniversalConfig()
    project_config = BaseProjectConfig(
        universal_config,
        config={"noyaml": True, "project": {"package": {"api_version": "46.0"}}},
    )
    keychain = BaseProjectKeychain(project_config, "")
    project_config.set_keychain(keychain)
    org_config = DummyOrgConfig(
        {"instance_url": "https://example.com", "access_token": "abc123"}, "test"
    )
    return task_class(project_config, task_config, org_config)
示例#5
0
 def test_retry_on_exception(self):
     """ calling _retry() should call try until the task succeeds.  """
     task_config = TaskConfig({
         "options": {
             "retries": 5,
             "retry_interval": 1,
             "retry_interval_add": 1
         }
     })
     task = BaseTask(self.project_config, task_config, self.org_config)
     task._try = mock.Mock(side_effect=[Exception, Exception, 1])
     task._retry()
     self.assertEqual(task._try.call_count, 3)
示例#6
0
    def setUp(self):
        self.global_config = BaseGlobalConfig()
        self.project_config = BaseProjectConfig(self.global_config,
                                                config={"noyaml": True})
        self.task_config = TaskConfig()

        self._task_log_handler.reset()
        self.task_log = self._task_log_handler.messages

        self.Popen = MockPopen()
        self.r = Replacer()
        self.r.replace("cumulusci.tasks.command.subprocess.Popen", self.Popen)
        self.addCleanup(self.r.restore)
示例#7
0
 def test_run_task(self, CommitDir):
     task_config = TaskConfig()
     task = CommitApexDocs(self.project_config, task_config)
     commit_dir = mock.Mock()
     CommitDir.return_value = commit_dir
     task()
     commit_dir.assert_called_once_with(
         os.path.join("docs", "ApexDocumentation"),
         "master",
         "docs",
         "Update Apex docs",
         False,
     )
示例#8
0
    def _get_task(self, stepnum, step_config):
        task_config = copy.deepcopy(step_config['task_config'].config)
        task_config = TaskConfig(task_config)

        task_name = step_config['step_config']['task']

        if 'options' not in task_config.config:
            task_config.config['options'] = {}
        task_config.config['options'].update(step_config['step_config'].get(
            'options', {}))
        # If there were task option overrides passed in, merge them
        if task_name in self.task_options:
            task_config.config['options'].update(self.task_options[task_name])

        # Handle dynamic value lookups in the format ^^task_name.attr1.attr2
        for option, value in list(task_config.options.items()):
            if str(value).startswith('^^'):
                value_parts = value[2:].split('.')
                parent = self._find_step_by_name(value_parts[0])
                n = 0
                while isinstance(parent, BaseFlow):
                    n += 1
                    parent = parent._find_step_by_name(value_parts[n])
                for attr in value_parts[(n + 1):]:
                    if getattr(parent, 'nested', None):
                        parent = parent._find_step_by_name()
                    else:
                        parent = parent.return_values.get(attr)
                task_config.config['options'][option] = parent

        task_class = import_class(task_config.class_path)

        task = task_class(self.project_config,
                          task_config,
                          org_config=self.org_config,
                          name=task_name,
                          stepnum=stepnum,
                          flow=self)
        return task
示例#9
0
 def setUp(self):
     self.global_config = BaseGlobalConfig()
     self.project_config = BaseProjectConfig(self.global_config,
                                             config={"noyaml": True})
     self.task_config = TaskConfig({"options": {"command": "ls"}})
     self.org_config = OrgConfig(
         {
             "access_token": "TOKEN",
             "instance_url": "https://na01.salesforce.com"
         },
         "test",
     )
     self.org_config.refresh_oauth_token = mock.Mock()
示例#10
0
 def test_tag_not_found(self, commit_dir, extract_github):
     responses.add(
         method=responses.GET,
         url=self.repo_api_url,
         json=self._get_expected_repo(owner=self.repo_owner, name=self.repo_name),
     )
     responses.add(
         responses.GET,
         self.repo_api_url + "/releases/latest",
         json=self._get_expected_release("release/1.0"),
     )
     responses.add(
         method=responses.GET,
         url=self.public_repo_url,
         json=self._get_expected_repo(
             owner=self.public_owner, name=self.public_name
         ),
     )
     responses.add(
         method=responses.GET,
         url=self.repo_api_url + "/git/refs/tags/release/1.0",
         status=201,
         json=self._get_expected_tag_ref("release/1.0", "SHA"),
     )
     responses.add(
         responses.GET,
         self.public_repo_url + "/releases/tags/release/1.0",
         json=self._get_expected_release("release/1.0"),
     )
     responses.add(
         method=responses.GET, url=self.repo_api_url + "/git/tags/SHA", status=404
     )
     task_config = TaskConfig(
         {
             "options": {
                 "branch": "master",
                 "version": "latest",
                 "repo_url": self.public_repo_url,
                 "includes": ["tasks/foo.py", "unpackaged/pre/foo/package.xml"],
             }
         }
     )
     extract_github.return_value.namelist.return_value = [
         "tasks/foo.py",
         "unpackaged/pre/foo/package.xml",
         "force-app",
     ]
     task = PublishSubtree(self.project_config, task_config)
     with pytest.raises(GithubException) as exc:
         task()
     assert "Tag release/1.0 not found" == str(exc.value)
示例#11
0
 def test_run_task(self, removeXmlElement):
     with temporary_dir() as path:
         revert_path = os.path.join(os.path.dirname(path),
                                    os.path.basename(path) + "_revert")
         project_config = BaseProjectConfig(BaseGlobalConfig())
         task_config = TaskConfig(
             {"options": {
                 "path": path,
                 "revert_path": revert_path
             }})
         task = CreateUnmanagedEESrc(project_config, task_config)
         task()
         removeXmlElement.assert_called_once_with("availableFields", path,
                                                  "*.object")
示例#12
0
 def test_renames_not_list_error(self):
     task_config = TaskConfig({
         "options": {
             "branch": "master",
             "repo_url": self.public_repo_url,
             "includes": ["tasks/foo.py", "unpackaged/pre/foo/package.xml"],
             "renames": ["tasks/foo.py", "unpackaged/pre/foo/package.xml"],
         }
     })
     with pytest.raises(TaskOptionsError) as exc:
         PublishSubtree(self.project_config, task_config)
     assert (
         "Renamed paths must be a list of dicts with `local:` and `target:` keys."
         == str(exc.value))
示例#13
0
 def test_get_test_class_query__exclude(self):
     task_config = TaskConfig({
         "options": {
             "test_name_match": "%_TEST",
             "test_name_exclude": "EXCL"
         }
     })
     task = RunApexTests(self.project_config, task_config, self.org_config)
     query = task._get_test_class_query()
     self.assertEqual(
         "SELECT Id, Name FROM ApexClass WHERE NamespacePrefix = null "
         "AND (Name LIKE '%_TEST') AND (NOT Name LIKE 'EXCL')",
         query,
     )
示例#14
0
    def test_run_task__retry_tests_fails(self):
        self._mock_apex_class_query()
        self._mock_run_tests()
        self._mock_run_tests(body="JOBID_9999")
        self._mock_get_failed_test_classes()
        self._mock_get_failed_test_classes(job_id="JOBID_9999")
        self._mock_tests_complete()
        self._mock_tests_complete(job_id="JOBID_9999")
        self._mock_get_test_results("Fail", "UNABLE_TO_LOCK_ROW")
        self._mock_get_test_results("Fail",
                                    "DUPLICATES_DETECTED",
                                    job_id="JOBID_9999")

        task_config = TaskConfig()
        task_config.config["options"] = {
            "junit_output": "results_junit.xml",
            "poll_interval": 1,
            "test_name_match": "%_TEST",
            "retry_failures": ["UNABLE_TO_LOCK_ROW"],
        }
        task = RunApexTests(self.project_config, task_config, self.org_config)
        with self.assertRaises(ApexTestException):
            task()
示例#15
0
文件: cli.py 项目: tet3/CumulusCI
def task_info(config, task_name):
    check_project_config(config)
    task_config = getattr(config.project_config, 'tasks__{}'.format(task_name))
    if not task_config:
        raise TaskNotFoundError('Task not found: {}'.format(task_name))

    task_config = TaskConfig(task_config)
    click.echo(rst2ansi(doc_task(task_name, task_config)))
    return
    class_path = task_config.get('class_path')
    task_class = import_class(class_path)

    # General task info
    click.echo('Description: {}'.format(task_config.get('description')))
    click.echo('Class: {}'.format(task_config.get('class_path')))

    # Default options
    default_options = task_config.get('options', {})
    if default_options:
        click.echo('')
        click.echo('Default Option Values')
        for key, value in default_options.items():
            click.echo('    {}: {}'.format(key, value))

    # Task options
    task_options = getattr(task_class, 'task_options', {})
    if task_options:
        click.echo('')
        data = []
        headers = ['Option', 'Required', 'Description']
        for key, option in task_options.items():
            if option.get('required'):
                data.append((key, '*', option.get('description')))
            else:
                data.append((key, '', option.get('description')))
        table = Table(data, headers)
        click.echo(table)
示例#16
0
    def test_run_task__status_not_found(self):
        self.init_github()
        repo_response = self._get_expected_repo("TestOwner", "TestRepo")
        responses.add(method=responses.GET,
                      url=self.repo_api_url,
                      json=repo_response)
        responses.add(
            method=responses.GET,
            url=f"{self.repo_api_url}/commits/abcdef",
            json=self._get_expected_commit("abcdef"),
        )
        responses.add(
            method=responses.GET,
            url=f"{self.repo_api_url}/commits/abcdef/status",
            json={
                "url": f"{self.repo_api_url}/abcdef/status",
                "commit_url": f"{self.repo_api_url}/abcdef",
                "repository": repo_response,
                "sha": "abcdef",
                "state": "success",
                "statuses": [],
                "total_count": 0,
            },
        )

        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 package version id in '2gp' commit status",
        ):
            task._run_task()
示例#17
0
    def test_is_retriable_failure(self):
        task_config = TaskConfig()
        task_config.config["options"] = {
            "junit_output":
            "results_junit.xml",
            "poll_interval":
            1,
            "test_name_match":
            "%_TEST",
            "retry_failures": [
                "UNABLE_TO_LOCK_ROW",
                "unable to obtain exclusive access to this record",
            ],
        }
        task = RunApexTests(self.project_config, task_config, self.org_config)
        task._init_options(task_config.config["options"])

        self.assertTrue(
            task._is_retriable_failure({
                "Message": "UNABLE_TO_LOCK_ROW",
                "StackTrace": "test",
                "Outcome": "Fail",
            }))
        self.assertTrue(
            task._is_retriable_failure({
                "Message": "TEST",
                "StackTrace":
                "unable to obtain exclusive access to this record",
                "Outcome": "Fail",
            }))
        self.assertFalse(
            task._is_retriable_failure({
                "Message": "DUPLICATES_DETECTED",
                "StackTrace": "test",
                "Outcome": "Fail",
            }))
示例#18
0
 def test_init_devhub__from_service(self, project_config, org_config):
     project_config.keychain.services["devhub"] = ServiceConfig(
         {"username": "******"})
     task = CreatePackageVersion(
         project_config,
         TaskConfig({
             "options": {
                 "package_type": "Unlocked",
                 "package_name": "Test Package",
             }
         }),
         org_config,
     )
     devhub_config = task._init_devhub()
     assert devhub_config.username == "*****@*****.**"
示例#19
0
 def test_FindReplace_env_replace_error(self, find_replace):
     with pytest.raises(TaskOptionsError):
         task_config = TaskConfig({
             "options": {
                 "find": "foo",
                 "replace": "bar",
                 "env_replace": True,
                 "path": ".",
                 "max": 1,
             }
         })
         task = util.FindReplace(self.project_config, task_config,
                                 self.org_config)
         task()
         find_replace.assert_called_once()
示例#20
0
 def test_run_task(self):
     with temporary_dir() as revert_path:
         with open(os.path.join(revert_path, "file"), "w") as f:
             pass
         path = os.path.join(os.path.dirname(revert_path),
                             os.path.basename(revert_path) + "_orig")
         project_config = BaseProjectConfig(BaseGlobalConfig())
         task_config = TaskConfig(
             {"options": {
                 "path": path,
                 "revert_path": revert_path
             }})
         task = RevertUnmanagedEESrc(project_config, task_config)
         task()
         self.assertTrue(os.path.exists(os.path.join(path, "file")))
示例#21
0
    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"])
示例#22
0
 def test_run_string_only(self):
     task_config = TaskConfig(
         {"options": {
             "apex": 'System.debug("test");'
         }})
     task = AnonymousApexTask(self.project_config, task_config,
                              self.org_config)
     url = self.base_tooling_url + "executeAnonymous"
     responses.add(responses.GET,
                   url,
                   status=200,
                   json={
                       "compiled": True,
                       "success": True
                   })
     task()
示例#23
0
def task(project_config, devhub_config, org_config):
    task = CreatePackageVersion(
        project_config,
        TaskConfig({
            "options": {
                "package_type": "Unlocked",
                "org_dependent": False,
                "package_name": "Test Package",
                "static_resource_path": "static-resources",
            }
        }),
        org_config,
    )
    task._init_devhub = mock.Mock(return_value=devhub_config)
    task._init_task()
    return task
示例#24
0
    def run_task_class(self, class_path, **options):
        """ Runs a CumulusCI task class with task options via kwargs.

            Use this keyword to run logic from CumulusCI tasks which have not
            been configured in the project's cumulusci.yml file.  This is
            most useful in cases where a test needs to use task logic for
            logic unique to the test and thus not worth making into a named
            task for the project

            Examples:
            | =Keyword=      | =task_class=                     | =task_options=                            |
            | Run Task Class | cumulusci.task.utils.DownloadZip | url=http://test.com/test.zip dir=test_zip |
        """
        logger.console("\n")
        task_class, task_config = self._init_task(class_path, options, TaskConfig())
        return self._run_task(task_class, task_config)
示例#25
0
 def test_freeze_steps__skip(self):
     project_config = create_project_config()
     project_config.keychain.set_service(
         "metadeploy", ServiceConfig({"url": "https://metadeploy", "token": "TOKEN"})
     )
     plan_config = {
         "title": "Test Install",
         "slug": "install",
         "tier": "primary",
         "steps": {1: {"task": "None"}},
     }
     task_config = TaskConfig({"options": {"tag": "release/1.0"}})
     task = Publish(project_config, task_config)
     task._init_task()
     steps = task._freeze_steps(project_config, plan_config)
     assert steps == []
示例#26
0
 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()
示例#27
0
 def test_FindReplace_env_replace(self, find_replace):
     with mock.patch.dict(os.environ, {"bar": "bars"}):
         task_config = TaskConfig({
             "options": {
                 "find": "foo",
                 "replace": "bar",
                 "env_replace": True,
                 "path": ".",
                 "max": 1,
             }
         })
         task = util.FindReplace(self.project_config, task_config,
                                 self.org_config)
         task()
         assert task.options["replace"] == "bars"
         find_replace.assert_called_once()
示例#28
0
def _deploy_org_settings(*, cci, org_name, scratch_org_config, scratch_org):
    """Deploy org settings via Metadata API.

    Do a Metadata API deployment to configure org settings as specified
    in the scratch org definition file.
    """
    org_config = refresh_access_token(
        scratch_org=scratch_org,
        config=scratch_org_config.config,
        org_name=org_name,
        keychain=cci.keychain,
    )
    path = os.path.join(cci.project_config.repo_root, scratch_org_config.config_file)
    task_config = TaskConfig({"options": {"definition_file": path}})
    task = DeployOrgSettings(cci.project_config, task_config, org_config)
    task()
    return org_config
示例#29
0
 def test_run_task(self, removeXmlElement):
     with temporary_dir() as path:
         revert_path = os.path.join(os.path.dirname(path),
                                    os.path.basename(path) + "_revert")
         project_config = BaseProjectConfig(BaseGlobalConfig(),
                                            config={"noyaml": True})
         task_config = TaskConfig(
             {"options": {
                 "path": path,
                 "revert_path": revert_path
             }})
         task = CreateUnmanagedEESrc(project_config, task_config)
         task()
         removeXmlElement.assert_has_calls([
             mock.call("availableFields", path, "*.object"),
             mock.call("visibility[.='Protected']", path, "*.object"),
         ])
示例#30
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
示例#31
0
 def setUp(self):
     self.api_version = 36.0
     self.global_config = BaseGlobalConfig(
         {'project': {'package': {'api_version': self.api_version}}})
     self.project_config = BaseProjectConfig(self.global_config)
     self.project_config.config['project'] = {
         'package': {
             'api_version': self.api_version,
         }
     }
     self.task_config = TaskConfig()
     self.org_config = OrgConfig({
         'instance_url': 'example.com',
         'access_token': 'abc123',
     })
     self.base_tooling_url = 'https://{}/services/data/v{}/tooling/'.format(
         self.org_config.instance_url, self.api_version)
示例#32
0
    def test_run_task(self):
        responses.add(
            method=responses.GET,
            url=self.repo_api_url,
            json=self._get_expected_repo(owner=self.repo_owner,
                                         name=self.repo_name),
        )
        responses.add(
            method=responses.GET,
            url=self.repo_api_url + "/releases?per_page=100",
            json=[],
        )
        responses.add(
            method=responses.GET,
            url=self.repo_api_url + "/git/refs/tags/release/1.0",
            status=404,
        )
        responses.add(
            method=responses.POST,
            url=self.repo_api_url + "/git/tags",
            json=self._get_expected_tag("release/1.0", "SHA"),
            status=201,
        )
        responses.add(
            method=responses.POST,
            url=self.repo_api_url + "/git/refs",
            json={},
            status=201,
        )
        responses.add(
            method=responses.POST,
            url=self.repo_api_url + "/releases",
            json=self._get_expected_release("release"),
            status=201,
        )

        task = CreateRelease(self.project_config,
                             TaskConfig({"options": {
                                 "version": "1.0"
                             }}))
        task()
        self.assertEqual({
            "tag_name": "release/1.0",
            "name": "1.0"
        }, task.return_values)