diff --git a/connector_jira/README.rst b/connector_jira/README.rst new file mode 100644 index 000000000..dd76dbfa3 --- /dev/null +++ b/connector_jira/README.rst @@ -0,0 +1,271 @@ +============== +JIRA Connector +============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:e9e5cd0fa4ce03daa11965f2935e792dd22adaaeccc3ed7a37ddfbc7ddb1a394 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fconnector--jira-lightgray.png?logo=github + :target: https://github.com/OCA/connector-jira/tree/17.0/connector_jira + :alt: OCA/connector-jira +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/connector-jira-17-0/connector-jira-17-0-connector_jira + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/connector-jira&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds Jira synchronization feature. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +You need the following Python packages: + +- requests +- jira +- oauthlib +- requests-oauthlib +- requests-toolbelt +- PyJWT +- cryptography + +Once the addon is installed, follow these steps: + +Job Queue +--------- + +In ``odoo.conf``, configure similarly: + +:: + + [queue_job] + channels = root:1,root.connector_jira.import:2 + +Backend +------- + +1. Open the menu Connectors > Jira > Backends +2. Create a new Jira Backend + + - Put the name you want + - Set the URL of your Jira, like https://jira.example.com + - You can also select the company where records will be created and + the default project template used when Odoo will create the + projects in Jira + +3. Save and continue with the Authentication + +Authentication of Backend +------------------------- + +1. On the created backend, click on the Authenticate button, a popup + with keys will appear, keep these open in a tab +2. Open Jira and go to System > Applications > Application links +3. Enter the name of the application, example: odoo, and click on + "Create new link" +4. In the popup, set the URL where JIRA can reach Odoo. Jira might + complain and reopen the popup, confirm it again and a new popup + appears +5. In the new popup, do not set anything in the fields and click on + Continue +6. The link should be created now, edit it with the pen on the right +7. Open the Incoming Authentication panel, be warned that it may take + some time to load +8. Copy-paste the consumer key and public key from Odoo to the Jira + link's Incoming Authentication. Set a consumer name (e.g. odoo) and + leave the consumer callback url and 2 legged auth blank. +9. Click on save at the bottom of the form (you need to scroll) +10. Back on Odoo, click on Continue +11. A link is displayed, click on it - you may need to login again - and + click on "Allow". +12. Back on Odoo again, click on Continue +13. Authentication is complete! + +Configuration of the Backend +---------------------------- + +**Setup the webhooks** + +It is advised to setup the webhooks so the synchronizations are in +realtime. + +1. On the Jira Backend, set the "Base Odoo URL for Webhooks" to URL of + Odoo, it must be reachable from Jira. +2. Click on "Install Webhooks" + +**Configure the Epic Link** + +If you use Epics, you need to click on "Configure Epic Link", Odoo will +search the name of the custom field used for the Epic Link. + +**Configuration done** + +You can now click on the button "Configuration Done". + +Usage +===== + +The tasks and worklogs are always imported from JIRA to Odoo, there is +no synchronization in the other direction. + +Initial synchronizations +------------------------ + +You can already select the "Imports" tab in the Backend and click on +"Link users" and "Import issue types". The users will be matched either +by login or by email. + +Create and export a project +--------------------------- + +Projects can be created in Odoo and exported to Jira. You can then +create a project, and use the action "Link with JIRA" and use the +"Export to JIRA" action. + +When you choose to export a project to JIRA, if you change the name or +the key of the project, the new values will be pushed to JIRA. + +Link a project with JIRA +------------------------ + +If you already have a project on JIRA or prefer to create it first on +JIRA, you can link an Odoo project. Use the "Link with JIRA" action on +the project and select the "Link with JIRA" action. + +This action establish the link, then changes of the name or the key on +either side are not pushed. + +Issue Types on Projects +----------------------- + +When you link a project, you have to select which issue types are +synchronized. Only tasks of the selected types will be created in Odoo. + +If a JIRA worklog is added to a type of issue that is not synchronized, +will attach to the closest task following these rules: + +- if a subtask, find the parent task +- if no parent task, find the epic task (only if it is on the same + project) +- if no epic, attach to the project without being linked to a task + +Change synchronization configuration on a project +------------------------------------------------- + +If you want to change the configuration of a project, such as which +issue types are synchronized, you can open the "Connector" tab in the +project settings and edit the "binding" with the backend. + +Synchronize tasks and worklogs +------------------------------ + +If the webhooks are active, as soon as they are created in Jira they +should appear in Odoo. If they are not active, you can open the Jira +Backend and run the synchronizations manually, or activate the Scheduled +Actions to run the batch imports. It is important to select the issue +types so don't miss this step (need improvement). + +Known issues / Roadmap +====================== + +- If an odoo user has no linked employee, worklogs will still be + imported but with no employee. + +**Allowing several bindings per project** + +The design evolved to allow more than one Jira binding per project in +Odoo. This conveniently allows to fetch tasks and worklogs for many +projects in Jira, which will be tracked in only one project in Odoo. + +In order to push data to Jira, we have to apply restrictions on these +"multi-bindings" projects, as we cannot know to which binding data must +be pushed: + +- Not more than one project (can be zero) can have a "Sync Action" set + to "Export to JIRA". As this configuration pushes the name and key of + the project to Jira, we cannot push it to more than one project. +- If we implement push of tasks to Jira, we'll have to add a way to + restrict or choose to which project we push the task, this is not + supported yet (for instance, add a Boolean "export tasks" on the + project binding, or explicitly select the target binding on the task) + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp + +Contributors +------------ + +- `Camptocamp `__: + + - Damien Crier + - Thierry Ducrest + - Tonow-c2c + - Simone Orsi + - Timon Tschanz + - jcoux + - Patrick Tombez + - Guewen Baconnier + - Akim Juillerat + +- `CorporateHub `__ + + - Alexey Pelykh + +- `Trobz `__: + + - Son Ho + +- `Avoin.Systems `__: + + - Nedas Žilinskas + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/connector-jira `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/connector_jira/__init__.py b/connector_jira/__init__.py new file mode 100644 index 000000000..7b9e7ed4c --- /dev/null +++ b/connector_jira/__init__.py @@ -0,0 +1,8 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import cli +from . import fields +from . import components +from . import controllers +from . import models +from . import wizards diff --git a/connector_jira/__manifest__.py b/connector_jira/__manifest__.py new file mode 100644 index 000000000..c1d24de92 --- /dev/null +++ b/connector_jira/__manifest__.py @@ -0,0 +1,50 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "JIRA Connector", + "version": "17.0.1.0.0", + "author": "Camptocamp,Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Connector", + "depends": [ + "connector", + "project", + "hr_timesheet", + "queue_job", + "web", + "web_widget_url_advanced", + "multi_step_wizard", + ], + "external_dependencies": { + "python": [ + "requests", + "jira", + "oauthlib", + "requests-oauthlib", + "requests-toolbelt", + "PyJWT", + "cryptography", + ], + }, + "website": "https://github.com/OCA/connector-jira", + "data": [ + "views/jira_menus.xml", + "wizards/jira_backend_auth_views.xml", + "views/project_link_jira_views.xml", + "views/task_link_jira_views.xml", + "views/jira_backend_views.xml", + "views/jira_backend_report_templates.xml", + "views/project_project_views.xml", + "views/project_task_views.xml", + "views/res_users_views.xml", + "views/jira_issue_type_views.xml", + "views/timesheet_account_analytic_line.xml", + "wizards/jira_account_analytic_line_import_views.xml", + "security/ir.model.access.csv", + "security/ir_rule.xml", + "data/cron.xml", + "data/queue_job_data.xml", + ], + "demo": ["demo/jira_backend_demo.xml"], + "installable": True, +} diff --git a/connector_jira/cli/__init__.py b/connector_jira/cli/__init__.py new file mode 100644 index 000000000..6e338c80c --- /dev/null +++ b/connector_jira/cli/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import jira_oauth_dance diff --git a/connector_jira/cli/jira_oauth_dance.py b/connector_jira/cli/jira_oauth_dance.py new file mode 100644 index 000000000..3db70d920 --- /dev/null +++ b/connector_jira/cli/jira_oauth_dance.py @@ -0,0 +1,141 @@ +"""Odoo CLI command to initiate the Oauth access with Jira + +Mostly to be used for the test databases as a wizard does the +same thing from Odoo's UI. + +It is plugged in the Odoo CLI commands. The same way "odoo shell" +can be started from the command line, you can use it with the command:: + + odoo jiraoauthdance + +By default, it will configure the authentication for the Demo Backend +(as it is used in tests). If the demo backend doesn't exist, it will use +the first Jira backend it can find. You can specify a backend ID with:: + + odoo jiraoauthdance --backend-id=2 + +You have to target the database that you want to link, either in the +configuration file, either using the ``--database`` option. + +""" + +# this is a cli tool, we want to use print statements +# pylint: disable=print-used + +import argparse +import logging +import os +import signal +import sys +from contextlib import contextmanager + +import odoo +from odoo.cli import Command +from odoo.tools import config + +_logger = logging.getLogger(__name__) + + +def raise_keyboard_interrupt(*a): + raise KeyboardInterrupt() + + +class JiraOauthDance(Command): + def init(self, args): + config.parse_config(args) + odoo.cli.server.report_configuration() + odoo.service.server.start(preload=[], stop=True) + signal.signal(signal.SIGINT, raise_keyboard_interrupt) + + @contextmanager + def env(self, dbname): + registry = odoo.registry(dbname) + with registry.cursor() as cr: + uid = odoo.SUPERUSER_ID + ctx_environment = odoo.api.Environment(cr, uid, {})["res.users"] + ctx = ctx_environment.context_get() + env = odoo.api.Environment(cr, uid, ctx) + yield env + + def _find_backend(self, env, backend_id=None): + if backend_id: + backend = env["jira.backend"].browse(backend_id) + if not backend.exists(): + die(f"no backend with id found {backend_id}") + else: + backend = env.ref( + "connector_jira.jira_backend_demo", raise_if_not_found=False + ) + if not backend: + backend = self.env["jira.backend"].search([], limit=1) + return backend + + def oauth_dance(self, dbname, options): + with self.env(dbname) as env: + backend = self._find_backend(env, backend_id=options.backend_id) + auth_wizard = env["jira.backend.auth"].create({"backend_id": backend.id}) + print() + print(r"Welcome to the Jira Oauth dance \o| \o/ |o/") + print() + print( + "You are working on the backend {} (id: {}) with uri {}".format( + backend.name, backend.id, backend.uri + ) + ) + print( + "Now, copy the consumer and public key " "in the Jira application link" + ) + print() + print("Consumer key:") + print() + print(auth_wizard.consumer_key) + print() + print("Public key:") + print() + print(auth_wizard.public_key) + print() + input("Press any key when you have pasted these values in Jira") + + auth_wizard.do_oauth_leg_1() + print() + print( + "Jira wants you to open this link (hostname may change if" + " you use Docker) and approve the link (no clickbait):" + ) + print() + print(auth_wizard.auth_uri) + print() + input("Press any key when approved") + auth_wizard.do_oauth_leg_3() + print() + print("That's all folks! Keep these tokens for your tests:") + print() + print(f'JIRA_TEST_URL="{backend.uri}"') + print(f'JIRA_TEST_TOKEN_ACCESS="{backend.access_token}"') + print(f'JIRA_TEST_TOKEN_SECRET="{backend.access_secret}"') + + def run(self, cmdargs): + parser = argparse.ArgumentParser( + prog="%s jiraauthdance" % sys.argv[0].split(os.path.sep)[-1], + description=self.__doc__, + ) + parser.add_argument( + "--backend-id", + dest="backend_id", + type=int, + help="ID of the backend to authenticate. " + "(by default the demo backend if exists or the first found)", + ) + + args, unknown = parser.parse_known_args(args=cmdargs) + + self.init(unknown) + if not config["db_name"]: + die("need a db_name") + self.oauth_dance(config["db_name"], args) + return 0 + + +def die(message, code=1): + print(message, file=sys.stderr) + sys.exit(code) diff --git a/connector_jira/components/__init__.py b/connector_jira/components/__init__.py new file mode 100644 index 000000000..f30a2ad29 --- /dev/null +++ b/connector_jira/components/__init__.py @@ -0,0 +1,8 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import base +from . import backend_adapter +from . import binder +from . import exporter +from . import importer +from . import mapper diff --git a/connector_jira/components/backend_adapter.py b/connector_jira/components/backend_adapter.py new file mode 100644 index 000000000..12d184a99 --- /dev/null +++ b/connector_jira/components/backend_adapter.py @@ -0,0 +1,102 @@ +# Copyright 2016-2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging +from contextlib import contextmanager + +import requests + +from odoo import _, exceptions + +from odoo.addons.component.core import Component +from odoo.addons.connector.exception import IDMissingInBackend + +_logger = logging.getLogger(__name__) + +try: + import jira +except ImportError as err: + _logger.debug(err) + + +JIRA_JQL_DATETIME_FORMAT = "%Y-%m-%d %H:%M" # no seconds :-( + + +class JiraAdapter(Component): + """Generic adapter for using the JIRA backend""" + + _name = "jira.webservice.adapter" + _inherit = ["base.backend.adapter.crud", "jira.base"] + _usage = "backend.adapter" + + def __init__(self, work_context): + super().__init__(work_context) + self._client = None + + @property + def client(self): + # lazy load the client, initialize only when actually needed + if not self._client: + self._client = self.backend_record.get_api_client() + return self._client + + def _post_get_json( + self, + path, + data=None, + base=jira.resources.Resource.JIRA_BASE_URL, + ): + """Get the json for a given path and payload + + :param path: The subpath required + :type path: str + :param data: a payload for the method + :type data: A json payload + :param base: The Base JIRA URL, defaults to the instance base. + :type base: Optional[str] + :rtype: Union[Dict[str, Any], List[Dict[str, str]]] + """ + url = self.client._get_url(path, base) + r = self.client._session.post(url, data=data) + try: + r_json = jira.utils.json_loads(r) + except ValueError as e: + logging.error(f"{e}\n{r.text}") + raise e + return r_json + + @contextmanager + def handle_404(self): + """Context manager to handle 404 errors on the API + + 404 (no record found) on the API are re-raised as: + ``odoo.addons.connector.exception.IDMissingInBackend`` + """ + try: + yield + except jira.exceptions.JIRAError as err: + if err.status_code == 404: + raise IDMissingInBackend(f"{err.text} (url: {err.url})") from err + raise + + @contextmanager + def handle_user_api_errors(self): + """Contextmanager to use when the API is used user-side + + It catches the common network or Jira errors and reraise them + to the user using the Odoo UserError. + """ + try: + yield + except requests.exceptions.ConnectionError as err: + _logger.exception("Jira ConnectionError") + message = _("Error during connection with Jira: %s") % (err,) + raise exceptions.UserError(message) from err + except jira.exceptions.JIRAError as err: + _logger.exception("Jira JIRAError") + message = _("Jira Error: %s") % (err,) + raise exceptions.UserError(message) from err + except IDMissingInBackend as err: + _logger.exception("Jira 404 for an ID") + message = _("Record does not exist in Jira: %s") % (err,) + raise exceptions.UserError(message) from err diff --git a/connector_jira/components/base.py b/connector_jira/components/base.py new file mode 100644 index 000000000..dab31f13d --- /dev/null +++ b/connector_jira/components/base.py @@ -0,0 +1,15 @@ +# Copyright 2018-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.addons.component.core import AbstractComponent + + +class BaseJiraConnectorComponent(AbstractComponent): + """Base Jira Connector Component + + All components of this connector should inherit from it. + """ + + _name = "jira.base" + _inherit = "base.connector" + _collection = "jira.backend" diff --git a/connector_jira/components/binder.py b/connector_jira/components/binder.py new file mode 100644 index 000000000..85e13518f --- /dev/null +++ b/connector_jira/components/binder.py @@ -0,0 +1,72 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import fields, models + +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + + +class JiraBinder(Component): + """Binder for Odoo models + + Where we create an additional model holding the external id. + The advantages to have a second models are: + * we can link more than 1 JIRA instance to the same record + * we can work with, lock, edit the jira binding without touching the + normal record + + Default binder when no specific binder is defined for a model. + """ + + _name = "jira.binder" + _inherit = ["base.binder", "jira.base"] + + def sync_date(self, binding): + assert self._sync_date_field + sync_date = binding[self._sync_date_field] + if not sync_date: + return + return fields.Datetime.from_string(sync_date) + + +class JiraModelBinder(Component): + """Binder for standalone models + + When we synchronize a model that has no equivalent + in Odoo, we create a model that hold the Jira records + without `_inherits`. + + """ + + _name = "jira.model.binder" + _inherit = ["base.binder", "jira.base"] + + _apply_on = [ + "jira.issue.type", + ] + + _odoo_field = "id" + + def to_internal(self, external_id, unwrap=False): + if unwrap: + _logger.warning( + "unwrap has no effect when the " + "binding is not an inherits " + "(model %s)", + self.model._name, + ) + return super().to_internal(external_id, unwrap=False) + + def unwrap_binding(self, binding): + if isinstance(binding, models.BaseModel): + binding.ensure_one() + else: + binding = self.model.browse(binding) + return binding + + def unwrap_model(self): + return self.model diff --git a/connector_jira/components/exporter.py b/connector_jira/components/exporter.py new file mode 100644 index 000000000..218b0b6dc --- /dev/null +++ b/connector_jira/components/exporter.py @@ -0,0 +1,324 @@ +# Copyright 2016-2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +""" + +Exporters for Jira. + +In addition to its export job, an exporter has to: + +* check in Jira if the record has been updated more recently than the + last sync date and if yes, delay an import +* call the ``bind`` method of the binder to update the last sync date + +""" + +import logging +from contextlib import contextmanager + +import psycopg2 + +from odoo import _, fields, tools + +from odoo.addons.component.core import AbstractComponent, Component +from odoo.addons.queue_job.exception import RetryableJobError + +from .mapper import iso8601_to_utc_datetime + +_logger = logging.getLogger(__name__) + + +class JiraBaseExporter(AbstractComponent): + """Base exporter for Jira""" + + _name = "jira.base.exporter" + _inherit = ["base.exporter", "jira.base"] + _usage = "record.exporter" + + def __init__(self, work_context): + super().__init__(work_context) + self.binding = None + self.external_id = None + + def _delay_import(self): + """Schedule an import of the record. + + Adapt in the sub-classes when the model is not imported + using ``import_record``. + """ + # force is True because the sync_date will be more recent + # so the import would be skipped if it was not forced + assert self.external_id + self.binding.import_record(self.backend_record, self.external_id, force=True) + + def _should_import(self): + """Before the export, compare the update date + in Jira and the last sync date in Odoo, + if the former is more recent, schedule an import + to not miss changes done in Jira. + """ + assert self.binding + if not self.external_id: + return False + sync = self.binder.sync_date(self.binding) + if not sync: + return True + jira_updated = self.backend_adapter.read(self.external_id, fields=["updated"])[ + "fields" + ]["updated"] + + sync_date = fields.Datetime.from_string(sync) + jira_date = iso8601_to_utc_datetime(jira_updated) + return sync_date < jira_date + + def _lock(self): + """Lock the binding record. + + Lock the binding record so we are sure that only one export + job is running for this record if concurrent jobs have to export the + same record. + + When concurrent jobs try to export the same record, the first one + will lock and proceed, the others will fail to lock and will be + retried later. + + This behavior works also when the export becomes multilevel + with :meth:`_export_dependencies`. Each level will set its own lock + on the binding record it has to export. + """ + self.component("record.locker").lock(self.binding) + + def run(self, binding, *args, **kwargs): + """Run the synchronization + + :param binding: binding record to export + """ + self.binding = binding + + if not self.binding.exists(): + return _("Record to export does no longer exist.") + + # prevent other jobs to export the same record + # will be released on commit (or rollback) + self._lock() + + self.external_id = self.binder.to_external(self.binding) + result = self._run(*args, **kwargs) + self.binder.bind(self.external_id, self.binding) + # commit so we keep the external ID if several exports + # are called and one of them fails + if not tools.config["test_enable"]: + self.env.cr.commit() # pylint: disable=invalid-commit + return result + + def _run(self, *args, **kwargs): + """Flow of the synchronization, implemented in inherited classes""" + raise NotImplementedError + + +class JiraExporter(Component): + """Common exporter flow for Jira + + If no specific exporter overrides the exporter for a model, this one is + used. + """ + + _name = "jira.exporter" + _inherit = ["jira.base.exporter"] + _usage = "record.exporter" + + def _has_to_skip(self): + """Return True if the export can be skipped""" + return False + + @contextmanager + def _retry_unique_violation(self): + """Context manager: catch Unique constraint error and retry the + job later. + + When we execute several jobs workers concurrently, it happens + that 2 jobs are creating the same record at the same time (binding + record created by :meth:`_export_dependency`), resulting in: + + IntegrityError: duplicate key value violates unique + constraint "jira_project_project_odoo_uniq" + DETAIL: Key (backend_id, odoo_id)=(1, 4851) already exists. + + In that case, we'll retry the import just later. + + """ + try: + yield + except psycopg2.IntegrityError as err: + if err.pgcode == psycopg2.errorcodes.UNIQUE_VIOLATION: + raise RetryableJobError( + "A database error caused the failure of the job:\n" + "%s\n\n" + "Likely due to 2 concurrent jobs wanting to create " + "the same record. The job will be retried later." % err + ) from err + else: + raise + + def _export_dependency(self, relation, binding_model, component=None): + """ + Export a dependency. + + .. warning:: a commit is done at the end of the export of each + dependency. The reason for that is that we pushed a record + on the backend and we absolutely have to keep its ID. + + So you *must* take care to not modify the Odoo database + excepted when writing back the external ID or eventual + external data to keep on this side. + + You should call this method only in the beginning of + exporter synchronization (in `~._export_dependencies`) + and do not write data which should be rollbacked in case + of error. + + :param relation: record to export if not already exported + :type relation: :py:class:`odoo.models.BaseModel` + :param binding_model: name of the binding model for the relation + :type binding_model: str | unicode + :param component: component to use for the export + By default: lookup a component by usage + 'record.exporter' and model + :type exporter_cls: :py:class:`odoo.addons.component.core.Component` + """ + if not relation: + return + rel_binder = self.binder_for(binding_model) + # wrap is typically True if the relation is a 'project.project' + # record but the binding model is 'jira.project.project' + wrap = relation._model._name != binding_model + + if wrap and hasattr(relation, "jira_bind_ids"): + domain = [ + ("odoo_id", "=", relation.id), + ("backend_id", "=", self.backend_record.id), + ] + model = self.env[binding_model].with_context(active_test=False) + binding = model.search(domain) + if binding: + binding.ensure_one() + else: + # we are working with a unwrapped record (e.g. + # product.template) and the binding does not exist yet. + # Example: I created a product.product and its binding + # jira.project.project, it is exported, but we need to + # create the binding for the template. + bind_values = { + "backend_id": self.backend_record.id, + "odoo_id": relation.id, + } + # If 2 jobs create it at the same time, retry + # one later. A unique constraint (backend_id, + # odoo_id) should exist on the binding model + with self._retry_unique_violation(): + model_c = ( + self.env[binding_model] + .sudo() + .with_context(connector_no_export=True) + ) + binding = model_c.create(bind_values) + # Eager commit to avoid having 2 jobs + # exporting at the same time. + if not tools.config["test_enable"]: + self.env.cr.commit() # pylint: disable=invalid-commit + else: + # If jira_bind_ids does not exist we are typically in a + # "direct" binding (the binding record is the same record). + # If wrap is True, relation is already a binding record. + binding = relation + + if not rel_binder.to_external(binding): + if component is None: + component = self.component( + usage="record.exporter", model_name=binding_model + ) + component.run(binding.id) + + def _export_dependencies(self): + """Export the dependencies for the record""" + return + + def _map_data(self, fields=None): + """Returns an instance of + :py:class:`~odoo.addons.component.core.Component` + + """ + return self.mapper.map_record(self.binding) + + def _validate_data(self, data): + """Check if the values to import are correct + + Pro-actively check before the ``Model.create`` or + ``Model.update`` if some fields are missing + + Raise `InvalidDataError` + """ + return + + def _create_data(self, map_record, fields=None, **kwargs): + """Get the data to pass to :py:meth:`_create`. + + Jira expect that we pass always all the fields, not only + the modified fields. That's why the `fields` argument + is None. + + """ + return map_record.values(for_create=True, fields=None, **kwargs) + + def _create(self, data): + """Create the Jira record""" + self._validate_data(data) + return self.backend_adapter.create(data) + + def _update_data(self, map_record, fields=None, **kwargs): + """Get the data to pass to :py:meth:`_update`. + + Jira expect that we pass always all the fields, not only + the modified fields. That's why the `fields` argument + is None. + + """ + return map_record.values(fields=None, **kwargs) + + def _update(self, data): + """Update a Jira record""" + assert self.external_id + self._validate_data(data) + self.backend_adapter.write(self.external_id, data) + + def _run(self, fields=None): + """Flow of the synchronization, implemented in inherited classes. + + `~._export_dependencies` might commit exported ids to the database, + so please do not do changes in the database before the export of the + dependencies because they won't be rollbacked. + """ + assert self.binding + + if not self.external_id: + fields = None # should be created with all the fields + + if self._has_to_skip(): + return + + # export the missing linked resources + self._export_dependencies() + + map_record = self._map_data(fields=fields) + + if self.external_id: + record = self._update_data(map_record, fields=fields) + if not record: + return _("Nothing to export.") + self._update(record) + else: + record = self._create_data(map_record, fields=fields) + if not record: + return _("Nothing to export.") + self.external_id = self._create(record) + return _("Record exported with ID %s on Jira.") % self.external_id diff --git a/connector_jira/components/importer.py b/connector_jira/components/importer.py new file mode 100644 index 000000000..2a683fa7c --- /dev/null +++ b/connector_jira/components/importer.py @@ -0,0 +1,558 @@ +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +""" + +Importers for Jira. + +An import can be skipped if the last sync date is more recent than +the last update in Jira. + +They should call the ``bind`` method if the binder even if the records +are already bound, to update the last sync date. + +""" + +import logging +from contextlib import closing, contextmanager +from datetime import datetime, timedelta + +from psycopg2 import IntegrityError, errorcodes + +import odoo +from odoo import _, tools + +from odoo.addons.component.core import AbstractComponent, Component +from odoo.addons.connector.exception import IDMissingInBackend +from odoo.addons.queue_job.exception import RetryableJobError + +from .backend_adapter import JIRA_JQL_DATETIME_FORMAT +from .mapper import iso8601_to_utc_datetime + +_logger = logging.getLogger(__name__) + +RETRY_ON_ADVISORY_LOCK = 1 # seconds +RETRY_WHEN_CONCURRENT_DETECTED = 1 # seconds +# when we import using JQL, we always import tasks from +# slightly before the last batch import, because Jira +# does not send the results from the past minute and +# maybe sometimes more +IMPORT_DELTA = 300 # seconds + + +class JiraImporter(Component): + """Base importer for Jira + + If no specific importer is defined for a model, this one is used. + """ + + _name = "jira.importer" + _inherit = ["base.importer", "jira.base"] + _usage = "record.importer" + + def __init__(self, work_context): + super().__init__(work_context) + self.external_id = None + self.external_record = None + + def _get_external_data(self): + """Return the raw Jira data for ``self.external_id``""" + return self.backend_adapter.read(self.external_id) + + def must_skip(self, force=False): + """Returns a reason as string if the import must be skipped. + + Returns None to continue with the import. + """ + assert self.external_record + + def _before_import(self): + """Hook called before the import, when we have the Jira + data""" + + def _get_external_updated_at(self): + assert self.external_record + ext_fields = self.external_record.get("fields", {}) + external_updated_at = ext_fields.get("updated") + if not external_updated_at: + return None + return iso8601_to_utc_datetime(external_updated_at) + + def _is_uptodate(self, binding): + """Return True if the import should be skipped because + it is already up-to-date in Odoo""" + external_date = self._get_external_updated_at() + if not external_date: + return False # no update date on Jira, always import it. + if not binding: + return # it does not exist so it should not be skipped + # We store the jira "updated_at" field in the binding, + # so for further imports, we can check accurately if the + # record is already up-to-date (this field has a millisecond + # precision). + if binding.jira_updated_at: + return external_date < binding.jira_updated_at + return False + + def _import_dependency( + self, external_id, binding_model, component=None, record=None, always=False + ): + """ + Import a dependency. + + The component that will be used for the dependency can be injected + with the ``component``. + + :param external_id: id of the related binding to import + :param binding_model: name of the binding model for the relation + :type binding_model: str | unicode + :param component: component to use for the importer + By default: lookup component for the model with + usage ``record.importer`` + :type importer_cls: :py:class:`odoo.addons.component.core.Component` + :param record: if we already have the data of the dependency, we + can pass it along to the dependency's importer + :type record: dict + :param always: if True, the record is updated even if it already + exists, + it is still skipped if it has not been modified on Jira + :type always: boolean + """ + if not external_id: + return + binder = self.binder_for(binding_model) + if always or not binder.to_internal(external_id): + if component is None: + component = self.component( + usage="record.importer", model_name=binding_model + ) + component.run(external_id, record=record, force=True) + + def _import_dependencies(self): + """Import the dependencies for the record""" + return + + def _map_data(self): + """Returns an instance of + :py:class:`~odoo.addons.component.core.Component` + + """ + return self.mapper.map_record(self.external_record) + + def _validate_data(self, data): + """Check if the values to import are correct + + Pro-actively check before the ``_create`` or + ``_update`` if some fields are missing or invalid. + + Raise `InvalidDataError` + """ + return + + def _filter_data(self, binding, data): + """Filter values that aren't actually changing""" + binding.ensure_one() + fields = list(data.keys()) + new_values = binding._convert_to_write( + data, + ) + old_values = binding._convert_to_write( + binding.read( + fields, + load="_classic_write", + )[0], + ) + new_data = {} + for field in fields: + if new_values[field] == old_values[field]: + continue + new_data[field] = data[field] + return new_data + + def _get_binding(self): + """Return the binding id from the jira id""" + return self.binder.to_internal(self.external_id) + + def _create_data(self, map_record, **kwargs): + """Get the data to pass to :py:meth:`_create`""" + return map_record.values( + for_create=True, + external_updated_at=self._get_external_updated_at(), + **kwargs, + ) + + @contextmanager + def _retry_unique_violation(self): + """Context manager: catch Unique constraint error and retry the + job later. + + When we execute several jobs workers concurrently, it happens + that 2 jobs are creating the same record at the same time + (especially product templates as they are shared by a lot of + sales orders), resulting in: + + IntegrityError: duplicate key value violates unique + constraint "jira_project_project_external_id_uniq" + DETAIL: Key (backend_id, external_id)=(1, 4851) already exists. + + In that case, we'll retry the import just later. + + """ + try: + yield + except IntegrityError as err: + if err.pgcode == errorcodes.UNIQUE_VIOLATION: + raise RetryableJobError( + "A database error caused the failure of the job:\n" + "%s\n\n" + "Likely due to 2 concurrent jobs wanting to create " + "the same record. The job will be retried later." % err + ) from err + else: + raise + + def _create_context(self): + return { + "connector_jira": True, + "connector_no_export": True, + "tracking_disable": True, + } + + def _create(self, data): + """Create the Odoo record""" + # special check on data before import + self._validate_data(data) + with self._retry_unique_violation(): + model_ctx = self.model.with_context(**self._create_context()) + binding = model_ctx.sudo().create(data) + + _logger.debug("%s created from Jira %s", binding, self.external_id) + return binding + + def _update_data(self, map_record, **kwargs): + """Get the data to pass to :py:meth:`_update`""" + return map_record.values( + external_updated_at=self._get_external_updated_at(), **kwargs + ) + + def _update_context(self): + return { + "connector_jira": True, + "connector_no_export": True, + "tracking_disable": True, + } + + def _update(self, binding, data): + """Update an Odoo record""" + data = self._filter_data(binding, data) + if not data: + _logger.debug( + "%s not updated from Jira %s as nothing changed", + binding, + self.external_id, + ) + return + self._validate_data(data) + binding_ctx = binding.with_context(**self._update_context()) + binding_ctx.sudo().write(data) + _logger.debug("%s updated from Jira %s", binding, self.external_id) + return + + def _after_import(self, binding): + """Hook called at the end of the import""" + return + + @contextmanager + def do_in_new_work_context(self, model_name=None): + """Context manager that yields a new component work context + + Using a new Odoo Environment thus a new PG transaction. + + This can be used to make a preemptive check in a new transaction, + for instance to see if another transaction already made the work. + """ + registry = odoo.registry(self.env.cr.dbname) + with closing(registry.cursor()) as cr: + try: + new_env = odoo.api.Environment(cr, self.env.uid, self.env.context) + backend = self.backend_record.with_env(new_env) + with backend.work_on(model_name or self.model._name) as work: + yield work + except Exception: + cr.rollback() + raise + else: + if not tools.config["test_enable"]: + cr.commit() # pylint: disable=invalid-commit + + def _handle_record_missing_on_jira(self): + """Hook called when we are importing a record missing on Jira + + By default it deletes the matching record or binding if it exists on + Odoo and returns a result to show on the job, job will be done. + """ + binding = self._get_binding() + if binding: + # emptying the external_id allows to unlink the binding + binding.external_id = False + binding.unlink() + return _("Record does no longer exist in Jira") + + def run(self, external_id, force=False, record=None, **kwargs): + """Run the synchronization + + A record can be given, reducing number of calls when + a call already returns data (example: user returns addresses) + + :param external_id: identifier of the record on Jira + """ + self.external_id = external_id + lock_name = "import({}, {}, {}, {})".format( + self.backend_record._name, + self.backend_record.id, + self.model._name, + self.external_id, + ) + # Keep a lock on this import until the transaction is committed + self.advisory_lock_or_retry(lock_name, retry_seconds=RETRY_ON_ADVISORY_LOCK) + if record is not None: + self.external_record = record + else: + try: + self.external_record = self._get_external_data() + except IDMissingInBackend: + return self._handle_record_missing_on_jira() + binding = self._get_binding() + if not binding: + with self.do_in_new_work_context() as new_work: + # Even when we use an advisory lock, we may have + # concurrent issues. + # Explanation: + # We import Partner A and B, both of them import a + # partner category X. + # + # The squares represent the duration of the advisory + # lock, the transactions starts and ends on the + # beginnings and endings of the 'Import Partner' + # blocks. + # T1 and T2 are the transactions. + # + # ---Time---> + # > T1 /------------------------\ + # > T1 | Import Partner A | + # > T1 \------------------------/ + # > T1 /-----------------\ + # > T1 | Imp. Category X | + # > T1 \-----------------/ + # > T2 /------------------------\ + # > T2 | Import Partner B | + # > T2 \------------------------/ + # > T2 /-----------------\ + # > T2 | Imp. Category X | + # > T2 \-----------------/ + # + # As you can see, the locks for Category X do not + # overlap, and the transaction T2 starts before the + # commit of T1. So no lock prevents T2 to import the + # category X and T2 does not see that T1 already + # imported it. + # + # The workaround is to open a new DB transaction at the + # beginning of each import (e.g. at the beginning of + # "Imp. Category X") and to check if the record has been + # imported meanwhile. If it has been imported, we raise + # a Retryable error so T2 is rollbacked and retried + # later (and the new T3 will be aware of the category X + # from the its inception). + binder = new_work.component(usage="binder") + if binder.to_internal(self.external_id): + raise RetryableJobError( + "Concurrent error. The job will be retried later", + seconds=RETRY_WHEN_CONCURRENT_DETECTED, + ignore_retry=True, + ) + + reason = self.must_skip(force=force) + if reason: + return reason + + if not force and self._is_uptodate(binding): + return _("Already up-to-date.") + + self._before_import() + + # import the missing linked resources + self._import_dependencies() + + self._import(binding, **kwargs) + + def _import(self, binding, **kwargs): + """Import the external record. + + Can be inherited to modify for instance the environment + (change current user, values in context, ...) + + """ + map_record = self._map_data() + + if binding: + record = self._update_data(map_record) + self._update(binding, record) + else: + record = self._create_data(map_record) + binding = self._create(record) + + with self._retry_unique_violation(): + self.binder.bind(self.external_id, binding) + + self._after_import(binding) + + +class BatchImporter(AbstractComponent): + """The role of a BatchImporter is to search for a list of + items to import, then it can either import them directly or delay + the import of each item separately. + """ + + _name = "jira.batch.importer" + _inherit = ["base.importer", "jira.base"] + _usage = "batch.importer" + + def run(self): + """Run the synchronization, search all JIRA records""" + record_ids = self._search() + for record_id in record_ids: + self._import_record(record_id) + + def _search(self): + return self.backend_adapter.search() + + def _import_record(self, record_id, **kwargs): + """Import a record directly or delay the import of the record. + + Method to implement in sub-classes. + """ + raise NotImplementedError + + +class DirectBatchImporter(AbstractComponent): + """Import the records directly, without delaying the jobs.""" + + _name = "jira.direct.batch.importer" + _inherit = ["jira.batch.importer"] + + def _import_record(self, record_id, force=False, record=None): + """Import the record directly""" + self.model.import_record( + self.backend_record, record_id, force=force, record=record + ) + + +class DelayedBatchImporter(AbstractComponent): + """Delay import of the records""" + + _name = "jira.delayed.batch.importer" + _inherit = ["jira.batch.importer"] + + def _import_record(self, record_id, force=False, record=None, **kwargs): + """Delay the import of the records""" + self.model.with_delay(**kwargs).import_record( + self.backend_record, record_id, force=force, record=record + ) + + +class TimestampBatchImporter(AbstractComponent): + """Batch Importer working with a jira.backend.timestamp.record + + It locks the timestamp to ensure no other job is working on it, + and uses the latest timestamp value as reference for the search. + + The role of a BatchImporter is to search for a list of + items to import, then it can either import them directly or delay + the import of each item separately. + """ + + _name = "jira.timestamp.batch.importer" + _inherit = ["base.importer", "jira.base"] + _usage = "timestamp.batch.importer" + + def run(self, timestamp, force=False, **kwargs): + """Run the synchronization using the timestamp""" + original_timestamp_value = timestamp.last_timestamp + if not timestamp._lock(): + self._handle_lock_failed(timestamp) + + next_timestamp_value, records = self._search(timestamp) + + timestamp._update_timestamp(next_timestamp_value) + + number = self._handle_records(records, force=force) + + return _( + "Batch from {original_timestamp_value} UTC to " + "{next_timestamp_value} UTC generated {number} imports" + ).format( + original_timestamp_value=original_timestamp_value, + next_timestamp_value=next_timestamp_value, + number=number, + ) + + def _handle_records(self, records, force=False): + """Handle the records to import and return the number handled""" + for record_id in records: + self._import_record(record_id, force=force) + return len(records) + + def _handle_lock_failed(self, timestamp): + _logger.warning("Failed to acquire timestamps %s", timestamp, exc_info=True) + raise RetryableJobError( + "Concurrent job / process already syncing", + ignore_retry=True, + ) + + def _search(self, timestamp): + """Return a tuple (next timestamp value, jira record ids)""" + until = datetime.now() + + parts = [] + if timestamp.last_timestamp: + since = timestamp.last_timestamp + from_date = since.strftime(JIRA_JQL_DATETIME_FORMAT) + parts.append('updated >= "%s"' % from_date) + to_date = until.strftime(JIRA_JQL_DATETIME_FORMAT) + parts.append('updated <= "%s"' % to_date) + + next_timestamp = max(until - timedelta(seconds=IMPORT_DELTA), since) + record_ids = self.backend_adapter.search(" and ".join(parts)) + return (next_timestamp, record_ids) + + def _import_record(self, record_id, force=False, record=None, **kwargs): + """Delay the import of the records""" + self.model.with_delay(**kwargs).import_record( + self.backend_record, + record_id, + force=force, + record=record, + ) + + +class JiraDeleter(Component): + _name = "jira.deleter" + _inherit = ["base.deleter", "jira.base"] + _usage = "record.deleter" + + def run(self, external_id, only_binding=False, set_inactive=False): + binding = self.binder.to_internal(external_id) + if not binding.exists(): + return _("Binding not found") + if set_inactive: + binding.active = False + else: + record = binding.odoo_id + # emptying the external_id allows to unlink the binding + binding.external_id = False + binding.unlink() + if not only_binding: + record.unlink() + return _("Record deleted") diff --git a/connector_jira/components/mapper.py b/connector_jira/components/mapper.py new file mode 100644 index 000000000..31c84b1d8 --- /dev/null +++ b/connector_jira/components/mapper.py @@ -0,0 +1,184 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +import pytz +from dateutil import parser + +from odoo import fields + +from odoo.addons.component.core import AbstractComponent, Component +from odoo.addons.connector.components.mapper import mapping + + +class JiraImportMapper(AbstractComponent): + """Base Import Mapper for Jira""" + + _name = "jira.import.mapper" + _inherit = ["base.import.mapper", "jira.base"] + + @mapping + def jira_updated_at(self, record): + if self.options.external_updated_at: + return {"jira_updated_at": self.options.external_updated_at} + + +def iso8601_to_utc_datetime(isodate): + """Returns the UTC datetime from an iso8601 date + + A JIRA date is formatted using the ISO 8601 format. + Example: 2013-11-04T13:52:01+0100 + """ + parsed = parser.parse(isodate) + if not parsed.tzinfo: + return parsed + utc = pytz.timezone("UTC") + # set as UTC and then remove the tzinfo so the date becomes naive + return parsed.astimezone(utc).replace(tzinfo=None) + + +def utc_datetime_to_iso8601(dt): + """Returns an iso8601 datetime from a datetime. + + Example: 2013-11-04 12:52:01 → 2013-11-04T12:52:01+0000 + + """ + utc = pytz.timezone("UTC") + utc_dt = utc.localize(dt, is_dst=False) # UTC = no DST + return utc_dt.isoformat() + + +def iso8601_to_utc(field): + """A modifier intended to be used on the ``direct`` mappings for + importers. + + A Jira date is formatted using the ISO 8601 format. + Convert an ISO 8601 timestamp to an UTC datetime as string + as expected by Odoo. + + Example: 2013-11-04T13:52:01+0100 -> 2013-11-04 12:52:01 + + Usage:: + + direct = [(iso8601_to_utc('date_field'), 'date_field')] + + :param field: name of the source field in the record + + """ + + def modifier(self, record, to_attr): + value = record.get(field) + if not value: + return False + utc_date = iso8601_to_utc_datetime(value) + return fields.Datetime.to_string(utc_date) + + return modifier + + +def iso8601_to_naive_date(isodate): + """Returns the naive date from an iso8601 date + + Keep only the date, when we want to keep only the naive date. + It's safe to extract it directly from the tz-aware timestamp. + Example with 2014-10-07T00:34:59+0200: we want 2014-10-07 and not + 2014-10-06 that we would have using the timestamp converted to UTC. + """ + naive_date = isodate[:10] + return datetime.strptime(naive_date, "%Y-%m-%d").date() + + +def iso8601_naive_date(field): + """A modifier intended to be used on the ``direct`` mappings for + importers. + + A JIRA datetime is formatted using the ISO 8601 format. + Returns the naive date from an iso8601 datetime. + + Keep only the date, when we want to keep only the naive date. + It's safe to extract it directly from the tz-aware timestamp. + Example with 2014-10-07T00:34:59+0200: we want 2014-10-07 and not + 2014-10-06 that we would have using the timestamp converted to UTC. + + Usage:: + + direct = [(iso8601_naive_date('name'), 'name')] + + :param field: name of the source field in the record + + """ + + def modifier(self, record, to_attr): + value = record.get(field) + if not value: + return False + naive_date = iso8601_to_naive_date(value) + return fields.Date.to_string(naive_date) + + return modifier + + +def follow_dict_path(field): + """A modifier intended to be used on ``direct`` mappings. + + 'Follows' children keys in dictionaries + If a key is missing along the path, ``None`` is returned. + + Examples: + Assuming a dict `{'a': {'b': 1}} + + direct = [ + (follow_dict_path('a.b'), 'cat')] + + Then 'cat' will be 1. + + :param field: field "path", using dots for subkeys + """ + + def modifier(self, record, to_attr): + attrs = field.split(".") + value = record + for attr in attrs: + value = value.get(attr) + if not value: + break + return value + + return modifier + + +def whenempty(field, default_value): + """Set a default value when the value is evaluated to False + + A modifier intended to be used on the ``direct`` mappings. + + Example:: + + direct = [(whenempty('source', 'default value'), 'target')] + + :param field: name of the source field in the record + :param default_value: value to set when the source value is False-ish + """ + + def modifier(self, record, to_attr): + value = record[field] + if not value: + return default_value + return value + + return modifier + + +class FromFields(Component): + _name = "jira.mapper.from.attrs" + _inherit = ["jira.base"] + _usage = "map.from.attrs" + + def values(self, record, mapper_): + values = {} + from_fields_mappings = getattr(mapper_, "from_fields", []) + fields_values = record.get("fields", {}) + for source, target in from_fields_mappings: + values[target] = mapper_._map_direct(fields_values, source, target) + return values diff --git a/connector_jira/controllers/__init__.py b/connector_jira/controllers/__init__.py new file mode 100644 index 000000000..c47ab2c2d --- /dev/null +++ b/connector_jira/controllers/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import main diff --git a/connector_jira/controllers/main.py b/connector_jira/controllers/main.py new file mode 100644 index 000000000..8e7f735b3 --- /dev/null +++ b/connector_jira/controllers/main.py @@ -0,0 +1,95 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +""" + +Receive webhooks from Jira + +Webhooks to create in Jira: + +1. Odoo Issues + URL: http://odoo:8069/connector_jira/webhooks/issue/${issue.id} + Events: Issue{created, updated, deleted} + Exclude body: yes + +1. Odoo Worklogs + URL: http://odoo:8069/connector_jira/webhooks/worklog + Events: Issue{created, updated, deleted} + Exclude body: no + + +JIRA could well send all the data in the webhook request's body, +which would avoid Odoo to make another GET to get this data, but +JIRA webhooks are potentially insecure as we don't know if it really +comes from JIRA. So we don't use the data sent by the webhook and the job +gets the data by itself (with the nice side-effect that the job is retryable). + +""" + +import logging + +import odoo +from odoo import _, http +from odoo.http import request + +from odoo.addons.web.controllers.main import ensure_db + +_logger = logging.getLogger(__name__) + + +class JiraWebhookController(http.Controller): + @http.route("/connector_jira/webhooks/issue", type="json", auth="none", csrf=False) + def webhook_issue(self, issue_id=None, **kw): + ensure_db() + request.uid = odoo.SUPERUSER_ID + env = request.env + backend = env["jira.backend"].search([("use_webhooks", "=", True)], limit=1) + if not backend: + _logger.warning( + "Received a webhook from Jira but cannot find a " + "Jira backend with webhooks activated" + ) + return + + action = request.jsonrequest["webhookEvent"] + + worklog = request.jsonrequest["issue"] + issue_id = worklog["id"] + + delayable_model = env["jira.project.task"].with_delay() + if action == "jira:issue_deleted": + delayable_model.delete_record(backend, issue_id) + else: + delayable_model.import_record(backend, issue_id) + + @http.route( + "/connector_jira/webhooks/worklog", type="json", auth="none", csrf=False + ) + def webhook_worklog(self, **kw): + ensure_db() + request.uid = odoo.SUPERUSER_ID + env = request.env + backend = env["jira.backend"].search([("use_webhooks", "=", True)], limit=1) + if not backend: + _logger.warning( + "Received a webhook from Jira but cannot find a " + "Jira backend with webhooks activated" + ) + return + + action = request.jsonrequest["webhookEvent"] + + worklog = request.jsonrequest["worklog"] + issue_id = worklog["issueId"] + worklog_id = worklog["id"] + + if action == "worklog_deleted": + env["jira.account.analytic.line"].with_delay( + description=_( + "Delete a local worklog which has " "been deleted on JIRA" + ) + ).delete_record(backend, worklog_id) + else: + env["jira.account.analytic.line"].with_delay( + description=_("Import a worklog from JIRA") + ).import_record(backend, issue_id, worklog_id) diff --git a/connector_jira/data/cron.xml b/connector_jira/data/cron.xml new file mode 100644 index 000000000..da4883d49 --- /dev/null +++ b/connector_jira/data/cron.xml @@ -0,0 +1,51 @@ + + + + JIRA - Import Project Tasks + + code + model._scheduler_import_project_task() + + + 10 + minutes + -1 + + + + JIRA - Import Users + + code + model._scheduler_import_res_users() + + + 10 + minutes + -1 + + + + JIRA - Import Worklogs + + code + model._scheduler_import_analytic_line() + + + 10 + minutes + -1 + + + + JIRA - Import Deleted Worklogs + + code + model._scheduler_delete_analytic_line() + + + 10 + minutes + -1 + + + diff --git a/connector_jira/data/queue_job_data.xml b/connector_jira/data/queue_job_data.xml new file mode 100644 index 000000000..2cd85ee60 --- /dev/null +++ b/connector_jira/data/queue_job_data.xml @@ -0,0 +1,65 @@ + + + + + connector_jira.import + + + + + + + + import_record + + + + + + + + + import_batch + + + + + + run_batch_timestamp + + + + + + delete_record + + + + + + import_record + + + + + + + export_record + + + + + + + + + import_batch + + + diff --git a/connector_jira/demo/jira_backend_demo.xml b/connector_jira/demo/jira_backend_demo.xml new file mode 100644 index 000000000..306ecda8e --- /dev/null +++ b/connector_jira/demo/jira_backend_demo.xml @@ -0,0 +1,7 @@ + + + + Jira + http://jira:8080 + + diff --git a/connector_jira/fields.py b/connector_jira/fields.py new file mode 100644 index 000000000..40f309300 --- /dev/null +++ b/connector_jira/fields.py @@ -0,0 +1,63 @@ +import time +from datetime import date, datetime + +from odoo import fields + +MILLI_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f" +MILLI_DATETIME_LENGTH = len(MILLI_DATETIME_FORMAT) + + +class MilliDatetime(fields.Field): + """Field storing Datetime with milliseconds precision + + There are no widgets for this field, it is only technical + for storing Jira timestamps. + + As Jira uses Unix Timestamps on some webservices methods, + this field provides conversions utilities. + + Beware, unlike the Datetime field (prior 12.0), the MilliDatetime + field works with datetime objects. + """ + + type = "millidatetime" + column_type = ("timestamp", "timestamp") + + @staticmethod + def from_string(value): + """Convert a string to :class:`datetime` including milliseconds""" + if not value: + return None + if isinstance(value, datetime): + if value.tzinfo: + raise ValueError( + "MilliDatetime field expects a naive datetime: %s" % value + ) + return value + if len(value) > fields.DATETIME_LENGTH: + return datetime.strptime(value, MILLI_DATETIME_FORMAT) + else: + return fields.Datetime.from_string(value) + + @staticmethod + def to_string(value): + """Convert a :class:`datetime` including milliseconds to a string""" + return value.strftime(MILLI_DATETIME_FORMAT) if value else False + + @staticmethod + def from_timestamp(value): + return datetime.fromtimestamp(value / 1000) + + @staticmethod + def to_timestamp(value): + assert not value.tzinfo + return int(time.mktime(value.timetuple()) * 1000 + value.microsecond / 1000) + + def convert_to_cache(self, value, record, validate=True): + if not value: + return False + if isinstance(value, date) and not isinstance(value, datetime): + raise TypeError( + f"{value} (field {self}) must be string or datetime, not date." + ) + return self.from_string(value) diff --git a/connector_jira/i18n/connector_jira.pot b/connector_jira/i18n/connector_jira.pot new file mode 100644 index 000000000..1d7eaa93a --- /dev/null +++ b/connector_jira/i18n/connector_jira.pot @@ -0,0 +1,3844 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector_jira +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__accesses_count +msgid "# Access Rights" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__collaborator_count +msgid "# Collaborators" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__groups_count +msgid "# Groups" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_count +msgid "# Ratings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__rules_count +msgid "# Record Rules" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__task_count +msgid "# Tasks" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#: code:addons/connector_jira/models/project_project/common.py:0 +#: code:addons/connector_jira/models/project_project/common.py:0 +#: code:addons/connector_jira/models/project_project/project_link_jira.py:0 +#, python-format +msgid "%s is not a valid JIRA Key" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.backend_report_user_sync +msgid "" +"-\n" +" detail:" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "(" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid ")" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.backend_report_user_sync +msgid "error:" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_task/common.py:0 +#, python-format +msgid "A Jira task cannot be deleted." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_defaults +msgid "" +"A Python dictionary that will be evaluated to provide default values when " +"creating new records for this alias." +msgstr "" + +#. module: connector_jira +#: model:ir.model.constraint,message:connector_jira.constraint_jira_account_analytic_line_jira_binding_uniq +#: model:ir.model.constraint,message:connector_jira.constraint_jira_binding_jira_binding_uniq +#: model:ir.model.constraint,message:connector_jira.constraint_jira_issue_type_jira_binding_uniq +#: model:ir.model.constraint,message:connector_jira.constraint_jira_organization_jira_binding_uniq +#: model:ir.model.constraint,message:connector_jira.constraint_jira_project_project_jira_binding_uniq +#: model:ir.model.constraint,message:connector_jira.constraint_jira_project_task_jira_binding_uniq +#: model:ir.model.constraint,message:connector_jira.constraint_jira_res_users_jira_binding_uniq +msgid "A binding already exists for this Jira record" +msgstr "" + +#. module: connector_jira +#: model:ir.model.constraint,message:connector_jira.constraint_jira_account_analytic_line_jira_binding_backend_uniq +msgid "A binding already exists for this line and this backend." +msgstr "" + +#. module: connector_jira +#: model:ir.model.constraint,message:connector_jira.constraint_jira_project_task_jira_binding_backend_uniq +msgid "A binding already exists for this task and this backend." +msgstr "" + +#. module: connector_jira +#: model:ir.model.constraint,message:connector_jira.constraint_jira_backend_timestamp_timestamp_field_uniq +msgid "A timestamp already exists." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "API Configuration" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__api_key_ids +msgid "API Keys" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__access_secret +msgid "Access Secret" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__access_token +msgid "Access Token" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__access_warning +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__access_warning +msgid "Access warning" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_needaction +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_needaction +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "" +"Activate the synchronization of the Epic Link field.\n" +" Only on JIRA Software. The field contains the name of\n" +" the JIRA custom field that contains the Epic Link.\n" +"\n" +" Note that if a project does not synchronize the Epics,\n" +" the field will be empty." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__active +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__active +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__active +msgid "Active" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__analytic_account_active +msgid "Active Analytic Account" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__active_lang_count +msgid "Active Lang Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_ids +msgid "Activities" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_exception_decoration +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_exception_decoration +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_exception_decoration +msgid "Activity Exception Decoration" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_state +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_state +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_state +msgid "Activity State" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_type_icon +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_type_icon +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_type_icon +msgid "Activity Type Icon" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__additional_note +msgid "Additional Note" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__additional_info +msgid "Additional info" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__address_home_id +msgid "Address" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__type +msgid "Address Type" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Advanced Configuration" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_id +msgid "Alias" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_contact +msgid "Alias Contact Security" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_name +msgid "Alias Name" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_domain +msgid "Alias domain" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_value +msgid "Alias email" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_model_id +msgid "Aliased Model" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__lang +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__private_lang +msgid "" +"All the emails and documents sent to this contact will be translated in this" +" language." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__allow_back +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__allow_back +msgid "Allow Back" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__allow_subtasks +msgid "Allow Sub-tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__allow_timesheets +msgid "Allow timesheets" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/importer.py:0 +#, python-format +msgid "Already up-to-date." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__amount +msgid "Amount" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__account_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__analytic_account_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__analytic_account_id +msgid "Analytic Account" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_account_analytic_line +msgid "Analytic Line" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__analytic_tag_ids +msgid "Analytic Tag" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__analytic_account_id +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__project_analytic_account_id +msgid "" +"Analytic account to which this project is linked for financial management. " +"Use an analytic account to record cost and revenue on your project." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__analytic_account_id +msgid "" +"Analytic account to which this task is linked for financial management. Use " +"an analytic account to record cost and revenue on your task. If empty, the " +"analytic account of the project will be used." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend__worklog_date_timezone_mode__naive +msgid "As-is (naive)" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__user_ids +msgid "Assignees" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__date_assign +msgid "Assigning Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__timesheet_ids +msgid "Associated Timesheets" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_aa_line_import +msgid "" +"At confirmation, the selected lines will be reimported from Jira in\n" +" background. If a line was linked to the wrong project (e.g. the fallback\n" +" project) and the project binding has been corrected meanwhile, the line\n" +" will be moved to the expected target project." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_attachment_count +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_attachment_count +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__attachment_ids +msgid "Attachments that don't come from a message." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__auth_uri +msgid "Auth Uri" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend__state__authenticate +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Authenticate" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__avatar_1920 +msgid "Avatar" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__avatar_1024 +msgid "Avatar 1024" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__avatar_128 +msgid "Avatar 128" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__avatar_256 +msgid "Avatar 256" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__avatar_512 +msgid "Avatar 512" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__backend_id +msgid "Backend" +msgstr "" + +#. module: connector_jira +#: model:ir.ui.menu,name:connector_jira.menu_jira_backend +msgid "Backends" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__barcode +msgid "Badge ID" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__analytic_account_balance +msgid "Balance" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__bank_ids +msgid "Banks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__odoo_webhook_base_url +msgid "Base Odoo URL for Webhooks" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/account_analytic_line/deleter.py:0 +#, python-format +msgid "Batch from {} UTC to {} UTC generated {} delete jobs" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/importer.py:0 +#, python-format +msgid "Batch from {} UTC to {} UTC generated {} imports" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/importer.py:0 +#, python-format +msgid "Binding not found" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__is_blacklisted +msgid "Blacklist" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__mobile_blacklisted +msgid "Blacklisted Phone Is Mobile" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__phone_blacklisted +msgid "Blacklisted Phone is Phone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__dependent_ids +msgid "Block" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__depend_on_ids +msgid "Blocked By" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_bounce +msgid "Bounce" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "" +"By clicking on the buttons,\n" +" you will initiate the synchronizations\n" +" with Jira.\n" +" Note that the import or exports\n" +" won't be done directly,\n" +" they will create 'Jobs'\n" +" executed as soon as possible." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__can_edit +msgid "Can Edit" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_aa_line_import +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Cancel" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__category +msgid "Category" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__certificate +msgid "Certificate Level" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__channel_ids +msgid "Channels" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Check Connection" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__partner_is_company +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__is_company +msgid "Check if the contact is a company, otherwise it is a person" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__employee +msgid "Check this box if this contact is an Employee." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__child_text +msgid "Child Text" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__partner_city +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__city +msgid "City" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Close" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__is_closed +msgid "Closing Stage" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__coach_id +msgid "Coach" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__collaborator_ids +msgid "Collaborators" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__color +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__color +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__color +msgid "Color Index" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__commercial_partner_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__commercial_partner_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__commercial_partner_id +msgid "Commercial Entity" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__company_ids +msgid "Companies" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__company_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__company_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__company_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__company_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__company_id +msgid "Company" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__company_name +msgid "Company Name" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__commercial_company_name +msgid "Company Name Entity" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__company_type +msgid "Company Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__partner_gid +msgid "Company database ID" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_id +msgid "Company employee" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend_auth__state__done +msgid "Complete" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__contact_address +msgid "Complete Address" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__component_usage +msgid "Component Usage" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Configuration Done" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Configure Epic Link" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Configure worklog fields" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_aa_line_import +msgid "Confirm" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "Connection successful" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.edit_project +#: model_terms:ir.ui.view,arch_db:connector_jira.view_task_form2 +#: model_terms:ir.ui.view,arch_db:connector_jira.view_users_form +msgid "Connector" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__consumer_key +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__consumer_key +msgid "Consumer Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__child_ids +msgid "Contact" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Continue" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Continue (Only After Above Authorization)" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_account_analytic_line__product_uom_category_id +msgid "" +"Conversion between Units of Measure can only occur if they belong to the " +"same category. The conversion will be made based on the ratios." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Copy the values in the JIRA application link" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_bounce +msgid "Counter of the number of bounced emails for this contact" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__country_id +msgid "Country" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__country_code +msgid "Country Code" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__country_of_birth +msgid "Country of Birth" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__displayed_image_id +msgid "Cover Image" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.project_project_view_form_simplified +msgid "Create and Link with JIRA" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__create_uid +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__create_uid +msgid "Created by" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__create_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__create_date +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__create_date +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__create_date +msgid "Created on" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__credit_limit +msgid "Credit Limit" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__currency_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__currency_id +msgid "Currency" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_bounced_content +msgid "Custom Bounced Message" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__partner_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__partner_id +msgid "Customer" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__access_url +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__access_url +msgid "Customer Portal URL" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_active +msgid "Customer Ratings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_status +msgid "Customer Ratings Status" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__date +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__date +msgid "Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__birthday +msgid "Date of Birth" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_weekday +msgid "Day Of The Week" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__date_deadline +msgid "Deadline" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__project_template +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_base_mixin__project_template +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__project_template +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__project_template +msgid "Default Project Template" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_base_mixin__project_template_shared +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__project_template_shared +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__project_template_shared +msgid "Default Shared Template" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__project_template_shared +msgid "Default Shared Template Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_defaults +msgid "Default Values" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__resource_calendar_id +msgid "Default Working Hours" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__resource_calendar_id +msgid "Define the schedule of resource" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_base_mixin__sync_action +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__sync_action +#: model:ir.model.fields,help:connector_jira.field_project_link_jira__sync_action +msgid "" +"Defines if the information of the project (name and key) are exported to " +"JIRA when changed. Link meansthe project already exists on JIRA, no sync of " +"the project details once the link is established. Tasks are always imported " +"from JIRA, not pushed." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__delete_analytic_line_from_date +msgid "Delete Extra Worklogs from date" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/controllers/main.py:0 +#: code:addons/connector_jira/models/account_analytic_line/deleter.py:0 +#, python-format +msgid "Delete a local worklog which has been deleted on JIRA" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__department_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__department_id +msgid "Department" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__dependent_tasks_count +msgid "Dependent Tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__name +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__description +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__description +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__description +msgid "Description" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/wizards/jira_backend_auth.py:0 +#: code:addons/connector_jira/wizards/jira_backend_auth.py:0 +#, python-format +msgid "" +"Did not get token (%(token)s) or secret (%(secret)s)" +" from Jira. Resp %(resp)s" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__display_name +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__display_name +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__display_name +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__display_name +msgid "Display Name" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__display_project_id +msgid "Display Project" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__progress +msgid "Display progress of current task." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__partner_share +msgid "" +"Either customer (not a user), either shared user. Indicated the current " +"partner is a customer without access or with a limited access created for " +"sharing data." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__partner_email +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__partner_email +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__email +msgid "Email" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__email_from +msgid "Email From" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__signature +msgid "Email Signature" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__email_cc +msgid "Email cc" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__emergency_contact +msgid "Emergency Contact" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__emergency_phone +msgid "Emergency Phone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__employee_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee +msgid "Employee" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_count +msgid "Employee Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_lang +msgid "Employee Lang" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__category_ids +msgid "Employee Tags" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_type +msgid "Employee Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__employee_bank_account_id +msgid "Employee bank salary account" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_bank_account_id +msgid "Employee's Bank Account Number" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_country_id +msgid "Employee's Country" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employees_count +msgid "Employees Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__allow_timesheets +msgid "Enable timesheeting on the project." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__encode_uom_in_days +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__encode_uom_in_days +msgid "Encode Uom In Days" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__encoding_uom_id +msgid "Encoding Uom" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_until +msgid "End Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__date_end +msgid "Ending Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__address_home_id +msgid "" +"Enter here the private address of the employee, not the one linked to your " +"company." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_epic_link_id +msgid "Epic" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__epic_link_field_name +msgid "Epic Link Field" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__epic_link_on_epic +msgid "Epic Link On Epic" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__epic_name_field_name +msgid "Epic Name Field" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend__epic_link_on_epic +msgid "" +"Epics on JIRA cannot be linked to another epic. Check this boxto fill the " +"epic field with itself on Odoo." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/backend_adapter.py:0 +#, python-format +msgid "Error during connection with Jira: %s" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__date +msgid "Expiration Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_project_base_mixin__sync_action__export +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_project_project__sync_action__export +#: model:ir.model.fields.selection,name:connector_jira.selection__project_link_jira__sync_action__export +msgid "Export to JIRA" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_project/common.py:0 +#, python-format +msgid "Exported project cannot be deleted." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__share +msgid "" +"External user with limited access, created only for the purpose of sharing " +"data." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "Failed to connect (%s)" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.backend_report_user_sync +msgid "Failed user sync" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__worklog_fallback_project_id +msgid "Fallback for Worklogs" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__study_field +msgid "Field of Study" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__phone_sanitized +msgid "" +"Field used to store sanitized phone number. Helps speeding up searches and " +"comparisons." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_follower_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_follower_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_partner_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_partner_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__activity_type_icon +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__activity_type_icon +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__activity_type_icon +msgid "Font awesome icon e.g. fa-tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__email_formatted +msgid "Format email address \"Name \"" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__email_formatted +msgid "Formatted Email" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__fri +msgid "Fri" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__from_date_field +msgid "From Date Field" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__gender +msgid "Gender" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Generate new key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__partner_latitude +msgid "Geo Latitude" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__partner_longitude +msgid "Geo Longitude" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__sequence +msgid "Gives the sequence order when displaying a list of Projects." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__sequence +msgid "Gives the sequence order when displaying a list of tasks." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__group_id +msgid "Group" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__groups_id +msgid "Groups" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__has_message +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__has_message +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__has_message +msgid "Has Message" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__has_planned_hours_tasks +msgid "Has Planned Hours Tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__action_id +msgid "Home Action" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__km_home_work +msgid "Home-Work Distance" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__effective_hours +msgid "Hours Spent" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__rating_status +msgid "" +"How to get customer feedback?\n" +"- Rating when changing stage: an email will be sent when a task is pulled to another stage.\n" +"- Periodic rating: an email will be sent periodically.\n" +"\n" +"Don't forget to set up the email templates on the stages for which you want to get customer feedback." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__hr_presence_state +msgid "Hr Presence State" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__id +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__id +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__id +msgid "ID" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_parent_thread_id +msgid "" +"ID of the parent record holding the alias (example: project holding the task" +" creation alias)" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__external_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_binding__external_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__external_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__external_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__external_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__external_id +msgid "ID on Jira" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__barcode +msgid "ID used for employee identification." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__im_status +msgid "IM Status" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_exception_icon +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_exception_icon +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_exception_icon +msgid "Icon" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__activity_exception_icon +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__activity_exception_icon +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__activity_exception_icon +msgid "Icon to indicate an exception activity." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__identification_id +msgid "Identification No" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_needaction +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_unread +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_needaction +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_unread +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_needaction +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_unread +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_has_error +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_has_sms_error +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_has_error +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_has_sms_error +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_has_error +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_has_sms_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_bounced_content +msgid "" +"If set, this content will automatically be sent out to unauthorized users " +"instead of the default message." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__action_id +msgid "" +"If specified, this action will be opened at log on for this user, in " +"addition to the standard menu." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__active +msgid "" +"If the active field is set to False, it will allow you to hide the project " +"without removing it." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__is_blacklisted +msgid "" +"If the email address is on the blacklist, the contact won't receive mass " +"mailing anymore, from any list" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__phone_sanitized_blacklisted +msgid "" +"If the sanitized phone number is on the blacklist, the contact won't receive" +" mass mailing sms anymore, from any list" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "" +"If you change the base URL, you must delete and create the Webhooks again." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__image_1920 +msgid "Image" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__image_1024 +msgid "Image 1024" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__image_128 +msgid "Image 128" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__image_256 +msgid "Image 256" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__image_512 +msgid "Image 512" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__import_analytic_line_force +msgid "Import Analytic Line Force" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Import Issue Types" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__import_project_task_force +msgid "Import Project Task Force" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__import_project_task_from_date +msgid "Import Project Tasks from date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__import_analytic_line_from_date +msgid "Import Worklogs from date" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/controllers/main.py:0 +#, python-format +msgid "Import a worklog from JIRA" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Import deleted worklogs since" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Import project tasks since" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Import worklogs since" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Imports" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__mobile_blacklisted +msgid "" +"Indicates if a blacklisted sanitized phone number is a mobile number. Helps " +"distinguish which number is blacklisted when there is both a " +"mobile and phone field in a model." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__phone_blacklisted +msgid "" +"Indicates if a blacklisted sanitized phone number is a phone number. Helps " +"distinguish which number is blacklisted when there is both a " +"mobile and phone field in a model." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__industry_id +msgid "Industry" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__planned_hours +msgid "Initially Planned Hours" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Install Webhooks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_id +msgid "" +"Internal email associated with this project. Incoming emails are " +"automatically synchronized with Tasks (or optionally Issues if the Issue " +"Tracker module is installed)." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__type +msgid "" +"Invoice & Delivery addresses are used in sales orders. Private addresses are" +" only visible by authorized users." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_is_follower +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_is_follower +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__is_internal_project +msgid "Is Internal Project" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__is_private +msgid "Is Private" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__is_system +msgid "Is System" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__partner_is_company +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__is_company +msgid "Is a Company" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_base_mixin__sync_issue_type_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__sync_issue_type_ids +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__sync_issue_type_ids +msgid "Issue Levels to Synchronize" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_issue_type_id +msgid "Issue Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__issue_type_ids +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Issue Types" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.server,name:connector_jira.ir_cron_jira_delete_analytic_line_ir_actions_server +#: model:ir.cron,cron_name:connector_jira.ir_cron_jira_delete_analytic_line +#: model:ir.cron,name:connector_jira.ir_cron_jira_delete_analytic_line +msgid "JIRA - Import Deleted Worklogs" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.server,name:connector_jira.ir_cron_jira_import_project_task_ir_actions_server +#: model:ir.cron,cron_name:connector_jira.ir_cron_jira_import_project_task +#: model:ir.cron,name:connector_jira.ir_cron_jira_import_project_task +msgid "JIRA - Import Project Tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.server,name:connector_jira.ir_cron_jira_import_res_users_ir_actions_server +#: model:ir.cron,cron_name:connector_jira.ir_cron_jira_import_res_users +#: model:ir.cron,name:connector_jira.ir_cron_jira_import_res_users +msgid "JIRA - Import Users" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.server,name:connector_jira.ir_cron_jira_import_analytic_line_ir_actions_server +#: model:ir.cron,cron_name:connector_jira.ir_cron_jira_import_analytic_line +#: model:ir.cron,name:connector_jira.ir_cron_jira_import_analytic_line +msgid "JIRA - Import Worklogs" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_epic_link_task_id +#: model:ir.model.fields,field_description:connector_jira.field_project_task__jira_epic_link_task_id +#: model_terms:ir.ui.view,arch_db:connector_jira.hr_timesheet_line_search +#: model_terms:ir.ui.view,arch_db:connector_jira.view_task_search_form +msgid "JIRA Epic" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_issue_type +#: model:ir.model.fields,field_description:connector_jira.field_project_task__jira_issue_type +#: model_terms:ir.ui.view,arch_db:connector_jira.view_task_search_form +msgid "JIRA Issue Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_base_mixin__jira_key +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__jira_key +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_compound_key +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__jira_key +#: model:ir.model.fields,field_description:connector_jira.field_project_project__jira_key +#: model:ir.model.fields,field_description:connector_jira.field_project_task__jira_compound_key +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__jira_key +#: model_terms:ir.ui.view,arch_db:connector_jira.project_link_jira_form +#: model_terms:ir.ui.view,arch_db:connector_jira.task_link_jira_form +msgid "JIRA Key" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.hr_timesheet_line_search +msgid "JIRA Original Epic" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.hr_timesheet_line_search +msgid "JIRA Original Issue" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.hr_timesheet_line_search +msgid "JIRA Original Issue Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_parent_task_id +#: model:ir.model.fields,field_description:connector_jira.field_project_task__jira_parent_task_id +msgid "JIRA Parent" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_project_base_mixin +msgid "JIRA Project Base Mixin" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_issue_url +#: model:ir.model.fields,field_description:connector_jira.field_project_task__jira_issue_url +#: model_terms:ir.ui.view,arch_db:connector_jira.hr_timesheet_line_search +msgid "JIRA issue" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_task_kanban +msgid "JIRA:" +msgstr "" + +#. module: connector_jira +#: model:ir.ui.menu,name:connector_jira.menu_jira_root +#: model_terms:ir.ui.view,arch_db:connector_jira.edit_project +#: model_terms:ir.ui.view,arch_db:connector_jira.view_task_form2 +#: model_terms:ir.ui.view,arch_db:connector_jira.view_users_form +msgid "Jira" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.act_window,name:connector_jira.action_jira_backend_auth +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Jira Auth" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Jira Authentication" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_backend +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_binding__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__backend_id +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__backend_id +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Jira Backend" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_backend_auth +msgid "Jira Backend Auth" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_backend_timestamp +msgid "Jira Backend Import Timestamps" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.act_window,name:connector_jira.action_jira_backend +msgid "Jira Backends" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_binding +msgid "Jira Binding (abstract)" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/backend_adapter.py:0 +#, python-format +msgid "Jira Error: %s" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_issue_id +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_project_task_form +msgid "Jira Issue" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_issue_type +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_issue_type_form +msgid "Jira Issue Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__jira_project_id +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_project_project_form +msgid "Jira Project" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_project_bind_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_project_bind_id +msgid "Jira Project Bind" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_project_project +msgid "Jira Projects" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__jira_task_id +msgid "Jira Task" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_project_task +msgid "Jira Tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__uri +msgid "Jira URI" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_updated_at +#: model:ir.model.fields,field_description:connector_jira.field_jira_binding__jira_updated_at +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__jira_updated_at +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__jira_updated_at +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_updated_at +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__jira_updated_at +msgid "Jira Updated At" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_res_users +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend__worklog_date_timezone_mode__user +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_res_users_form +msgid "Jira User" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_account_analytic_line +msgid "Jira Worklog" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__function +msgid "Job Position" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__job_title +msgid "Job Title" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__legend_blocked +msgid "Kanban Blocked Explanation" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__legend_normal +msgid "Kanban Ongoing Explanation" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__kanban_state_label +msgid "Kanban State Label" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__legend_done +msgid "Kanban Valid Explanation" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__password +msgid "" +"Keep empty if you don't want the user to be able to connect on the system." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_key +msgid "Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__label_tasks +msgid "Label used for the tasks of the project." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__lang +msgid "Language" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__last_activity +msgid "Last Activity" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__last_activity_time +msgid "Last Activity Time" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task____last_update +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users____last_update +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira____last_update +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira____last_update +msgid "Last Modified on" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__date_last_stage_update +msgid "Last Stage Update" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__last_timestamp +msgid "Last Timestamp" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__last_update_id +msgid "Last Update" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__last_update_color +msgid "Last Update Color" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__last_update_status +msgid "Last Update Status" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__write_uid +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line_import__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_timestamp__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__write_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__write_date +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__write_date +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__write_date +msgid "Last Updated on" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__sync_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_binding__sync_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__sync_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__sync_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__sync_date +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__login_date +msgid "Latest authentication" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_project_link_jira +msgid "Link Project with JIRA" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_task_link_jira +msgid "Link Task with JIRA" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Link users" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.act_window,name:connector_jira.open_project_link_jira +#: model:ir.actions.act_window,name:connector_jira.open_task_link_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_project_base_mixin__sync_action__link +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_project_project__sync_action__link +#: model:ir.model.fields.selection,name:connector_jira.selection__project_link_jira__sync_action__link +#: model_terms:ir.ui.view,arch_db:connector_jira.view_project_kanban_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_task_kanban +msgid "Link with JIRA" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_users_form +msgid "Link with Jira" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__linked_backend_ids +msgid "Linked Backend" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__email_cc +msgid "List of cc from incoming emails." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__login +msgid "Login" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_main_attachment_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_main_attachment_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_main_attachment_id +msgid "Main Attachment" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__attachment_ids +msgid "Main Attachments" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Main Configuration" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_parent_id +msgid "Manager" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__marital +msgid "Marital Status" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__favorite_user_ids +msgid "Members" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_has_error +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_has_error +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_ids +msgid "Messages" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__milestone_ids +msgid "Milestone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__milestone_count +msgid "Milestone Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__mobile +msgid "Mobile" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__mon +msgid "Mon" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__my_activity_date_deadline +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__my_activity_date_deadline +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__my_activity_date_deadline +msgid "My Activity Deadline" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__name +#: model:ir.model.fields,field_description:connector_jira.field_jira_issue_type__name +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__name +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__name +msgid "Name" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_date_deadline +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_date_deadline +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_summary +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_summary +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_summary +msgid "Next Activity Summary" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_type_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_type_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_type_id +msgid "Next Activity Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__recurrence_message +msgid "Next Recurrencies" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/res_users/common.py:0 +#, python-format +msgid "No JIRA user could be found" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/res_users/importer.py:0 +#, python-format +msgid "" +"No user found for jira account %(jira_key)s (%(email)s). Please link it " +"manually from the Odoo user's form." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/account_analytic_line/importer.py:0 +#, python-format +msgid "" +"No user found with login \"%(jira_author_key)s\" or email \"%(email)s\".You " +"must create a user or link it manually if the login/email differs." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_task/importer.py:0 +#, python-format +msgid "" +"No user found with login \"%(jira_key)s\" or email \"%(email)s\".You must " +"create a user or link it manually if the login/email differs." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__email_normalized +msgid "Normalized Email" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__comment +msgid "Notes" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/exporter.py:0 +#: code:addons/connector_jira/components/exporter.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__notification_type +msgid "Notification" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_needaction_counter +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_needaction_counter +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__children +msgid "Number of Children" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__companies_count +msgid "Number of Companies" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__accesses_count +msgid "Number of access rights that apply to the current user" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__doc_count +msgid "Number of documents attached" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_has_error_counter +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_has_error_counter +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_has_error_counter +msgid "Number of errors" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__groups_count +msgid "Number of groups that apply to the current user" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_needaction_counter +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_needaction_counter +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_has_error_counter +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_has_error_counter +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__rules_count +msgid "Number of record rules that apply to the current user" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__message_unread_counter +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__message_unread_counter +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__message_unread_counter +msgid "Number of unread messages" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend_auth__state__leg_2 +msgid "OAuth Remote Auth" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend_auth__state__leg_1 +msgid "OAuth Remote Config" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "OAuth configuration complete" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__odoobot_state +msgid "OdooBot Status" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__odoobot_failed +msgid "Odoobot Failed" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "" +"Once imported,\n" +" some types of records,\n" +" like the products or categories,\n" +" need a manual review.\n" +" You will find the list\n" +" of the new records to review\n" +" in the menu 'Connectors > Checkpoint'." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "" +"Once you have checked the configuration and\n" +" activated the webhooks and the Epic Link (if\n" +" wanted), click on the \"Configuration Done\"\n" +" button." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_base_mixin__sync_issue_type_ids +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__sync_issue_type_ids +#: model:ir.model.fields,help:connector_jira.field_project_link_jira__sync_issue_type_ids +msgid "" +"Only issues of these levels are imported. When a worklog is imported no a " +"level which is not sync'ed, it is attached to the nearest sync'ed parent " +"level. If no parent can be found, it is attached to a special 'Unassigned' " +"task." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "" +"Only one JIRA backend can use the webhook at a time. You must disable them " +"on the backend \"%s\" before activating them here." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_project/common.py:0 +#, python-format +msgid "" +"Only one Jira binding can be configured with the Sync. Action \"Export\" for" +" a project. \"%s\" already has one." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "Only one backend can listen to webhooks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_force_thread_id +msgid "" +"Optional ID of a thread (record) to which all incoming messages will be " +"attached, even if they did not reply to it. If set, this will disable the " +"creation of new records completely." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_epic_issue_key +msgid "Original Epic Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_issue_type_id +msgid "Original Issue Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_account_analytic_line__jira_epic_issue_key +msgid "Original JIRA Epic Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_account_analytic_line__jira_epic_issue_url +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_epic_issue_url +msgid "Original JIRA Epic Link" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_account_analytic_line__jira_issue_key +msgid "Original JIRA Issue Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_account_analytic_line__jira_issue_type_id +msgid "Original JIRA Issue Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_account_analytic_line__jira_issue_url +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_issue_url +msgid "Original JIRA issue Link" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_issue_key +msgid "Original Task Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__legend_blocked +msgid "" +"Override the default value displayed for the blocked state for kanban " +"selection when the task or issue is in that stage." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__legend_done +msgid "" +"Override the default value displayed for the done state for kanban selection" +" when the task or issue is in that stage." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__legend_normal +msgid "" +"Override the default value displayed for the normal state for kanban " +"selection when the task or issue is in that stage." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__overtime +msgid "Overtime" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_user_id +msgid "Owner" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__pin +msgid "PIN" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__pin +msgid "" +"PIN used to Check In/Out in the Kiosk Mode of the Attendance application (if" +" enabled in Configuration) and to change the cashier in the Point of Sale " +"application." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_parent_id +msgid "Parent Issue" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_parent_model_id +msgid "Parent Model" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_parent_thread_id +msgid "Parent Record Thread ID" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__parent_id +msgid "Parent Task" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__jira_parent_id +msgid "" +"Parent issue when the issue is a subtask. Empty if the type of parent is " +"filtered out of the synchronizations." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_parent_model_id +msgid "" +"Parent model holding the alias. The model holding the alias reference is not" +" necessarily the model given by alias_model_id (example: project " +"(parent_model) and task (model))" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__parent_name +msgid "Parent name" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__partner_id +msgid "Partner" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__active_partner +msgid "Partner is Active" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__same_vat_partner_id +msgid "Partner with same Tax ID" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__partner_id +msgid "Partner-related data of the user" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__passport_id +msgid "Passport No" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__password +msgid "Password" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__privacy_visibility +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__project_privacy_visibility +msgid "" +"People to whom this project and its tasks will be visible.\n" +"\n" +"- Invited internal users: when following a project, internal users will get access to all of its tasks without distinction. Otherwise, they will only get access to the specific tasks they are following.\n" +" A user with the project > administrator access right level can still access this project and its tasks, even if they are not explicitly part of the followers.\n" +"\n" +"- All internal users: all internal users can access the project and all of its tasks without distinction.\n" +"\n" +"- Invited portal users and all internal users: all internal users can access the project and all of its tasks without distinction.\n" +"When following a project, portal users will get access to all of its tasks without distinction. Otherwise, they will only get access to the specific tasks they are following.\n" +"\n" +"When a project is shared in read-only, the portal user is redirected to their portal. They can view the tasks, but not edit them.\n" +"When a project is shared in edit, the portal user is redirected to the kanban and list views of the tasks. They can modify a selected number of fields on the tasks.\n" +"\n" +"In any case, an internal user with no project access rights can still access a task, provided that they are given the corresponding URL (and that they are part of the followers if the project is private)." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__rating_percentage_satisfaction +msgid "Percentage of happy ratings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__personal_stage_type_ids +msgid "Personal Stage" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__personal_stage_id +msgid "Personal Stage State" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__personal_stage_type_id +msgid "Personal User Stage" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__partner_phone +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__partner_phone +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__phone +msgid "Phone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__phone_sanitized_blacklisted +msgid "Phone Blacklisted" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__phone_mobile_search +msgid "Phone/Mobile" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__place_of_birth +msgid "Place of Birth" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__notification_type +msgid "" +"Policy on how to handle Chatter notifications:\n" +"- Handle by Emails: notifications are sent to your email address\n" +"- Handle in Odoo: notifications appear in your Odoo Inbox" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_contact +msgid "" +"Policy to post a message on the document using the mailgateway.\n" +"- everyone: everyone can post\n" +"- partners: only authenticated partners\n" +"- followers: only followers of the related document or members of following channels\n" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__access_url +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__access_url +msgid "Portal Access URL" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__portal_user_names +msgid "Portal User Names" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_city +msgid "Private City" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_country_id +msgid "Private Country" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_email +msgid "Private Email" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__private_key +msgid "Private Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_phone +msgid "Private Phone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_state_id +msgid "Private State" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_street +msgid "Private Street" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_street2 +msgid "Private Street2" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__private_zip +msgid "Private Zip" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__progress +msgid "Progress" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_project_project +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__project_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__odoo_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__project_id +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__project_id +msgid "Project" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__project_analytic_account_id +msgid "Project Analytic Account" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__jira_bind_ids +#: model:ir.model.fields,field_description:connector_jira.field_project_project__jira_bind_ids +msgid "Project Bindings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__user_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__manager_id +msgid "Project Manager" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__project_type +msgid "Project Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__project_privacy_visibility +msgid "Project Visibility" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_task/importer.py:0 +#, python-format +msgid "Project or issue type is not synchronized." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_project/common.py:0 +#, python-format +msgid "Project template with key \"%s\" not found." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__public_key +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__public_key +msgid "Public Key" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__unit_amount +msgid "Quantity" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__rating_ids +msgid "Rating" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__rating_avg +msgid "Rating Average" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_status_period +msgid "Rating Frequency" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__rating_last_feedback +msgid "Rating Last Feedback" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__rating_last_image +msgid "Rating Last Image" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__rating_last_value +msgid "Rating Last Value" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_request_deadline +msgid "Rating Request Deadline" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_percentage_satisfaction +msgid "Rating Satisfaction" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__rating_count +msgid "Rating count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__rating_ids +msgid "Ratings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__rating_last_feedback +msgid "Reason of the rating" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_force_thread_id +msgid "Record Thread ID" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/importer.py:0 +#, python-format +msgid "Record deleted" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/importer.py:0 +#: code:addons/connector_jira/models/account_analytic_line/importer.py:0 +#, python-format +msgid "Record does no longer exist in Jira" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/backend_adapter.py:0 +#, python-format +msgid "Record does not exist in Jira: %s" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/exporter.py:0 +#, python-format +msgid "Record exported with ID %s on Jira." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/components/exporter.py:0 +#, python-format +msgid "Record to export does no longer exist." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__recurrence_id +msgid "Recurrence" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__recurrence_update +msgid "Recurrence Update" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__recurring_task +msgid "Recurrent" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__allow_recurring_tasks +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__allow_recurring_tasks +msgid "Recurring Tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__ref +msgid "Reference" +msgstr "" + +#. module: connector_jira +#: model:ir.actions.act_window,name:connector_jira.action_jira_aa_line_import +msgid "Refresh Worklogs from Jira" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_jira_account_analytic_line_import +msgid "Reimport Jira Worklogs" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_aa_line_import +msgid "Reimport lines" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__parent_id +msgid "Related Company" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__partner_id +msgid "Related Partner" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__employee_ids +msgid "Related employee" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__remaining_hours +msgid "Remaining Hours" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__remaining_hours +msgid "Remaining Invoiced Time" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Remove Webhooks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_day +msgid "Repeat Day" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_interval +msgid "Repeat Every" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_month +msgid "Repeat Month" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_on_month +msgid "Repeat On Month" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_on_year +msgid "Repeat On Year" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_show_day +msgid "Repeat Show Day" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_show_dow +msgid "Repeat Show Dow" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_show_month +msgid "Repeat Show Month" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_show_week +msgid "Repeat Show Week" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_unit +msgid "Repeat Unit" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_week +msgid "Repeat Week" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_number +msgid "Repetitions" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__report_user_sync +msgid "Report User Sync" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__request_secret +msgid "Request Secret" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__request_token +msgid "Request Token" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__res_users_settings_ids +msgid "Res Users Settings" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Reset Authentication" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__resource_ids +msgid "Resources" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__activity_user_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__activity_user_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__activity_user_id +msgid "Responsible User" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Run" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Run in background" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend__state__running +msgid "Running" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_has_sms_error +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_has_sms_error +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_has_sms_error +msgid "SMS Delivery error" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/wizards/jira_backend_auth.py:0 +#: code:addons/connector_jira/wizards/jira_backend_auth.py:0 +#, python-format +msgid "SSL error during negociation: %s" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__user_id +msgid "Salesperson" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__phone_sanitized +msgid "Sanitized Number" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__sat +msgid "Sat" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__study_school +msgid "School" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__access_token +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__access_token +msgid "Security Token" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__coach_id +msgid "" +"Select the \"Employee\" who is the coach of this employee.\n" +"The \"Coach\" has no specific rights or responsibilities by default." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__self +msgid "Self" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__sequence +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__sequence +msgid "Sequence" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__new_password +msgid "Set Password" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend__state__setup +msgid "Setup" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/res_users/importer.py:0 +#, python-format +msgid "" +"Several users found (%(login)s) for jira account%(jira_key)s (%(email)s). " +"Please link it manually from the Odoo user's form." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/res_users/common.py:0 +#, python-format +msgid "" +"Several users found with \"%(resolve_by_key)s\"set to " +"\"%(resolve_by_value)s\". Set it manually." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__partner_share +msgid "Share Partner" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__share +msgid "Share User" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__is_favorite +msgid "Show Project on Dashboard" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__signup_expiration +msgid "Signup Expiration" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__signup_token +msgid "Signup Token" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__signup_type +msgid "Signup Token Type" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__signup_valid +msgid "Signup Token is Valid" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__signup_url +msgid "Signup URL" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields.selection,name:connector_jira.selection__jira_backend__worklog_date_timezone_mode__specific +msgid "Specific" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__new_password +msgid "" +"Specify a value only when creating a user or if you're changing the user's " +"password, otherwise leave empty. After a change of password, the user has to" +" login again." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__spouse_birthdate +msgid "Spouse Birthdate" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__spouse_complete_name +msgid "Spouse Complete Name" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__stage_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__stage_id +msgid "Stage" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__priority +msgid "Starred" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__date_start +msgid "Start Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__state +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend_auth__state +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__state_id +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__state +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__state +msgid "State" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__kanban_state +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__state +msgid "Status" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__activity_state +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__activity_state +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__activity_state +msgid "" +"Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__street +msgid "Street" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__street2 +msgid "Street2" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__subtask_count +msgid "Sub-task Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__allow_subtasks +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__child_ids +msgid "Sub-tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__subtask_effective_hours +msgid "Sub-tasks Hours Spent" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__subtask_planned_hours +msgid "Sub-tasks Planned Hours" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__subtask_planned_hours +msgid "" +"Sum of the time planned of all the sub-tasks linked to this task. Usually " +"less than or equal to the initially planned time of this task." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__sun +msgid "Sun" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_base_mixin__sync_action +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__sync_action +#: model:ir.model.fields,field_description:connector_jira.field_project_link_jira__sync_action +msgid "Sync Action" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__tag_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__tag_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__tag_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__category_id +msgid "Tags" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_project_task +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__task_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__odoo_id +#: model:ir.model.fields,field_description:connector_jira.field_task_link_jira__task_id +msgid "Task" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__tasks +msgid "Task Activities" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__jira_bind_ids +#: model:ir.model.fields,field_description:connector_jira.field_project_task__jira_bind_ids +msgid "Task Bindings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__task_count +msgid "Task Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__task_count_with_subtasks +msgid "Task Count With Subtasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__allow_task_dependencies +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__allow_task_dependencies +msgid "Task Dependencies" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_task/common.py:0 +#, python-format +msgid "Task can not be created in project linked to JIRA!" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_task/common.py:0 +#, python-format +msgid "Task linked to JIRA Issue can not be deleted!" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_task/common.py:0 +#, python-format +msgid "Task linked to JIRA Issue can not be modified!" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__task_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__task_ids +msgid "Tasks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__type_ids +msgid "Tasks Stages" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__recurring_count +msgid "Tasks in Recurrence" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__is_closed +msgid "Tasks in this stage are considered as closed." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__vat +msgid "Tax ID" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend__epic_link_field_name +msgid "" +"The 'Epic Link' field on JIRA is a custom field. The name of the field is " +"something like 'customfield_10002'. " +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend__epic_name_field_name +msgid "" +"The 'Epic Name' field on JIRA is a custom field. The name of the field is " +"something like 'customfield_10003'. " +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__country_code +msgid "" +"The ISO country code in two chars. \n" +"You can use this field for quick search." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_project/common.py:0 +#, python-format +msgid "The JIRA Key is mandatory in order to link a project" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "The Odoo Webhook base URL must be set." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__vat +msgid "" +"The Tax Identification Number. Complete it if the contact is subjected to " +"government taxes. Used in some legal statements." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.project_link_jira_form +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_project_project_form +msgid "" +"The checkboxes define which types of JIRA issues will be\n" +" imported\n" +" into Odoo. For instance, if you check 'Story', only issues of type\n" +" Story will be imported. Several choices possible." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__personal_stage_id +msgid "The current user's personal stage." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__personal_stage_type_id +msgid "The current user's personal task stage." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__company_id +msgid "The default company for this user." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__is_address_home_a_company +msgid "The employee address has a company linked" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__employee_type +msgid "" +"The employee type. Although the primary purpose may seem to categorize " +"employees, this field has also an impact in the Contract History. Only " +"Employee type is supposed to be under contract and will have a Contract " +"History." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__user_id +msgid "The internal user in charge of this contact." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_model_id +msgid "" +"The model (Odoo Document Kind) to which this alias corresponds. Any incoming" +" email that does not reply to an existing record will cause the creation of " +"a new record of this model (e.g. a Project Task)" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_name +msgid "" +"The name of the email alias, e.g. 'jobs' if you want to catch emails for " +"" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__alias_user_id +msgid "" +"The owner of records created upon receiving emails on this alias. If this " +"field is not set the system will attempt to find the right owner based on " +"the sender (From) address, or will use the Administrator account if no " +"system user is found for that address." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_project/common.py:0 +#, python-format +msgid "The project %s is already linked with the same JIRA project." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.project_link_jira_form +msgid "The project is now linked with JIRA." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/project_project/common.py:0 +#, python-format +msgid "The project template cannot be modified." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.project_link_jira_form +msgid "The project will be created on JIRA in background." +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "" +"The synchronization timestamp is currently locked, probably due to an " +"ongoing synchronization." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.task_link_jira_form +msgid "The task is now linked with JIRA." +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.project_link_jira_form +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_project_project_form +msgid "" +"There is a direct implication on the Worklogs.\n" +" When a worklog is done on a JIRA Sub-Task and this type is not\n" +" sync'ed, the worklog will be attached to the parent Task of the\n" +" Sub-Task. If the Task is not sync'ed, it will be attached to the\n" +" Epic. Finally, if there is no Epic, the worklog will not be\n" +" attached to any task." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__email_from +msgid "These people will receive email." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__email_normalized +msgid "" +"This field is used to search on email address as the primary email field can" +" contain more than strictly an email address." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__timesheet_encode_uom_id +msgid "" +"This will set the unit of measure used to encode timesheet. This will simply provide tools\n" +" and widgets to help the encoding. All reporting will still be expressed in hours (default value)." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__thu +msgid "Thu" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__planned_hours +msgid "Time planned to achieve this task (including its sub-tasks)." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__subtask_effective_hours +msgid "Time spent on the sub-tasks (and their own sub-tasks) of this task." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__effective_hours +msgid "Time spent on this task, excluding its sub-tasks." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__total_hours_spent +msgid "Time spent on this task, including its sub-tasks." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__timesheet_count +msgid "Timesheet Count" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__timesheet_encode_uom_id +msgid "Timesheet Encoding Unit" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__odoo_id +msgid "Timesheet Line" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/account_analytic_line/common.py:0 +#, python-format +msgid "Timesheet can not be created in project linked to JIRA!" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/account_analytic_line/common.py:0 +#, python-format +msgid "Timesheet linked to JIRA Worklog can not be deleted!" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/account_analytic_line/common.py:0 +#, python-format +msgid "Timesheet linked to JIRA Worklog can not be modified!" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__allow_timesheets +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__timesheet_ids +msgid "Timesheets" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__allow_timesheets +msgid "Timesheets can be logged on this task." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__tz +msgid "Timezone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__tz_offset +msgid "Timezone offset" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__name +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__title +msgid "Title" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__total_hours_spent +msgid "Total Hours" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__total_timesheet_time +msgid "Total Timesheet Time" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__total_timesheet_time +msgid "" +"Total number of time (in the proper UoM) recorded in the project, rounded to" +" the unit." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__remaining_hours +msgid "" +"Total remaining time, can be re-estimated periodically by the assignee of " +"the task." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__totp_secret +msgid "Totp Secret" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__has_planned_hours_tasks +msgid "True if any of the project's task has a set planned hours" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__totp_trusted_device_ids +msgid "Trusted Devices" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__tue +msgid "Tue" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__totp_enabled +msgid "Two-factor authentication" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__activity_exception_decoration +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__activity_exception_decoration +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__activity_exception_decoration +msgid "Type of the exception activity on record." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__product_uom_id +msgid "Unit of Measure" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_unread +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_unread +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_unread +msgid "Unread Messages" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__message_unread_counter +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__message_unread_counter +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__message_unread_counter +msgid "Unread Messages Counter" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__repeat_type +msgid "Until" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__product_uom_category_id +msgid "UoM Category" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__update_ids +msgid "Update" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__alias_enabled +msgid "Use Email Alias" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__label_tasks +msgid "Use Tasks as" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__use_webhooks +msgid "Use Webhooks" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend_timestamp__component_usage +msgid "" +"Used by the connector to find which component execute the batch import " +"(technical)." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__login +msgid "Used to log into the system" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__user_id +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__odoo_id +msgid "User" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__jira_bind_ids +#: model:ir.model.fields,field_description:connector_jira.field_res_users__jira_bind_ids +msgid "User Bindings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__log_ids +msgid "User log entries" +msgstr "" + +#. module: connector_jira +#: model:ir.model,name:connector_jira.model_res_users +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__user_ids +msgid "Users" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__verify_ssl +msgid "Verify SSL?" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__visa_expire +msgid "Visa Expire Date" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__visa_no +msgid "Visa No" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__privacy_visibility +msgid "Visibility" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_auth_form +msgid "Visit this URL, authorize and continue" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/jira_backend/common.py:0 +#, python-format +msgid "Warning" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__webhook_issue_jira_id +msgid "Webhook Issue Jira" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__webhook_worklog_jira_id +msgid "Webhook Worklog Jira" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "" +"Webhooks can be created only on one instance of\n" +" JIRA.\n" +" When webhooks are activated, each\n" +" modification of tasks and worklogs are\n" +" directly transmitted to Odoo." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend__use_webhooks +msgid "" +"Webhooks need to be configured on the Jira instance. When activated, " +"synchronization from Jira is blazing fast. It can be activated only on one " +"Jira backend at a time. " +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__website +msgid "Website Link" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__website_message_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__website_message_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__website_message_ids +#: model:ir.model.fields,help:connector_jira.field_jira_project_task__website_message_ids +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__website_message_ids +msgid "Website communication history" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__wed +msgid "Wed" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_res_users__tz +msgid "" +"When printing documents and exporting/importing data, time values are computed according to this timezone.\n" +"If the timezone is not set, UTC (Coordinated Universal Time) is used.\n" +"Anywhere else, time values are computed according to the time offset of your web client." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_project_project__is_favorite +msgid "Whether this project should be displayed on your dashboard." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__address_id +msgid "Work Address" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__work_email +msgid "Work Email" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__work_location_id +msgid "Work Location" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__mobile_phone +msgid "Work Mobile" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__permit_no +msgid "Work Permit No" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__work_phone +msgid "Work Phone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__working_days_open +msgid "Working Days to Assign" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__working_days_close +msgid "Working Days to Close" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__working_hours_open +msgid "Working Hours to Assign" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_task__working_hours_close +msgid "Working Hours to Close" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_project_project__resource_calendar_id +msgid "Working Time" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_account_analytic_line__jira_bind_ids +#: model:ir.model.fields,field_description:connector_jira.field_jira_account_analytic_line__jira_bind_ids +msgid "Worklog Bindings" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__worklog_date_timezone +msgid "Worklog Date Timezone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_backend__worklog_date_timezone_mode +msgid "Worklog Date Timezone Mode" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "Worklog date timezone" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend__worklog_date_timezone_mode +msgid "" +"Worklog/Timesheet date timezone modes:\n" +" - As-is (naive): ignore timezone information\n" +" - Jira User: use author's timezone\n" +" - Specific: use pre-configured timezone\n" +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,help:connector_jira.field_jira_backend__worklog_fallback_project_id +msgid "" +"Worklogs which could not be linked to any project will be created in this " +"project. Worklogs landing in the fallback project can be reassigned to the " +"correct project by: 1. linking the expected project with the Jira one, 2. " +"using 'Refresh Worklogs from Jira' on the timesheet lines." +msgstr "" + +#. module: connector_jira +#: model:ir.model.fields,field_description:connector_jira.field_jira_res_users__zip +msgid "Zip" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "e.g. https://example.com/jira" +msgstr "" + +#. module: connector_jira +#: model_terms:ir.ui.view,arch_db:connector_jira.view_jira_backend_form +msgid "forced" +msgstr "" + +#. module: connector_jira +#: code:addons/connector_jira/models/account_analytic_line/importer.py:0 +#, python-format +msgid "missing description" +msgstr "" diff --git a/connector_jira/models/__init__.py b/connector_jira/models/__init__.py new file mode 100644 index 000000000..e4401c464 --- /dev/null +++ b/connector_jira/models/__init__.py @@ -0,0 +1,12 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import jira_binding # must be before the others + +from . import account_analytic_line +from . import jira_backend +from . import jira_issue_type +from . import project_project +from . import project_task +from . import res_users +from . import queue_job +from . import timesheets_analysis_report diff --git a/connector_jira/models/account_analytic_line/__init__.py b/connector_jira/models/account_analytic_line/__init__.py new file mode 100644 index 000000000..fd0b0ed43 --- /dev/null +++ b/connector_jira/models/account_analytic_line/__init__.py @@ -0,0 +1,5 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common +from . import deleter +from . import importer diff --git a/connector_jira/models/account_analytic_line/common.py b/connector_jira/models/account_analytic_line/common.py new file mode 100644 index 000000000..b9819c5a8 --- /dev/null +++ b/connector_jira/models/account_analytic_line/common.py @@ -0,0 +1,322 @@ +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import json +from collections import namedtuple + +from odoo import _, api, exceptions, fields, models + +from odoo.addons.component.core import Component + +UpdatedWorklog = namedtuple( + "UpdatedWorklog", + "worklog_id updated", + # id as integer, timestamp +) + +UpdatedWorklogSince = namedtuple( + "UpdatedWorklogSince", + "since until updated_worklogs", + # timestamp, timestamp, [UpdatedWorklog] +) + + +DeletedWorklogSince = namedtuple( + "DeletedWorklogSince", + "since until deleted_worklog_ids", + # timestamp, timestamp, [ids as integer] +) + + +class JiraAccountAnalyticLine(models.Model): + _name = "jira.account.analytic.line" + _inherit = "jira.binding" + _inherits = {"account.analytic.line": "odoo_id"} + _description = "Jira Worklog" + + odoo_id = fields.Many2one( + comodel_name="account.analytic.line", + string="Timesheet Line", + required=True, + index=True, + ondelete="restrict", + ) + # The REST API needs issue id + worklog id, so we keep it along + # in case we'll need it for an eventual export + jira_issue_id = fields.Char() + + # As we can have more than one jira binding on a project.project, we store + # to which one a task binding is related. + jira_project_bind_id = fields.Many2one( + comodel_name="jira.project.project", + ondelete="restrict", + ) + + # we have to store these fields on the analytic line because + # they may be different than the ones on their odoo task: + # for instance, we do not import "Tasks" but we import "Epics", + # the analytic line for a "Task" will be linked to an "Epic" on + # Odoo, but we still want to know the original task here + jira_issue_key = fields.Char( + string="Original Task Key", + readonly=True, + ) + jira_issue_type_id = fields.Many2one( + comodel_name="jira.issue.type", + string="Original Issue Type", + readonly=True, + ) + jira_issue_url = fields.Char( + string="Original JIRA issue Link", + compute="_compute_jira_issue_url", + ) + jira_epic_issue_key = fields.Char( + string="Original Epic Key", + readonly=True, + ) + jira_epic_issue_url = fields.Char( + string="Original JIRA Epic Link", + compute="_compute_jira_issue_url", + ) + + _sql_constraints = [ + ( + "jira_binding_backend_uniq", + "unique(backend_id, odoo_id)", + "A binding already exists for this line and this backend.", + ), + ] + + def _is_linked(self): + return self.mapped("jira_project_bind_id")._is_linked() + + @api.depends( + "backend_id", "backend_id.uri", "jira_issue_key", "jira_epic_issue_key" + ) + def _compute_jira_issue_url(self): + """Compute the external URL to JIRA.""" + for record in self: + record.jira_issue_url = self.backend_id.make_issue_url( + record.jira_issue_key + ) + record.jira_epic_issue_url = self.backend_id.make_issue_url( + record.jira_epic_issue_key + ) + + @api.model + def import_record(self, backend, issue_id, worklog_id, force=False): + """Import a worklog from JIRA""" + with backend.work_on(self._name) as work: + importer = work.component(usage="record.importer") + return importer.run(worklog_id, issue_id=issue_id, force=force) + + def force_reimport(self): + for binding in self.sudo().mapped("jira_bind_ids"): + binding.with_delay(priority=8).import_record( + binding.backend_id, + binding.jira_issue_id, + binding.external_id, + force=True, + ) + + +class AccountAnalyticLine(models.Model): + _inherit = "account.analytic.line" + + jira_bind_ids = fields.One2many( + comodel_name="jira.account.analytic.line", + inverse_name="odoo_id", + copy=False, + string="Worklog Bindings", + context={"active_test": False}, + ) + # fields needed to display JIRA issue link in views + jira_issue_key = fields.Char( + string="Original JIRA Issue Key", + compute="_compute_jira_references", + store=True, + ) + jira_issue_url = fields.Char( + string="Original JIRA issue Link", + compute="_compute_jira_references", + compute_sudo=True, + ) + jira_epic_issue_key = fields.Char( + compute="_compute_jira_references", + string="Original JIRA Epic Key", + store=True, + ) + jira_epic_issue_url = fields.Char( + string="Original JIRA Epic Link", + compute="_compute_jira_references", + compute_sudo=True, + ) + + jira_issue_type_id = fields.Many2one( + comodel_name="jira.issue.type", + string="Original JIRA Issue Type", + compute="_compute_jira_references", + store=True, + ) + + @api.depends( + "jira_bind_ids.jira_issue_key", + "jira_bind_ids.jira_issue_type_id", + "jira_bind_ids.jira_epic_issue_key", + ) + def _compute_jira_references(self): + """Compute the various references to JIRA. + + We assume that we have only one external record for a line + """ + for record in self: + if not record.jira_bind_ids: + record.jira_issue_url = False + record.jira_epic_issue_key = False + record.jira_epic_issue_url = False + continue + main_binding = record.jira_bind_ids[0] + record.jira_issue_key = main_binding.jira_issue_key + record.jira_issue_url = main_binding.jira_issue_url + record.jira_issue_type_id = main_binding.jira_issue_type_id + record.jira_epic_issue_key = main_binding.jira_epic_issue_key + record.jira_epic_issue_url = main_binding.jira_epic_issue_url + + @api.model + def _get_connector_jira_fields(self): + return [ + "jira_bind_ids", + "project_id", + "task_id", + "user_id", + "employee_id", + "name", + "date", + "unit_amount", + ] + + @api.model + def _connector_jira_create_validate(self, vals): + ProjectProject = self.env["project.project"] + project_id = vals.get("project_id") + if project_id: + project_id = ProjectProject.sudo().browse(project_id) + if ( + not self.env.context.get("connector_jira") + and project_id.mapped("jira_bind_ids")._is_linked() + ): + raise exceptions.UserError( + _("Timesheet can not be created in project linked to JIRA!") + ) + + def _connector_jira_write_validate(self, vals): + if ( + not self.env.context.get("connector_jira") + and self.mapped("jira_bind_ids")._is_linked() + ): + fields = list(vals.keys()) + new_values = self._convert_to_write( + vals, + ) + for old_values in self.read(fields, load="_classic_write"): + old_values = self._convert_to_write( + old_values, + ) + for field in self._get_connector_jira_fields(): + if field not in fields: + continue + if new_values[field] == old_values[field]: + continue + raise exceptions.UserError( + _("Timesheet linked to JIRA Worklog can not be modified!") + ) + + def _connector_jira_unlink_validate(self): + if ( + not self.env.context.get("connector_jira") + and self.mapped("jira_bind_ids")._is_linked() + ): + raise exceptions.UserError( + _("Timesheet linked to JIRA Worklog can not be deleted!") + ) + + @api.model + def create(self, vals): + self._connector_jira_create_validate(vals) + return super().create(vals) + + def write(self, vals): + self._connector_jira_write_validate(vals) + return super().write(vals) + + def unlink(self): + self._connector_jira_unlink_validate() + return super().unlink() + + +class WorklogAdapter(Component): + _name = "jira.worklog.adapter" + _inherit = "jira.webservice.adapter" + _apply_on = ["jira.account.analytic.line"] + + def read(self, issue_id, worklog_id): + # pylint: disable=W8106 + with self.handle_404(): + return self.client.worklog(issue_id, worklog_id).raw + + def search(self, issue_id): + """Search worklogs of an issue""" + worklogs = self.client.worklogs(issue_id) + return [worklog.id for worklog in worklogs] + + @staticmethod + def _chunks(whole, size): + """Yield successive n-sized chunks from l.""" + for i in range(0, len(whole), size): + yield whole[i : i + size] + + def yield_read(self, worklog_ids): + """Generator returning worklog ids data""" + path = "worklog/list" + + # the method returns max 1000 results + for chunk in self._chunks(worklog_ids, 1000): + payload = json.dumps({"ids": chunk}) + result = self._post_get_json(path, data=payload) + yield from result + + def updated_since(self, since=None): + path = "worklog/updated" + + start_since = since + updated_worklogs = [] + + while True: + result = self.client._get_json(path, params={"since": since}) + updated_worklogs += [ + UpdatedWorklog(worklog_id=row["worklogId"], updated=row["updatedTime"]) + for row in result["values"] + ] + until = since = result["until"] + if result["lastPage"]: + break + return UpdatedWorklogSince( + since=start_since, until=until, updated_worklogs=updated_worklogs + ) + + def deleted_since(self, since=None): + path = "worklog/deleted" + + start_since = since + deleted_worklog_ids = [] + + while True: + result = self.client._get_json(path, params={"since": since}) + deleted_worklog_ids += [row["worklogId"] for row in result["values"]] + until = since = result["until"] + if result["lastPage"]: + break + return DeletedWorklogSince( + since=start_since, until=until, deleted_worklog_ids=deleted_worklog_ids + ) diff --git a/connector_jira/models/account_analytic_line/deleter.py b/connector_jira/models/account_analytic_line/deleter.py new file mode 100644 index 000000000..36f729040 --- /dev/null +++ b/connector_jira/models/account_analytic_line/deleter.py @@ -0,0 +1,82 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import _ + +from odoo.addons.component.core import Component +from odoo.addons.queue_job.exception import RetryableJobError + +from ...fields import MilliDatetime + +_logger = logging.getLogger(__name__) + + +class AnalyticLineBatchDeleter(Component): + """Batch Deleter working with a jira.backend.timestamp.record + + It locks the timestamp to ensure no other job is working on it, + and uses the latest timestamp value as reference for the search. + + The role of a BatchDeleter is to search for a list of + items to delete and schedule jobs for the deletions. + """ + + _name = "jira.analytic.line.timestamp.batch.deleter" + _inherit = ["base.synchronizer", "jira.base"] + _usage = "timestamp.batch.deleter" + + def run(self, timestamp, **kwargs): + """Run the synchronization using the timestamp""" + original_timestamp_value = timestamp.last_timestamp + if not timestamp._lock(): + self._handle_lock_failed(timestamp) + + next_timestamp_value, records = self._search(timestamp) + + timestamp._update_timestamp(next_timestamp_value) + + number = self._handle_records(records) + + return _( + "Batch from {original_timestamp_value} UTC to" + " {next_timestamp_value} UTC " + "generated {number} delete jobs" + ).format( + original_timestamp_value=original_timestamp_value, + next_timestamp_value=next_timestamp_value, + number=number, + ) + + def _handle_records(self, records): + """Handle the records to import and return the number handled""" + for record_id in records: + self._delete_record(record_id) + return len(records) + + def _handle_lock_failed(self, timestamp): + _logger.warning("Failed to acquire timestamps %s", timestamp, exc_info=True) + raise RetryableJobError( + "Concurrent job / process already syncing", + ignore_retry=True, + ) + + def _search(self, timestamp): + unix_timestamp = MilliDatetime.to_timestamp(timestamp.last_timestamp) + result = self.backend_adapter.deleted_since(since=unix_timestamp) + worklog_ids = result.deleted_worklog_ids + next_timestamp = MilliDatetime.from_timestamp(result.until) + return (next_timestamp, worklog_ids) + + def _delete_record(self, record_id, **kwargs): + """Delay the delete of the records""" + self.model.with_delay( + description=_("Delete a local worklog which has " "been deleted on JIRA"), + **kwargs, + ).delete_record( + self.backend_record, + record_id, + only_binding=False, + set_inactive=False, + ) diff --git a/connector_jira/models/account_analytic_line/importer.py b/connector_jira/models/account_analytic_line/importer.py new file mode 100644 index 000000000..d0fc29522 --- /dev/null +++ b/connector_jira/models/account_analytic_line/importer.py @@ -0,0 +1,367 @@ +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from pytz import timezone, utc + +from odoo import _ + +from odoo.addons.component.core import Component +from odoo.addons.connector.components.mapper import mapping +from odoo.addons.connector.exception import MappingError + +from ...components.mapper import ( + iso8601_to_naive_date, + iso8601_to_utc_datetime, + whenempty, +) +from ...fields import MilliDatetime + +_logger = logging.getLogger(__name__) + + +class AnalyticLineMapper(Component): + _name = "jira.analytic.line.mapper" + _inherit = "jira.import.mapper" + _apply_on = ["jira.account.analytic.line"] + + direct = [ + (whenempty("comment", _("missing description")), "name"), + ] + + @mapping + def issue(self, record): + issue = self.options.linked_issue + assert issue + refs = { + "jira_issue_id": record["issueId"], + "jira_issue_key": issue["key"], + } + task_mapper = self.component( + usage="import.mapper", + model_name="jira.project.task", + ) + issue_type_dict = task_mapper.issue_type(issue) + refs.update(issue_type_dict) + epic_field_name = self.backend_record.epic_link_field_name + if epic_field_name and epic_field_name in issue["fields"]: + refs["jira_epic_issue_key"] = issue["fields"][epic_field_name] + if self.backend_record.epic_link_on_epic: + issue_type = self.env["jira.issue.type"].browse( + issue_type_dict.get("jira_issue_type_id") + ) + if issue_type.name == "Epic": + refs["jira_epic_issue_key"] = issue.get("key") + return refs + + @mapping + def date(self, record): + mode = self.backend_record.worklog_date_timezone_mode + started = record["started"] + if not mode or mode == "naive": + return {"date": iso8601_to_naive_date(started)} + started = iso8601_to_utc_datetime(started).replace(tzinfo=utc) + if mode == "user": + tz = timezone(record["author"]["timeZone"]) + elif mode == "specific": + tz = timezone(self.backend_record.worklog_date_timezone) + return {"date": started.astimezone(tz).date()} + + @mapping + def duration(self, record): + spent = float(record["timeSpentSeconds"]) + # amount is in float in odoo... 2h30 = 2.5 + return {"unit_amount": spent / 60 / 60} + + @mapping + def author(self, record): + jira_author = record["author"] + jira_author_key = jira_author["key"] + binder = self.binder_for("jira.res.users") + user = binder.to_internal(jira_author_key, unwrap=True) + if not user: + email = jira_author["emailAddress"] + raise MappingError( + _( + 'No user found with login "%(jira_author_key)s" ' + 'or email "%(email)s".' + "You must create a user or link it manually if the " + "login/email differs.", + jira_author_key=jira_author_key, + email=email, + ) + ) + employee = ( + self.env["hr.employee"] + .with_context( + active_test=False, + ) + .search([("user_id", "=", user.id)], limit=1) + ) + return {"user_id": user.id, "employee_id": employee.id} + + @mapping + def project_and_task(self, record): + assert ( + self.options.task_binding + or self.options.project_binding + or self.options.fallback_project + ) + task_binding = self.options.task_binding + if not task_binding: + if self.options.fallback_project: + return {"project_id": self.options.fallback_project.id} + project = self.options.project_binding.odoo_id + if project: + return { + "project_id": project.id, + "jira_project_bind_id": self.options.project_binding.id, + } + + project = task_binding.project_id + return { + "task_id": task_binding.odoo_id.id, + "project_id": project.id, + "jira_project_bind_id": task_binding.jira_project_bind_id.id, + } + + @mapping + def backend_id(self, record): + return {"backend_id": self.backend_record.id} + + +class AnalyticLineBatchImporter(Component): + """Import the Jira worklogs + + For every id in in the list, a delayed job is created. + Import from a date + """ + + _name = "jira.analytic.line.batch.importer" + _inherit = "jira.timestamp.batch.importer" + _apply_on = ["jira.account.analytic.line"] + + def _search(self, timestamp): + unix_timestamp = MilliDatetime.to_timestamp(timestamp.last_timestamp) + result = self.backend_adapter.updated_since(since=unix_timestamp) + worklog_ids = self._filter_update(result.updated_worklogs) + # We need issue_id + worklog_id for the worklog importer (the jira + # "read" method for worklogs asks both), get it from yield_read. + # TODO we might consider to optimize the import process here: + # yield_read reads worklogs data, then the individual + # import will do a request again (and 2 with the tempo module) + next_timestamp = MilliDatetime.from_timestamp(result.until) + return (next_timestamp, self.backend_adapter.yield_read(worklog_ids)) + + def _handle_records(self, records, force=False): + count = 0 + for worklog in records: + count += 1 + worklog_id = worklog["id"] + issue_id = worklog["issueId"] + self._import_record(issue_id, worklog_id, force=force) + return count + + def _filter_update(self, updated_worklogs): + """Filter only the worklogs needing an update + + The result from Jira contains the worklog id and + the last update on Jira. So we keep only the worklog + ids with an sync_date before the Jira last update. + """ + if not updated_worklogs: + return [] + self.env.cr.execute( + "SELECT external_id, jira_updated_at " + "FROM jira_account_analytic_line " + "WHERE external_id IN %s ", + (tuple(str(r.worklog_id) for r in updated_worklogs),), + ) + bindings = {int(row[0]): row[1] for row in self.env.cr.fetchall()} + worklog_ids = [] + for worklog in updated_worklogs: + worklog_id = worklog.worklog_id + # we store the latest "updated_at" value on the binding + # so we can check if we already know the latest value, + # for instance because we imported the record from a + # webhook before, we can skip the import + binding_updated_at = bindings.get(worklog_id) + if not binding_updated_at: + worklog_ids.append(worklog_id) + continue + binding_updated_at = MilliDatetime.from_string(binding_updated_at) + jira_updated_at = MilliDatetime.from_timestamp(worklog.updated) + if binding_updated_at < jira_updated_at: + worklog_ids.append(worklog_id) + return worklog_ids + + def _import_record(self, issue_id, worklog_id, force=False, **kwargs): + """Delay the import of the records""" + self.model.with_delay(**kwargs).import_record( + self.backend_record, + issue_id, + worklog_id, + force=force, + ) + + +class AnalyticLineImporter(Component): + _name = "jira.analytic.line.importer" + _inherit = "jira.importer" + _apply_on = ["jira.account.analytic.line"] + + def __init__(self, work_context): + super().__init__(work_context) + self.external_issue_id = None + self.task_binding = None + self.project_binding = None + self.fallback_project = None + + def _get_external_updated_at(self): + assert self.external_record + external_updated_at = self.external_record.get("updated") + if not external_updated_at: + return None + return iso8601_to_utc_datetime(external_updated_at) + + @property + def _issue_fields_to_read(self): + epic_field_name = self.backend_record.epic_link_field_name + return ["issuetype", "project", "parent", epic_field_name] + + def _recurse_import_task(self): + """Import and return the task of proper type for the worklog + + As we decide which type of issues are imported for a project, + a worklog could be linked to an issue that we don't import. + In that case, we climb the parents of the issue until we find + a issue of a type we synchronize. + + It ensures that the 'to-be-linked' issue is imported and return it. + + """ + issue_adapter = self.component( + usage="backend.adapter", model_name="jira.project.task" + ) + issue_binder = self.binder_for("jira.project.task") + issue_type_binder = self.binder_for("jira.issue.type") + jira_issue_id = self.external_record["issueId"] + epic_field_name = self.backend_record.epic_link_field_name + project_matcher = self.component(usage="jira.task.project.matcher") + current_project_id = self.external_issue["fields"]["project"]["id"] + while jira_issue_id: + issue = issue_adapter.read( + jira_issue_id, + fields=self._issue_fields_to_read, + ) + + jira_project_id = issue["fields"]["project"]["id"] + jira_issue_type_id = issue["fields"]["issuetype"]["id"] + project_binding = project_matcher.find_project_binding(issue) + issue_type_binding = issue_type_binder.to_internal(jira_issue_type_id) + # JIRA allows to set an EPIC of a different project. + # If it happens, we discard it. + if ( + jira_project_id == current_project_id + and issue_type_binding.is_sync_for_project(project_binding) + ): + break + if issue["fields"].get("parent"): + # 'parent' is used on sub-tasks relating to their parent task + jira_issue_id = issue["fields"]["parent"]["id"] + elif issue["fields"].get(epic_field_name): + # the epic link is set on a jira custom field + epic_key = issue["fields"][epic_field_name] + epic = issue_adapter.read(epic_key, fields="id") + # we got the key of the epic issue, so we translate + # it to the ID with a call to the API + jira_issue_id = epic["id"] + else: + # no parent issue of a type we are synchronizing has been + # found, the worklog will be assigned to no task + jira_issue_id = None + + if jira_issue_id: + self._import_dependency(jira_issue_id, "jira.project.task") + return issue_binder.to_internal(jira_issue_id) + + def _create_data(self, map_record, **kwargs): + return super()._create_data( + map_record, + task_binding=self.task_binding, + project_binding=self.project_binding, + fallback_project=self.fallback_project, + linked_issue=self.external_issue, + ) + + def _update_data(self, map_record, **kwargs): + return super()._update_data( + map_record, + task_binding=self.task_binding, + project_binding=self.project_binding, + fallback_project=self.fallback_project, + linked_issue=self.external_issue, + ) + + def run(self, external_id, force=False, record=None, **kwargs): + assert "issue_id" in kwargs + self.external_issue_id = kwargs.pop("issue_id") + return super().run(external_id, force=force, record=record, **kwargs) + + def _handle_record_missing_on_jira(self): + """Hook called when we are importing a record missing on Jira + + For worklogs, we drop the analytic line if we discover it doesn't exist + on Jira, as the latter is the master. + """ + binding = self._get_binding() + if binding: + record = binding.odoo_id + binding.unlink() + record.unlink() + return _("Record does no longer exist in Jira") + + def _get_external_data(self): + """Return the raw Jira data for ``self.external_id``""" + issue_adapter = self.component( + usage="backend.adapter", model_name="jira.project.task" + ) + self.external_issue = issue_adapter.read(self.external_issue_id) + return self.backend_adapter.read(self.external_issue_id, self.external_id) + + def _before_import(self): + task_binding = self._recurse_import_task() + if task_binding and task_binding.active: + self.task_binding = task_binding + if not self.task_binding: + # when no task exists in Odoo (because we don't synchronize + # the issue type for instance), we link the line directly + # to the corresponding project, not linked to any task + issue = self.external_issue + assert issue + matcher = self.component(usage="jira.task.project.matcher") + project_binding = matcher.find_project_binding(issue) + if project_binding and project_binding.active: + self.project_binding = project_binding + else: + self.fallback_project = matcher.fallback_project_for_worklogs() + + def _import(self, binding, **kwargs): + if not (self.task_binding or self.project_binding or self.fallback_project): + _logger.debug( + "No task or project synchronized for attaching worklog %s", + self.external_record["id"], + ) + return + return super()._import(binding, **kwargs) + + def _import_dependency_assignee(self): + jira_assignee = self.external_record["author"] + jira_key = jira_assignee.get("key") + self._import_dependency(jira_key, "jira.res.users", record=jira_assignee) + + def _import_dependencies(self): + """Import the dependencies for the record""" + self._import_dependency_assignee() diff --git a/connector_jira/models/jira_backend/__init__.py b/connector_jira/models/jira_backend/__init__.py new file mode 100644 index 000000000..63602330c --- /dev/null +++ b/connector_jira/models/jira_backend/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common diff --git a/connector_jira/models/jira_backend/common.py b/connector_jira/models/jira_backend/common.py new file mode 100644 index 000000000..a924c5bae --- /dev/null +++ b/connector_jira/models/jira_backend/common.py @@ -0,0 +1,710 @@ +# Copyright: 2015 LasLabs, Inc. +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import binascii +import json +import logging +import urllib.parse +from contextlib import closing, contextmanager +from datetime import datetime +from os import urandom + +import psycopg2 +import pytz +import requests + +import odoo +from odoo import _, api, exceptions, fields, models, tools + +from odoo.addons.component.core import Component + +from ...fields import MilliDatetime + +_logger = logging.getLogger(__name__) + +JIRA_TIMEOUT = 30 # seconds + +try: + from jira import JIRA, JIRAError + from jira.utils import json_loads +except ImportError as err: + _logger.debug(err) + +try: + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import serialization + from cryptography.hazmat.primitives.asymmetric import rsa +except ImportError as err: + _logger.debug(err) + + +@contextmanager +def new_env(env): + registry = odoo.registry(env.cr.dbname) + with closing(registry.cursor()) as cr: + new_env = api.Environment(cr, env.uid, env.context) + try: + yield new_env + except Exception: + cr.rollback() + raise + else: + if not tools.config["test_enable"]: + cr.commit() # pylint: disable=invalid-commit + + +class JiraBackend(models.Model): + _name = "jira.backend" + _description = "Jira Backend" + _inherit = "connector.backend" + + RSA_BITS = 4096 + RSA_PUBLIC_EXPONENT = 65537 + KEY_LEN = 255 # 255 == max Atlassian db col len + + def _default_consumer_key(self): + """Generate a rnd consumer key of length self.KEY_LEN""" + return binascii.hexlify(urandom(self.KEY_LEN))[: self.KEY_LEN] + + uri = fields.Char(string="Jira URI", required=True) + name = fields.Char() + company_id = fields.Many2one( + comodel_name="res.company", + string="Company", + required=True, + default=lambda self: self.env.company, + ) + worklog_fallback_project_id = fields.Many2one( + comodel_name="project.project", + string="Fallback for Worklogs", + help="Worklogs which could not be linked to any project " + "will be created in this project. Worklogs landing in " + "the fallback project can be reassigned to the correct " + "project by: 1. linking the expected project with the Jira one, " + "2. using 'Refresh Worklogs from Jira' on the timesheet lines.", + ) + worklog_date_timezone_mode = fields.Selection( + selection=[ + ("naive", "As-is (naive)"), + ("user", "Jira User"), + ("specific", "Specific"), + ], + default="naive", + help=( + "Worklog/Timesheet date timezone modes:\n" + " - As-is (naive): ignore timezone information\n" + " - Jira User: use author's timezone\n" + " - Specific: use pre-configured timezone\n" + ), + ) + worklog_date_timezone = fields.Selection( + selection=lambda self: [(x, x) for x in pytz.all_timezones], + default=(lambda self: self._context.get("tz") or self.env.user.tz or "UTC"), + ) + state = fields.Selection( + selection=[ + ("authenticate", "Authenticate"), + ("setup", "Setup"), + ("running", "Running"), + ], + default="authenticate", + required=True, + readonly=True, + ) + private_key = fields.Text( + readonly=True, + groups="connector.group_connector_manager", + ) + public_key = fields.Text(readonly=True) + consumer_key = fields.Char( + default=lambda self: self._default_consumer_key(), + readonly=True, + groups="connector.group_connector_manager", + ) + + access_token = fields.Char( + readonly=True, + groups="connector.group_connector_manager", + ) + access_secret = fields.Char( + readonly=True, + groups="connector.group_connector_manager", + ) + + access_method = fields.Selection( + [ + ("system", "System-level"), + ("user", "User-level"), + ], + "Access Method", + required=True, + default="system", + help="If you don't have system-level access to Jira, you can still " + "access the API as a user given that you have generated an access " + "token. If you do, prefer the system-level access that uses OAuth " + "for authentication." + ) + + username = fields.Char( + groups="connector.group_connector_manager", + ) + + user_token = fields.Char( + groups="connector.group_connector_manager", + ) + + verify_ssl = fields.Boolean(default=True, string="Verify SSL?") + + project_template = fields.Selection( + selection="_selection_project_template", + string="Default Project Template", + default="Scrum software development", + required=True, + ) + project_template_shared = fields.Char( + string="Default Shared Template Key", + ) + + use_webhooks = fields.Boolean( + readonly=True, + help="Webhooks need to be configured on the Jira instance. " + "When activated, synchronization from Jira is blazing fast. " + "It can be activated only on one Jira backend at a time. ", + ) + + import_project_task_from_date = fields.Datetime( + compute="_compute_last_import_date", + inverse="_inverse_import_project_task_from_date", + string="Import Project Tasks from date", + ) + import_project_task_force = fields.Boolean() + + import_analytic_line_from_date = fields.Datetime( + compute="_compute_last_import_date", + inverse="_inverse_import_analytic_line_from_date", + string="Import Worklogs from date", + ) + import_analytic_line_force = fields.Boolean() + + delete_analytic_line_from_date = fields.Datetime( + compute="_compute_last_import_date", + inverse="_inverse_delete_analytic_line_from_date", + string="Delete Extra Worklogs from date", + ) + + issue_type_ids = fields.One2many( + comodel_name="jira.issue.type", + inverse_name="backend_id", + string="Issue Types", + readonly=True, + ) + + epic_link_field_name = fields.Char( + string="Epic Link Field", + help="The 'Epic Link' field on JIRA is a custom field. " + "The name of the field is something like 'customfield_10002'. ", + ) + epic_name_field_name = fields.Char( + string="Epic Name Field", + help="The 'Epic Name' field on JIRA is a custom field. " + "The name of the field is something like 'customfield_10003'. ", + ) + epic_link_on_epic = fields.Boolean( + help="Epics on JIRA cannot be linked to another epic. Check this box" + "to fill the epic field with itself on Odoo.", + ) + + odoo_webhook_base_url = fields.Char( + string="Base Odoo URL for Webhooks", + default=lambda self: self._default_odoo_webhook_base_url(), + ) + webhook_issue_jira_id = fields.Char() + webhook_worklog_jira_id = fields.Char() + # TODO: use something better to show this info + # For instance, we could use web_notify to simply show a system msg. + report_user_sync = fields.Html(readonly=True) + + @api.model + def _default_odoo_webhook_base_url(self): + params = self.env["ir.config_parameter"] + return params.get_param("web.base.url", "") + + @api.model + def _selection_project_template(self): + return [ + ("Scrum software development", "Scrum software development (Software)"), + ("Kanban software development", "Kanban software development (Software)"), + ("Basic software development", "Basic software development (Software)"), + ("Project management", "Project management (Business)"), + ("Task management", "Task management (Business)"), + ("Process management", "Process management (Business)"), + ("shared", "From a shared template"), + ] + + @api.constrains("project_template_shared") + def check_jira_key(self): + for backend in self: + if not backend.project_template_shared: + continue + valid = self.env["jira.project.project"]._jira_key_valid + if not valid(backend.project_template_shared): + raise exceptions.ValidationError( + _("%s is not a valid JIRA Key") % backend.project_template_shared + ) + + @api.depends() + def _compute_last_import_date(self): + for backend in self: + self.env.cr.execute( + """ + SELECT from_date_field, last_timestamp + FROM jira_backend_timestamp + WHERE backend_id = %s""", + (backend.id,), + ) + rows = self.env.cr.dictfetchall() + for row in rows: + field = row["from_date_field"] + if field in self._fields: + backend[field] = row["last_timestamp"] + if not rows: + backend.update( + { + "import_project_task_from_date": False, + "import_analytic_line_from_date": False, + "delete_analytic_line_from_date": False, + } + ) + + def _inverse_date_fields(self, field_name, component_usage): + for rec in self: + ts_model = self.env["jira.backend.timestamp"] + timestamp = ts_model._timestamp_for_field(rec, field_name, component_usage) + if not timestamp._lock(): + raise exceptions.UserError( + _( + "The synchronization timestamp is currently locked, " + "probably due to an ongoing synchronization." + ) + ) + value = getattr(rec, field_name) + # As the timestamp field is using MilliDatetime, we lose + # the milliseconds precision when a user writes a new + # date on the backend. This is not really an issue as we + # expect mostly to use the milliseconds precision for + # the dates coming from the Jira webservices (they use + # milliseconds unix timestamp on some -only some- methods) + if not value: + value = datetime.fromtimestamp(0) + timestamp._update_timestamp(value) + + def _inverse_import_project_task_from_date(self): + self._inverse_date_fields( + "import_project_task_from_date", + "timestamp.batch.importer", + ) + + def _inverse_import_analytic_line_from_date(self): + self._inverse_date_fields( + "import_analytic_line_from_date", + "timestamp.batch.importer", + ) + + def _inverse_delete_analytic_line_from_date(self): + self._inverse_date_fields( + "delete_analytic_line_from_date", + "timestamp.batch.deleter", + ) + + def _run_background_from_date( + self, model, from_date_field, component_usage, force=False + ): + """Import records from a date + + Create jobs and update the sync timestamp in a savepoint; if a + concurrency issue arises, it will be logged and rollbacked silently. + """ + self.ensure_one() + ts_model = self.env["jira.backend.timestamp"] + timestamp = ts_model._timestamp_for_field( + self, + from_date_field, + component_usage, + ) + self.env[model].with_delay(priority=9).run_batch_timestamp( + self, timestamp, force=force + ) + + @api.constrains("use_webhooks") + def _check_use_webhooks_unique(self): + if len(self.search([("use_webhooks", "=", True)])) > 1: + raise exceptions.ValidationError( + _("Only one backend can listen to webhooks") + ) + + @api.model + def create(self, values): + record = super().create(values) + record.create_rsa_key_vals() + return record + + def create_rsa_key_vals(self): + """Create public/private RSA keypair""" + for backend in self: + private_key = rsa.generate_private_key( + public_exponent=self.RSA_PUBLIC_EXPONENT, + key_size=self.RSA_BITS, + backend=default_backend(), + ) + pem = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + public_pem = private_key.public_key().public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo, + ) + backend.write({"private_key": pem, "public_key": public_pem}) + + def button_setup(self): + self.state_running() + + def activate_epic_link(self): + self.ensure_one() + with self.work_on("jira.backend") as work: + adapter = work.component(usage="backend.adapter") + jira_fields = adapter.list_fields() + for field in jira_fields: + custom_ref = field.get("schema", {}).get("custom") + if custom_ref == "com.pyxis.greenhopper.jira:gh-epic-link": + self.epic_link_field_name = field["id"] + elif custom_ref == "com.pyxis.greenhopper.jira:gh-epic-label": + self.epic_name_field_name = field["id"] + + def state_setup(self): + for backend in self: + if backend.state == "authenticate": + backend.state = "setup" + + def state_running(self): + for backend in self: + if backend.state == "setup": + backend.state = "running" + + def create_webhooks(self): + self.ensure_one() + other_using_webhook = self.search( + [("use_webhooks", "=", True), ("id", "!=", self.id)] + ) + if other_using_webhook: + raise exceptions.UserError( + _( + "Only one JIRA backend can use the webhook at a time. " + 'You must disable them on the backend "%s" before ' + "activating them here." + ) + % (other_using_webhook.name,) + ) + + # open a new cursor because we'll commit after the creations + # to be sure to keep the webhook ids + with new_env(self.env) as env: + backend = env[self._name].browse(self.id) + base_url = backend.odoo_webhook_base_url + if not base_url: + raise exceptions.UserError(_("The Odoo Webhook base URL must be set.")) + + with self.work_on("jira.backend") as work: + backend.use_webhooks = True + + adapter = work.component(usage="backend.adapter") + # TODO: we could update the JQL of the webhook + # each time a new project is sync'ed, so we would + # filter out the useless events + url = urllib.parse.urljoin(base_url, "/connector_jira/webhooks/issue") + webhook = adapter.create_webhook( + name="Odoo Issues", + url=url, + events=[ + "jira:issue_created", + "jira:issue_updated", + "jira:issue_deleted", + ], + ) + # the only place where to find the hook id is in + # the 'self' url, looks like + # u'http://jira:8080/rest/webhooks/1.0/webhook/5' + webhook_id = webhook["self"].split("/")[-1] + backend.webhook_issue_jira_id = webhook_id + if not tools.config["test_enable"]: + env.cr.commit() # pylint: disable=invalid-commit + + url = urllib.parse.urljoin(base_url, "/connector_jira/webhooks/worklog") + webhook = adapter.create_webhook( + name="Odoo Worklogs", + url=url, + events=["worklog_created", "worklog_updated", "worklog_deleted"], + ) + webhook_id = webhook["self"].split("/")[-1] + backend.webhook_worklog_jira_id = webhook_id + if not tools.config["test_enable"]: + env.cr.commit() # pylint: disable=invalid-commit + + @api.onchange("odoo_webhook_base_url") + def onchange_odoo_webhook_base_url(self): + if self.use_webhooks: + msg = _( + "If you change the base URL, you must delete and create " + "the Webhooks again." + ) + return {"warning": {"title": _("Warning"), "message": msg}} + + @api.onchange("worklog_date_timezone_mode") + def _onchange_worklog_date_import_timezone_mode(self): + for jira_backend in self: + if jira_backend.worklog_date_timezone_mode == "specific": + continue + jira_backend.worklog_date_timezone = False + + def delete_webhooks(self): + self.ensure_one() + with self.work_on("jira.backend") as work: + adapter = work.component(usage="backend.adapter") + if self.webhook_issue_jira_id: + try: + adapter.delete_webhook(self.webhook_issue_jira_id) + except JIRAError as err: + # 404 means it has been deleted in JIRA, ignore it + if err.status_code != 404: + raise + if self.webhook_worklog_jira_id: + try: + adapter.delete_webhook(self.webhook_worklog_jira_id) + except JIRAError as err: + # 404 means it has been deleted in JIRA, ignore it + if err.status_code != 404: + raise + self.use_webhooks = False + + def check_connection(self, raise_when_successful=True): + self.ensure_one() + try: + self.get_api_client().myself() + except (ValueError, requests.exceptions.ConnectionError) as err: + raise exceptions.UserError(_("Failed to connect (%s)") % (err,)) from err + except JIRAError as err: + raise exceptions.UserError(_("Failed to connect (%s)") % (err.text,)) + + if raise_when_successful: + raise exceptions.UserError(_("Connection successful")) + + def authenticate_user(self): + self.check_connection(raise_when_successful=False) + self.state_setup() + + def import_project_task(self): + self._run_background_from_date( + "jira.project.task", + "import_project_task_from_date", + "timestamp.batch.importer", + force=self.import_project_task_force, + ) + return True + + def import_analytic_line(self): + self._run_background_from_date( + "jira.account.analytic.line", + "import_analytic_line_from_date", + "timestamp.batch.importer", + force=self.import_analytic_line_force, + ) + return True + + def delete_analytic_line(self): + self._run_background_from_date( + "jira.account.analytic.line", + "delete_analytic_line_from_date", + "timestamp.batch.deleter", + ) + return True + + def import_res_users(self): + self.report_user_sync = None + result = self.env["res.users"].search([]).link_with_jira(backends=self) + for __, bknd_result in result.items(): + if bknd_result.get("error"): + self.report_user_sync = self.env.ref( + "connector_jira.backend_report_user_sync" + ).render({"backend": self, "result": bknd_result}) + return True + + def get_user_resolution_order(self): + """User resolution should happen by login first as it's unique, while + resolving by email is likely to give false positives""" + return ["login", "email"] + + def import_issue_type(self): + self.env["jira.issue.type"].import_batch(self) + return True + + @api.model + def get_api_client(self): + self.ensure_one() + # tokens are only readable by connector managers + backend = self.sudo() + + options = { + "server": backend.uri, + "verify": backend.verify_ssl, + } + if backend.access_method == "system": + oauth = { + "access_token": backend.access_token, + "access_token_secret": backend.access_secret, + "consumer_key": backend.consumer_key, + "key_cert": backend.private_key, + } + return JIRA(options=options, oauth=oauth, timeout=JIRA_TIMEOUT) + elif backend.access_method == "user": + basic_auth = (backend.username, backend.user_token) + return JIRA(options=options, basic_auth=basic_auth, timeout=JIRA_TIMEOUT) + else: + raise exceptions.UserError(_(f"Invalid access method '%s'") % backend.access_method) + + @api.model + def _scheduler_import_project_task(self): + self.search([]).import_project_task() + + @api.model + def _scheduler_import_res_users(self): + self.search([]).import_res_users() + + @api.model + def _scheduler_import_analytic_line(self): + self.search([]).import_analytic_line() + + @api.model + def _scheduler_delete_analytic_line(self): + self.search([]).delete_analytic_line() + + def make_issue_url(self, jira_issue_id): + return urllib.parse.urljoin(self.uri, f"/browse/{jira_issue_id}") + + +class JiraBackendTimestamp(models.Model): + _name = "jira.backend.timestamp" + _description = "Jira Backend Import Timestamps" + + backend_id = fields.Many2one( + comodel_name="jira.backend", + string="Jira Backend", + required=True, + ) + from_date_field = fields.Char( + required=True, + ) + # For worklogs, jira allows to work with milliseconds + # unix timestamps, we keep this precision by using a new type + # of field. The ORM values for this field are Unix timestamps the + # same way Jira use them: unix timestamp as integer multiplied * 1000 + # to keep the milli precision with 3 digits (example 1554318348000). + last_timestamp = MilliDatetime( + string="Last Timestamp", + required=True, + ) + + # The content of this field must match to the "usage" of a component. + # The method JiraBinding.run_batch_timestamp() will find the matching + # component for the model and call "run()" on it. + component_usage = fields.Char( + required=True, + help="Used by the connector to find which component " + "execute the batch import (technical).", + ) + + _sql_constraints = [ + ( + "timestamp_field_uniq", + "unique(backend_id, from_date_field, component_usage)", + "A timestamp already exists.", + ), + ] + + @api.model + def _timestamp_for_field(self, backend, field_name, component_usage): + """Return the timestamp for a field""" + timestamp = self.search( + [ + ("backend_id", "=", backend.id), + ("from_date_field", "=", field_name), + ("component_usage", "=", component_usage), + ] + ) + if not timestamp: + timestamp = self.env["jira.backend.timestamp"].create( + { + "backend_id": backend.id, + "from_date_field": field_name, + "component_usage": component_usage, + "last_timestamp": datetime.fromtimestamp(0), + } + ) + return timestamp + + def _update_timestamp(self, timestamp): + self.ensure_one() + self.last_timestamp = timestamp + + def _lock(self): + """Update the timestamp for a synchro + + thus, we prevent 2 synchros to be launched at the same time. + The lock is released at the commit of the transaction. + + Return True if the lock could be acquired. + """ + self.ensure_one() + query = """ + SELECT id FROM jira_backend_timestamp + WHERE id = %s + FOR UPDATE NOWAIT + """ + try: + self.env.cr.execute(query, (self.id,)) + except psycopg2.OperationalError: + return False + row = self.env.cr.fetchone() + return bool(row) + + +class BackendAdapter(Component): + _name = "jira.backend.adapter" + _inherit = "jira.webservice.adapter" + _apply_on = ["jira.backend"] + + webhook_base_path = "{server}/rest/webhooks/1.0/{path}" + + def list_fields(self): + return self.client._get_json("field") + + def create_webhook( + self, name=None, url=None, events=None, jql="", exclude_body=False + ): + assert name and url and events + data = { + "name": name, + "url": url, + "events": events, + "jqlFilter": jql, + "excludeIssueDetails": exclude_body, + } + url = self.client._get_url("webhook", base=self.webhook_base_path) + response = self.client._session.post(url, data=json.dumps(data)) + return json_loads(response) + + def delete_webhook(self, id_): + url = self.client._get_url("webhook/%s" % id_, base=self.webhook_base_path) + return json_loads(self.client._session.delete(url)) diff --git a/connector_jira/models/jira_binding/__init__.py b/connector_jira/models/jira_binding/__init__.py new file mode 100644 index 000000000..63602330c --- /dev/null +++ b/connector_jira/models/jira_binding/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common diff --git a/connector_jira/models/jira_binding/common.py b/connector_jira/models/jira_binding/common.py new file mode 100644 index 000000000..31cc238b4 --- /dev/null +++ b/connector_jira/models/jira_binding/common.py @@ -0,0 +1,77 @@ +# Copyright 2016-2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + +from ...fields import MilliDatetime + + +class JiraBinding(models.AbstractModel): + """Abstract Model for the Bindings. + + All the models used as bindings between Jira and Odoo + (``jira.product.product``, ...) should ``_inherit`` it. + """ + + _name = "jira.binding" + _inherit = "external.binding" + _description = "Jira Binding (abstract)" + + # odoo-side id must be declared in concrete model + # odoo_id = fields.Many2one(...) + backend_id = fields.Many2one( + comodel_name="jira.backend", + string="Jira Backend", + required=True, + ondelete="restrict", + ) + jira_updated_at = MilliDatetime() + external_id = fields.Char(string="ID on Jira", index=True) + + _sql_constraints = [ + ( + "jira_binding_uniq", + "unique(backend_id, external_id)", + "A binding already exists for this Jira record", + ), + ] + + @api.model + def import_batch(self, backend): + """Prepare import of a batch of record""" + with backend.work_on(self._name) as work: + importer = work.component(usage="batch.importer") + return importer.run() + + @api.model + def run_batch_timestamp(self, backend, timestamp, force=False): + """Prepare batch of records""" + with backend.work_on(self._name) as work: + importer = work.component(usage=timestamp.component_usage) + return importer.run(timestamp, force=force) + + @api.model + def import_record(self, backend, external_id, force=False, record=None): + """Import a record""" + with backend.work_on(self._name) as work: + importer = work.component(usage="record.importer") + return importer.run(external_id, force=force, record=record) + + @api.model + def delete_record( + self, backend, external_id, only_binding=False, set_inactive=False + ): + """Delete a record on Odoo""" + with backend.work_on(self._name) as work: + importer = work.component(usage="record.deleter") + return importer.run( + external_id, + only_binding=only_binding, + set_inactive=set_inactive, + ) + + def export_record(self, fields=None): + self.ensure_one() + with self.backend_id.work_on(self._name) as work: + exporter = work.component(usage="record.exporter") + return exporter.run(self, fields=fields) diff --git a/connector_jira/models/jira_issue_type/__init__.py b/connector_jira/models/jira_issue_type/__init__.py new file mode 100644 index 000000000..ea8197b11 --- /dev/null +++ b/connector_jira/models/jira_issue_type/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common +from . import importer diff --git a/connector_jira/models/jira_issue_type/common.py b/connector_jira/models/jira_issue_type/common.py new file mode 100644 index 000000000..6690e9f5d --- /dev/null +++ b/connector_jira/models/jira_issue_type/common.py @@ -0,0 +1,46 @@ +# Copyright 2016-2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + +from odoo.addons.component.core import Component + + +class JiraIssueType(models.Model): + _name = "jira.issue.type" + _inherit = "jira.binding" + _description = "Jira Issue Type" + + name = fields.Char(required=True, readonly=True) + description = fields.Char(readonly=True) + backend_id = fields.Many2one(ondelete="cascade") + + def is_sync_for_project(self, project_binding): + self.ensure_one() + if not project_binding: + return False + return self in project_binding.sync_issue_type_ids + + def import_batch(self, backend, from_date=None, to_date=None): + """Prepare a batch import of issue types from Jira + + from_date and to_date are ignored for issue types + """ + with backend.work_on(self._name) as work: + importer = work.component(usage="batch.importer") + importer.run() + + +class IssueTypeAdapter(Component): + _name = "jira.issue.type.adapter" + _inherit = ["jira.webservice.adapter"] + _apply_on = ["jira.issue.type"] + + def read(self, id_): + # pylint: disable=W8106 + with self.handle_404(): + return self.client.issue_type(id_).raw + + def search(self): + issues = self.client.issue_types() + return [issue.id for issue in issues] diff --git a/connector_jira/models/jira_issue_type/importer.py b/connector_jira/models/jira_issue_type/importer.py new file mode 100644 index 000000000..557df5235 --- /dev/null +++ b/connector_jira/models/jira_issue_type/importer.py @@ -0,0 +1,38 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.addons.component.core import Component +from odoo.addons.connector.components.mapper import mapping + + +class IssueTypeMapper(Component): + _name = "jira.issue.type.mapper" + _inherit = ["jira.import.mapper"] + _apply_on = "jira.issue.type" + + direct = [ + ("name", "name"), + ("description", "description"), + ] + + @mapping + def backend_id(self, record): + return {"backend_id": self.backend_record.id} + + +class IssueTypeBatchImporter(Component): + """Import the Jira Issue Types + + For every id in in the list of issue types, a direct import is done. + Import from a date + """ + + _name = "jira.issue.type.batch.importer" + _inherit = "jira.direct.batch.importer" + _apply_on = ["jira.issue.type"] + + def run(self): + """Run the synchronization""" + record_ids = self.backend_adapter.search() + for record_id in record_ids: + self._import_record(record_id) diff --git a/connector_jira/models/project_project/__init__.py b/connector_jira/models/project_project/__init__.py new file mode 100644 index 000000000..654c9a438 --- /dev/null +++ b/connector_jira/models/project_project/__init__.py @@ -0,0 +1,6 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import binder +from . import common +from . import project_link_jira +from . import exporter diff --git a/connector_jira/models/project_project/binder.py b/connector_jira/models/project_project/binder.py new file mode 100644 index 000000000..5474bc342 --- /dev/null +++ b/connector_jira/models/project_project/binder.py @@ -0,0 +1,55 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import models + +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + + +class JiraProjectBinder(Component): + _name = "jira.project.binder" + _inherit = "jira.binder" + + _apply_on = [ + "jira.project.project", + ] + + def _domain_to_external(self, binding): + return [ + (self._odoo_field, "=", binding.id), + (self._backend_field, "=", self.backend_record.id), + ("sync_action", "=", "export"), + ] + + def to_external(self, binding, wrap=False): + """Give the external ID for an Odoo binding ID + + More than one jira binding is possible on projects, but we still + have to know to which one we have to export. Currently, we'll only + pick the binding with Sync. Action "export". However, if later we + add, for instance, a push of tasks, we may consider adding other + means to get the external id. + + :param binding: Odoo binding for which we want the external id + :param wrap: if True, binding is a normal record, the + method will search the corresponding binding and return + the external id of the binding + :return: external ID of the record + """ + if isinstance(binding, models.BaseModel): + binding.ensure_one() + else: + binding = self.model.browse(binding) + if wrap: + binding = self.model.with_context(active_test=False).search( + self._domain_to_external() + ) + if not binding: + return None + binding.ensure_one() + return binding[self._external_field] + return binding[self._external_field] diff --git a/connector_jira/models/project_project/common.py b/connector_jira/models/project_project/common.py new file mode 100644 index 000000000..663d3089d --- /dev/null +++ b/connector_jira/models/project_project/common.py @@ -0,0 +1,353 @@ +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import json +import logging +import re +import tempfile + +from odoo import _, api, exceptions, fields, models, tools + +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + +try: + from jira import JIRAError + from jira.utils import json_loads +except ImportError as err: + _logger.debug(err) + + +class JiraProjectBaseFields(models.AbstractModel): + """JIRA Project Base fields + + Shared by the binding jira.project.project + and the wizard to link/create a JIRA project + """ + + _name = "jira.project.base.mixin" + _description = "JIRA Project Base Mixin" + + jira_key = fields.Char( + string="JIRA Key", + required=True, + size=10, + ) # limit on JIRA + sync_issue_type_ids = fields.Many2many( + comodel_name="jira.issue.type", + string="Issue Levels to Synchronize", + domain="[('backend_id', '=', backend_id)]", + help="Only issues of these levels are imported. " + "When a worklog is imported no a level which is " + "not sync'ed, it is attached to the nearest " + "sync'ed parent level. If no parent can be found, " + "it is attached to a special 'Unassigned' task.", + ) + project_template = fields.Selection( + selection="_selection_project_template", + string="Default Project Template", + default="Scrum software development", + ) + project_template_shared = fields.Char( + string="Default Shared Template", + ) + sync_action = fields.Selection( + selection=[("link", "Link with JIRA"), ("export", "Export to JIRA")], + default="link", + required=True, + help="Defines if the information of the project (name " + "and key) are exported to JIRA when changed. Link means" + "the project already exists on JIRA, no sync of the project" + " details once the link is established." + " Tasks are always imported from JIRA, not pushed.", + ) + + @api.model + def _selection_project_template(self): + return self.env["jira.backend"]._selection_project_template() + + +class JiraProjectProject(models.Model): + _name = "jira.project.project" + _inherit = ["jira.binding", "jira.project.base.mixin"] + _inherits = {"project.project": "odoo_id"} + _description = "Jira Projects" + + odoo_id = fields.Many2one( + comodel_name="project.project", + string="Project", + required=True, + index=True, + ondelete="restrict", + ) + project_type = fields.Selection(selection="_selection_project_type") + + @api.model + def _selection_project_type(self): + return [ + ("software", "Software"), + ("business", "Business"), + ] + + # Disable and implement the constraint jira_binding_uniq as python because + # we need to override the in connector_jira_service_desk and it would try + # to create it again at every update because of the base implementation + # in the binding's parent model. + def _add_sql_constraints(self): + # we replace the sql constraint by a python one + # to include the organizations + for key, definition, _msg in self._sql_constraints: + conname = f"{self._table}_{key}" + if key == "jira_binding_uniq": + has_definition = tools.constraint_definition( + self.env.cr, self._table, conname + ) + if has_definition: + tools.drop_constraint(self.env.cr, self._table, conname) + else: + tools.add_constraint(self.env.cr, self._table, conname, definition) + return super()._add_sql_constraints() + + def _export_binding_domain(self): + """Return the domain for the constraints on export bindings""" + self.ensure_one() + domain = [ + ("odoo_id", "=", self.odoo_id.id), + ("backend_id", "=", self.backend_id.id), + ("sync_action", "=", "export"), + ] + return domain + + @api.constrains("backend_id", "odoo_id", "sync_action") + def _constrains_odoo_jira_sync_action_export_uniq(self): + """Add a constraint on backend+odoo id for export action + + Only one binding can have the sync_action "export", as it pushes the + name and key to Jira, we cannot export the same values to several + projects. + """ + for binding in self: + export_bindings = self.with_context(active_test=False).search( + self._export_binding_domain() + ) + if len(export_bindings) > 1: + raise exceptions.ValidationError( + _( + "Only one Jira binding can be configured with the Sync." + ' Action "Export" for a project. "%s" already' + " has one." + ) + % (binding.display_name,) + ) + + @api.constrains("backend_id", "external_id") + def _constrains_jira_uniq(self): + """Add a constraint on backend+jira id + + Defined as a python method rather than a postgres constraint + in order to ease the override in connector_jira_servicedesk + """ + for binding in self: + if not binding.external_id: + continue + same_link_bindings = self.with_context(active_test=False).search( + [ + ("id", "!=", binding.id), + ("backend_id", "=", binding.backend_id.id), + ("external_id", "=", binding.external_id), + ] + ) + if same_link_bindings: + raise exceptions.ValidationError( + _("The project %s is already linked with the same" " JIRA project.") + % (same_link_bindings.display_name) + ) + + @api.constrains("jira_key") + def check_jira_key(self): + for project in self: + if not project.jira_key: + continue + if not self._jira_key_valid(project.jira_key): + raise exceptions.ValidationError( + _("%s is not a valid JIRA Key") % project.jira_key + ) + + @api.onchange("backend_id") + def onchange_project_backend_id(self): + self.project_template = self.backend_id.project_template + self.project_template_shared = self.backend_id.project_template_shared + + @staticmethod + def _jira_key_valid(key): + return bool(re.match(r"^[A-Z][A-Z0-9]{1,9}$", key)) + + @api.constrains("project_template_shared") + def check_project_template_shared(self): + for binding in self: + if not binding.project_template_shared: + continue + if not self._jira_key_valid(binding.project_template_shared): + raise exceptions.ValidationError( + _("%s is not a valid JIRA Key") % binding.project_template_shared + ) + + def _is_linked(self): + for project in self: + if project.sync_action == "link": + return True + return False + + @api.model + def create(self, values): + record = super().create(values) + record._ensure_jira_key() + return record + + def write(self, values): + if "project_template" in values: + raise exceptions.UserError(_("The project template cannot be modified.")) + res = super().write(values) + self._ensure_jira_key() + return res + + def _ensure_jira_key(self): + if self.env.context.get("connector_no_export"): + return + for record in self: + if not record.jira_key: + raise exceptions.UserError( + _("The JIRA Key is mandatory in order to link a project") + ) + + def unlink(self): + if any(self.mapped("external_id")): + raise exceptions.UserError(_("Exported project cannot be deleted.")) + return super().unlink() + + +class ProjectProject(models.Model): + _inherit = "project.project" + _rec_names_search = ["name", "jira_key"] + + jira_bind_ids = fields.One2many( + comodel_name="jira.project.project", + inverse_name="odoo_id", + copy=False, + string="Project Bindings", + context={"active_test": False}, + ) + jira_key = fields.Char( + string="JIRA Key", + compute="_compute_jira_key", + store=True, + ) + + @api.depends("jira_bind_ids.jira_key") + def _compute_jira_key(self): + for project in self: + keys = project.mapped("jira_bind_ids.jira_key") + project.jira_key = ", ".join(keys) + + @api.depends("jira_key") + def _compute_display_name(self): + res = super()._compute_display_name() + + for rec in self: + if not rec.jira_key: + continue + + rec.display_name = f"[{rec.jira_key}] {rec.display_name}" + + return res + + def create_and_link_jira(self): + action_link = self.env.ref("connector_jira.open_project_link_jira") + action = action_link.read()[0] + action["context"] = dict( + self.env.context, + active_id=self.id, + active_model=self._name, + ) + return action + + +class ProjectAdapter(Component): + _name = "jira.project.adapter" + _inherit = ["jira.webservice.adapter"] + _apply_on = ["jira.project.project"] + + def read(self, id_): + # pylint: disable=W8106 + with self.handle_404(): + return self.get(id_).raw + + def get(self, id_): + with self.handle_404(): + return self.client.project(id_) + + def write(self, id_, values): + super().write(id_, values) + with self.handle_404(): + return self.get(id_).update(values) + + def create(self, key=None, name=None, template_name=None, values=None): + super().create(key=key, name=name, template_name=template_name, values=values) + project = self.client.create_project( + key=key, + name=name, + template_name=template_name, + ) + if values: + project.update(values) + return project + + def create_shared(self, key=None, name=None, shared_key=None, lead=None): + assert key and name and shared_key + # There is no public method for creating a shared project: + # https://jira.atlassian.com/browse/JRA-45929 + # People found a private method for doing so, which is explained on: + # https://jira.atlassian.com/browse/JRASERVER-27256 + + try: + project = self.read(shared_key) + project_id = project["id"] + except JIRAError as err: + if err.status_code == 404: + raise exceptions.UserError( + _('Project template with key "%s" not found.') % shared_key + ) from err + else: + raise + + url = ( + self.client._options["server"] + + "/rest/project-templates/1.0/createshared/%s" % project_id + ) + payload = { + "name": name, + "key": key, + "lead": lead, + } + + r = self.client._session.post(url, data=json.dumps(payload)) + if r.status_code == 200: + r_json = json_loads(r) + return r_json + + f = tempfile.NamedTemporaryFile( + suffix=".html", + prefix="python-jira-error-create-shared-project-", + delete=False, + ) + f.write(r.text) + + if self.logging: + logging.error( + "Unexpected result while running create shared project." + f"Server response saved in {f.name} for further investigation " + f"[HTTP response={r.status_code}]." + ) + return False diff --git a/connector_jira/models/project_project/exporter.py b/connector_jira/models/project_project/exporter.py new file mode 100644 index 000000000..e17e3a823 --- /dev/null +++ b/connector_jira/models/project_project/exporter.py @@ -0,0 +1,92 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.addons.component.core import Component +from odoo.addons.component_event import skip_if + + +class JiraProjectProjectListener(Component): + _name = "jira.project.project.listener" + _inherit = ["base.connector.listener"] + _apply_on = ["jira.project.project"] + + @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) + def on_record_create(self, record, fields=None): + if record.sync_action == "export": + record.with_delay(priority=10).export_record(fields=fields) + + @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) + def on_record_write(self, record, fields=None): + if record.sync_action == "export": + record.with_delay(priority=10).export_record(fields=fields) + + +class ProjectProjectListener(Component): + _name = "project.project.listener" + _inherit = ["base.connector.listener"] + _apply_on = ["project.project"] + + @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) + def on_record_write(self, record, fields=None): + if fields == ["jira_bind_ids"] or fields == ["message_follower_ids"]: + # When vals is esb_bind_ids: + # Binding edited from the record's view. When only this field has + # been modified, an other job has already been delayed for the + # binding record so can exit this event early. + + # When vals is message_follower_ids: + # MailThread.message_subscribe() has been called, this + # method does a write on the field message_follower_ids, + # we never want to export that. + return + for binding in record.jira_bind_ids: + if binding.sync_action == "export": + binding.with_delay(priority=10).export_record(fields=fields) + + +class JiraProjectProjectExporter(Component): + _name = "jira.project.project.exporter" + _inherit = ["jira.exporter"] + _apply_on = ["jira.project.project"] + + def _create_project(self, adapter, key, name, template, values): + project = adapter.create( + key=key, + name=name, + template_name=template, + values=values, + ) + return project["projectId"] + + def _create_shared_project(self, adapter, key, name, shared_key, lead): + project = adapter.create_shared( + key=key, + name=name, + shared_key=shared_key, + lead=lead, + ) + return project["projectId"] + + def _update_project(self, adapter, values): + adapter.write(self.external_id, values) + + def _run(self, fields=None): + adapter = self.component(usage="backend.adapter") + + key = self.binding.jira_key + name = self.binding.name[:80] + template = self.binding.project_template + # TODO: add lead + + if self.external_id: + self._update_project(adapter, {"name": name, "key": key}) + else: + if template == "shared": + shared_key = self.binding.project_template_shared + self.external_id = self._create_shared_project( + adapter, key, name, shared_key, None + ) + else: + self.external_id = self._create_project( + adapter, key, name, template, {} + ) diff --git a/connector_jira/models/project_project/project_link_jira.py b/connector_jira/models/project_project/project_link_jira.py new file mode 100644 index 000000000..b8686f907 --- /dev/null +++ b/connector_jira/models/project_project/project_link_jira.py @@ -0,0 +1,156 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import _, api, exceptions, fields, models + +_logger = logging.getLogger(__name__) + + +class ProjectLinkJira(models.TransientModel): + _name = "project.link.jira" + _inherit = ["jira.project.base.mixin", "multi.step.wizard.mixin"] + _description = "Link Project with JIRA" + + project_id = fields.Many2one( + comodel_name="project.project", + name="Project", + required=True, + ondelete="cascade", + default=lambda self: self._default_project_id(), + ) + jira_key = fields.Char( + default=lambda self: self._default_jira_key(), + ) + backend_id = fields.Many2one( + comodel_name="jira.backend", + string="Jira Backend", + required=True, + ondelete="cascade", + default=lambda self: self._default_backend_id(), + ) + jira_project_id = fields.Many2one( + comodel_name="jira.project.project", + ondelete="cascade", + ) + + @api.model + def _default_project_id(self): + return self.env.context.get("active_id") + + @api.model + def _default_jira_key(self): + project_id = self._default_project_id() + if not project_id: + return + project = self.env["project.project"].browse(project_id) + valid = self.env["jira.project.project"]._jira_key_valid + if valid(project.name): + return project.name + + @api.model + def _default_backend_id(self): + backends = self.env["jira.backend"].search([]) + if len(backends) == 1: + return backends.id + + @api.model + def _selection_state(self): + return [ + ("start", "Start"), + ("issue_types", "Issue Types"), + ("export_config", "Export Config."), + ("final", "Final"), + ] + + @api.constrains("jira_key") + def check_jira_key(self): + for record in self: + valid = self.env["jira.project.project"]._jira_key_valid + if not valid(record.jira_key): + raise exceptions.ValidationError( + _("%s is not a valid JIRA Key") % record.jira_key + ) + + def add_all_issue_types(self): + issue_types = self.env["jira.issue.type"].search( + [("backend_id", "=", self.backend_id.id)] + ) + self.sync_issue_type_ids = issue_types.ids + + def state_exit_start(self): + if self.sync_action == "export": + self.add_all_issue_types() + elif self.sync_action == "link": + if not self.jira_project_id: + self._link_binding() + self.state = "issue_types" + + def state_exit_issue_types(self): + if self.sync_action == "export": + self.state = "export_config" + elif self.sync_action == "link": + self._copy_issue_types() + self.state = "final" + + def state_exit_export_config(self): + if not self.jira_project_id: + self._create_export_binding() + self.state = "final" + + def _prepare_base_binding_values(self): + values = { + "backend_id": self.backend_id.id, + "odoo_id": self.project_id.id, + "jira_key": self.jira_key, + } + return values + + def _prepare_export_binding_values(self): + values = self._prepare_base_binding_values() + values.update( + { + "backend_id": self.backend_id.id, + "odoo_id": self.project_id.id, + "sync_action": "export", + "sync_issue_type_ids": [(6, 0, self.sync_issue_type_ids.ids)], + "project_template": self.project_template, + "project_template_shared": self.project_template_shared, + } + ) + return values + + def _create_export_binding(self): + values = self._prepare_export_binding_values() + self.jira_project_id = self.env["jira.project.project"].create(values) + + def _link_binding(self): + with self.backend_id.work_on("jira.project.project") as work: + adapter = work.component(usage="backend.adapter") + with adapter.handle_user_api_errors(): + jira_project = adapter.get(self.jira_key) + self._link_with_jira_project(work, jira_project) + + def _link_with_jira_project(self, work, jira_project): + values = self._prepare_link_binding_values(jira_project) + self.jira_project_id = self.env["jira.project.project"].create(values) + type_binder = work.component(usage="binder", model_name="jira.issue.type") + issue_types = self.env["jira.issue.type"].browse() + for jira_issue_type in jira_project.issueTypes: + issue_types |= type_binder.to_internal(jira_issue_type.id) + self.sync_issue_type_ids = issue_types.ids + + def _prepare_link_binding_values(self, jira_project): + values = self._prepare_base_binding_values() + values.update( + { + "sync_action": self.sync_action, + "external_id": jira_project.id, + "project_type": jira_project.projectTypeKey, + } + ) + return values + + def _copy_issue_types(self): + self.jira_project_id.sync_issue_type_ids = self.sync_issue_type_ids.ids diff --git a/connector_jira/models/project_task/__init__.py b/connector_jira/models/project_task/__init__.py new file mode 100644 index 000000000..fbb9dae9f --- /dev/null +++ b/connector_jira/models/project_task/__init__.py @@ -0,0 +1,5 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common +from . import importer +from . import task_link_jira diff --git a/connector_jira/models/project_task/common.py b/connector_jira/models/project_task/common.py new file mode 100644 index 000000000..4699b0f64 --- /dev/null +++ b/connector_jira/models/project_task/common.py @@ -0,0 +1,268 @@ +# Copyright 2016-2019 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, exceptions, fields, models + +from odoo.addons.component.core import Component + +PROJECT_TASK_READABLE_FIELDS = { + "jira_bind_ids", +} + + +class JiraProjectTask(models.Model): + _name = "jira.project.task" + _inherit = "jira.binding" + _inherits = {"project.task": "odoo_id"} + _description = "Jira Tasks" + + odoo_id = fields.Many2one( + comodel_name="project.task", + string="Task", + required=True, + index=True, + ondelete="restrict", + ) + # As we can have more than one jira binding on a project.project, we store + # to which one a task binding is related. + jira_project_bind_id = fields.Many2one( + comodel_name="jira.project.project", + ondelete="restrict", + ) + jira_key = fields.Char( + string="Key", + readonly=True, + ) + jira_issue_type_id = fields.Many2one( + comodel_name="jira.issue.type", + string="Issue Type", + readonly=True, + ) + jira_epic_link_id = fields.Many2one( + comodel_name="jira.project.task", + string="Epic", + readonly=True, + ) + jira_parent_id = fields.Many2one( + comodel_name="jira.project.task", + string="Parent Issue", + readonly=True, + help="Parent issue when the issue is a subtask. " + "Empty if the type of parent is filtered out " + "of the synchronizations.", + ) + jira_issue_url = fields.Char( + string="JIRA issue", + compute="_compute_jira_issue_url", + ) + + _sql_constraints = [ + ( + "jira_binding_backend_uniq", + "unique(backend_id, odoo_id)", + "A binding already exists for this task and this backend.", + ), + ] + + def _is_linked(self): + return self.mapped("jira_project_bind_id")._is_linked() + + def unlink(self): + if any(self.mapped("external_id")): + raise exceptions.UserError(_("A Jira task cannot be deleted.")) + return super().unlink() + + @api.depends("jira_key") + def _compute_jira_issue_url(self): + """Compute the external URL to JIRA.""" + for record in self: + record.jira_issue_url = record.backend_id.make_issue_url(record.jira_key) + + +class ProjectTask(models.Model): + _inherit = "project.task" + _rec_names_search = ["name", "jira_compound_key"] + + jira_bind_ids = fields.One2many( + comodel_name="jira.project.task", + inverse_name="odoo_id", + copy=False, + string="Task Bindings", + context={"active_test": False}, + ) + jira_issue_type = fields.Char( + compute="_compute_jira_issue_type", + string="JIRA Issue Type", + store=True, + ) + jira_compound_key = fields.Char( + compute="_compute_jira_compound_key", + string="JIRA Key", + store=True, + ) + jira_epic_link_task_id = fields.Many2one( + comodel_name="project.task", + compute="_compute_jira_epic_link_task_id", + string="JIRA Epic", + store=True, + ) + jira_parent_task_id = fields.Many2one( + comodel_name="project.task", + compute="_compute_jira_parent_task_id", + string="JIRA Parent", + store=True, + ) + jira_issue_url = fields.Char( + string="JIRA issue", + compute="_compute_jira_issue_url", + ) + + @property + def SELF_READABLE_FIELDS(self): + return super().SELF_READABLE_FIELDS | PROJECT_TASK_READABLE_FIELDS + + @api.depends("jira_bind_ids.jira_issue_type_id.name") + def _compute_jira_issue_type(self): + for record in self: + types = record.mapped("jira_bind_ids.jira_issue_type_id.name") + record.jira_issue_type = ",".join([t for t in types if t]) + + @api.depends("jira_bind_ids.jira_key") + def _compute_jira_compound_key(self): + for record in self: + keys = record.mapped("jira_bind_ids.jira_key") + record.jira_compound_key = ",".join([k for k in keys if k]) + + @api.depends("jira_bind_ids.jira_epic_link_id.odoo_id") + def _compute_jira_epic_link_task_id(self): + for record in self: + tasks = record.mapped("jira_bind_ids.jira_epic_link_id.odoo_id") + if len(tasks) == 1: + record.jira_epic_link_task_id = tasks + + @api.depends("jira_bind_ids.jira_parent_id.odoo_id") + def _compute_jira_parent_task_id(self): + for record in self: + tasks = record.mapped("jira_bind_ids.jira_parent_id.odoo_id") + if len(tasks) == 1: + record.jira_parent_task_id = tasks + + @api.depends("jira_bind_ids.jira_key") + def _compute_jira_issue_url(self): + """Compute the external URL to JIRA. + + We assume that we have only one external record. + """ + for record in self: + if not record.jira_bind_ids: + record.jira_issue_url = False + continue + main_binding = record.jira_bind_ids[0] + record.jira_issue_url = main_binding.jira_issue_url + + @api.depends("jira_compound_key") + def _compute_display_name(self): + res = super()._compute_display_name() + + for rec in self: + if not rec.jira_compound_key: + continue + + rec.display_name = f"[{rec.jira_compound_key}] {rec.display_name}" + + return res + + @api.model + def _get_connector_jira_fields(self): + return [ + "jira_bind_ids", + "name", + "date_deadline", + "user_id", + "description", + "active", + "project_id", + "allocated_hours", + "stage_id", + ] + + @api.model + def _connector_jira_create_validate(self, vals): + ProjectProject = self.env["project.project"] + project_id = vals.get("project_id") + if project_id: + project_id = ProjectProject.sudo().browse(project_id) + if ( + not self.env.context.get("connector_jira") + and project_id.mapped("jira_bind_ids")._is_linked() + ): + raise exceptions.UserError( + _("Task can not be created in project linked to JIRA!") + ) + + def _connector_jira_write_validate(self, vals): + if ( + not self.env.context.get("connector_jira") + and self.mapped("jira_bind_ids")._is_linked() + ): + fields = list(vals.keys()) + self._update_cache(vals) + new_values = self._convert_to_write( + vals, + ) + for old_values in self.read(fields, load="_classic_write"): + old_values = self._convert_to_write( + old_values, + ) + for field in self._get_connector_jira_fields(): + if field not in fields: + continue + if new_values[field] == old_values[field]: + continue + raise exceptions.UserError( + _("Task linked to JIRA Issue can not be modified!") + ) + + def _connector_jira_unlink_validate(self): + if ( + not self.env.context.get("connector_jira") + and self.mapped("jira_bind_ids")._is_linked() + ): + raise exceptions.UserError( + _("Task linked to JIRA Issue can not be deleted!") + ) + + @api.model + def create(self, vals): + self._connector_jira_create_validate(vals) + return super().create(vals) + + def write(self, vals): + self._connector_jira_write_validate(vals) + return super().write(vals) + + def unlink(self): + self._connector_jira_unlink_validate() + return super().unlink() + + +class TaskAdapter(Component): + _name = "jira.project.task.adapter" + _inherit = ["jira.webservice.adapter"] + _apply_on = ["jira.project.task"] + + def read(self, id_, fields=None): + # pylint: disable=W8106 + return self.get(id_, fields=fields).raw + + def get(self, id_, fields=None): + with self.handle_404(): + return self.client.issue(id_, fields=fields, expand=["renderedFields"]) + + def search(self, jql): + # we need to have at least one field which is not 'id' or 'key' + # due to this bug: https://github.com/pycontribs/jira/pull/289 + fields = "id,updated" + issues = self.client.search_issues(jql, fields=fields, maxResults=None) + return [issue.id for issue in issues] diff --git a/connector_jira/models/project_task/importer.py b/connector_jira/models/project_task/importer.py new file mode 100644 index 000000000..423906b6f --- /dev/null +++ b/connector_jira/models/project_task/importer.py @@ -0,0 +1,262 @@ +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import _ + +from odoo.addons.component.core import Component +from odoo.addons.connector.components.mapper import mapping +from odoo.addons.connector.exception import MappingError + + +class ProjectTaskMapper(Component): + _name = "jira.project.task.mapper" + _inherit = "jira.import.mapper" + _apply_on = ["jira.project.task"] + + direct = [ + ("key", "jira_key"), + ] + + from_fields = [ + ("duedate", "date_deadline"), + ] + + @mapping + def from_attributes(self, record): + return self.component(usage="map.from.attrs").values(record, self) + + @mapping + def name(self, record): + # On an Epic, you have 2 fields: + + # a field like 'customfield_10003' labelled "Epic Name" + # a field 'summary' labelled "Sumarry" + + # The other types of tasks have only the 'summary' field, the other is + # empty. To simplify, we always try to read the Epic Name, which + # will always be empty for other types. + epic_name_field = self.backend_record.epic_name_field_name + name = False + if epic_name_field: + name = record["fields"].get(epic_name_field) + if not name: + name = record["fields"]["summary"] + return {"name": name} + + @mapping + def issue_type(self, record): + binder = self.binder_for("jira.issue.type") + jira_type_id = record["fields"]["issuetype"]["id"] + binding = binder.to_internal(jira_type_id) + return {"jira_issue_type_id": binding.id} + + @mapping + def assignee(self, record): + assignee = record["fields"].get("assignee") + if not assignee: + return {"user_ids": False} + jira_key = assignee["key"] + binder = self.binder_for("jira.res.users") + user = binder.to_internal(jira_key, unwrap=True) + if not user: + email = assignee["emailAddress"] + raise MappingError( + _( + 'No user found with login "%(jira_key)s" or email "%(email)s".' + "You must create a user or link it manually if the " + "login/email differs.", + jira_key=jira_key, + email=email, + ) + ) + return {"user_ids": user} + + @mapping + def description(self, record): + return {"description": record["renderedFields"]["description"]} + + @mapping + def project(self, record): + binder = self.binder_for("jira.project.project") + project = binder.unwrap_binding(self.options.project_binding) + values = { + "project_id": project.id, + "company_id": project.company_id.id, + "jira_project_bind_id": self.options.project_binding.id, + } + if not project.active: + values["active"] = False + return values + + @mapping + def epic(self, record): + if not self.options.jira_epic: + return {} + jira_epic_id = self.options.jira_epic["id"] + binder = self.binder_for("jira.project.task") + binding = binder.to_internal(jira_epic_id) + return {"jira_epic_link_id": binding.id} + + @mapping + def parent(self, record): + jira_parent = record["fields"].get("parent") + if not jira_parent: + return {} + jira_parent_id = jira_parent["id"] + binder = self.binder_for("jira.project.task") + binding = binder.to_internal(jira_parent_id) + return {"jira_parent_id": binding.id} + + @mapping + def backend_id(self, record): + return {"backend_id": self.backend_record.id} + + @mapping + def status(self, record): + status = record["fields"].get("status", {}) + status_name = status.get("name") + if not status_name: + return {"stage_id": False} + project_binder = self.binder_for("jira.project.project") + project_id = project_binder.unwrap_binding(self.options.project_binding) + stage = self.env["project.task.type"].search( + [("name", "=", status_name), ("project_ids", "=", project_id.id)], + limit=1, + ) + return {"stage_id": stage.id} + + @mapping + def time_estimate(self, record): + original_estimate = record["fields"].get("timeoriginalestimate") + if not original_estimate: + return {"allocated_hours": False} + return {"allocated_hours": float(original_estimate) / 3600.0} + + def finalize(self, map_record, values): + values = values.copy() + if values.get("odoo_id"): + # If a mapping binds the issue to an existing odoo + # task, we should not change the project. + # It's not only unexpected, but would fail as soon + # as we have invoiced timesheet lines on the task. + values.pop("project_id") + return values + + +class ProjectTaskBatchImporter(Component): + """Import the Jira tasks + + For every id in in the list of tasks, a delayed job is created. + Import from a date + """ + + _name = "jira.project.task.batch.importer" + _inherit = ["jira.timestamp.batch.importer"] + _apply_on = ["jira.project.task"] + + +class ProjectTaskProjectMatcher(Component): + _name = "jira.task.project.matcher" + _inherit = ["jira.base"] + _usage = "jira.task.project.matcher" + + def find_project_binding(self, jira_task_data, unwrap=False): + jira_project_id = jira_task_data["fields"]["project"]["id"] + binder = self.binder_for("jira.project.project") + return binder.to_internal(jira_project_id, unwrap=unwrap) + + def fallback_project_for_worklogs(self): + return self.backend_record.worklog_fallback_project_id + + +class ProjectTaskImporter(Component): + _name = "jira.project.task.importer" + _inherit = ["jira.importer"] + _apply_on = ["jira.project.task"] + + def __init__(self, work_context): + super().__init__(work_context) + self.jira_epic = None + self.project_binding = None + + def _get_external_data(self): + """Return the raw Jira data for ``self.external_id``""" + result = super()._get_external_data() + epic_field_name = self.backend_record.epic_link_field_name + if epic_field_name: + issue_adapter = self.component( + usage="backend.adapter", model_name="jira.project.task" + ) + epic_key = result["fields"][epic_field_name] + if epic_key: + self.jira_epic = issue_adapter.read(epic_key) + return result + + def _find_project_binding(self): + matcher = self.component(usage="jira.task.project.matcher") + self.project_binding = matcher.find_project_binding(self.external_record) + + def _is_issue_type_sync(self): + project_binding = self.project_binding + task_sync_type_id = self.external_record["fields"]["issuetype"]["id"] + task_sync_type_binder = self.binder_for("jira.issue.type") + task_sync_type_binding = task_sync_type_binder.to_internal( + task_sync_type_id, + ) + return task_sync_type_binding.is_sync_for_project(project_binding) + + def _create_data(self, map_record, **kwargs): + return super()._create_data( + map_record, + jira_epic=self.jira_epic, + project_binding=self.project_binding, + **kwargs, + ) + + def _update_data(self, map_record, **kwargs): + return super()._update_data( + map_record, + jira_epic=self.jira_epic, + project_binding=self.project_binding, + **kwargs, + ) + + def _import(self, binding, **kwargs): + # called at the beginning of _import because we must be sure + # that dependencies are there (project and issue type) + self._find_project_binding() + if not self._is_issue_type_sync(): + return _("Project or issue type is not synchronized.") + return super()._import(binding, **kwargs) + + def _import_dependency_assignee(self): + jira_assignee = self.external_record["fields"].get("assignee") or {} + jira_key = jira_assignee.get("key") + self._import_dependency(jira_key, "jira.res.users", record=jira_assignee) + + def _import_dependency_issue_type(self): + jira_issue_type = self.external_record["fields"]["issuetype"] + jira_issue_type_id = jira_issue_type["id"] + self._import_dependency( + jira_issue_type_id, "jira.issue.type", record=jira_issue_type + ) + + def _import_dependency_parent(self): + jira_parent = self.external_record["fields"].get("parent") + if jira_parent: + jira_parent_id = jira_parent["id"] + self._import_dependency(jira_parent_id, "jira.project.task") + + def _import_dependency_epic(self): + if self.jira_epic: + self._import_dependency( + self.jira_epic["id"], "jira.project.task", record=self.jira_epic + ) + + def _import_dependencies(self): + """Import the dependencies for the record""" + self._import_dependency_assignee() + self._import_dependency_issue_type() + self._import_dependency_parent() + self._import_dependency_epic() diff --git a/connector_jira/models/project_task/task_link_jira.py b/connector_jira/models/project_task/task_link_jira.py new file mode 100644 index 000000000..dde32f028 --- /dev/null +++ b/connector_jira/models/project_task/task_link_jira.py @@ -0,0 +1,93 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class TaskLinkJira(models.TransientModel): + _name = "task.link.jira" + _inherit = "multi.step.wizard.mixin" + _description = "Link Task with JIRA" + + task_id = fields.Many2one( + comodel_name="project.task", + name="Task", + required=True, + ondelete="cascade", + ) + jira_key = fields.Char( + string="JIRA Key", + required=True, + ) + backend_id = fields.Many2one( + comodel_name="jira.backend", + string="Jira Backend", + required=True, + ondelete="cascade", + domain="[('id', 'in', linked_backend_ids)]", + ) + linked_backend_ids = fields.Many2many( + comodel_name="jira.backend", + ) + jira_task_id = fields.Many2one( + comodel_name="jira.project.task", + ondelete="cascade", + ) + + @api.model + def _selection_state(self): + return [ + ("start", "Start"), + ("final", "Final"), + ] + + @api.model + def default_get(self, fields): + values = super().default_get(fields) + context = self.env.context + if context.get("active_model") == "project.task" and context.get("active_id"): + task = self.env["project.task"].browse(context["active_id"]) + project_linked_backends = task.mapped("project_id.jira_bind_ids.backend_id") + values.update( + { + "task_id": task.id, + "linked_backend_ids": [(6, 0, project_linked_backends.ids)], + } + ) + if len(project_linked_backends) == 1: + values["backend_id"] = project_linked_backends.id + return values + + def state_exit_start(self): + if not self.jira_task_id: + self._link_binding() + self.state = "final" + + def _link_binding(self): + with self.backend_id.work_on("jira.project.task") as work: + adapter = work.component(usage="backend.adapter") + with adapter.handle_user_api_errors(): + jira_task = adapter.get(self.jira_key) + self._link_with_jira_task(work, jira_task) + self._run_import_jira_task(work, jira_task) + + def _link_with_jira_task(self, work, jira_task): + values = self._prepare_link_binding_values(jira_task) + self.jira_task_id = self.env["jira.project.task"].create(values) + + def _run_import_jira_task(self, work, jira_task): + importer = work.component(usage="record.importer") + importer.run(jira_task.id, force=True, record=jira_task.raw) + + def _prepare_link_binding_values(self, jira_task): + values = { + "backend_id": self.backend_id.id, + "odoo_id": self.task_id.id, + "jira_key": self.jira_key, + "external_id": jira_task.id, + } + return values diff --git a/connector_jira/models/queue_job/__init__.py b/connector_jira/models/queue_job/__init__.py new file mode 100644 index 000000000..63602330c --- /dev/null +++ b/connector_jira/models/queue_job/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common diff --git a/connector_jira/models/queue_job/common.py b/connector_jira/models/queue_job/common.py new file mode 100644 index 000000000..81d826c70 --- /dev/null +++ b/connector_jira/models/queue_job/common.py @@ -0,0 +1,38 @@ +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import models + + +class QueueJob(models.Model): + _inherit = "queue.job" + + def related_action_jira_link(self): + """Open a jira url for an issue""" + self.ensure_one() + + model_name = self.model_name + # only tested on issues so far + issue_models = ("jira.project.task", "jira.account.analytic.line") + if model_name not in issue_models: + return + + backend = self.args[0] + jira_id = self.args[1] + + # Get the key of the issue to generate the URI. + # JIRA doesn't have an URI to show an issue by id. + # And at this point, we may be importing a Jira record + # that is not yet imported in Odoo or fails to import, + # so we cannot use the URL computed on the Jira binding. + with backend.work_on("jira.project.task") as work: + adapter = work.component(usage="backend.adapter") + with adapter.handle_user_api_errors(): + jira_record = adapter.get(jira_id) + jira_key = jira_record.key + + return { + "type": "ir.actions.act_url", + "target": "new", + "url": backend.make_issue_url(jira_key), + } diff --git a/connector_jira/models/res_users/__init__.py b/connector_jira/models/res_users/__init__.py new file mode 100644 index 000000000..ea8197b11 --- /dev/null +++ b/connector_jira/models/res_users/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common +from . import importer diff --git a/connector_jira/models/res_users/common.py b/connector_jira/models/res_users/common.py new file mode 100644 index 000000000..a309d7d0a --- /dev/null +++ b/connector_jira/models/res_users/common.py @@ -0,0 +1,165 @@ +# Copyright 2016-2022 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from itertools import groupby + +from odoo import _, exceptions, fields, models + +from odoo.addons.component.core import Component + + +class JiraResUsers(models.Model): + _name = "jira.res.users" + _inherit = "jira.binding" + _inherits = {"res.users": "odoo_id"} + _description = "Jira User" + + odoo_id = fields.Many2one( + comodel_name="res.users", + string="User", + required=True, + index=True, + ondelete="restrict", + ) + + +class ResUsers(models.Model): + _inherit = "res.users" + + jira_bind_ids = fields.One2many( + comodel_name="jira.res.users", + inverse_name="odoo_id", + copy=False, + string="User Bindings", + context={"active_test": False}, + ) + + def button_link_with_jira(self): + self.ensure_one() + self.link_with_jira(raise_if_mismatch=True) + if not self.jira_bind_ids: + raise exceptions.UserError(_("No JIRA user could be found")) + + def link_with_jira(self, backends=None, raise_if_mismatch=False): + if backends is None: + backends = self.env["jira.backend"].search([]) + result = {} + for backend in backends: + bknd_result = { + "success": [], + "error": [], + } + with backend.work_on("jira.res.users") as work: + binder = work.component(usage="binder") + adapter = work.component(usage="backend.adapter") + for user in self: + if binder.to_external(user, wrap=True): + continue + jira_user = None + for resolve_by in backend.get_user_resolution_order(): + resolve_by_key = resolve_by + resolve_by_value = user[resolve_by] + jira_user = adapter.search(fragment=resolve_by_value) + if jira_user: + break + if not jira_user: + continue + elif len(jira_user) > 1: + if raise_if_mismatch: + raise exceptions.UserError( + _( + 'Several users found with "%(resolve_by_key)s"' + 'set to "%(resolve_by_value)s". ' + "Set it manually.", + resolve_by_key=resolve_by_key, + resolve_by_value=resolve_by_value, + ) + ) + bknd_result["error"].append( + { + "key": resolve_by_key, + "value": resolve_by_value, + "error": "multiple_found", + "detail": [x.key for x in jira_user], + } + ) + continue + jira_user = jira_user[0] + existing = ( + self.env["jira.res.users"] + .with_context( + active_test=False, + ) + .search( + [ + ("backend_id", "=", backend.id), + ("external_id", "=", jira_user.key), + ("odoo_id", "!=", user.id), + ] + ) + ) + if existing: + bknd_result["error"].append( + { + "key": resolve_by_key, + "value": resolve_by_value, + "error": "other_user_bound", + "detail": f"linked with {existing.login}", + } + ) + continue + try: + binding = self.env["jira.res.users"].create( + {"backend_id": backend.id, "odoo_id": user.id} + ) + binder.bind(jira_user.key, binding) + bknd_result["success"].append( + { + "key": "login", + "value": user.login, + "detail": jira_user.key, + } + ) + except Exception as err: + bknd_result["error"].append( + { + "key": "login", + "value": user.login, + "error": "binding_error", + "detail": str(err), + } + ) + result[backend] = bknd_result + return result + + +class UserAdapter(Component): + _name = "jira.res.users.adapter" + _inherit = ["jira.webservice.adapter"] + _apply_on = ["jira.res.users"] + + def read(self, id_): + # pylint: disable=W8106 + with self.handle_404(): + return self.client.user(id_).raw + + def search(self, fragment=None): + """Search users + + :param fragment: a string to match usernames, name or email against. + """ + users = self.client.search_users( + fragment, maxResults=None, includeActive=True, includeInactive=True + ) + + # User 'key' is unique and if same key appears several times, it means + # that same user is present in multiple User Directories + users = list( + map( + lambda group: list(group[1])[0], + groupby(users, key=lambda user: user.key), + ) + ) + + return users diff --git a/connector_jira/models/res_users/importer.py b/connector_jira/models/res_users/importer.py new file mode 100644 index 000000000..4be76fecc --- /dev/null +++ b/connector_jira/models/res_users/importer.py @@ -0,0 +1,45 @@ +# Copyright 2016-2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import _ + +from odoo.addons.component.core import Component +from odoo.addons.queue_job.exception import JobError + + +class UserImporter(Component): + _name = "jira.res.users.importer" + _inherit = ["jira.importer"] + _apply_on = ["jira.res.users"] + + def _import(self, binding): + record = self.external_record + jira_key = self.external_id + binder = self.binder_for("jira.res.users") + user = binder.to_internal(jira_key, unwrap=True) + if not user: + email = record["emailAddress"] + user = self.env["res.users"].search( + ["|", ("login", "=", jira_key), ("email", "=", email)], + ) + if len(user) > 1: + raise JobError( + _( + "Several users found (%(login)s) for jira account" + "%(jira_key)s (%(email)s)." + " Please link it manually from the Odoo user's form.", + login=user.mapped("login"), + jira_key=jira_key, + email=email, + ) + ) + elif not user: + raise JobError( + _( + "No user found for jira account %(jira_key)s (%(email)s)." + " Please link it manually from the Odoo user's form.", + jira_key=jira_key, + email=email, + ) + ) + return user.link_with_jira(backends=self.backend_record) diff --git a/connector_jira/models/timesheets_analysis_report/__init__.py b/connector_jira/models/timesheets_analysis_report/__init__.py new file mode 100644 index 000000000..63602330c --- /dev/null +++ b/connector_jira/models/timesheets_analysis_report/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import common diff --git a/connector_jira/models/timesheets_analysis_report/common.py b/connector_jira/models/timesheets_analysis_report/common.py new file mode 100644 index 000000000..5f749eead --- /dev/null +++ b/connector_jira/models/timesheets_analysis_report/common.py @@ -0,0 +1,23 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class TimesheetsAnalysisReport(models.Model): + _inherit = "timesheets.analysis.report" + + jira_issue_key = fields.Char("Original Task Key", readonly=True) + jira_epic_issue_key = fields.Char("Original JIRA Epic Key", readonly=True) + jira_issue_type_id = fields.Many2one( + comodel_name="jira.issue.type", + string="Original Issue Type", + readonly=True, + ) + + @api.model + def _select(self): + res = super()._select() + res += ", A.jira_issue_key AS jira_issue_key" + res += ", A.jira_epic_issue_key AS jira_epic_issue_key" + res += ", A.jira_issue_type_id AS jira_issue_type_id" + return res diff --git a/connector_jira/pyproject.toml b/connector_jira/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/connector_jira/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/connector_jira/readme/CONTRIBUTORS.md b/connector_jira/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..5951c03f5 --- /dev/null +++ b/connector_jira/readme/CONTRIBUTORS.md @@ -0,0 +1,24 @@ +- [Camptocamp](https://camptocamp.com): + + - Damien Crier + - Thierry Ducrest + - Tonow-c2c + - Simone Orsi \<\> + - Timon Tschanz \<\> + - jcoux \<\> + - Patrick Tombez \<\> + - Guewen Baconnier \<\> + - Akim Juillerat \<\> + +- [CorporateHub](https://corporatehub.eu/) + + - Alexey Pelykh \<\> + +- [Trobz](https://trobz.com): + + > - Son Ho \<\> + +- [Avoin.Systems](https://avoin.systems): + + > - Nedas Žilinskas \<\> + > - Miku Laitinen \<\> diff --git a/connector_jira/readme/DESCRIPTION.md b/connector_jira/readme/DESCRIPTION.md new file mode 100644 index 000000000..f4bd376ad --- /dev/null +++ b/connector_jira/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module adds Jira synchronization feature. diff --git a/connector_jira/readme/INSTALL.md b/connector_jira/readme/INSTALL.md new file mode 100644 index 000000000..bec56a1ff --- /dev/null +++ b/connector_jira/readme/INSTALL.md @@ -0,0 +1,90 @@ +You need the following Python packages: + +- requests +- jira +- oauthlib +- requests-oauthlib +- requests-toolbelt +- PyJWT +- cryptography + +Once the addon is installed, follow these steps: + +## Job Queue + +In `odoo.conf`, configure similarly: + +``` +[queue_job] +channels = root:1,root.connector_jira.import:2 +``` + +## Backend + +1. Open the menu Connectors \> Jira \> Backends +2. Create a new Jira Backend + - Put the name you want + - Set the URL of your Jira, like + - You can also select the company where records will be created and + the default project template used when Odoo will create the + projects in Jira +3. Save and continue with the Authentication + +## Authentication of Backend (OAuth / System-level) + +1. On the created backend, click on the Authenticate button, a popup + with keys will appear, keep these open in a tab +2. Open Jira and go to System \> Applications \> Application links +3. Enter the name of the application, example: odoo, and click on + "Create new link" +4. In the popup, set the URL where JIRA can reach Odoo. Jira might + complain and reopen the popup, confirm it again and a new popup + appears +5. In the new popup, do not set anything in the fields and click on + Continue +6. The link should be created now, edit it with the pen on the right +7. Open the Incoming Authentication panel, be warned that it may take + some time to load +8. Copy-paste the consumer key and public key from Odoo to the Jira + link's Incoming Authentication. Set a consumer name (e.g. odoo) and + leave the consumer callback url and 2 legged auth blank. +9. Click on save at the bottom of the form (you need to scroll) +10. Back on Odoo, click on Continue +11. A link is displayed, click on it - you may need to login again - and + click on "Allow". +12. Back on Odoo again, click on Continue +13. Authentication is complete! + +## Authentication of Backend (Basic / User-level) + +You can use a user's username and API token as an access method. This is useful +if you don't have administrator's access to the accessed Jira. + +1. On the created backend, select "User-level" as the Access Method +2. Type your Jira username / email to the Username field +3. Open Jira and click your avatar in the top right corner > Account settings +4. Go to Security > Create and manage API tokens > Create API token +5. Enter the name of the API token (eg. "Odoo") +6. Copy-paste the generated API token from Jira to the User Token field. +7. Click on the Authenticate button +8. The connection will be checked + +## Configuration of the Backend + +**Setup the webhooks** + +It is advised to setup the webhooks so the synchronizations are in +realtime. + +1. On the Jira Backend, set the "Base Odoo URL for Webhooks" to URL of + Odoo, it must be reachable from Jira. +2. Click on "Install Webhooks" + +**Configure the Epic Link** + +If you use Epics, you need to click on "Configure Epic Link", Odoo will +search the name of the custom field used for the Epic Link. + +**Configuration done** + +You can now click on the button "Configuration Done". diff --git a/connector_jira/readme/ROADMAP.md b/connector_jira/readme/ROADMAP.md new file mode 100644 index 000000000..794d8a6a3 --- /dev/null +++ b/connector_jira/readme/ROADMAP.md @@ -0,0 +1,20 @@ +- If an odoo user has no linked employee, worklogs will still be + imported but with no employee. + +**Allowing several bindings per project** + +The design evolved to allow more than one Jira binding per project in +Odoo. This conveniently allows to fetch tasks and worklogs for many +projects in Jira, which will be tracked in only one project in Odoo. + +In order to push data to Jira, we have to apply restrictions on these +"multi-bindings" projects, as we cannot know to which binding data must +be pushed: + +- Not more than one project (can be zero) can have a "Sync Action" set + to "Export to JIRA". As this configuration pushes the name and key of + the project to Jira, we cannot push it to more than one project. +- If we implement push of tasks to Jira, we'll have to add a way to + restrict or choose to which project we push the task, this is not + supported yet (for instance, add a Boolean "export tasks" on the + project binding, or explicitly select the target binding on the task) diff --git a/connector_jira/readme/USAGE.md b/connector_jira/readme/USAGE.md new file mode 100644 index 000000000..adc6ae464 --- /dev/null +++ b/connector_jira/readme/USAGE.md @@ -0,0 +1,53 @@ +The tasks and worklogs are always imported from JIRA to Odoo, there is +no synchronization in the other direction. + +## Initial synchronizations + +You can already select the "Imports" tab in the Backend and click on +"Link users" and "Import issue types". The users will be matched either +by login or by email. + +## Create and export a project + +Projects can be created in Odoo and exported to Jira. You can then +create a project, and use the action "Link with JIRA" and use the +"Export to JIRA" action. + +When you choose to export a project to JIRA, if you change the name or +the key of the project, the new values will be pushed to JIRA. + +## Link a project with JIRA + +If you already have a project on JIRA or prefer to create it first on +JIRA, you can link an Odoo project. Use the "Link with JIRA" action on +the project and select the "Link with JIRA" action. + +This action establish the link, then changes of the name or the key on +either side are not pushed. + +## Issue Types on Projects + +When you link a project, you have to select which issue types are +synchronized. Only tasks of the selected types will be created in Odoo. + +If a JIRA worklog is added to a type of issue that is not synchronized, +will attach to the closest task following these rules: + +- if a subtask, find the parent task +- if no parent task, find the epic task (only if it is on the same + project) +- if no epic, attach to the project without being linked to a task + +## Change synchronization configuration on a project + +If you want to change the configuration of a project, such as which +issue types are synchronized, you can open the "Connector" tab in the +project settings and edit the "binding" with the backend. + +## Synchronize tasks and worklogs + +If the webhooks are active, as soon as they are created in Jira they +should appear in Odoo. If they are not active, you can open the Jira +Backend and run the synchronizations manually, or activate the Scheduled +Actions to run the batch imports. It is important to select the issue +types so don't miss this step (need improvement). diff --git a/connector_jira/security/ir.model.access.csv b/connector_jira/security/ir.model.access.csv new file mode 100644 index 000000000..31a4ac302 --- /dev/null +++ b/connector_jira/security/ir.model.access.csv @@ -0,0 +1,28 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_jira_backend","jira_backend connector manager","model_jira_backend","connector.group_connector_manager",1,1,1,1 +"access_jira_backend_user","jira_backend user","model_jira_backend","base.group_user",1,0,0,0 +"access_jira_backend_timestamp_user","jira_backend_timestamp user","model_jira_backend_timestamp","base.group_user",1,0,0,0 +"access_jira_backend_timestamp","jira_backend_timestamp connector manager","model_jira_backend_timestamp","connector.group_connector_manager",1,1,1,1 +"access_jira_project_project","jira_project_project connector manager","model_jira_project_project","connector.group_connector_manager",1,1,1,1 +"access_jira_project_project_manager","jira_project_project manager","model_jira_project_project","base.group_user",1,0,0,0 +"access_jira_project_project_portal","jira_project_project portal","model_jira_project_project","base.group_portal",1,0,0,0 +"access_jira_project_project_user","jira_project_project user","model_jira_project_project","project.group_project_manager",1,1,1,1 +"access_jira_project_task","jira_project_task connector manager","model_jira_project_task","connector.group_connector_manager",1,1,1,1 +"access_jira_project_task_user","jira_project_task user","model_jira_project_task","base.group_user",1,0,0,0 +"access_jira_project_task_portal","jira_project_task portal","model_jira_project_task","base.group_portal",1,0,0,0 +"access_jira_project_task_manager","jira_project_task manager","model_jira_project_task","project.group_project_manager",1,1,1,1 +"access_jira_res_users","jira_res_users connector manager","model_jira_res_users","connector.group_connector_manager",1,1,1,1 +"access_jira_res_users_user","jira_res_users user","model_jira_res_users","base.group_user",1,0,0,0 +"access_jira_res_users_manager","jira_res_users manager","model_jira_res_users","project.group_project_manager",1,1,1,1 +"access_jira_issue_type","jira_issue_type connector manager","model_jira_issue_type","connector.group_connector_manager",1,1,1,1 +"access_jira_issue_type_user","jira_issue_type user","model_jira_issue_type","base.group_user",1,0,0,0 +"access_jira_account_analytic_line","jira_account_analytic_line connector manager","model_jira_account_analytic_line","connector.group_connector_manager",1,1,1,1 +"access_jira_account_analytic_line_manager","jira_account_analytic_line manager","model_jira_account_analytic_line","base.group_user",1,0,0,0 +"access_project_link_jira_manager","access_project_link_jira manager","connector_jira.model_project_link_jira","project.group_project_manager",1,1,1,1 +"access_project_link_jira","access_project_link_jira user",connector_jira.model_project_link_jira,base.group_user,1,0,0,0 +"access_task_link_jira_task_manager","access_task_link_jira manager","connector_jira.model_task_link_jira","connector.group_connector_manager",1,1,1,1 +"access_task_link_jira","access_task_link_jira user","connector_jira.model_task_link_jira",base.group_user,1,0,0,0 +"access_jira_backend_auth_manager","access_jira_backend_auth manager","connector_jira.model_jira_backend_auth","connector.group_connector_manager",1,1,1,1 +"access_jira_backend_auth","access_jira_backend_auth","connector_jira.model_jira_backend_auth","base.group_user",1,0,0,0 +"access_jira_account_analytic_line_import_manager","access_jira_account_analytic_line_import","connector_jira.model_jira_account_analytic_line_import","connector.group_connector_manager",1,1,1,1 +"access_jira_account_analytic_line_import","access_jira_account_analytic_line_import","connector_jira.model_jira_account_analytic_line_import","base.group_user",1,0,0,0 diff --git a/connector_jira/security/ir_rule.xml b/connector_jira/security/ir_rule.xml new file mode 100644 index 000000000..b2e38b26c --- /dev/null +++ b/connector_jira/security/ir_rule.xml @@ -0,0 +1,34 @@ + + + + + Project/Task (Jira): portal users: portal user can edit with project sharing feature + + 0 + [ + ('project_id.privacy_visibility', '=', 'portal'), + ('active', '=', True), + '|', + ('project_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + ('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + ('project_id.collaborator_ids.partner_id', 'in', [user.partner_id.id]), + ] + + + + + + + + + Project (Jira): portal users: portal and following + + [ + '&', + ('privacy_visibility', '=', 'portal'), + ('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + ] + + + + diff --git a/connector_jira/static/description/icon.png b/connector_jira/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/connector_jira/static/description/icon.png differ diff --git a/connector_jira/static/description/index.html b/connector_jira/static/description/index.html new file mode 100644 index 000000000..82ec975d8 --- /dev/null +++ b/connector_jira/static/description/index.html @@ -0,0 +1,626 @@ + + + + + + +JIRA Connector + + + +
+

JIRA Connector

+ + +

Beta License: AGPL-3 OCA/connector-jira Translate me on Weblate Try me on Runboat

+

This module adds Jira synchronization feature.

+

Table of contents

+ +
+

Installation

+

You need the following Python packages:

+
    +
  • requests
  • +
  • jira
  • +
  • oauthlib
  • +
  • requests-oauthlib
  • +
  • requests-toolbelt
  • +
  • PyJWT
  • +
  • cryptography
  • +
+

Once the addon is installed, follow these steps:

+
+

Job Queue

+

In odoo.conf, configure similarly:

+
+[queue_job]
+channels = root:1,root.connector_jira.import:2
+
+
+
+

Backend

+
    +
  1. Open the menu Connectors > Jira > Backends
  2. +
  3. Create a new Jira Backend
      +
    • Put the name you want
    • +
    • Set the URL of your Jira, like https://jira.example.com
    • +
    • You can also select the company where records will be created and +the default project template used when Odoo will create the +projects in Jira
    • +
    +
  4. +
  5. Save and continue with the Authentication
  6. +
+
+
+

Authentication of Backend

+
    +
  1. On the created backend, click on the Authenticate button, a popup +with keys will appear, keep these open in a tab
  2. +
  3. Open Jira and go to System > Applications > Application links
  4. +
  5. Enter the name of the application, example: odoo, and click on +“Create new link”
  6. +
  7. In the popup, set the URL where JIRA can reach Odoo. Jira might +complain and reopen the popup, confirm it again and a new popup +appears
  8. +
  9. In the new popup, do not set anything in the fields and click on +Continue
  10. +
  11. The link should be created now, edit it with the pen on the right
  12. +
  13. Open the Incoming Authentication panel, be warned that it may take +some time to load
  14. +
  15. Copy-paste the consumer key and public key from Odoo to the Jira +link’s Incoming Authentication. Set a consumer name (e.g. odoo) and +leave the consumer callback url and 2 legged auth blank.
  16. +
  17. Click on save at the bottom of the form (you need to scroll)
  18. +
  19. Back on Odoo, click on Continue
  20. +
  21. A link is displayed, click on it - you may need to login again - and +click on “Allow”.
  22. +
  23. Back on Odoo again, click on Continue
  24. +
  25. Authentication is complete!
  26. +
+
+
+

Configuration of the Backend

+

Setup the webhooks

+

It is advised to setup the webhooks so the synchronizations are in +realtime.

+
    +
  1. On the Jira Backend, set the “Base Odoo URL for Webhooks” to URL of +Odoo, it must be reachable from Jira.
  2. +
  3. Click on “Install Webhooks”
  4. +
+

Configure the Epic Link

+

If you use Epics, you need to click on “Configure Epic Link”, Odoo will +search the name of the custom field used for the Epic Link.

+

Configuration done

+

You can now click on the button “Configuration Done”.

+
+
+
+

Usage

+

The tasks and worklogs are always imported from JIRA to Odoo, there is +no synchronization in the other direction.

+
+

Initial synchronizations

+

You can already select the “Imports” tab in the Backend and click on +“Link users” and “Import issue types”. The users will be matched either +by login or by email.

+
+
+

Create and export a project

+

Projects can be created in Odoo and exported to Jira. You can then +create a project, and use the action “Link with JIRA” and use the +“Export to JIRA” action.

+

When you choose to export a project to JIRA, if you change the name or +the key of the project, the new values will be pushed to JIRA.

+
+ +
+

Issue Types on Projects

+

When you link a project, you have to select which issue types are +synchronized. Only tasks of the selected types will be created in Odoo.

+

If a JIRA worklog is added to a type of issue that is not synchronized, +will attach to the closest task following these rules:

+
    +
  • if a subtask, find the parent task
  • +
  • if no parent task, find the epic task (only if it is on the same +project)
  • +
  • if no epic, attach to the project without being linked to a task
  • +
+
+
+

Change synchronization configuration on a project

+

If you want to change the configuration of a project, such as which +issue types are synchronized, you can open the “Connector” tab in the +project settings and edit the “binding” with the backend.

+
+
+

Synchronize tasks and worklogs

+

If the webhooks are active, as soon as they are created in Jira they +should appear in Odoo. If they are not active, you can open the Jira +Backend and run the synchronizations manually, or activate the Scheduled +Actions to run the batch imports. It is important to select the issue +types so don’t miss this step (need improvement).

+
+
+
+

Known issues / Roadmap

+
    +
  • If an odoo user has no linked employee, worklogs will still be +imported but with no employee.
  • +
+

Allowing several bindings per project

+

The design evolved to allow more than one Jira binding per project in +Odoo. This conveniently allows to fetch tasks and worklogs for many +projects in Jira, which will be tracked in only one project in Odoo.

+

In order to push data to Jira, we have to apply restrictions on these +“multi-bindings” projects, as we cannot know to which binding data must +be pushed:

+
    +
  • Not more than one project (can be zero) can have a “Sync Action” set +to “Export to JIRA”. As this configuration pushes the name and key of +the project to Jira, we cannot push it to more than one project.
  • +
  • If we implement push of tasks to Jira, we’ll have to add a way to +restrict or choose to which project we push the task, this is not +supported yet (for instance, add a Boolean “export tasks” on the +project binding, or explicitly select the target binding on the task)
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/connector-jira project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/connector_jira/tests/__init__.py b/connector_jira/tests/__init__.py new file mode 100644 index 000000000..f31493043 --- /dev/null +++ b/connector_jira/tests/__init__.py @@ -0,0 +1,10 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import test_auth +from . import test_backend +from . import test_delete_analytic_line +from . import test_import_issue_type +from . import test_import_task +from . import test_import_analytic_line +from . import test_batch_timestamp_import +from . import test_batch_timestamp_delete diff --git a/connector_jira/tests/common.py b/connector_jira/tests/common.py new file mode 100644 index 000000000..88f192488 --- /dev/null +++ b/connector_jira/tests/common.py @@ -0,0 +1,223 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +"""Tests for connector_jira + +# Running tests + +Tests are run normally, you can either execute them with odoo's +``--test-enable`` option or using `pytest-odoo +`_ + +The requests to Jira are recorded and simulated using `vcrpy +`_. Which means +the tests can be executed without having a Jira service running. + +However, in order to write new tests or modify the existing ones, you may need +to have a service running to record the Webservice interactions. + +# Recording new tests with vcr.py + +First, you will need a running Jira. We use a docker image, a simple +composition is enough:: + + version: '2' + services: + + jira: + image: cptactionhank/atlassian-jira-software:7.12.3 + volumes: + - "data-jira:/var/atlassian/jira" + ports: + - 8080:8080 + + volumes: + data-jira: + +When you first access to Jira, it will guide you through a procedure +to obtain a demo license. + +Once connected, you will need to do the Oauth dance to obtain tokens. + +You can do so using the CLI command line:: + + odoo jiraoauthdance + +See details in ``connector_jira/cli/jira_oauth_dance.py``. + +Once you have tokens (access+secret), you will need to set them +in environment variables when you run your tests: + +- JIRA_TEST_URL +- JIRA_TEST_TOKEN_ACCESS +- JIRA_TEST_TOKEN_SECRET + +From now on, you can write your tests using the ``recorder.use_cassette`` +decorator or context manager. If you are changing existing tests, you might +need either to manually edit the cassette files in "tests/fixtures/cassettes" +or record the tests again (in such case, IDs may change). + +""" + +import logging +import os +from contextlib import contextmanager +from os.path import dirname, join +from unittest import mock + +import requests +from vcr import VCR + +from odoo.addons.component.tests.common import TransactionComponentCase + +_logger = logging.getLogger(__name__) + +jira_test_url = os.environ.get("JIRA_TEST_URL", "http://jira:8080") +jira_test_token_access = os.environ.get("JIRA_TEST_TOKEN_ACCESS", "") +jira_test_token_secret = os.environ.get("JIRA_TEST_TOKEN_SECRET", "") + + +def get_recorder(base_path=None, **kw): + base_path = base_path or dirname(__file__) + defaults = dict( + record_mode="once", + cassette_library_dir=join(base_path, "fixtures/cassettes"), + path_transformer=VCR.ensure_suffix(".yaml"), + match_on=["method", "path", "query"], + filter_headers=["Authorization"], + decode_compressed_response=True, + ) + defaults.update(kw) + return VCR(**defaults) + + +recorder = get_recorder() + + +class JiraTransactionComponentCase(TransactionComponentCase): + """Base class for tests with Jira""" + + @classmethod + def setUpClass(cls): + cls._super_send = requests.Session.send + + super().setUpClass() + + context = cls.env.context.copy() + context["tracking_disable"] = True + cls.env = cls.env(context=context) + + cls.backend_record = cls.env.ref("connector_jira.jira_backend_demo") + cls.backend_record.write( + { + "uri": jira_test_url, + "access_token": jira_test_token_access, + "access_secret": jira_test_token_secret, + "epic_link_field_name": "customfield_10101", + } + ) + + # Warning: if you add new tests or change the cassettes + # you might need to change these values + # to make issue types match + _base_issue_types = [ + ("Task", "10002"), + ("Sub-task", "10003"), + ("Story", "10001"), + ("Bug", "10004"), + ("Epic", "10000"), + ] + + @classmethod + def _request_handler(cls, s, r, /, **kw): + """Don't block external requests.""" + return cls._super_send(s, r, **kw) + + @classmethod + def _link_user(cls, user, jira_login): + return ( + cls.env["jira.res.users"] + .with_context(no_connector_export=True) + .create( + { + "odoo_id": user.id, + "backend_id": cls.backend_record.id, + "external_id": jira_login, + } + ) + ) + + @classmethod + def _create_issue_type_bindings(cls): + for name, jira_id in cls._base_issue_types: + cls.env["jira.issue.type"].create( + { + "name": name, + "backend_id": cls.backend_record.id, + "external_id": jira_id, + } + ) + + @classmethod + def _create_project_binding( + cls, project, sync_action="link", issue_types=None, **extra + ): + values = { + "odoo_id": project.id, + "jira_key": "TEST", + "sync_action": sync_action, + "backend_id": cls.backend_record.id, + # dummy id + "external_id": "9999", + } + if issue_types: + values.update({"sync_issue_type_ids": [(6, 0, issue_types.ids)]}) + values.update(**extra) + return ( + cls.env["jira.project.project"] + .with_context(no_connector_export=True) + .create(values) + ) + + @classmethod + def _create_task_binding(cls, task, **extra): + values = { + "odoo_id": task.id, + "jira_key": "TEST", + "backend_id": cls.backend_record.id, + # dummy id + "external_id": "9999", + } + values.update(**extra) + return ( + cls.env["jira.project.task"] + .with_context(no_connector_export=True) + .create(values) + ) + + @classmethod + def _create_analytic_line_binding(cls, line, **extra): + values = { + "odoo_id": line.id, + "backend_id": cls.backend_record.id, + # dummy id + "external_id": "9999", + } + values.update(**extra) + return ( + cls.env["jira.account.analytic.line"] + .with_context(no_connector_export=True) + .create(values) + ) + + @contextmanager + def mock_with_delay(self): + with mock.patch( + "odoo.addons.queue_job.models.base.DelayableRecordset", + name="DelayableRecordset", + spec=True, + ) as delayable_cls: + # prepare the mocks + delayable = mock.MagicMock(name="DelayableBinding") + delayable_cls.return_value = delayable + yield delayable_cls, delayable diff --git a/connector_jira/tests/fixtures/cassettes/test_auth_basic.yaml b/connector_jira/tests/fixtures/cassettes/test_auth_basic.yaml new file mode 100644 index 000000000..8eed5dde6 --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_auth_basic.yaml @@ -0,0 +1,322 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-03T16:07:19.756+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 16:07:19 GMT"] + Set-Cookie: + [ + JSESSIONID=3137F318B729C7876F866A7B49A5A474; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_2aad58b7529761dd022e19fb8654325b4b0f8859_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [967x756x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [109kqxb] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yYWFkNThiNzUyOTc2MWRk + MDIyZTE5ZmI4NjU0MzI1YjRiMGY4ODU5X2xpbjsgSlNFU1NJT05JRD0zMTM3RjMxOEI3MjlDNzg3 + NkY4NjZBN0I0OUE1QTQ3NA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 16:07:19 GMT"] + Set-Cookie: [JSESSIONID=1CF7A0A7B49089B08A6BB1723E4732BD; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [967x757x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [7pffyo] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yYWFkNThiNzUyOTc2MWRk + MDIyZTE5ZmI4NjU0MzI1YjRiMGY4ODU5X2xpbjsgSlNFU1NJT05JRD0xQ0Y3QTBBN0I0OTA4OUIw + OEE2QkIxNzIzRTQ3MzJCRA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/myself + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","key":"gbaconnier","name":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT","locale":"en_US","groups":{"size":2,"items":[]},"applicationRoles":{"size":1,"items":[]},"expand":"groups,applicationRoles"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 16:07:19 GMT"] + Set-Cookie: [JSESSIONID=6149484F0565750836475A1F1B3FA362; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [967x758x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [ywtrwx] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["694"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_auth_check_connection.yaml b/connector_jira/tests/fixtures/cassettes/test_auth_check_connection.yaml new file mode 100644 index 000000000..8eed5dde6 --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_auth_check_connection.yaml @@ -0,0 +1,322 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-03T16:07:19.756+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 16:07:19 GMT"] + Set-Cookie: + [ + JSESSIONID=3137F318B729C7876F866A7B49A5A474; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_2aad58b7529761dd022e19fb8654325b4b0f8859_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [967x756x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [109kqxb] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yYWFkNThiNzUyOTc2MWRk + MDIyZTE5ZmI4NjU0MzI1YjRiMGY4ODU5X2xpbjsgSlNFU1NJT05JRD0zMTM3RjMxOEI3MjlDNzg3 + NkY4NjZBN0I0OUE1QTQ3NA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 16:07:19 GMT"] + Set-Cookie: [JSESSIONID=1CF7A0A7B49089B08A6BB1723E4732BD; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [967x757x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [7pffyo] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yYWFkNThiNzUyOTc2MWRk + MDIyZTE5ZmI4NjU0MzI1YjRiMGY4ODU5X2xpbjsgSlNFU1NJT05JRD0xQ0Y3QTBBN0I0OTA4OUIw + OEE2QkIxNzIzRTQ3MzJCRA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/myself + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","key":"gbaconnier","name":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT","locale":"en_US","groups":{"size":2,"items":[]},"applicationRoles":{"size":1,"items":[]},"expand":"groups,applicationRoles"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 16:07:19 GMT"] + Set-Cookie: [JSESSIONID=6149484F0565750836475A1F1B3FA362; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [967x758x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [ywtrwx] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["694"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_auth_check_connection_failure.yaml b/connector_jira/tests/fixtures/cassettes/test_auth_check_connection_failure.yaml new file mode 100644 index 000000000..f45a7fdbc --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_auth_check_connection_failure.yaml @@ -0,0 +1,391 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 11:39:00 GMT"] + Set-Cookie: + [ + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_24361ed8c1e67b559e8a490045880a8bfdf361a1_lout; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [699x1203x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["244"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yNDM2MWVkOGMxZTY3YjU1 + OWU4YTQ5MDA0NTg4MGE4YmZkZjM2MWExX2xvdXQ= + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: + {string: "[{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"\ + issue\",\"issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"\ + timespent\"}},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"\ + type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3\ + \ Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\"\ + :\"aggregatetimespent\"}},{\"id\":\"timetracking\",\"name\":\"Time + Tracking\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[],\"schema\":{\"type\":\"timetracking\",\"system\":\"timetracking\"\ + }},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[\"attachments\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"attachment\",\"system\":\"attachment\"\ + }},{\"id\":\"aggregatetimeestimate\",\"name\":\"\u03A3 Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimeestimate\"\ + }},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolutiondate\"\ + ,\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\":\"resolutiondate\"\ + }},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"workratio\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"}},{\"id\":\"lastViewed\"\ + ,\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"],\"schema\":{\"\ + type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"watches\",\"name\"\ + :\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\":\"watches\",\"\ + system\":\"watches\"}},{\"id\":\"creator\",\"name\":\"Creator\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"creator\"],\"schema\":{\"type\":\"user\",\"system\":\"creator\"}},{\"\ + id\":\"thumbnail\",\"name\":\"Images\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[]},{\"id\":\"subtasks\"\ + ,\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"created\"\ + ,\"name\":\"Created\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"created\",\"createdDate\"],\"schema\"\ + :{\"type\":\"datetime\",\"system\":\"created\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\"\ + :{\"type\":\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"updated\",\"name\":\"Updated\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"datetime\"\ + ,\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 11:39:00 GMT"] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [699x1204x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["4695"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yNDM2MWVkOGMxZTY3YjU1 + OWU4YTQ5MDA0NTg4MGE4YmZkZjM2MWExX2xvdXQ= + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/myself + response: + body: + { + string: + '{"message":"Client must be authenticated to access this + resource.","status-code":401}', + } + headers: + Cache-Control: [no-transform] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 11:39:00 GMT"] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + WWW-Authenticate: [OAuth realm="http%3A%2F%2Fjira%3A8080"] + X-AREQUESTID: [699x1205x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["85"] + status: {code: 401, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yNDM2MWVkOGMxZTY3YjU1 + OWU4YTQ5MDA0NTg4MGE4YmZkZjM2MWExX2xvdXQ= + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/myself + response: + body: + { + string: + '{"message":"Client must be authenticated to access this + resource.","status-code":401}', + } + headers: + Cache-Control: [no-transform] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 11:39:09 GMT"] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + WWW-Authenticate: [OAuth realm="http%3A%2F%2Fjira%3A8080"] + X-AREQUESTID: [699x1206x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["85"] + status: {code: 401, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yNDM2MWVkOGMxZTY3YjU1 + OWU4YTQ5MDA0NTg4MGE4YmZkZjM2MWExX2xvdXQ= + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/myself + response: + body: + { + string: + '{"message":"Client must be authenticated to access this + resource.","status-code":401}', + } + headers: + Cache-Control: [no-transform] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 11:39:27 GMT"] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + WWW-Authenticate: [OAuth realm="http%3A%2F%2Fjira%3A8080"] + X-AREQUESTID: [699x1207x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["85"] + status: {code: 401, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18yNDM2MWVkOGMxZTY3YjU1 + OWU4YTQ5MDA0NTg4MGE4YmZkZjM2MWExX2xvdXQ= + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/myself + response: + body: + { + string: + '{"message":"Client must be authenticated to access this + resource.","status-code":401}', + } + headers: + Cache-Control: [no-transform] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 11:39:28 GMT"] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + WWW-Authenticate: [OAuth realm="http%3A%2F%2Fjira%3A8080"] + X-AREQUESTID: [699x1208x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["85"] + status: {code: 401, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_auth_oauth.yaml b/connector_jira/tests/fixtures/cassettes/test_auth_oauth.yaml new file mode 100644 index 000000000..d74304d00 --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_auth_oauth.yaml @@ -0,0 +1,88 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + Ki8q + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Length: + - !!binary | + MA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + method: POST + uri: http://jira:8080/plugins/servlet/oauth/request-token + response: + body: + { + string: oauth_token=ygdy5CS2FGTKnGHoX29TehoRQvb6T19X&oauth_token_secret=pwq9Qzc7iax0JtoQqZdLvPlv4ReECZGh, + } + headers: + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [text/plain;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 14:49:44 GMT"] + Set-Cookie: + [ + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_391215749860b95636848223385ab73412134dc5_lout; + Path=/, + ] + Vary: [User-Agent] + X-AREQUESTID: [889x732x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["96"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + Ki8q + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Length: + - !!binary | + MA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMTkuMQ== + method: POST + uri: http://jira:8080/plugins/servlet/oauth/access-token + response: + body: + { + string: oauth_token=o7XglNpQdA3pwzGZw9r6WA2X2XZcjaaI&oauth_token_secret=pwq9Qzc7iax0JtoQqZdLvPlv4ReECZGh&oauth_expires_in=157680000&oauth_session_handle=WYSDJUpF0KTQjsX5vAq3vcWJtcfcNw8C&oauth_authorization_expires_in=160272000, + } + headers: + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [text/plain;charset=UTF-8] + Date: ["Wed, 03 Apr 2019 14:51:49 GMT"] + Set-Cookie: + [ + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_a09f0120c8cc6d03ffc01dce7a72b73f1cae63d2_lout; + Path=/, + ] + Vary: [User-Agent] + X-AREQUESTID: [891x742x1] + X-ASEN: [SEN-L13384799] + X-AUSERNAME: [anonymous] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-XSS-Protection: [1; mode=block] + content-length: ["218"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_delete_batch_timestamp_analytic_line.yaml b/connector_jira/tests/fixtures/cassettes/test_delete_batch_timestamp_analytic_line.yaml new file mode 100644 index 000000000..4b82ce641 --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_delete_batch_timestamp_analytic_line.yaml @@ -0,0 +1,320 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-08T14:13:20.209+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 14:13:20 GMT"] + Set-Cookie: + [ + JSESSIONID=EF69BE3FCA9FDA8E4307E37E862CE100; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_74fee64e4f04e7b5286a05a23a51974ba8e4771f_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [853x1402x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [13w47d8] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT183NGZlZTY0ZTRmMDRlN2I1 + Mjg2YTA1YTIzYTUxOTc0YmE4ZTQ3NzFmX2xpbjsgSlNFU1NJT05JRD1FRjY5QkUzRkNBOUZEQThF + NDMwN0UzN0U4NjJDRTEwMA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 14:13:20 GMT"] + Set-Cookie: [JSESSIONID=5BCCC0362E54D5592EA8F6ABEA7C9148; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [853x1403x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [6zt26j] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT183NGZlZTY0ZTRmMDRlN2I1 + Mjg2YTA1YTIzYTUxOTc0YmE4ZTQ3NzFmX2xpbjsgSlNFU1NJT05JRD01QkNDQzAzNjJFNTRENTU5 + MkVBOEY2QUJFQTdDOTE0OA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/worklog/deleted?since=1554422400000 + response: + body: + { + string: '{"values":[{"worklogId":10103,"updatedTime":1554731466007},{"worklogId":10104,"updatedTime":1554731497945}],"since":1554422400000,"until":1554731497945,"self":"http://jira:8080/rest/api/2/worklog/deleted?since=1554422400000","lastPage":true}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 14:13:20 GMT"] + Set-Cookie: [JSESSIONID=04C9B40EB740333E6EF7D80C005881E7; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [853x1404x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [bkw2xl] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["241"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_batch_timestamp_analytic_line.yaml b/connector_jira/tests/fixtures/cassettes/test_import_batch_timestamp_analytic_line.yaml new file mode 100644 index 000000000..f5ecea129 --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_batch_timestamp_analytic_line.yaml @@ -0,0 +1,431 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-08T13:22:01.348+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 13:22:01 GMT"] + Set-Cookie: + [ + JSESSIONID=60CE0FB0FC969ED86ACBA2F291D29AF2; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_84bc83db3a80278ab3c746ebbc39355238a2f677_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [802x917x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [vmsm1d] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT184NGJjODNkYjNhODAyNzhh + YjNjNzQ2ZWJiYzM5MzU1MjM4YTJmNjc3X2xpbjsgSlNFU1NJT05JRD02MENFMEZCMEZDOTY5RUQ4 + NkFDQkEyRjI5MUQyOUFGMg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 13:22:01 GMT"] + Set-Cookie: [JSESSIONID=0072FB246E07EB2450708C9111E07FDB; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [802x918x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [5j0yz4] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT184NGJjODNkYjNhODAyNzhh + YjNjNzQ2ZWJiYzM5MzU1MjM4YTJmNjc3X2xpbjsgSlNFU1NJT05JRD0wMDcyRkIyNDZFMDdFQjI0 + NTA3MDhDOTExMUUwN0ZEQg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/worklog/updated?since=1554422400000 + response: + body: + { + string: '{"values":[{"worklogId":10100,"updatedTime":1554726685540},{"worklogId":10101,"updatedTime":1554726717005},{"worklogId":10102,"updatedTime":1554726739311}],"since":1554422400000,"until":1554726739311,"self":"http://jira:8080/rest/api/2/worklog/updated?since=1554422400000","lastPage":true}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 13:22:01 GMT"] + Set-Cookie: [JSESSIONID=747807680CB681690D558F853575A7A3; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [802x919x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [gzyyh8] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["289"] + status: {code: 200, message: ""} + - request: + body: '{"ids": [10100, 10101, 10102]}' + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Length: ["30"] + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT184NGJjODNkYjNhODAyNzhh + YjNjNzQ2ZWJiYzM5MzU1MjM4YTJmNjc3X2xpbjsgSlNFU1NJT05JRD03NDc4MDc2ODBDQjY4MTY5 + MEQ1NThGODUzNTc1QTdBMw== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: POST + uri: http://jira:8080/rest/api/2/worklog/list + response: + body: + {string: "[{\"self\":\"http://jira:8080/rest/api/2/issue/10102/worklog/10100\"\ + ,\"author\":{\"self\":\"http://jira:8080/rest/api/2/user?username=gbaconnier\"\ + ,\"name\":\"gbaconnier\",\"key\":\"gbaconnier\",\"emailAddress\":\"guewen.baconnier@camptocamp.com\"\ + ,\"avatarUrls\":{\"48x48\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48\"\ + ,\"24x24\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24\"\ + ,\"16x16\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16\"\ + ,\"32x32\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32\"\ + },\"displayName\":\"Guewen Baconnier\",\"active\":true,\"timeZone\":\"GMT\"\ + },\"updateAuthor\":{\"self\":\"http://jira:8080/rest/api/2/user?username=gbaconnier\"\ + ,\"name\":\"gbaconnier\",\"key\":\"gbaconnier\",\"emailAddress\":\"guewen.baconnier@camptocamp.com\"\ + ,\"avatarUrls\":{\"48x48\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48\"\ + ,\"24x24\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24\"\ + ,\"16x16\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16\"\ + ,\"32x32\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32\"\ + },\"displayName\":\"Guewen Baconnier\",\"active\":true,\"timeZone\":\"GMT\"\ + },\"comment\":\"use vcrpy to record + tests\\r\\n\\r\\n\_\",\"created\":\"2019-04-08T12:31:25.540+0000\"\ + ,\"updated\":\"2019-04-08T12:31:25.540+0000\",\"started\":\"2019-04-08T12:31:00.000+0000\"\ + ,\"timeSpent\":\"1h\",\"timeSpentSeconds\":3600,\"id\":\"10100\",\"issueId\"\ + :\"10102\"},{\"self\":\"http://jira:8080/rest/api/2/issue/10100/worklog/10102\"\ + ,\"author\":{\"self\":\"http://jira:8080/rest/api/2/user?username=gbaconnier\"\ + ,\"name\":\"gbaconnier\",\"key\":\"gbaconnier\",\"emailAddress\":\"guewen.baconnier@camptocamp.com\"\ + ,\"avatarUrls\":{\"48x48\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48\"\ + ,\"24x24\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24\"\ + ,\"16x16\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16\"\ + ,\"32x32\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32\"\ + },\"displayName\":\"Guewen Baconnier\",\"active\":true,\"timeZone\":\"GMT\"\ + },\"updateAuthor\":{\"self\":\"http://jira:8080/rest/api/2/user?username=gbaconnier\"\ + ,\"name\":\"gbaconnier\",\"key\":\"gbaconnier\",\"emailAddress\":\"guewen.baconnier@camptocamp.com\"\ + ,\"avatarUrls\":{\"48x48\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48\"\ + ,\"24x24\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24\"\ + ,\"16x16\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16\"\ + ,\"32x32\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32\"\ + },\"displayName\":\"Guewen Baconnier\",\"active\":true,\"timeZone\":\"GMT\"\ + },\"comment\":\"add tests\",\"created\":\"2019-04-08T12:32:19.311+0000\",\"\ + updated\":\"2019-04-08T12:32:19.311+0000\",\"started\":\"2019-04-08T12:32:00.000+0000\"\ + ,\"timeSpent\":\"2h + 15m\",\"timeSpentSeconds\":8100,\"id\":\"10102\",\"issueId\"\ + :\"10100\"},{\"self\":\"http://jira:8080/rest/api/2/issue/10101/worklog/10101\"\ + ,\"author\":{\"self\":\"http://jira:8080/rest/api/2/user?username=gbaconnier\"\ + ,\"name\":\"gbaconnier\",\"key\":\"gbaconnier\",\"emailAddress\":\"guewen.baconnier@camptocamp.com\"\ + ,\"avatarUrls\":{\"48x48\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48\"\ + ,\"24x24\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24\"\ + ,\"16x16\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16\"\ + ,\"32x32\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32\"\ + },\"displayName\":\"Guewen Baconnier\",\"active\":true,\"timeZone\":\"GMT\"\ + },\"updateAuthor\":{\"self\":\"http://jira:8080/rest/api/2/user?username=gbaconnier\"\ + ,\"name\":\"gbaconnier\",\"key\":\"gbaconnier\",\"emailAddress\":\"guewen.baconnier@camptocamp.com\"\ + ,\"avatarUrls\":{\"48x48\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48\"\ + ,\"24x24\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24\"\ + ,\"16x16\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16\"\ + ,\"32x32\":\"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32\"\ + },\"displayName\":\"Guewen Baconnier\",\"active\":true,\"timeZone\":\"GMT\"\ + },\"comment\":\"use Jira method + 'deleted-since'\",\"created\":\"2019-04-08T12:31:57.005+0000\"\ + ,\"updated\":\"2019-04-08T12:31:57.005+0000\",\"started\":\"2019-04-05T12:31:00.000+0000\"\ + ,\"timeSpent\":\"1h + 30m\",\"timeSpentSeconds\":5400,\"id\":\"10101\",\"issueId\"\ + :\"10101\"}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 13:22:01 GMT"] + Set-Cookie: [JSESSIONID=22D93E29D62060EF5D623E45F15B4AA6; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [802x920x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [s7hzzc] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["4401"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_batch_timestamp_tasks.yaml b/connector_jira/tests/fixtures/cassettes/test_import_batch_timestamp_tasks.yaml new file mode 100644 index 000000000..da56050c9 --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_batch_timestamp_tasks.yaml @@ -0,0 +1,374 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-08T12:51:45.070+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 12:51:45 GMT"] + Set-Cookie: + [ + JSESSIONID=37AE6A08D05ECF383A84F6142927D431; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_d276e436bdeda01a7e0efd7ef6581a1107aed31c_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [771x912x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1o6l6kn] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD0zN0FFNkEwOEQwNUVDRjM4M0E4NEY2MTQyOTI3RDQzMTsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kMjc2ZTQzNmJkZWRhMDFhN2UwZWZkN2VmNjU4 + MWExMTA3YWVkMzFjX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 12:51:45 GMT"] + Set-Cookie: [JSESSIONID=A9E2F67AF2F8C6142DD7B5D59504B083; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [771x913x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1d3mppo] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1BOUUyRjY3QUYyRjhDNjE0MkREN0I1RDU5NTA0QjA4MzsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kMjc2ZTQzNmJkZWRhMDFhN2UwZWZkN2VmNjU4 + MWExMTA3YWVkMzFjX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/search?startAt=0&validateQuery=True&fields=issuekey&fields=updated&jql=updated+%3E%3D+%222019-04-05+00%3A00%22+and+updated+%3C%3D+%222019-04-08+12%3A51%22 + response: + body: + { + string: '{"expand":"schema,names","startAt":0,"maxResults":50,"total":4,"issues":[{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10103","self":"http://jira:8080/rest/api/2/issue/10103","key":"TEST-7","fields":{"updated":"2019-04-08T12:38:01.000+0000"}},{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10102","self":"http://jira:8080/rest/api/2/issue/10102","key":"TEST-6","fields":{"updated":"2019-04-08T12:37:55.000+0000"}},{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10101","self":"http://jira:8080/rest/api/2/issue/10101","key":"TEST-5","fields":{"updated":"2019-04-08T12:37:44.000+0000"}},{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10100","self":"http://jira:8080/rest/api/2/issue/10100","key":"TEST-4","fields":{"updated":"2019-04-08T12:38:01.000+0000"}}]}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 12:51:45 GMT"] + Set-Cookie: [JSESSIONID=3EF9F21BED163A7F93DDA2F4E9E82C45; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [771x914x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1km321n] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["922"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1BOUUyRjY3QUYyRjhDNjE0MkREN0I1RDU5NTA0QjA4MzsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kMjc2ZTQzNmJkZWRhMDFhN2UwZWZkN2VmNjU4 + MWExMTA3YWVkMzFjX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/search?startAt=0&validateQuery=True&fields=issuekey&fields=updated&jql=updated+%3E%3D+%222019-04-05+00%3A00%22+and+updated+%3C%3D+%222019-04-08+12%3A51%22&maxResults=100 + response: + body: + { + string: '{"expand":"schema,names","startAt":0,"maxResults":50,"total":4,"issues":[{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10103","self":"http://jira:8080/rest/api/2/issue/10103","key":"TEST-7","fields":{"updated":"2019-04-08T12:38:01.000+0000"}},{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10102","self":"http://jira:8080/rest/api/2/issue/10102","key":"TEST-6","fields":{"updated":"2019-04-08T12:37:55.000+0000"}},{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10101","self":"http://jira:8080/rest/api/2/issue/10101","key":"TEST-5","fields":{"updated":"2019-04-08T12:37:44.000+0000"}},{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"10100","self":"http://jira:8080/rest/api/2/issue/10100","key":"TEST-4","fields":{"updated":"2019-04-08T12:38:01.000+0000"}}]}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Mon, 08 Apr 2019 12:51:45 GMT"] + Set-Cookie: [JSESSIONID=3EF9F21BED163A7F93DDA2F4E9E82C45; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [771x914x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1km321n] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["922"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_issue_type_batch.yaml b/connector_jira/tests/fixtures/cassettes/test_import_issue_type_batch.yaml new file mode 100644 index 000000000..4c227fcaa --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_issue_type_batch.yaml @@ -0,0 +1,1938 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-04T08:47:50.944+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: + [ + JSESSIONID=A284F9F3C946F4DE90B46F23A9D322E4; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_3a9e497f41c4cbb37d12feff7f471568305cbff1_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x865x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [nhuy89] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1BMjg0RjlGM0M5NDZGNERFOTBCNDZGMjNBOUQzMjJFNDsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18zYTllNDk3ZjQxYzRjYmIzN2QxMmZlZmY3ZjQ3 + MTU2ODMwNWNiZmYxX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=6761E3CECDCBF4CB54F5BA1A68863929; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x866x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [5b6jp7] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD02NzYxRTNDRUNEQ0JGNENCNTRGNUJBMUE2ODg2MzkyOTsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18zYTllNDk3ZjQxYzRjYmIzN2QxMmZlZmY3ZjQ3 + MTU2ODMwNWNiZmYxX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issuetype + response: + body: + { + string: + '[{"self":"http://jira:8080/rest/api/2/issuetype/10002","id":"10002","description":"A + task that needs to be + done.","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype","name":"Task","subtask":false,"avatarId":10318},{"self":"http://jira:8080/rest/api/2/issuetype/10003","id":"10003","description":"The + sub-task of the + issue","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10316&avatarType=issuetype","name":"Sub-task","subtask":true,"avatarId":10316},{"self":"http://jira:8080/rest/api/2/issuetype/10001","id":"10001","description":"Created + by Jira Software - do not edit or delete. Issue type for a user + story.","iconUrl":"http://jira:8080/images/icons/issuetypes/story.svg","name":"Story","subtask":false},{"self":"http://jira:8080/rest/api/2/issuetype/10004","id":"10004","description":"A + problem which impairs or prevents the functions of the + product.","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10303&avatarType=issuetype","name":"Bug","subtask":false,"avatarId":10303},{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false}]', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=09FE672783BC464570E54E584261DAAB; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x867x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [2pq75o] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["1348"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-04T08:47:51.032+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: + [ + JSESSIONID=8FBBA4B8926FF9A4281D349789C62AA1; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_c2c24c965e11aa18ea0402e2a5477e8c26f723a9_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x868x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [19oay4n] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD04RkJCQTRCODkyNkZGOUE0MjgxRDM0OTc4OUM2MkFBMTsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19jMmMyNGM5NjVlMTFhYTE4ZWEwNDAyZTJhNTQ3 + N2U4YzI2ZjcyM2E5X2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=B39C784459149141BDC06785E4E4CA0B; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x869x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [apvf7q] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1CMzlDNzg0NDU5MTQ5MTQxQkRDMDY3ODVFNEU0Q0EwQjsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19jMmMyNGM5NjVlMTFhYTE4ZWEwNDAyZTJhNTQ3 + N2U4YzI2ZjcyM2E5X2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issuetype/10002 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issuetype/10002","id":"10002","description":"A + task that needs to be + done.","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype","name":"Task","subtask":false,"avatarId":10318}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=6F0F6E51042053CFA951AD74C7B13578; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x870x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [yw9uvr] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["255"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-04T08:47:51.124+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: + [ + JSESSIONID=7D9C5AFDAC293751E952A422A64000C8; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_37be6e80153b108551846cda18072cbee346b443_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x871x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [187k70u] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD03RDlDNUFGREFDMjkzNzUxRTk1MkE0MjJBNjQwMDBDODsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18zN2JlNmU4MDE1M2IxMDg1NTE4NDZjZGExODA3 + MmNiZWUzNDZiNDQzX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=8B2DF9092966563AA3CD7796DC071B70; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x872x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1lco607] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD04QjJERjkwOTI5NjY1NjNBQTNDRDc3OTZEQzA3MUI3MDsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18zN2JlNmU4MDE1M2IxMDg1NTE4NDZjZGExODA3 + MmNiZWUzNDZiNDQzX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issuetype/10003 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issuetype/10003","id":"10003","description":"The + sub-task of the + issue","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10316&avatarType=issuetype","name":"Sub-task","subtask":true,"avatarId":10316}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=4EB098AA2D926B6D3CD93F4E735A65DC; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x873x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [vjasnw] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["254"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-04T08:47:51.203+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: + [ + JSESSIONID=BF85A8C3CD4EAEB937336E33BF7C94A0; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_3393f556ff4f62b6731dbaadc6375383c9f2e44b_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x874x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [njv9cs] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1CRjg1QThDM0NENEVBRUI5MzczMzZFMzNCRjdDOTRBMDsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18zMzkzZjU1NmZmNGY2MmI2NzMxZGJhYWRjNjM3 + NTM4M2M5ZjJlNDRiX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=944AB3971637AA62CD2D1BC08F20525A; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x875x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [11lkqre] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD05NDRBQjM5NzE2MzdBQTYyQ0QyRDFCQzA4RjIwNTI1QTsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18zMzkzZjU1NmZmNGY2MmI2NzMxZGJhYWRjNjM3 + NTM4M2M5ZjJlNDRiX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issuetype/10001 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issuetype/10001","id":"10001","description":"Created + by Jira Software - do not edit or delete. Issue type for a user + story.","iconUrl":"http://jira:8080/images/icons/issuetypes/story.svg","name":"Story","subtask":false}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=EAC894290BAE5618DEEA90ED16627DCA; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x876x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1wxvpx8] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["256"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-04T08:47:51.278+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: + [ + JSESSIONID=ACF11B7F5582201B91581B11F31637FA; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_0d796386486fa2c80ade6e265d8b6d1c5339bb65_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x877x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [c2163r] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1BQ0YxMUI3RjU1ODIyMDFCOTE1ODFCMTFGMzE2MzdGQTsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18wZDc5NjM4NjQ4NmZhMmM4MGFkZTZlMjY1ZDhi + NmQxYzUzMzliYjY1X2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=91B78D3112BCBA30F361CA3D894981F0; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x878x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [18xj5fc] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD05MUI3OEQzMTEyQkNCQTMwRjM2MUNBM0Q4OTQ5ODFGMDsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18wZDc5NjM4NjQ4NmZhMmM4MGFkZTZlMjY1ZDhi + NmQxYzUzMzliYjY1X2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issuetype/10004 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issuetype/10004","id":"10004","description":"A + problem which impairs or prevents the functions of the + product.","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10303&avatarType=issuetype","name":"Bug","subtask":false,"avatarId":10303}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=9717EDAECB93F99C8AA9B5300684D7AE; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x879x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1n3azds] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["290"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-04T08:47:51.355+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: + [ + JSESSIONID=71E64EB8460FC6084682A409CCC54D0F; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_58499d4673de026e97ade13f4b59cb151f60092c_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x880x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [5a2fr7] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD03MUU2NEVCODQ2MEZDNjA4NDY4MkE0MDlDQ0M1NEQwRjsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT181ODQ5OWQ0NjczZGUwMjZlOTdhZGUxM2Y0YjU5 + Y2IxNTFmNjAwOTJjX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"timespent\"],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"\ + }},{\"id\":\"timeoriginalestimate\",\"name\":\"Original + Estimate\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"originalEstimate\",\"timeoriginalestimate\"],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"timeoriginalestimate\"}},{\"id\":\"project\",\"name\":\"Project\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\",\"system\":\"\ + project\"}},{\"id\":\"description\",\"name\":\"Description\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + description\"],\"schema\":{\"type\":\"string\",\"system\":\"description\"\ + }},{\"id\":\"fixVersions\",\"name\":\"Fix Version/s\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"version\",\"system\"\ + :\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\":\"\u03A3 Time + Spent\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[],\"schema\":{\"type\":\"number\",\"system\":\"aggregatetimespent\"\ + }},{\"id\":\"resolution\",\"name\":\"Resolution\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"resolution\"\ + ],\"schema\":{\"type\":\"resolution\",\"system\":\"resolution\"}},{\"id\"\ + :\"timetracking\",\"name\":\"Time Tracking\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"timetracking\",\"system\":\"timetracking\"}},{\"id\":\"customfield_10104\"\ + ,\"name\":\"Epic Color\",\"custom\":true,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"cf[10104]\",\"Epic Color\"],\"\ + schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\"\ + ,\"customId\":10104}},{\"id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\"\ + :true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"cf[10105]\",\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"security\",\"name\":\"Security Level\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"level\"],\"schema\":{\"type\":\"securitylevel\",\"system\"\ + :\"security\"}},{\"id\":\"customfield_10106\",\"name\":\"Story Points\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"resolutiondate\",\"name\"\ + :\"Resolved\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\"\ + :\"datetime\",\"system\":\"resolutiondate\"}},{\"id\":\"workratio\",\"name\"\ + :\"Work Ratio\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"workratio\"],\"schema\":{\"type\":\"\ + number\",\"system\":\"workratio\"}},{\"id\":\"summary\",\"name\":\"Summary\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"\ + summary\"}},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"lastViewed\"],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"\ + }},{\"id\":\"watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"watchers\"\ + ],\"schema\":{\"type\":\"watches\",\"system\":\"watches\"}},{\"id\":\"creator\"\ + ,\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"creator\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"creator\"}},{\"id\":\"thumbnail\",\"name\":\"Images\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[]},{\"id\":\"subtasks\",\"name\":\"Sub-Tasks\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"subtasks\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"\ + }},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"created\"\ + ,\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"created\"\ + }},{\"id\":\"reporter\",\"name\":\"Reporter\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"reporter\"\ + ],\"schema\":{\"type\":\"user\",\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\"\ + ,\"name\":\"\u03A3 + Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\"\ + ,\"system\":\"aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\"\ + :\"Development\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\"\ + :{\"type\":\"any\",\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"\ + }},{\"id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"timeestimate\",\"name\":\"Remaining Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"duedate\",\"name\":\"Due Date\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"due\",\"duedate\"\ + ],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"id\":\"progress\"\ + ,\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\":{\"type\"\ + :\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\":\"Comment\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"\ + clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\",\"system\"\ + :\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"votes\"\ + ],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\":\"issuelinks\"\ + ,\"name\":\"Linked + Issues\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"id\":\"worklog\"\ + ,\"name\":\"Log + Work\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"\ + searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"array\",\"items\"\ + :\"worklog\",\"system\":\"worklog\"}},{\"id\":\"assignee\",\"name\":\"Assignee\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"assignee\"],\"schema\":{\"type\":\"user\",\"system\":\"assignee\"\ + }},{\"id\":\"updated\",\"name\":\"Updated\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"updated\"\ + ,\"updatedDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"updated\"\ + }},{\"id\":\"status\",\"name\":\"Status\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"status\"],\"schema\"\ + :{\"type\":\"status\",\"system\":\"status\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=DFEB7770E9D27B2E88E1693E54937AF2; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x881x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [gsma0i] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["9557"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1ERkVCNzc3MEU5RDI3QjJFODhFMTY5M0U1NDkzN0FGMjsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT181ODQ5OWQ0NjczZGUwMjZlOTdhZGUxM2Y0YjU5 + Y2IxNTFmNjAwOTJjX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issuetype/10000 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Thu, 04 Apr 2019 08:47:50 GMT"] + Set-Cookie: [JSESSIONID=CFC29C747288A6659FA67FDC373E6DF5; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [527x882x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [45y3el] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["287"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_task_epic.yaml b/connector_jira/tests/fixtures/cassettes/test_import_task_epic.yaml new file mode 100644 index 000000000..c70daa12a --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_task_epic.yaml @@ -0,0 +1,404 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:52:03.017+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:52:03 GMT"] + Set-Cookie: + [ + JSESSIONID=0B35641D29E8A8BC5CC7DC552B4BD010; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_dfde8680c1b7b5fd0abd1f5fdad56a9d3eddef6d_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [712x1x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [ihy8d5] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD0wQjM1NjQxRDI5RThBOEJDNUNDN0RDNTUyQjRCRDAxMDsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kZmRlODY4MGMxYjdiNWZkMGFiZDFmNWZkYWQ1 + NmE5ZDNlZGRlZjZkX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:52:03 GMT"] + Set-Cookie: [JSESSIONID=17827319AAF981E5BE8654372F302957; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [712x2x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [15mykmh] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD0xNzgyNzMxOUFBRjk4MUU1QkU4NjU0MzcyRjMwMjk1NzsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kZmRlODY4MGMxYjdiNWZkMGFiZDFmNWZkYWQ1 + NmE5ZDNlZGRlZjZkX2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10000?expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10000","self":"http://jira:8080/rest/api/2/issue/10000","key":"TEST-1","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false},"timespent":3600,"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[],"aggregatetimespent":3600,"resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":"0|hzzzzz:","customfield_10106":null,"resolutiondate":null,"workratio":-1,"lastViewed":"2019-04-08T13:51:13.798+0000","watches":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/watchers","watchCount":1,"isWatching":true},"created":"2019-04-04T09:31:27.779+0000","priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":null,"customfield_10102":{"self":"http://jira:8080/rest/api/2/customFieldOption/10000","value":"To + Do","id":"10000"},"labels":[],"customfield_10103":"Epic1","timeestimate":0,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2019-04-04T11:01:47.600+0000","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"components":[],"timeoriginalestimate":null,"description":null,"timetracking":{"remainingEstimate":"0m","timeSpent":"1h","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":0,"customfield_10208":null,"summary":"Epic1","creator":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"subtasks":[],"reporter":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@771fe2ca[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@21a6f48f[overall=PullRequestOverallBean{stateCount=0, + state=''OPEN'', details=PullRequestOverallDetails{openCount=0, + mergedCount=0, declinedCount=0}},byInstanceType={}], + build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@2057762a[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@3643fc23[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6748c131[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@79424108[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@623f8e2c[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@4bb4d4ac[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6ad4c5a2[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@1f593f1[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@1fa5230d[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@72d995e1[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], + devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":3600,"total":3600,"percent":100},"customfield_10200":null,"customfield_10201":[],"customfield_10202":null,"environment":null,"duedate":null,"progress":{"progress":3600,"total":3600,"percent":100},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"write + tests","created":"2019-04-04T11:01:47.597+0000","updated":"2019-04-04T11:01:47.597+0000","started":"2019-04-04T11:01:00.000+0000","timeSpent":"1h","timeSpentSeconds":3600,"id":"10000","issueId":"10000"}]}},"renderedFields":{"issuetype":null,"timespent":"1 + hour","project":null,"fixVersions":null,"aggregatetimespent":"1 + hour","resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":null,"customfield_10106":null,"resolutiondate":null,"workratio":null,"lastViewed":"4 + days ago 1:51 PM","watches":null,"created":"04/Apr/19 9:31 + AM","priority":null,"customfield_10100":null,"customfield_10101":null,"customfield_10102":null,"labels":null,"customfield_10103":"Epic1","timeestimate":"0 + minutes","aggregatetimeoriginalestimate":null,"versions":null,"issuelinks":null,"assignee":null,"updated":"04/Apr/19 + 11:01 + AM","status":null,"components":null,"timeoriginalestimate":null,"description":"","timetracking":{"remainingEstimate":"0 + minutes","timeSpent":"1 + hour","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":"0 + minutes","customfield_10208":null,"summary":null,"creator":null,"subtasks":null,"reporter":null,"customfield_10000":null,"aggregateprogress":null,"customfield_10200":null,"customfield_10201":null,"customfield_10202":null,"environment":"","duedate":null,"progress":null,"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":null,"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"

write + tests

","created":"04/Apr/19 11:01 AM","updated":"04/Apr/19 11:01 + AM","started":"04/Apr/19 11:01 AM","timeSpent":"1 + hour","id":"10000","issueId":"10000"}]}}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:52:03 GMT"] + Set-Cookie: [JSESSIONID=0AA628C8AF77F4629FEDE666CAB9BA57; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [712x3x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1qd7zns] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["11017"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_task_parents.yaml b/connector_jira/tests/fixtures/cassettes/test_import_task_parents.yaml new file mode 100644 index 000000000..9a2a25c5a --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_task_parents.yaml @@ -0,0 +1,1186 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:57:14.811+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: + [ + JSESSIONID=AC03FEBC180CE9ABB167DE8CD4125559; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_81281e0e590a8e0c0155e37fd43000cd4ccd1850_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x17x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [fhqoit] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT184MTI4MWUwZTU5MGE4ZTBj + MDE1NWUzN2ZkNDMwMDBjZDRjY2QxODUwX2xpbjsgSlNFU1NJT05JRD1BQzAzRkVCQzE4MENFOUFC + QjE2N0RFOENENDEyNTU1OQ== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: [JSESSIONID=D6B6D3AD83B6FF65BE08C9C8062BF2F3; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x18x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1hw1k2y] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT184MTI4MWUwZTU5MGE4ZTBj + MDE1NWUzN2ZkNDMwMDBjZDRjY2QxODUwX2xpbjsgSlNFU1NJT05JRD1ENkI2RDNBRDgzQjZGRjY1 + QkUwOEM5QzgwNjJCRjJGMw== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10002?expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://jira:8080/rest/api/2/issue/10002","key":"TEST-3","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10003","id":"10003","description":"The + sub-task of the + issue","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10316&avatarType=issuetype","name":"Sub-task","subtask":true,"avatarId":10316},"parent":{"id":"10001","key":"TEST-2","self":"http://jira:8080/rest/api/2/issue/10001","fields":{"summary":"Task1","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10002","id":"10002","description":"A + task that needs to be + done.","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype","name":"Task","subtask":false,"avatarId":10318}}},"timespent":null,"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[],"aggregatetimespent":null,"resolution":null,"customfield_10105":"0|i0000f:","resolutiondate":null,"workratio":-1,"lastViewed":"2019-04-08T13:51:09.499+0000","watches":{"self":"http://jira:8080/rest/api/2/issue/TEST-3/watchers","watchCount":1,"isWatching":true},"created":"2019-04-04T09:59:08.525+0000","priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":null,"labels":[],"timeestimate":null,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2019-04-04T09:59:08.525+0000","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"components":[],"timeoriginalestimate":null,"description":null,"timetracking":{},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":null,"customfield_10208":null,"summary":"Subtask1","creator":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"subtasks":[],"reporter":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@489fbf69[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@1013d442[overall=PullRequestOverallBean{stateCount=0, + state=''OPEN'', details=PullRequestOverallDetails{openCount=0, + mergedCount=0, declinedCount=0}},byInstanceType={}], + build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@7621c65a[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@789ead18[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@174fbda5[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@5613affb[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@2ef8b075[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@23032edf[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@494b1d8f[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@26c1f2a[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@69fc6c0a[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@53b3c23c[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], + devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":0,"total":0},"customfield_10200":null,"customfield_10201":[],"customfield_10202":null,"environment":null,"duedate":null,"progress":{"progress":0,"total":0},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"http://jira:8080/rest/api/2/issue/TEST-3/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":0,"worklogs":[]}},"renderedFields":{"issuetype":null,"timespent":null,"project":null,"fixVersions":null,"aggregatetimespent":null,"resolution":null,"customfield_10105":null,"resolutiondate":null,"workratio":null,"lastViewed":"4 + days ago 1:51 PM","watches":null,"created":"04/Apr/19 9:59 + AM","priority":null,"customfield_10100":null,"customfield_10101":null,"labels":null,"timeestimate":null,"aggregatetimeoriginalestimate":null,"versions":null,"issuelinks":null,"assignee":null,"updated":"04/Apr/19 + 9:59 + AM","status":null,"components":null,"timeoriginalestimate":null,"description":"","timetracking":{},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":null,"customfield_10208":null,"summary":null,"creator":null,"subtasks":null,"reporter":null,"customfield_10000":null,"aggregateprogress":null,"customfield_10200":null,"customfield_10201":null,"customfield_10202":null,"environment":"","duedate":null,"progress":null,"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":null,"worklog":{"startAt":0,"maxResults":20,"total":0,"worklogs":[]}}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: [JSESSIONID=84C25F8E9064C9502E1975414747C9E5; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x19x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [146ru0s] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["8367"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:57:14.971+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: + [ + JSESSIONID=9722C21A1974ED419E57ADF5E6A0A5D1; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_6a93cbcb7d3f1d53e9d7128acc5b410609b30cf4_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x20x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [zqt63m] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT182YTkzY2JjYjdkM2YxZDUz + ZTlkNzEyOGFjYzViNDEwNjA5YjMwY2Y0X2xpbjsgSlNFU1NJT05JRD05NzIyQzIxQTE5NzRFRDQx + OUU1N0FERjVFNkEwQTVEMQ== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: [JSESSIONID=E46445E383F96976613868E9DC7754D0; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x21x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [17vr3t6] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT182YTkzY2JjYjdkM2YxZDUz + ZTlkNzEyOGFjYzViNDEwNjA5YjMwY2Y0X2xpbjsgSlNFU1NJT05JRD1FNDY0NDVFMzgzRjk2OTc2 + NjEzODY4RTlEQzc3NTREMA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10001?expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10001","self":"http://jira:8080/rest/api/2/issue/10001","key":"TEST-2","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10002","id":"10002","description":"A + task that needs to be + done.","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype","name":"Task","subtask":false,"avatarId":10318},"timespent":null,"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[],"aggregatetimespent":null,"resolution":null,"customfield_10105":"0|i00007:","resolutiondate":null,"workratio":-1,"lastViewed":"2019-04-08T13:51:10.599+0000","watches":{"self":"http://jira:8080/rest/api/2/issue/TEST-2/watchers","watchCount":1,"isWatching":true},"created":"2019-04-04T09:58:51.611+0000","priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":"TEST-1","labels":[],"timeestimate":null,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2019-04-04T09:58:51.785+0000","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"components":[],"timeoriginalestimate":16200,"description":"my + task","timetracking":{},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":null,"customfield_10208":null,"summary":"Task1","creator":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"subtasks":[{"id":"10002","key":"TEST-3","self":"http://jira:8080/rest/api/2/issue/10002","fields":{"summary":"Subtask1","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10003","id":"10003","description":"The + sub-task of the + issue","iconUrl":"http://jira:8080/secure/viewavatar?size=xsmall&avatarId=10316&avatarType=issuetype","name":"Sub-task","subtask":true,"avatarId":10316}}}],"reporter":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@6ab31ded[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6088f7fa[overall=PullRequestOverallBean{stateCount=0, + state=''OPEN'', details=PullRequestOverallDetails{openCount=0, + mergedCount=0, declinedCount=0}},byInstanceType={}], + build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@285ed1c0[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@f4ec416[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@35fd8a5c[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@6848a736[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@3646bb2e[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@4f51a784[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@16a76b58[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@3b7b0fad[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@38e74c27[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@7a48b138[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], + devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":0,"total":0},"customfield_10200":null,"customfield_10201":[],"customfield_10202":null,"environment":null,"duedate":null,"progress":{"progress":0,"total":0},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"http://jira:8080/rest/api/2/issue/TEST-2/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":0,"worklogs":[]}},"renderedFields":{"issuetype":null,"timespent":null,"project":null,"fixVersions":null,"aggregatetimespent":null,"resolution":null,"customfield_10105":null,"resolutiondate":null,"workratio":null,"lastViewed":"4 + days ago 1:51 PM","watches":null,"created":"04/Apr/19 9:58 + AM","priority":null,"customfield_10100":null,"customfield_10101":null,"labels":null,"timeestimate":null,"aggregatetimeoriginalestimate":null,"versions":null,"issuelinks":null,"assignee":null,"updated":"04/Apr/19 + 9:58 + AM","status":null,"components":null,"timeoriginalestimate":null,"description":"

my + task

","timetracking":{},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":null,"customfield_10208":null,"summary":null,"creator":null,"subtasks":null,"reporter":null,"customfield_10000":null,"aggregateprogress":null,"customfield_10200":null,"customfield_10201":null,"customfield_10202":null,"environment":"","duedate":null,"progress":null,"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":null,"worklog":{"startAt":0,"maxResults":20,"total":0,"worklogs":[]}}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: [JSESSIONID=AAAE42B93B4068D0CC1FED38ACCC6E57; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x22x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1w9kbon] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["8380"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:57:15.124+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: + [ + JSESSIONID=7FACEC51AC4A23F22785C6ACB8F2EED4; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_6aa3f50fae154bab6503e40913058121ee094621_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x23x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [19uxopc] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT182YWEzZjUwZmFlMTU0YmFi + NjUwM2U0MDkxMzA1ODEyMWVlMDk0NjIxX2xpbjsgSlNFU1NJT05JRD03RkFDRUM1MUFDNEEyM0Yy + Mjc4NUM2QUNCOEYyRUVENA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: [JSESSIONID=498D25C4EC682CF181F4BF07647A35AF; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x24x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [82xaep] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT182YWEzZjUwZmFlMTU0YmFi + NjUwM2U0MDkxMzA1ODEyMWVlMDk0NjIxX2xpbjsgSlNFU1NJT05JRD00OThEMjVDNEVDNjgyQ0Yx + ODFGNEJGMDc2NDdBMzVBRg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/TEST-1?expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10000","self":"http://jira:8080/rest/api/2/issue/10000","key":"TEST-1","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false},"timespent":3600,"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[],"aggregatetimespent":3600,"resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":"0|hzzzzz:","customfield_10106":null,"resolutiondate":null,"workratio":-1,"lastViewed":"2019-04-08T13:51:13.798+0000","watches":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/watchers","watchCount":1,"isWatching":true},"created":"2019-04-04T09:31:27.779+0000","priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":null,"customfield_10102":{"self":"http://jira:8080/rest/api/2/customFieldOption/10000","value":"To + Do","id":"10000"},"labels":[],"customfield_10103":"Epic1","timeestimate":0,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2019-04-04T11:01:47.600+0000","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"components":[],"timeoriginalestimate":null,"description":null,"timetracking":{"remainingEstimate":"0m","timeSpent":"1h","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":0,"customfield_10208":null,"summary":"Epic1","creator":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"subtasks":[],"reporter":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@46151be0[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@c6676c6[overall=PullRequestOverallBean{stateCount=0, + state=''OPEN'', details=PullRequestOverallDetails{openCount=0, + mergedCount=0, declinedCount=0}},byInstanceType={}], + build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@37fd2236[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@812a249[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@644e012f[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@72c64b18[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@2c743be4[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@3169d4c9[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@25baecb2[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@6564ed96[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@684241c5[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@17f21f98[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], + devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":3600,"total":3600,"percent":100},"customfield_10200":null,"customfield_10201":[],"customfield_10202":null,"environment":null,"duedate":null,"progress":{"progress":3600,"total":3600,"percent":100},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"write + tests","created":"2019-04-04T11:01:47.597+0000","updated":"2019-04-04T11:01:47.597+0000","started":"2019-04-04T11:01:00.000+0000","timeSpent":"1h","timeSpentSeconds":3600,"id":"10000","issueId":"10000"}]}},"renderedFields":{"issuetype":null,"timespent":"1 + hour","project":null,"fixVersions":null,"aggregatetimespent":"1 + hour","resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":null,"customfield_10106":null,"resolutiondate":null,"workratio":null,"lastViewed":"4 + days ago 1:51 PM","watches":null,"created":"04/Apr/19 9:31 + AM","priority":null,"customfield_10100":null,"customfield_10101":null,"customfield_10102":null,"labels":null,"customfield_10103":"Epic1","timeestimate":"0 + minutes","aggregatetimeoriginalestimate":null,"versions":null,"issuelinks":null,"assignee":null,"updated":"04/Apr/19 + 11:01 + AM","status":null,"components":null,"timeoriginalestimate":null,"description":"","timetracking":{"remainingEstimate":"0 + minutes","timeSpent":"1 + hour","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":"0 + minutes","customfield_10208":null,"summary":null,"creator":null,"subtasks":null,"reporter":null,"customfield_10000":null,"aggregateprogress":null,"customfield_10200":null,"customfield_10201":null,"customfield_10202":null,"environment":"","duedate":null,"progress":null,"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":null,"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"

write + tests

","created":"04/Apr/19 11:01 AM","updated":"04/Apr/19 11:01 + AM","started":"04/Apr/19 11:01 AM","timeSpent":"1 + hour","id":"10000","issueId":"10000"}]}}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:57:14 GMT"] + Set-Cookie: [JSESSIONID=C85F6614B10F4A49D1B8ED8A958822A3; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [717x25x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1ab5ubx] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["11016"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_task_type_not_synced.yaml b/connector_jira/tests/fixtures/cassettes/test_import_task_type_not_synced.yaml new file mode 100644 index 000000000..324bfb23a --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_task_type_not_synced.yaml @@ -0,0 +1,404 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:53:50.149+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:50 GMT"] + Set-Cookie: + [ + JSESSIONID=31A2C97F2E40FA6B0D07924080084C0C; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_1d370cc626337730b6cfb3a60590d620c501c619_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x14x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [10csrkv] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD0zMUEyQzk3RjJFNDBGQTZCMEQwNzkyNDA4MDA4NEMwQzsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18xZDM3MGNjNjI2MzM3NzMwYjZjZmIzYTYwNTkw + ZDYyMGM1MDFjNjE5X2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:50 GMT"] + Set-Cookie: [JSESSIONID=CDEAC0520AA7D8545A7C6B3CB60BAC35; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x15x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1a8k0ao] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + SlNFU1NJT05JRD1DREVBQzA1MjBBQTdEODU0NUE3QzZCM0NCNjBCQUMzNTsgYXRsYXNzaWFuLnhz + cmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18xZDM3MGNjNjI2MzM3NzMwYjZjZmIzYTYwNTkw + ZDYyMGM1MDFjNjE5X2xpbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10000?expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10000","self":"http://jira:8080/rest/api/2/issue/10000","key":"TEST-1","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false},"timespent":3600,"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[],"aggregatetimespent":3600,"resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":"0|hzzzzz:","customfield_10106":null,"resolutiondate":null,"workratio":-1,"lastViewed":"2019-04-08T13:51:13.798+0000","watches":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/watchers","watchCount":1,"isWatching":true},"created":"2019-04-04T09:31:27.779+0000","priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":null,"customfield_10102":{"self":"http://jira:8080/rest/api/2/customFieldOption/10000","value":"To + Do","id":"10000"},"labels":[],"customfield_10103":"Epic1","timeestimate":0,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2019-04-04T11:01:47.600+0000","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"components":[],"timeoriginalestimate":null,"description":null,"timetracking":{"remainingEstimate":"0m","timeSpent":"1h","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":0,"customfield_10208":null,"summary":"Epic1","creator":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"subtasks":[],"reporter":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@e2accf2[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@75023da6[overall=PullRequestOverallBean{stateCount=0, + state=''OPEN'', details=PullRequestOverallDetails{openCount=0, + mergedCount=0, declinedCount=0}},byInstanceType={}], + build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@3b04e3e4[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@5f8f162f[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@2d4514d5[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@4149dffb[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@5dce0ff5[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@7a57440d[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@7fb1142e[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@7008aa24[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@5d14b277[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@1da3f2f4[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], + devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":3600,"total":3600,"percent":100},"customfield_10200":null,"customfield_10201":[],"customfield_10202":null,"environment":null,"duedate":null,"progress":{"progress":3600,"total":3600,"percent":100},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"write + tests","created":"2019-04-04T11:01:47.597+0000","updated":"2019-04-04T11:01:47.597+0000","started":"2019-04-04T11:01:00.000+0000","timeSpent":"1h","timeSpentSeconds":3600,"id":"10000","issueId":"10000"}]}},"renderedFields":{"issuetype":null,"timespent":"1 + hour","project":null,"fixVersions":null,"aggregatetimespent":"1 + hour","resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":null,"customfield_10106":null,"resolutiondate":null,"workratio":null,"lastViewed":"4 + days ago 1:51 PM","watches":null,"created":"04/Apr/19 9:31 + AM","priority":null,"customfield_10100":null,"customfield_10101":null,"customfield_10102":null,"labels":null,"customfield_10103":"Epic1","timeestimate":"0 + minutes","aggregatetimeoriginalestimate":null,"versions":null,"issuelinks":null,"assignee":null,"updated":"04/Apr/19 + 11:01 + AM","status":null,"components":null,"timeoriginalestimate":null,"description":"","timetracking":{"remainingEstimate":"0 + minutes","timeSpent":"1 + hour","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":"0 + minutes","customfield_10208":null,"summary":null,"creator":null,"subtasks":null,"reporter":null,"customfield_10000":null,"aggregateprogress":null,"customfield_10200":null,"customfield_10201":null,"customfield_10202":null,"environment":"","duedate":null,"progress":null,"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":null,"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"

write + tests

","created":"04/Apr/19 11:01 AM","updated":"04/Apr/19 11:01 + AM","started":"04/Apr/19 11:01 AM","timeSpent":"1 + hour","id":"10000","issueId":"10000"}]}}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:50 GMT"] + Set-Cookie: [JSESSIONID=5B3313BF88023AA8365D8DEF3336DE74; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x16x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [28r26a] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["11017"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/fixtures/cassettes/test_import_worklog.yaml b/connector_jira/tests/fixtures/cassettes/test_import_worklog.yaml new file mode 100644 index 000000000..c08cb17ee --- /dev/null +++ b/connector_jira/tests/fixtures/cassettes/test_import_worklog.yaml @@ -0,0 +1,1204 @@ +interactions: + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:53:17.218+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: + [ + JSESSIONID=EF243EE22A4CEB877EBB4FF7E8C2A583; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_0acbb764967241cbca7225285c42b37386f26d2c_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x5x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1qjcn8p] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18wYWNiYjc2NDk2NzI0MWNi + Y2E3MjI1Mjg1YzQyYjM3Mzg2ZjI2ZDJjX2xpbjsgSlNFU1NJT05JRD1FRjI0M0VFMjJBNENFQjg3 + N0VCQjRGRjdFOEMyQTU4Mw== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=A1C8E46E1CFCAA70306AEC27313C8A98; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x6x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [mgigu3] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT18wYWNiYjc2NDk2NzI0MWNi + Y2E3MjI1Mjg1YzQyYjM3Mzg2ZjI2ZDJjX2xpbjsgSlNFU1NJT05JRD1BMUM4RTQ2RTFDRkNBQTcw + MzA2QUVDMjczMTNDOEE5OA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10000?expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10000","self":"http://jira:8080/rest/api/2/issue/10000","key":"TEST-1","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false},"timespent":3600,"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"fixVersions":[],"aggregatetimespent":3600,"resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":"0|hzzzzz:","customfield_10106":null,"resolutiondate":null,"workratio":-1,"lastViewed":"2019-04-08T13:51:13.798+0000","watches":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/watchers","watchCount":1,"isWatching":true},"created":"2019-04-04T09:31:27.779+0000","priority":{"self":"http://jira:8080/rest/api/2/priority/3","iconUrl":"http://jira:8080/images/icons/priorities/medium.svg","name":"Medium","id":"3"},"customfield_10100":null,"customfield_10101":null,"customfield_10102":{"self":"http://jira:8080/rest/api/2/customFieldOption/10000","value":"To + Do","id":"10000"},"labels":[],"customfield_10103":"Epic1","timeestimate":0,"aggregatetimeoriginalestimate":null,"versions":[],"issuelinks":[],"assignee":null,"updated":"2019-04-04T09:01:47.600+0000","status":{"self":"http://jira:8080/rest/api/2/status/10000","description":"","iconUrl":"http://jira:8080/","name":"To + Do","id":"10000","statusCategory":{"self":"http://jira:8080/rest/api/2/statuscategory/2","id":2,"key":"new","colorName":"blue-gray","name":"To + Do"}},"components":[],"timeoriginalestimate":null,"description":null,"timetracking":{"remainingEstimate":"0m","timeSpent":"1h","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":0,"customfield_10208":null,"summary":"Epic1","creator":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"subtasks":[],"reporter":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"customfield_10000":"{summaryBean=com.atlassian.jira.plugin.devstatus.rest.SummaryBean@719555b6[summary={pullrequest=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@485d26cf[overall=PullRequestOverallBean{stateCount=0, + state=''OPEN'', details=PullRequestOverallDetails{openCount=0, + mergedCount=0, declinedCount=0}},byInstanceType={}], + build=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6ba664e3[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BuildOverallBean@4a6c4c06[failedBuildCount=0,successfulBuildCount=0,unknownBuildCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + review=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@2f4012ac[overall=com.atlassian.jira.plugin.devstatus.summary.beans.ReviewsOverallBean@32e5c083[stateCount=0,state=,dueDate=,overDue=false,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + deployment-environment=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6abc2b40[overall=com.atlassian.jira.plugin.devstatus.summary.beans.DeploymentOverallBean@4298566d[topEnvironments=[],showProjects=false,successfulCount=0,count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + repository=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@6de2f9e0[overall=com.atlassian.jira.plugin.devstatus.summary.beans.CommitOverallBean@719fdd07[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}], + branch=com.atlassian.jira.plugin.devstatus.rest.SummaryItemBean@7af21e5f[overall=com.atlassian.jira.plugin.devstatus.summary.beans.BranchOverallBean@7a591452[count=0,lastUpdated=,lastUpdatedTimestamp=],byInstanceType={}]},errors=[],configErrors=[]], + devSummaryJson={\"cachedValue\":{\"errors\":[],\"configErrors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":\"OPEN\",\"details\":{\"openCount\":0,\"mergedCount\":0,\"declinedCount\":0,\"total\":0},\"open\":true},\"byInstanceType\":{}},\"build\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"failedBuildCount\":0,\"successfulBuildCount\":0,\"unknownBuildCount\":0},\"byInstanceType\":{}},\"review\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"stateCount\":0,\"state\":null,\"dueDate\":null,\"overDue\":false,\"completed\":false},\"byInstanceType\":{}},\"deployment-environment\":{\"overall\":{\"count\":0,\"lastUpdated\":null,\"topEnvironments\":[],\"showProjects\":false,\"successfulCount\":0},\"byInstanceType\":{}},\"repository\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}},\"branch\":{\"overall\":{\"count\":0,\"lastUpdated\":null},\"byInstanceType\":{}}}},\"isStale\":false}}","aggregateprogress":{"progress":3600,"total":3600,"percent":100},"customfield_10200":null,"customfield_10201":[],"customfield_10202":null,"environment":null,"duedate":null,"progress":{"progress":3600,"total":3600,"percent":100},"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":{"self":"http://jira:8080/rest/api/2/issue/TEST-1/votes","votes":0,"hasVoted":false},"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"write + tests","created":"2019-04-04T04:01:47.597+0800","updated":"2019-04-04T04:01:47.597+0800","started":"2019-04-04T11:01:00.000+0000","timeSpent":"1h","timeSpentSeconds":3600,"id":"10000","issueId":"10000"}]}},"renderedFields":{"issuetype":null,"timespent":"1 + hour","project":null,"fixVersions":null,"aggregatetimespent":"1 + hour","resolution":null,"customfield_10104":"ghx-label-1","customfield_10105":null,"customfield_10106":null,"resolutiondate":null,"workratio":null,"lastViewed":"4 + days ago 1:51 PM","watches":null,"created":"04/Apr/19 9:31 + AM","priority":null,"customfield_10100":null,"customfield_10101":null,"customfield_10102":null,"labels":null,"customfield_10103":"Epic1","timeestimate":"0 + minutes","aggregatetimeoriginalestimate":null,"versions":null,"issuelinks":null,"assignee":null,"updated":"04/Apr/19 + 11:01 + AM","status":null,"components":null,"timeoriginalestimate":null,"description":"","timetracking":{"remainingEstimate":"0 + minutes","timeSpent":"1 + hour","remainingEstimateSeconds":0,"timeSpentSeconds":3600},"customfield_10203":null,"customfield_10204":null,"customfield_10205":null,"customfield_10206":null,"attachment":[],"customfield_10207":null,"aggregatetimeestimate":"0 + minutes","customfield_10208":null,"summary":null,"creator":null,"subtasks":null,"reporter":null,"customfield_10000":null,"aggregateprogress":null,"customfield_10200":null,"customfield_10201":null,"customfield_10202":null,"environment":"","duedate":null,"progress":null,"comment":{"comments":[],"maxResults":0,"total":0,"startAt":0},"votes":null,"worklog":{"startAt":0,"maxResults":20,"total":1,"worklogs":[{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"

write + tests

","created":"04/Apr/19 11:01 AM","updated":"04/Apr/19 11:01 + AM","started":"04/Apr/19 11:01 AM","timeSpent":"1 + hour","id":"10000","issueId":"10000"}]}}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=C98D19B85587CE17D9ED9CB5008CD8FE; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x7x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [vk7a84] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["11018"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:53:17.374+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: + [ + JSESSIONID=22809D6A41FD663F3A5064AEAC8863D5; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_dd01e5c0416c4fb409c96df11192b24103f7b64c_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x8x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1lllcl0] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kZDAxZTVjMDQxNmM0ZmI0 + MDljOTZkZjExMTkyYjI0MTAzZjdiNjRjX2xpbjsgSlNFU1NJT05JRD0yMjgwOUQ2QTQxRkQ2NjNG + M0E1MDY0QUVBQzg4NjNENQ== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=72CF3EFB88A8C3EFEDF4834B124E2963; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x9x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1da81bn] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kZDAxZTVjMDQxNmM0ZmI0 + MDljOTZkZjExMTkyYjI0MTAzZjdiNjRjX2xpbjsgSlNFU1NJT05JRD03MkNGM0VGQjg4QThDM0VG + RURGNDgzNEIxMjRFMjk2Mw== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10000/worklog/10000 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"write + tests","created":"2019-04-04T04:01:47.597+0800","updated":"2019-04-04T04:01:47.597+0800","started":"2019-04-04T04:01:47.597+0800","timeSpent":"1h","timeSpentSeconds":3600,"id":"10000","issueId":"10000"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=FF2EBA4C55F6FEA7747853DD2BA77F96; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x10x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [nxenvu] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["1449"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/serverInfo + response: + body: + { + string: '{"baseUrl":"http://localhost:8080","version":"7.12.3","versionNumbers":[7,12,3],"deploymentType":"Server","buildNumber":712004,"buildDate":"2018-10-12T00:00:00.000+0000","serverTime":"2019-04-12T11:53:17.482+0000","scmInfo":"5ef91d760d7124da5ebec5c16a948a4a807698df","serverTitle":"Jira"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: + [ + JSESSIONID=F93CF9F9B131BA6C1A3EE7A77C17CC5D; Path=/; HttpOnly, + atlassian.xsrf.token=BYG3-6SPF-0UM1-2LBO_ae6885b7bd01fc12e6636ca02e0932972ab01dcb_lin; + Path=/, + ] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x11x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [1so3bd3] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["288"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19hZTY4ODViN2JkMDFmYzEy + ZTY2MzZjYTAyZTA5MzI5NzJhYjAxZGNiX2xpbjsgSlNFU1NJT05JRD1GOTNDRjlGOUIxMzFCQTZD + MUEzRUU3QTc3QzE3Q0M1RA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/field + response: + body: {string: "[{\"id\":\"issuetype\",\"name\":\"Issue + Type\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + issuetype\",\"type\"],\"schema\":{\"type\":\"issuetype\",\"system\":\"issuetype\"\ + }},{\"id\":\"timespent\",\"name\":\"Time + Spent\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"timespent\"\ + ],\"schema\":{\"type\":\"number\",\"system\":\"timespent\"}},{\"id\":\"project\"\ + ,\"name\":\"Project\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"project\"],\"schema\":{\"type\":\"project\"\ + ,\"system\":\"project\"}},{\"id\":\"fixVersions\",\"name\":\"Fix + Version/s\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"fixVersion\"],\"schema\":{\"type\":\"array\",\"items\":\"\ + version\",\"system\":\"fixVersions\"}},{\"id\":\"aggregatetimespent\",\"name\"\ + :\"\u03A3 Time Spent\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimespent\"}},{\"id\":\"resolution\",\"name\":\"Resolution\"\ + ,\"custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"resolution\"],\"schema\":{\"type\":\"resolution\",\"system\"\ + :\"resolution\"}},{\"id\":\"customfield_10104\",\"name\":\"Epic Color\",\"\ + custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10104]\",\"Epic + Color\"],\"schema\":{\"type\":\"string\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-color\",\"customId\":10104}},{\"\ + id\":\"customfield_10105\",\"name\":\"Rank\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10105]\"\ + ,\"Rank\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-lexo-rank\"\ + ,\"customId\":10105}},{\"id\":\"customfield_10106\",\"name\":\"Story + Points\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10106]\",\"Story + Points\"],\"schema\":{\"type\":\"number\"\ + ,\"custom\":\"com.atlassian.jira.plugin.system.customfieldtypes:float\",\"\ + customId\":10106}},{\"id\":\"resolutiondate\",\"name\":\"Resolved\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"resolutiondate\",\"resolved\"],\"schema\":{\"type\":\"datetime\",\"system\"\ + :\"resolutiondate\"}},{\"id\":\"workratio\",\"name\":\"Work + Ratio\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"workratio\"],\"schema\":{\"type\":\"number\",\"system\":\"workratio\"\ + }},{\"id\":\"lastViewed\",\"name\":\"Last + Viewed\",\"custom\":false,\"orderable\"\ + :false,\"navigable\":true,\"searchable\":false,\"clauseNames\":[\"lastViewed\"\ + ],\"schema\":{\"type\":\"datetime\",\"system\":\"lastViewed\"}},{\"id\":\"\ + watches\",\"name\":\"Watchers\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[\"watchers\"],\"schema\":{\"type\"\ + :\"watches\",\"system\":\"watches\"}},{\"id\":\"thumbnail\",\"name\":\"Images\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[]},{\"id\":\"created\",\"name\":\"Created\",\"custom\":false,\"\ + orderable\":false,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + created\",\"createdDate\"],\"schema\":{\"type\":\"datetime\",\"system\":\"\ + created\"}},{\"id\":\"priority\",\"name\":\"Priority\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + priority\"],\"schema\":{\"type\":\"priority\",\"system\":\"priority\"}},{\"\ + id\":\"customfield_10100\",\"name\":\"Sprint\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10100]\"\ + ,\"Sprint\"],\"schema\":{\"type\":\"array\",\"items\":\"string\",\"custom\"\ + :\"com.pyxis.greenhopper.jira:gh-sprint\",\"customId\":10100}},{\"id\":\"\ + customfield_10101\",\"name\":\"Epic + Link\",\"custom\":true,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10101]\",\"Epic\ + \ + Link\"],\"schema\":{\"type\":\"any\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-link\"\ + ,\"customId\":10101}},{\"id\":\"customfield_10102\",\"name\":\"Epic + Status\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10102]\",\"Epic + Status\"],\"schema\":{\"type\":\"option\"\ + ,\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-status\",\"customId\":10102}},{\"\ + id\":\"labels\",\"name\":\"Labels\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"labels\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"string\",\"system\":\"labels\"}},{\"id\"\ + :\"customfield_10103\",\"name\":\"Epic Name\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"cf[10103]\"\ + ,\"Epic + Name\"],\"schema\":{\"type\":\"string\",\"custom\":\"com.pyxis.greenhopper.jira:gh-epic-label\"\ + ,\"customId\":10103}},{\"id\":\"timeestimate\",\"name\":\"Remaining + Estimate\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"\ + clauseNames\":[\"remainingEstimate\",\"timeestimate\"],\"schema\":{\"type\"\ + :\"number\",\"system\":\"timeestimate\"}},{\"id\":\"aggregatetimeoriginalestimate\"\ + ,\"name\":\"\u03A3 Original + Estimate\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"number\",\"system\":\"aggregatetimeoriginalestimate\"}},{\"id\":\"versions\"\ + ,\"name\":\"Affects + Version/s\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :true,\"searchable\":true,\"clauseNames\":[\"affectedVersion\"],\"schema\"\ + :{\"type\":\"array\",\"items\":\"version\",\"system\":\"versions\"}},{\"id\"\ + :\"issuelinks\",\"name\":\"Linked Issues\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[],\"schema\"\ + :{\"type\":\"array\",\"items\":\"issuelinks\",\"system\":\"issuelinks\"}},{\"\ + id\":\"assignee\",\"name\":\"Assignee\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"assignee\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"assignee\"}},{\"id\":\"updated\",\"name\"\ + :\"Updated\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"updated\",\"updatedDate\"],\"schema\":{\"type\":\"\ + datetime\",\"system\":\"updated\"}},{\"id\":\"status\",\"name\":\"Status\"\ + ,\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"status\"],\"schema\":{\"type\":\"status\",\"system\":\"status\"\ + }},{\"id\":\"components\",\"name\":\"Component/s\",\"custom\":false,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"component\"\ + ],\"schema\":{\"type\":\"array\",\"items\":\"component\",\"system\":\"components\"\ + }},{\"id\":\"issuekey\",\"name\":\"Key\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"id\",\"issue\",\"\ + issuekey\",\"key\"]},{\"id\":\"timeoriginalestimate\",\"name\":\"Original\ + \ + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[\"originalEstimate\",\"timeoriginalestimate\"],\"\ + schema\":{\"type\":\"number\",\"system\":\"timeoriginalestimate\"}},{\"id\"\ + :\"description\",\"name\":\"Description\",\"custom\":false,\"orderable\":true,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"description\"],\"\ + schema\":{\"type\":\"string\",\"system\":\"description\"}},{\"id\":\"timetracking\"\ + ,\"name\":\"Time + Tracking\",\"custom\":false,\"orderable\":true,\"navigable\"\ + :false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\":\"timetracking\"\ + ,\"system\":\"timetracking\"}},{\"id\":\"customfield_10203\",\"name\":\"Organizations\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10203]\",\"Organizations\"],\"schema\":{\"type\":\"array\"\ + ,\"items\":\"sd-customerorganization\",\"custom\":\"com.atlassian.servicedesk:sd-customer-organizations\"\ + ,\"customId\":10203}},{\"id\":\"customfield_10204\",\"name\":\"Satisfaction\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10204]\",\"Satisfaction\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.servicedesk:sd-request-feedback\",\"customId\"\ + :10204}},{\"id\":\"security\",\"name\":\"Security + Level\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + level\"],\"schema\":{\"type\":\"securitylevel\",\"system\":\"security\"}},{\"\ + id\":\"customfield_10205\",\"name\":\"Satisfaction + date\",\"custom\":true,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + cf[10205]\",\"Satisfaction + date\"],\"schema\":{\"type\":\"datetime\",\"custom\"\ + :\"com.atlassian.servicedesk:sd-request-feedback-date\",\"customId\":10205}},{\"\ + id\":\"customfield_10206\",\"name\":\"Approvers\",\"custom\":true,\"orderable\"\ + :true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"Approvers\"\ + ,\"cf[10206]\"],\"schema\":{\"type\":\"array\",\"items\":\"user\",\"custom\"\ + :\"com.atlassian.jira.plugin.system.customfieldtypes:multiuserpicker\",\"\ + customId\":10206}},{\"id\":\"attachment\",\"name\":\"Attachment\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":false,\"searchable\":true,\"clauseNames\"\ + :[\"attachments\"],\"schema\":{\"type\":\"array\",\"items\":\"attachment\"\ + ,\"system\":\"attachment\"}},{\"id\":\"aggregatetimeestimate\",\"name\":\"\ + \u03A3 Remaining + Estimate\",\"custom\":false,\"orderable\":false,\"navigable\"\ + :true,\"searchable\":false,\"clauseNames\":[],\"schema\":{\"type\":\"number\"\ + ,\"system\":\"aggregatetimeestimate\"}},{\"id\":\"customfield_10207\",\"name\"\ + :\"Time to + resolution\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"cf[10207]\",\"Time to resolution\"],\"\ + schema\":{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10207}},{\"id\":\"customfield_10208\",\"name\":\"Time to + first\ + \ + response\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10208]\",\"Time to first response\"],\"schema\"\ + :{\"type\":\"sd-servicelevelagreement\",\"custom\":\"com.atlassian.servicedesk:sd-sla-field\"\ + ,\"customId\":10208}},{\"id\":\"summary\",\"name\":\"Summary\",\"custom\"\ + :false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\"\ + :[\"summary\"],\"schema\":{\"type\":\"string\",\"system\":\"summary\"}},{\"\ + id\":\"creator\",\"name\":\"Creator\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":true,\"clauseNames\":[\"creator\"],\"schema\"\ + :{\"type\":\"user\",\"system\":\"creator\"}},{\"id\":\"subtasks\",\"name\"\ + :\"Sub-Tasks\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"\ + searchable\":false,\"clauseNames\":[\"subtasks\"],\"schema\":{\"type\":\"\ + array\",\"items\":\"issuelinks\",\"system\":\"subtasks\"}},{\"id\":\"reporter\"\ + ,\"name\":\"Reporter\",\"custom\":false,\"orderable\":true,\"navigable\":true,\"\ + searchable\":true,\"clauseNames\":[\"reporter\"],\"schema\":{\"type\":\"user\"\ + ,\"system\":\"reporter\"}},{\"id\":\"aggregateprogress\",\"name\":\"\u03A3\ + \ + Progress\",\"custom\":false,\"orderable\":false,\"navigable\":true,\"searchable\"\ + :false,\"clauseNames\":[],\"schema\":{\"type\":\"progress\",\"system\":\"\ + aggregateprogress\"}},{\"id\":\"customfield_10000\",\"name\":\"Development\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10000]\",\"Development\"],\"schema\":{\"type\":\"any\"\ + ,\"custom\":\"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary\"\ + ,\"customId\":10000}},{\"id\":\"customfield_10200\",\"name\":\"Approvals\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"Approvals\",\"cf[10200]\"],\"schema\":{\"type\":\"sd-approvals\"\ + ,\"custom\":\"com.atlassian.servicedesk.approvals-plugin:sd-approvals\",\"\ + customId\":10200}},{\"id\":\"customfield_10201\",\"name\":\"Request + participants\"\ + ,\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"cf[10201]\",\"Request participants\"],\"schema\":{\"type\"\ + :\"array\",\"items\":\"user\",\"custom\":\"com.atlassian.servicedesk:sd-request-participants\"\ + ,\"customId\":10201}},{\"id\":\"customfield_10202\",\"name\":\"Customer + Request\ + \ + Type\",\"custom\":true,\"orderable\":true,\"navigable\":true,\"searchable\"\ + :true,\"clauseNames\":[\"cf[10202]\",\"Customer Request Type\"],\"schema\"\ + :{\"type\":\"sd-customerrequesttype\",\"custom\":\"com.atlassian.servicedesk:vp-origin\"\ + ,\"customId\":10202}},{\"id\":\"environment\",\"name\":\"Environment\",\"\ + custom\":false,\"orderable\":true,\"navigable\":true,\"searchable\":true,\"\ + clauseNames\":[\"environment\"],\"schema\":{\"type\":\"string\",\"system\"\ + :\"environment\"}},{\"id\":\"duedate\",\"name\":\"Due + Date\",\"custom\":false,\"\ + orderable\":true,\"navigable\":true,\"searchable\":true,\"clauseNames\":[\"\ + due\",\"duedate\"],\"schema\":{\"type\":\"date\",\"system\":\"duedate\"}},{\"\ + id\":\"progress\",\"name\":\"Progress\",\"custom\":false,\"orderable\":false,\"\ + navigable\":true,\"searchable\":false,\"clauseNames\":[\"progress\"],\"schema\"\ + :{\"type\":\"progress\",\"system\":\"progress\"}},{\"id\":\"comment\",\"name\"\ + :\"Comment\",\"custom\":false,\"orderable\":true,\"navigable\":false,\"searchable\"\ + :true,\"clauseNames\":[\"comment\"],\"schema\":{\"type\":\"comments-page\"\ + ,\"system\":\"comment\"}},{\"id\":\"votes\",\"name\":\"Votes\",\"custom\"\ + :false,\"orderable\":false,\"navigable\":true,\"searchable\":false,\"clauseNames\"\ + :[\"votes\"],\"schema\":{\"type\":\"votes\",\"system\":\"votes\"}},{\"id\"\ + :\"worklog\",\"name\":\"Log Work\",\"custom\":false,\"orderable\":true,\"\ + navigable\":false,\"searchable\":true,\"clauseNames\":[],\"schema\":{\"type\"\ + :\"array\",\"items\":\"worklog\",\"system\":\"worklog\"}}]"} + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=E3544561B85AF48C3E7F6DFF2356BAC4; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x12x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [tze31o] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["12093"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19hZTY4ODViN2JkMDFmYzEy + ZTY2MzZjYTAyZTA5MzI5NzJhYjAxZGNiX2xpbjsgSlNFU1NJT05JRD1FMzU0NDU2MUI4NUFGNDhD + M0U3RjZERkYyMzU2QkFDNA== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/api/2/issue/10000?fields=issuetype&fields=project&fields=parent&fields=customfield_10101&expand=renderedFields + response: + body: + { + string: + '{"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations","id":"10000","self":"http://jira:8080/rest/api/2/issue/10000","key":"TEST-1","fields":{"issuetype":{"self":"http://jira:8080/rest/api/2/issuetype/10000","id":"10000","description":"Created + by Jira Software - do not edit or delete. Issue type for a big user story + that needs to be broken + down.","iconUrl":"http://jira:8080/images/icons/issuetypes/epic.svg","name":"Epic","subtask":false},"project":{"self":"http://jira:8080/rest/api/2/project/10000","id":"10000","key":"TEST","name":"TEST","avatarUrls":{"48x48":"http://jira:8080/secure/projectavatar?avatarId=10324","24x24":"http://jira:8080/secure/projectavatar?size=small&avatarId=10324","16x16":"http://jira:8080/secure/projectavatar?size=xsmall&avatarId=10324","32x32":"http://jira:8080/secure/projectavatar?size=medium&avatarId=10324"}},"customfield_10101":null},"renderedFields":{"issuetype":null,"project":null,"customfield_10101":null}}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=AB97A080AC02D262403305F7255BD6ED; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x13x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [er6uwz] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["989"] + status: {code: 200, message: ""} + - request: + body: null + headers: + Accept: + - !!binary | + YXBwbGljYXRpb24vanNvbiwqLio7cT0wLjk= + Accept-Encoding: + - !!binary | + Z3ppcCwgZGVmbGF0ZQ== + Cache-Control: + - !!binary | + bm8tY2FjaGU= + Connection: + - !!binary | + a2VlcC1hbGl2ZQ== + Content-Type: + - !!binary | + YXBwbGljYXRpb24vanNvbg== + Cookie: + - !!binary | + YXRsYXNzaWFuLnhzcmYudG9rZW49QllHMy02U1BGLTBVTTEtMkxCT19kZDAxZTVjMDQxNmM0ZmI0 + MDljOTZkZjExMTkyYjI0MTAzZjdiNjRjX2xpbjsgSlNFU1NJT05JRD03MkNGM0VGQjg4QThDM0VG + RURGNDgzNEIxMjRFMjk2Mw== + User-Agent: + - !!binary | + cHl0aG9uLXJlcXVlc3RzLzIuMjEuMA== + X-Atlassian-Token: + - !!binary | + bm8tY2hlY2s= + method: GET + uri: http://jira:8080/rest/tempo-timesheets/3/worklogs/10000 + response: + body: + { + string: + '{"self":"http://jira:8080/rest/api/2/issue/10000/worklog/10000","author":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"updateAuthor":{"self":"http://jira:8080/rest/api/2/user?username=gbaconnier","name":"gbaconnier","key":"gbaconnier","emailAddress":"guewen.baconnier@camptocamp.com","avatarUrls":{"48x48":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=48","24x24":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=24","16x16":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=16","32x32":"https://www.gravatar.com/avatar/ad252192c3f73885676b7d2e850ad13c?d=mm&s=32"},"displayName":"Guewen + Baconnier","active":true,"timeZone":"GMT"},"comment":"write + tests","created":"2019-04-04T04:01:47.597+0800","updated":"2019-04-04T04:01:47.597+0800","started":"2019-04-04T04:01:47.597+0800","timeSpent":"1h","timeSpentSeconds":3600,"id":"10000","issueId":"10000"}', + } + headers: + Cache-Control: ["no-cache, no-store, no-transform"] + Content-Security-Policy: [frame-ancestors 'self'] + Content-Type: [application/json;charset=UTF-8] + Date: ["Fri, 12 Apr 2019 11:53:17 GMT"] + Set-Cookie: [JSESSIONID=FF2EBA4C55F6FEA7747853DD2BA77F96; Path=/; HttpOnly] + Transfer-Encoding: [chunked] + Vary: [User-Agent] + X-AREQUESTID: [713x10x1] + X-ASEN: [SEN-L13384799] + X-ASESSIONID: [nxenvu] + X-AUSERNAME: [gbaconnier] + X-Content-Type-Options: [nosniff] + X-Frame-Options: [SAMEORIGIN] + X-Seraph-LoginReason: [OK] + X-XSS-Protection: [1; mode=block] + content-length: ["1449"] + status: {code: 200, message: ""} +version: 1 diff --git a/connector_jira/tests/test_auth.py b/connector_jira/tests/test_auth.py new file mode 100644 index 000000000..cf3a4c71d --- /dev/null +++ b/connector_jira/tests/test_auth.py @@ -0,0 +1,71 @@ +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import unittest + +from odoo import exceptions + +from .common import JiraTransactionComponentCase, recorder + + +class TestAuth(JiraTransactionComponentCase): + @recorder.use_cassette + def test_auth_oauth(self): + backend = self.backend_record + # reset access + backend.write({"access_token": False, "access_secret": False, "access_method": "system"}) + self.assertEqual(backend.state, "authenticate") + auth_wizard = self.env["jira.backend.auth"].create({"backend_id": backend.id}) + + self.assertEqual(auth_wizard.state, "leg_1") + # Here, the wizard generates a consumer key and + # a private/public key. User has to copy them in Jira. + self.assertTrue(auth_wizard.consumer_key) + self.assertTrue(auth_wizard.public_key) + self.assertTrue(auth_wizard.backend_id.private_key) + # Once copied in Jira, they have to confirm "Leg 1" + auth_wizard.do_oauth_leg_1() + + # during leg 1, Jira validates the keys and returns + # an authentication URL that the user has to open + # (will need to login). + # For this test, I manually validated the auth URI, + # as we record the requests, the recorded interactions + # will work for the test. + self.assertTrue(auth_wizard.auth_uri) + self.assertEqual(auth_wizard.state, "leg_2") + # returned by Jira: + self.assertTrue(auth_wizard.request_token) + self.assertTrue(auth_wizard.request_secret) + + auth_wizard.do_oauth_leg_3() + + # of course, these are dummy tokens recorded for the test + # on a demo Jira + self.assertEqual(backend.access_token, "o7XglNpQdA3pwzGZw9r6WA2X2XZcjaaI") + self.assertEqual(backend.access_secret, "pwq9Qzc7iax0JtoQqZdLvPlv4ReECZGh") + self.assertEqual(auth_wizard.state, "done") + + @recorder.use_cassette + def test_auth_basic(self): + backend = self.backend_record + backend.write({"username": "joeblow", "user_token": "dA3pwzGZw9r6WA2X2", "access_method": "user"}) + self.assertEqual(backend.state, "authenticate") + backend.authenticate_user() + self.assertEqual(backend.state, "setup") + + @recorder.use_cassette + def test_auth_check_connection(self): + with self.assertRaisesRegex(exceptions.UserError, "Connection successful"): + self.backend_record.check_connection() + + @unittest.skip( + "This test is slow because the jira lib retries " + "401 errors with an exponential backoff." + ) + @recorder.use_cassette + def test_auth_check_connection_failure(self): + # reset access + self.backend_record.write({"access_token": False, "access_secret": False}) + with self.assertRaisesRegex(exceptions.UserError, "Failed to connect"): + self.backend_record.check_connection() diff --git a/connector_jira/tests/test_backend.py b/connector_jira/tests/test_backend.py new file mode 100644 index 000000000..831b60ea5 --- /dev/null +++ b/connector_jira/tests/test_backend.py @@ -0,0 +1,121 @@ +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +from odoo import fields + +from ..fields import MilliDatetime +from .common import JiraTransactionComponentCase + + +class TestBackendTimestamp(JiraTransactionComponentCase): + def _create_timestamp(self): + return self.env["jira.backend.timestamp"].create( + { + "backend_id": self.backend_record.id, + "from_date_field": "import_project_task_from_date", + "last_timestamp": datetime.fromtimestamp(0), + "component_usage": "timestamp.batch.importer", + } + ) + + def test_millidatetime_field(self): + ts = self._create_timestamp() + self.assertEqual(ts.last_timestamp, datetime(1970, 1, 1, 0, 0)) + new_date = datetime(2019, 4, 8, 10, 30, 59, 375000) + ts._update_timestamp(new_date) + # keeps milliseconds precision and return datetime instance + self.assertEqual(ts.last_timestamp, new_date) + + def test_unix_timestamp_helpers(self): + as_datetime = datetime(2019, 4, 8, 10, 30, 59, 375000) + as_timestamp = MilliDatetime.to_timestamp(as_datetime) + self.assertEqual(as_timestamp, 1554719459375) + dt2 = MilliDatetime.from_timestamp(as_timestamp) + self.assertEqual(dt2, as_datetime) + + def test_from_to_string(self): + self.assertEqual( + MilliDatetime.to_string(datetime(2019, 4, 8, 10, 30, 59, 375000)), + "2019-04-08 10:30:59.375000", + ) + self.assertEqual( + MilliDatetime.from_string("2019-04-08 10:30:59.375000"), + datetime(2019, 4, 8, 10, 30, 59, 375000), + ) + + +class TestBackend(JiraTransactionComponentCase): + def _test_import_date_computed_field(self, timestamp_field_name, component_usage): + backend = self.backend_record + self.assertFalse(backend[timestamp_field_name]) + # We don't have milliseconds on the jira.backend fields, + # they are shown on the webclient. We lose precision when + # users fill dates, but we mostly want to keep precision + # for dates given by Jira. + test_date = "2019-04-08 10:30:59" + backend.write({timestamp_field_name: test_date}) + jira_ts = self.env["jira.backend.timestamp"].search( + [ + ("backend_id", "=", backend.id), + ("from_date_field", "=", timestamp_field_name), + ("component_usage", "=", component_usage), + ] + ) + # The field on jira.backend is a standard odoo Datetime field so works + # with strings (in 11.0). But the field on jira.backend.timestamp is a + # "custom" MilliDatetime field which works with datetime instances. + self.assertEqual(jira_ts.last_timestamp, fields.Datetime.from_string(test_date)) + + def test_import_project_task_from_date(self): + self._test_import_date_computed_field( + "import_project_task_from_date", "timestamp.batch.importer" + ) + + def test_import_analytic_line_from_date(self): + self._test_import_date_computed_field( + "import_analytic_line_from_date", "timestamp.batch.importer" + ) + + def test_delete_analytic_line_from_date(self): + self._test_import_date_computed_field( + "delete_analytic_line_from_date", "timestamp.batch.deleter" + ) + + def test_run_background_from_date(self): + test_date = "2019-04-08 10:30:59" + self.backend_record.write({"import_project_task_from_date": test_date}) + jira_ts = self.env["jira.backend.timestamp"].search( + [ + ("backend_id", "=", self.backend_record.id), + ("from_date_field", "=", "import_project_task_from_date"), + ("component_usage", "=", "timestamp.batch.importer"), + ] + ) + + with self.mock_with_delay() as (delayable_cls, delayable): + self.backend_record._run_background_from_date( + "jira.project.task", + "import_project_task_from_date", + "timestamp.batch.importer", + ) + delayable_cls.assert_called_once() + # arguments passed in 'with_delay()' + delay_args, delay_kwargs = delayable_cls.call_args + self.assertEqual( + (self.env["jira.project.task"],), + delay_args, + ) + + # job method called after 'with_delay()' + delayable.run_batch_timestamp.assert_called_once() + delay_args, __ = delayable.run_batch_timestamp.call_args + + self.assertEqual( + ( + self.backend_record, + jira_ts, + ), + delay_args, + ) diff --git a/connector_jira/tests/test_batch_timestamp_delete.py b/connector_jira/tests/test_batch_timestamp_delete.py new file mode 100644 index 000000000..5eb89ff4a --- /dev/null +++ b/connector_jira/tests/test_batch_timestamp_delete.py @@ -0,0 +1,80 @@ +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +from freezegun import freeze_time + +from .common import JiraTransactionComponentCase, recorder + + +class TestBatchTimestampDelete(JiraTransactionComponentCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._create_issue_type_bindings() + cls.epic_issue_type = cls.env["jira.issue.type"].search([("name", "=", "Epic")]) + cls.project = cls.env["project.project"].create({"name": "Jira Project"}) + + # note: when you are recording tests with VCR, Jira + # will reject any call when you pretend to have a time too + # different from now(). So adjust this date be rougly equal + # to now(). + @freeze_time("2019-04-08 14:13:10.325") + @recorder.use_cassette + def test_delete_batch_timestamp_analytic_line(self): + """Import all deleted worklogs since last timestamp""" + self._create_project_binding( + self.project, issue_types=self.epic_issue_type, external_id="10000" + ) + jira_ts = self.env["jira.backend.timestamp"]._timestamp_for_field( + self.backend_record, + "delete_analytic_line_from_date", + "timestamp.batch.deleter", + ) + since_date = "2019-04-05 00:00:00.000" + jira_ts._update_timestamp(since_date) + + with self.mock_with_delay() as (delayable_cls, delayable): + self.env["jira.account.analytic.line"].run_batch_timestamp( + self.backend_record, + jira_ts, + ) + # Jira WS returns 2 worklog ids to delete here, we expect to have 2 + # jobs delayed + number_of_worklogs = 2 + self.assertEqual(delayable_cls.call_count, number_of_worklogs) + # arguments passed in 'with_delay()' + delay_args, delay_kwargs = delayable_cls.call_args + self.assertEqual( + (self.env["jira.account.analytic.line"],), + delay_args, + ) + + # Job method called after 'with_delay()'. + self.assertEqual(delayable.delete_record.call_count, number_of_worklogs) + delay_args = delayable.delete_record.call_args_list + expected = [ + # backend, issue_id + ( + (self.backend_record, 10103), + {"only_binding": False, "set_inactive": False}, + ), + ( + (self.backend_record, 10104), + {"only_binding": False, "set_inactive": False}, + ), + ] + self.assertEqual( + sorted((args, kwargs) for args, kwargs in delay_args), + sorted(expected), + ) + # the lines would actually be deleted by the 'delete_record' jobs + + # For worklogs, Jira returns the youngest timestamp of the worklogs + # returned by the "deleted since" method, so the next time we look for + # deleted worklogs, we can reuse this timestamp as "since". It has a + # milliseconds precision + self.assertEqual( + jira_ts.last_timestamp, datetime(2019, 4, 8, 13, 51, 37, 945000) + ) diff --git a/connector_jira/tests/test_batch_timestamp_import.py b/connector_jira/tests/test_batch_timestamp_import.py new file mode 100644 index 000000000..241851db5 --- /dev/null +++ b/connector_jira/tests/test_batch_timestamp_import.py @@ -0,0 +1,125 @@ +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +from freezegun import freeze_time + +from .common import JiraTransactionComponentCase, recorder + + +class TestBatchTimestampImport(JiraTransactionComponentCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._create_issue_type_bindings() + cls.epic_issue_type = cls.env["jira.issue.type"].search([("name", "=", "Epic")]) + cls.project = cls.env["project.project"].create({"name": "Jira Project"}) + + # note: when you are recording tests with VCR, Jira + # will reject any call when you pretend to have a time too + # different from now(). So adjust this date be rougly equal + # to now(). + @freeze_time("2019-04-08 12:51:36.595") + @recorder.use_cassette + def test_import_batch_timestamp_tasks(self): + """Import all tasks since last timestamp""" + self._create_project_binding( + self.project, issue_types=self.epic_issue_type, external_id="10000" + ) + jira_ts = self.env["jira.backend.timestamp"]._timestamp_for_field( + self.backend_record, + "import_project_task_from_date", + "timestamp.batch.importer", + ) + since_date = "2019-04-05 00:00:00.000" + jira_ts._update_timestamp(since_date) + with self.mock_with_delay() as (delayable_cls, delayable): + self.env["jira.project.task"].run_batch_timestamp( + self.backend_record, + jira_ts, + ) + # Jira WS returns 4 task ids here, we expect to have 4 + # jobs delayed + number_of_tasks = 4 + self.assertEqual(delayable_cls.call_count, number_of_tasks) + # arguments passed in 'with_delay()' + delay_args, delay_kwargs = delayable_cls.call_args + self.assertEqual( + (self.env["jira.project.task"],), + delay_args, + ) + + # Job method called after 'with_delay()'. + self.assertEqual(delayable.import_record.call_count, number_of_tasks) + delay_args = delayable.import_record.call_args_list + expected = [ + ((self.backend_record, "10103"), {"force": False, "record": None}), + ((self.backend_record, "10102"), {"force": False, "record": None}), + ((self.backend_record, "10101"), {"force": False, "record": None}), + ((self.backend_record, "10100"), {"force": False, "record": None}), + ] + self.assertEqual( + sorted((args, kwargs) for args, kwargs in delay_args), + sorted(expected), + ) + + # For tasks, Jira does not return an "until" time, so we the timestamp + # to start the next import is now (the freezed time for this test) + # minus 5 minutes, the overlap being because the JQL query has a minute + # precision and does not return immediately the modified tasks + self.assertEqual( + jira_ts.last_timestamp, datetime(2019, 4, 8, 12, 46, 36, 595000) + ) + + @freeze_time("2019-04-08 13:22:07.325") + @recorder.use_cassette + def test_import_batch_timestamp_analytic_line(self): + """Import all worklogs since last timestamp""" + self._create_project_binding( + self.project, issue_types=self.epic_issue_type, external_id="10000" + ) + jira_ts = self.env["jira.backend.timestamp"]._timestamp_for_field( + self.backend_record, + "import_analytic_line_from_date", + "timestamp.batch.importer", + ) + since_date = "2019-04-05 00:00:00.000" + jira_ts._update_timestamp(since_date) + with self.mock_with_delay() as (delayable_cls, delayable): + self.env["jira.account.analytic.line"].run_batch_timestamp( + self.backend_record, + jira_ts, + ) + # Jira WS returns 3 worklog ids here, we expect to have 3 + # jobs delayed + number_of_worklogs = 3 + self.assertEqual(delayable_cls.call_count, number_of_worklogs) + # arguments passed in 'with_delay()' + delay_args, delay_kwargs = delayable_cls.call_args + self.assertEqual( + (self.env["jira.account.analytic.line"],), + delay_args, + ) + + # Job method called after 'with_delay()'. + self.assertEqual(delayable.import_record.call_count, number_of_worklogs) + delay_args = delayable.import_record.call_args_list + expected = [ + # backend, issue_id, worklog_id + ((self.backend_record, "10102", "10100"), {"force": False}), + ((self.backend_record, "10100", "10102"), {"force": False}), + ((self.backend_record, "10101", "10101"), {"force": False}), + ] + self.assertEqual( + sorted((args, kwargs) for args, kwargs in delay_args), + sorted(expected), + ) + + # For worklogs, Jira returns the youngest timestamp of + # the worklogs returned by the "updated since" method, so the + # next import, we can reuse this timestamp as "since". + # It has a milliseconds precision + self.assertEqual( + jira_ts.last_timestamp, datetime(2019, 4, 8, 12, 32, 19, 311000) + ) diff --git a/connector_jira/tests/test_delete_analytic_line.py b/connector_jira/tests/test_delete_analytic_line.py new file mode 100644 index 000000000..ec2b3167f --- /dev/null +++ b/connector_jira/tests/test_delete_analytic_line.py @@ -0,0 +1,43 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from .common import JiraTransactionComponentCase, recorder + + +class TestBatchTimestampDelete(JiraTransactionComponentCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._create_issue_type_bindings() + cls.epic_issue_type = cls.env["jira.issue.type"].search([("name", "=", "Epic")]) + cls.project = cls.env["project.project"].create({"name": "Jira Project"}) + + @recorder.use_cassette + def test_delete_analytic_line(self): + """Import all deleted worklogs since last timestamp""" + # Simulate a worklogs we would already have imported and is + # deleted in Jira. First create the binding as it would be + # in Odoo. + line = self.env["account.analytic.line"].create( + { + "project_id": self.project.id, + "amount": 30.0, + "date": "2019-04-08", + "name": "A worklog that will be deleted", + "user_id": self.env.user.id, + } + ) + self._create_project_binding( + self.project, issue_types=self.epic_issue_type, external_id="10000" + ) + binding = self._create_analytic_line_binding( + line, + jira_issue_id="10101", + external_id="10103", + ) + # This is usually delayed as a job from either a controller, + # either the component with usage "timestamp.batch.deleter" + self.env["jira.account.analytic.line"].delete_record( + self.backend_record, "10103", only_binding=False, set_inactive=False + ) + self.assertFalse(binding.exists()) + self.assertFalse(line.exists()) diff --git a/connector_jira/tests/test_import_analytic_line.py b/connector_jira/tests/test_import_analytic_line.py new file mode 100644 index 000000000..fc09a988f --- /dev/null +++ b/connector_jira/tests/test_import_analytic_line.py @@ -0,0 +1,231 @@ +# Copyright 2019 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from datetime import date, timedelta + +from .common import JiraTransactionComponentCase, recorder + + +class TestImportWorklogBase(JiraTransactionComponentCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._create_issue_type_bindings() + cls.project = cls.env["project.project"].create({"name": "Jira Project"}) + cls.task = cls.env["project.task"].create( + {"name": "My task", "project_id": cls.project.id} + ) + cls.project_binding = cls._create_project_binding( + cls.project, + issue_types=cls.env["jira.issue.type"].search([]), + external_id="10000", + ) + cls.epic_issue_type = cls.env["jira.issue.type"].search([("name", "=", "Epic")]) + # Warning: if you add new tests or change the cassettes + # you might need to change the username + cls._link_user(cls.env.user, "gbaconnier") + cls.env["hr.employee"].create( + {"name": "Test Employee", "user_id": cls.env.user.id} + ) + cls.fallback_project = cls.env["project.project"].create( + {"name": "Test Fallback Project"} + ) + cls.backend_record.write( + {"worklog_fallback_project_id": cls.fallback_project.id} + ) + + def _setup_import_worklog(self, task, jira_issue_id, jira_worklog_id=None): + self._create_task_binding(task, external_id=jira_issue_id) + jira_worklog_id = jira_worklog_id or jira_issue_id + self.env["jira.account.analytic.line"].import_record( + self.backend_record, jira_issue_id, jira_worklog_id + ) + binding = self.env["jira.account.analytic.line"].search( + [ + ("backend_id", "=", self.backend_record.id), + ("external_id", "=", jira_worklog_id), + ] + ) + self.assertEqual(len(binding), 1) + return binding + + +class TestImportAccountAnalyticLine(TestImportWorklogBase): + @recorder.use_cassette + def test_import_worklog(self): + """Import a worklog on a task existing in Odoo on activated project""" + self._test_import_worklog( + expected_project=self.project, expected_task=self.task + ) + + @recorder.use_cassette("test_import_worklog.yaml") + def test_import_worklog_deactivated_project(self): + """ + Import a worklog on a task existing in Odoo on deactivated project + """ + self.project.write({"active": False}) + self._test_import_worklog( + expected_project=self.fallback_project, expected_task=False + ) + + @recorder.use_cassette("test_import_worklog.yaml") + def test_import_worklog_deactivated_task(self): + """ + Import a worklog on a task existing in Odoo on deactivated task + """ + self.task.write({"active": False}) + self._test_import_worklog(expected_project=self.project, expected_task=False) + + def _test_import_worklog(self, expected_project, expected_task): + jira_worklog_id = jira_issue_id = "10000" + binding = self._setup_import_worklog(self.task, jira_issue_id, jira_worklog_id) + self.assertRecordValues( + binding, + [ + { + "account_id": expected_project.analytic_account_id.id, + "backend_id": self.backend_record.id, + "date": date(2019, 4, 4), + "employee_id": self.env.user.employee_ids[0].id, + "external_id": jira_worklog_id, + "jira_epic_issue_key": False, + "jira_issue_id": jira_issue_id, + "jira_issue_key": "TEST-1", + "jira_issue_type_id": self.epic_issue_type.id, + "name": "write tests", + "project_id": expected_project.id, + "tag_ids": [], + "task_id": expected_task.id if expected_task else False, + "unit_amount": 1.0, + "user_id": self.env.user.id, + } + ], + ) + + def test_reimport_worklog(self): + jira_issue_id = "10000" + jira_worklog_id = "10000" + with recorder.use_cassette("test_import_worklog.yaml"): + binding = self._setup_import_worklog( + self.task, + jira_issue_id, + jira_worklog_id, + ) + write_date = binding.write_date - timedelta(seconds=1) + binding.write({"write_date": write_date}) + with recorder.use_cassette("test_import_worklog.yaml"): + binding.force_reimport() + self.assertEqual(binding.write_date, write_date) + + @recorder.use_cassette("test_import_worklog.yaml") + def test_import_worklog_naive(self): + jira_worklog_id = jira_issue_id = "10000" + self.backend_record.worklog_date_timezone_mode = "naive" + binding = self._setup_import_worklog(self.task, jira_issue_id, jira_worklog_id) + self.assertRecordValues( + binding, + [ + { + "account_id": self.project.analytic_account_id.id, + "backend_id": self.backend_record.id, + "date": date(2019, 4, 4), + "employee_id": self.env.user.employee_ids[0].id, + "external_id": jira_worklog_id, + "jira_epic_issue_key": False, + "jira_issue_id": jira_issue_id, + "jira_issue_key": "TEST-1", + "jira_issue_type_id": self.epic_issue_type.id, + "name": "write tests", + "project_id": self.project.id, + "tag_ids": [], + "task_id": self.task.id if self.task else False, + "unit_amount": 1.0, + "user_id": self.env.user.id, + } + ], + ) + + @recorder.use_cassette("test_import_worklog.yaml") + def test_import_worklog_user(self): + jira_worklog_id = jira_issue_id = "10000" + self.backend_record.worklog_date_timezone_mode = "user" + binding = self._setup_import_worklog(self.task, jira_issue_id, jira_worklog_id) + self.assertRecordValues( + binding, + [ + { + "account_id": self.project.analytic_account_id.id, + "backend_id": self.backend_record.id, + "date": date(2019, 4, 3), + "employee_id": self.env.user.employee_ids[0].id, + "external_id": jira_worklog_id, + "jira_epic_issue_key": False, + "jira_issue_id": jira_issue_id, + "jira_issue_key": "TEST-1", + "jira_issue_type_id": self.epic_issue_type.id, + "name": "write tests", + "project_id": self.project.id, + "tag_ids": [], + "task_id": self.task.id if self.task else False, + "unit_amount": 1.0, + "user_id": self.env.user.id, + } + ], + ) + + @recorder.use_cassette("test_import_worklog.yaml") + def test_import_worklog_specific(self): + jira_worklog_id = jira_issue_id = "10000" + self.backend_record.worklog_date_timezone_mode = "specific" + self.backend_record.worklog_date_timezone = "Europe/London" + binding = self._setup_import_worklog(self.task, jira_issue_id, jira_worklog_id) + self.assertRecordValues( + binding, + [ + { + "account_id": self.project.analytic_account_id.id, + "backend_id": self.backend_record.id, + "date": date(2019, 4, 3), + "employee_id": self.env.user.employee_ids[0].id, + "external_id": jira_worklog_id, + "jira_epic_issue_key": False, + "jira_issue_id": jira_issue_id, + "jira_issue_key": "TEST-1", + "jira_issue_type_id": self.epic_issue_type.id, + "name": "write tests", + "project_id": self.project.id, + "tag_ids": [], + "task_id": self.task.id if self.task else False, + "unit_amount": 1.0, + "user_id": self.env.user.id, + } + ], + ) + + def _test_import_worklog_epic_link_on_epic(self, expected_project, expected_task): + jira_worklog_id = jira_issue_id = "10000" + self.backend_record.epic_link_on_epic = True + binding = self._setup_import_worklog(self.task, jira_issue_id, jira_worklog_id) + self.assertRecordValues( + binding, + [ + { + "account_id": expected_project.analytic_account_id.id, + "backend_id": self.backend_record.id, + "date": "2019-04-04", + "employee_id": self.env.user.employee_ids[0].id, + "external_id": jira_worklog_id, + "jira_epic_issue_key": "TEST-1", + "jira_issue_id": jira_issue_id, + "jira_issue_key": "TEST-1", + "jira_issue_type_id": self.epic_issue_type.id, + "name": "write tests", + "project_id": expected_project.id, + "tag_ids": [], + "task_id": expected_task.id if expected_task else False, + "unit_amount": 1.0, + "user_id": self.env.user.id, + } + ], + ) diff --git a/connector_jira/tests/test_import_issue_type.py b/connector_jira/tests/test_import_issue_type.py new file mode 100644 index 000000000..7f021f81d --- /dev/null +++ b/connector_jira/tests/test_import_issue_type.py @@ -0,0 +1,31 @@ +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from .common import JiraTransactionComponentCase, recorder + + +class TestImportIssueType(JiraTransactionComponentCase): + @recorder.use_cassette + def test_import_issue_type_batch(self): + issue_types = self.env["jira.issue.type"].search([]) + self.assertEqual(len(issue_types), 0) + self.env["jira.issue.type"].import_batch( + self.backend_record, + ) + issue_types = self.env["jira.issue.type"].search([]) + self.assertEqual(len(issue_types), 5) + + def test_import_is_issue_type_sync(self): + self._create_issue_type_bindings() + + epic_issue_type = self.env["jira.issue.type"].search([("name", "=", "Epic")]) + task_issue_type = self.env["jira.issue.type"].search([("name", "=", "Task")]) + + project = self.env["project.project"].create({"name": "Jira Project"}) + project_binding = self._create_project_binding( + project, + issue_types=epic_issue_type, + ) + + self.assertTrue(epic_issue_type.is_sync_for_project(project_binding)) + self.assertFalse(task_issue_type.is_sync_for_project(project_binding)) diff --git a/connector_jira/tests/test_import_task.py b/connector_jira/tests/test_import_task.py new file mode 100644 index 000000000..b4bc5ab68 --- /dev/null +++ b/connector_jira/tests/test_import_task.py @@ -0,0 +1,143 @@ +# Copyright 2019 Camptocamp SA +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import exceptions + +from .common import JiraTransactionComponentCase, recorder + + +class TestImportTask(JiraTransactionComponentCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._create_issue_type_bindings() + cls.epic_issue_type = cls.env["jira.issue.type"].search([("name", "=", "Epic")]) + cls.task_issue_type = cls.env["jira.issue.type"].search([("name", "=", "Task")]) + cls.subtask_issue_type = cls.env["jira.issue.type"].search( + [("name", "=", "Sub-task")] + ) + cls.project = cls.env["project.project"].create({"name": "Jira Project"}) + cls.env["project.task.type"].create( + {"name": "To Do", "sequence": 1, "project_ids": [(4, cls.project.id)]} + ) + + @recorder.use_cassette + def test_import_task_epic(self): + """ + Import Epic task where we sync this type issue on activated project + """ + self._test_import_task_epic(expected_active=True) + + @recorder.use_cassette("test_import_task_epic.yaml") + def test_import_task_epic_deactivated_project(self): + """ + Import Epic task where we sync this type issue on deactivated project + """ + self.project.write({"active": False}) + self._test_import_task_epic(expected_active=False) + + def _test_import_task_epic(self, expected_active): + self._create_project_binding( + self.project, issue_types=self.epic_issue_type, external_id="10000" + ) + jira_issue_id = "10000" + self.env["jira.project.task"].import_record(self.backend_record, jira_issue_id) + binding = ( + self.env["jira.project.task"] + .with_context(active_test=False) + .search( + [ + ("backend_id", "=", self.backend_record.id), + ("external_id", "=", jira_issue_id), + ] + ) + ) + self.assertEqual(len(binding), 1) + + self.assertEqual(binding.jira_key, "TEST-1") + self.assertEqual(binding.jira_issue_type_id, self.epic_issue_type) + self.assertFalse(binding.jira_epic_link_id) + self.assertFalse(binding.jira_parent_id) + + self.assertEqual(binding.odoo_id.active, expected_active) + self.assertEqual(binding.odoo_id.stage_id.name, "To Do") + + with self.assertRaises(exceptions.UserError): + binding.odoo_id.active = not expected_active + + with self.assertRaises(exceptions.UserError): + binding.odoo_id.unlink() + + @recorder.use_cassette + def test_import_task_type_not_synced(self): + """Import ask where we do not sync this type issue: ignored""" + self._create_project_binding(self.project, external_id="10000") + jira_issue_id = "10000" + self.env["jira.project.task"].import_record(self.backend_record, jira_issue_id) + binding = self.env["jira.project.task"].search( + [ + ("backend_id", "=", self.backend_record.id), + ("external_id", "=", jira_issue_id), + ] + ) + self.assertEqual(len(binding), 0) + + @recorder.use_cassette + def test_import_task_parents(self): + """Import Epic/Task/Subtask recursively""" + self._create_project_binding( + self.project, + issue_types=( + self.epic_issue_type + self.task_issue_type + self.subtask_issue_type + ), + external_id="10000", + ) + + projects_by_name = self.env["project.project"].name_search("TEST") + self.assertEqual(len(projects_by_name), 1) + + jira_subtask_issue_id = "10002" + self.env["jira.project.task"].import_record( + self.backend_record, jira_subtask_issue_id + ) + + binding = self.env["jira.project.task"].search( + [ + ("backend_id", "=", self.backend_record.id), + ("external_id", "=", jira_subtask_issue_id), + ] + ) + self.assertEqual(len(binding), 1) + + self.assertEqual(binding.jira_key, "TEST-3") + self.assertEqual(binding.name, "Subtask1") + self.assertEqual(binding.jira_issue_type_id, self.subtask_issue_type) + self.assertTrue(binding.jira_parent_id) + + task_binding = binding.jira_parent_id + self.assertEqual(task_binding.jira_key, "TEST-2") + self.assertEqual(task_binding.name, "Task1") + self.assertEqual(task_binding.jira_issue_type_id, self.task_issue_type) + self.assertTrue(task_binding.jira_epic_link_id) + self.assertAlmostEqual(task_binding.odoo_id.allocated_hours, 4.5) + + epic_binding = task_binding.jira_epic_link_id + self.assertEqual(epic_binding.jira_key, "TEST-1") + self.assertEqual(epic_binding.name, "Epic1") + self.assertEqual(epic_binding.jira_issue_type_id, self.epic_issue_type) + + tasks_by_name = self.env["project.task"].name_search("TEST-3") + self.assertEqual(len(tasks_by_name), 1) + self.assertEqual(tasks_by_name[0][0], binding.odoo_id.id) + + def test_task_restrict_create(self): + self._create_project_binding( + self.project, + issue_types=self.env["jira.issue.type"].search([]), + external_id="10000", + ) + with self.assertRaises(exceptions.UserError): + self.env["project.task"].create( + {"name": "My task", "project_id": self.project.id} + ) diff --git a/connector_jira/views/jira_backend_report_templates.xml b/connector_jira/views/jira_backend_report_templates.xml new file mode 100644 index 000000000..058a85cc5 --- /dev/null +++ b/connector_jira/views/jira_backend_report_templates.xml @@ -0,0 +1,20 @@ + + + + diff --git a/connector_jira/views/jira_backend_views.xml b/connector_jira/views/jira_backend_views.xml new file mode 100644 index 000000000..bf5362726 --- /dev/null +++ b/connector_jira/views/jira_backend_views.xml @@ -0,0 +1,369 @@ + + + + + + jira.backend.form + jira.backend + +
+
+
+ + +