Developer Resources
Content
Settings
Settings are defined in the settings.py
file in the root of the repo. Since the settings are stored in a Python file, it allows for a lot of flexibility to adapt to your specific environment requirements if needed. The settings file contains three main sections:
Authentication
Credentials are retrieved by default from environment variables:
SGJIRA_SG_SITE
: the Flow Production Tracking site urlSGJIRA_SG_SCRIPT_NAME
: a Flow Production Tracking script user nameSGJIRA_SG_SCRIPT_KEY
: the Flow Production Tracking script user Application KeySGJIRA_JIRA_SITE
: the Jira server urlSGJIRA_JIRA_USER
: the system name of the Jira user used to connect for the sync. This is usually your email address you sign in to Jira with. Jira does not have a concept of a "script" user so this will need to be the designated user account that will control the sync updates. It will need appropriate permissions to make any changes required.SGJIRA_JIRA_USER_SECRET
: the Jira user password or API Key.
Jira Cloud requires the use of an API token and will not work with a user password. See https://confluence.atlassian.com/x/Vo71Nw for information on how to generate a token.
Jira Server will still work with a user password and does not support API tokens.
For more information, see: https://developer.atlassian.com/cloud/jira/platform/jira-rest-api-basic-authentication/
You may set these in your environment or by installing python-dotenv and defining these in a .env
file.
# Flow Production Tracking credentials
SGJIRA_SG_SITE='https://mysite.shotgrid.autodesk.com'
SGJIRA_SG_SCRIPT_NAME='sg-jira-bridge'
SGJIRA_SG_SCRIPT_KEY='01234567@abcdef0123456789'
# Jira credentials
SGJIRA_JIRA_SITE='https://mystudio.atlassian.net'
SGJIRA_JIRA_USER='richard.hendricks@piedpiper.com'
SGJIRA_JIRA_USER_SECRET='youkn0wwh@tapa$5word1smAKeitag0odone3'
Logging
The Flow Production Tracking Jira Bridge uses standard Python logging. The logging configuration is stored in a LOGGING
dict using the standard logging.config
format.
Sync Settings
The sync settings are stored in a SYNC
dict in the format:
SYNC = {
"sync_settings_name": {
# The Syncer class to use with the module name included
"syncer": "sg_jira.MyCustomSyncer",
# And the specific settings which are passed to its __init__() method
"settings": {
"my_setting_name": "My Setting Value"
},
}
}
Each key is a settings name that contains a dictionary containing the syncer and the settings to use. The key is the settings name used when composing the URL for Flow Production Tracking Jira Bridge. For example, http://localhost:9090/sg2jira/my_settings
uses the settings named my_settings
.
syncer: The syncer class to use in the format
module_name.class_name
.settings: A dictionary containing the settings for the syncer where the key is the setting name and value is it's value. These settings will be used as parameters when instantiating the syncer class.
Each set of SYNC
settings defined in your settings.py
file must define a single Syncer
.
Custom syncers can be referenced in the settings file with their module path and their specific settings. You can easily allow the bridge to load your syncer by adding the directory that contains your custom syncer using sys.path
.
For example:
# Additional paths can be added for custom syncers
sys.path.append(os.path.abspath("./examples"))
SYNC = {
"default": {
# The syncer class to use
"syncer": "sg_jira.TaskIssueSyncer",
# And the specific settings which are passed to its __init__() method
"settings": {
"foo": "bar"
},
},
"test": {
# Example of a custom syncer with an additional parameter to define
# a log level.
"syncer": "example_sync.ExampleSync",
"settings": {
"log_level": logging.DEBUG
},
}
}
Useful Patterns
Rather than having to edit your settings in order to enable/disable testing, it may be useful to have two settings for your custom syncer, one for production and one for testing. In your testing settings you may wish to simply enable DEBUG
level logging messages.
You can take it a step further and have a base settings definition and then load that for other settings and only override the settings you need. This overly simplified example might look something like this:
import logging
import copy
SYNC = {
"default": {
# The syncer class to use
"syncer": "sg_jira.TaskIssueSyncer",
# And the specific settings which are passed to its __init__() method
"settings": {
"foo": "bar",
"color": "orange",
"do_something": False,
"log_level": logging.INFO
},
}
}
# create settings for default_test from default
SYNC["test_settings"] = copy.deepcopy(SYNC["default"])
# override the settings we need
SYNC["test_settings"]["settings"].update({
"log_level": logging.DEBUG,
"color": "red"
})
API
Connections to Flow Production Tracking and Jira
These classes manage the specific connections to Flow Production Tracking and Jira.
ShotgunSession
class sg_jira.shotgun_session.ShotgunSession(base_url, script_name=None, *args, **kwargs)text
Wraps a
shotgun_api3.shotgun.Shotgun
instance and provide some helpers and session caches.Ensures all the values we get from Flow Production Tracking are unicode and not utf-8 encoded strings. Utf-8 encodes unicode values before sending them to Flow Production Tracking.
Instantiate a
shotgun_api3.shotgun.Shotgun
with the sanitized parameters.
property current_user
Return the Flow Production Tracking user used for the connection. Returns:
- A Flow Production Tracking record dictionary with an id key and a type key.
setup()
Check the Flow Production Tracking site and cache site level values
Raises:
- RuntimeError – if the Flow Production Tracking site was not correctly configured to be used with this bridge.
assert_field(entity_type, field_name, field_type, check_unique=False)
Check if the given field with the given type exists for the given Flow Production Tracking Entity type.
Parameters:
entity_type (str) – A Flow Production Tracking Entity type.
field_name (str) – A Flow Production Tracking field name, e.g. ‘sg_my_precious’.
field_type (str) – A Flow Production Tracking field type, e.g. ‘text’.
check_unique (bool) – When
True
, check the specified field is configured to only accept unique values. Default isFalse
.Raises:
- RuntimeError – if the field does not exist or does not have the expected type.
get_field_schema(entity_type, field_name)
Return the Flow Production Tracking schema for the given Entity field.
Note: Flow Production Tracking schemas are cached and the bridge needs to be restarted if schemas are changed in Flow Production Tracking.Parameters:
entity_type (str) – A Flow Production Tracking Entity type.
field_name (str) – A Flow Production Tracking field name, e.g. ‘sg_my_precious’.
Returns:
- The Flow Production Tracking schema for the given field as a dictionary or
None
.
clear_cached_field_schema(entity_type=None)
Clear all cached Flow Production Tracking schema or just the cached schema for the given Flow Production Tracking Entity type.
Parameters:
- entity_type (str) – A Flow Production Tracking Entity type or
None
.
static get_entity_name_field(entity_type)
Return the Flow Production Tracking name field to use for the specified entity type.
Parameters:
- entity_type (str) – The entity type to get the name field for.
Returns:
- The name field for the specified entity type.
is_project_entity(entity_type)
Return True if the given Flow Production Tracking Entity type is a project Entity, that is an Entity linked to a Project, False if it is a non-project Entity.
Parameters:
- entity_type (str) – A Flow Production Tracking Entity type.
match_entity_by_name(name, entity_types, shotgun_project)
Retrieve a Flow Production Tracking Entity with the given name from the given list of Entity types.
Project Flow Production Tracking Entities are restricted to the given Flow Production Tracking Project.
Parameters:
name (str) – A name to match.
entity_types – A list of Flow Production Tracking Entity types to consider.
shotgun_project – A Flow Production Tracking Project dictionary.
Returns:
- A Flow Production Tracking Entity dictionary or None.
get_entity_page_url(shotgun_entity)
Return the Flow Production Tracking page url for the given Entity.
Parameters:
- shotgun_entity – A Flow Production Tracking Entity dictionary with at least a ‘type’ key and an ‘id’ key.
JiraSession
class sg_jira.jira_session.JiraSession(jira_site, *args, **kwargs)
Extend
jira.JIRA
with helpers.Instantiate a JiraSession.
Connect to the given Jira site with given parameters.
Parameters:
- jira_site (str) – A Jira site url.
Raises:
- RuntimeError – on Jira connection errors.
__init__(jira_site, *args, **kwargs)
Instantiate a JiraSession.
Connect to the given Jira site with given parameters.
Parameters:
- jira_site (str) – A Jira site url.
Raises:
- RuntimeError – on Jira connection errors.
setup()
Check the Jira site and cache site level values.
Raises:
- RuntimeError –- if the Jira site was not correctly configured to be used with this bridge.
property is_jira_cloud
Return if the site is a JIRA Cloud site.
Returns:
True
if the site is hosted in the cloud,False
otherwise.
get_jira_issue_field_id(name)
Return the Jira field id for the Issue field with the given name.
Returns:
- The id as a string or None if the field is unknown.
property jira_shotgun_type_field
Return the id of the Jira field used to store the type of a linked Flow Production Tracking Entity.
Two custom fields are used in Jira to store a reference to a Flow Production Tracking Entity: its Flow Production Tracking Entity type and id. This method returns the id of the Jira field used to store the Flow Production Tracking type.
property jira_shotgun_url_field
Return the id of the Jira field used to store the url of a linked Flow Production Tracking Entity.
sanitize_jira_update_value(jira_value, jira_field_schema)
Perform sanity checks for the given Jira value and ensure it can be used to update the Jira field with the given schema.
Returns:
- A Jira value which can safely be used to update the Jira field.
Raises:
- UserWarning – if a safe value can’t be obtained.
find_jira_assignee_for_issue(user_email, jira_project=None, jira_issue=None)
Return a Jira user the given issue can be assigned to, based on the given email address.
A Jira Project must be specified when creating an Issue. A Jira Issue must be specified when editing an Issue.
Parameters:
jira_project – A
jira.resources.Project
instance or None.jira_issue– A
jira.Issue
instance or None.user_email – An email address as a string.
Returns:
- A
jira.resources.User
instance or None.Raises:
- ValueError – if no Project nor Issue is specified.
find_jira_user(user_email, jira_project=None, jira_issue=None, for_assignment=False)
Return a Jira an assignable user or with browse permission for the given Project or Issue, with the given email address. Either a jira_project or jira_issue must be provided.
Note:Flow Production Tracking schemas are cached and the bridge needs to be restarted if schemas are changed in Flow Production Tracking.
Parameters:
user_email – An email address as a string.
jira_project – A
jira.resources.Project
instance or None.jira_issue – A
jira.Issue
instance or None.for_assignment – A boolean, if False the user just needs to have read permission. If True the user needs to be suitable for Issue assignments.
Returns:
- A
jira.resources.User
instance or None.Raises:
- ValueError – if no Project nor Issue is specified.
set_jira_issue_status(jira_issue, jira_status_name, comment)
Attempt to change the Jira Issue status to the given value.
Lookup for a Jira transition where the target status is the given one and try to apply it.
Parameters:
jira_issue - A
jira.Issue
instance.jira_status (str) - A Jira status name, e.g. In Progress.
comment - A string, a comment to apply to the Jira transition.
Returns:
- True if the status could be set, False otherwise.
create_issue_from_data(jira_project, issue_type, data)
Create an Issue from the given data.
Sanity check the data against Jira create meta data. Try to amend the data, if possible, to complete the Issue creation. Raise ValueError if the data can't be amended to complete the Issue creation.
Parameters:
jira_project - A
jira.resources.Project
instance.issue_type(str) - The target Issue type name.
data - A dictionary where keys are Jira Issue field ids and values are Jira values.
Returns:
- A
jira.Issue
instance.Raises:
RuntimeError -- if the Jira create meta data can't be retrieved.
ValueError -- if invalid and unfixable data is provided.
get_jira_issue_edit_meta(jira_issue)
Return the edit metadata for the given Jira Issue.
Parameters:
- jira_issue - A
jira.Issue
.Returns:
- The Jira Issue edit metadata fields property.
Raises:
- RuntimeError -- if the edit metadata can't be retrieved for the given Issue.
Bridge
This is the main class that holds handles to both Flow Production Tracking and Jira and handles dispatching events to both sites.
class sg_jira.Bridge(sg_site, sg_script, sg_script_key, jira_site, jira_user, jira_secret, sync_settings=None, sg_http_proxy=None)
A bridge between Flow Production Tracking and Jira.
The bridge handles connections to the Flow Production Tracking and Jira servers and dispatches sync events.
Instantiate a new bridge between the given PTR site and Jira site.
Note:
Jira Cloud requires the use of an API token and will not work with a user’s password. See https://confluence.atlassian.com/x/Vo71Nw for information on how to generate a token. Jira Server will use PAT so please provide empty string as SGJIRA_JIRA_USER.
Parameters:
sg_site (str) - A Flow Production Tracking URL.
sg_script (str) - A Flow Production Tracking script user name.
sg_script_key (str) - The script user key for the Flow Production Tracking script.
jira_site (str) - A Jira site url.
jira_user (str) - A Jira user name, either his email address or short name.
jira_secret (str) - The Jira user password or API key.
sync_settings - A dictionary where keys are settings names.
sg_http_proxy (str) -- Optional, a http proxy to use for the Flow Production Tracking connection, or None.
__init__(sg_site, sg_script, sg_script_key, jira_site, jira_user, jira_secret, sync_settings=None, sg_http_proxy=None)
Instantiate a new bridge between the given PTR site and Jira site.
Note:
Jira Cloud requires the use of an API token and will not work with a user's password. See https://confluence.atlassian.com/x/Vo71Nw for information on how to generate a token. Jira Server will use PAT so please provide empty string as SGJIRA_JIRA_USER.
Parameters:
sg_site (str) - A Flow Production Tracking URL.
sg_script (str) - A Flow Production Tracking script user name.
sg_script_key (str) - The script user key for the Flow Production Tracking script.
jira_site(str) - A Jira site url.
jira_user(str) - A Jira user name, either his email address or short name.
jira_secret (str) - The Jira user password or API key.
sync_settings - A dictionary where keys are settings names.
sg_http_proxy(str) - Optional, a http proxy to use for the Flow Production Tracking connection, or None.
classmethod get_bridge(settings_file)
Read the given settings and instantiate a new
Bridge
with them.Parameters:
- settings_file (str) - Path to a settings Python file.
Raises:
- ValueError - on missing required settings.
classmethod read_settings(settings_file)
Read the given settings file.
Parameters:
- settings_file (str) -- Path to a settings Python file.
Returns:
- A tuple of settings: (logger settings, shotgun settings, jira settings, sync settings)
Raises:
- ValueError -- if the file does not exist or if its name does not end with
.py
.
property shotgun
Return a connected
ShotgunSession
instance.
property current_shotgun_user
Return the Flow Production Tracking user used for the connection.
Returns:
- A Flow Production Tracking record dictionary with an id key and a type key.
property current_jira_username
Return the username of the current Jira user.
The jira API escapes special characters using %xx syntax when storing the username. For example, the username
richard+hendricks
is stored asrichard%2bhendricks
by the jira API. We decode the username here before returning it to ensure we return the exact value (eg.richard+hendricks
)Returns:
- A string with the username.
property jira
Return a connected
JiraSession
instance.
property sync_settings_names
Return the list of sync settings this bridge handles.
reset()
Reset the bridge.
Clears all caches.
get_syncer(name)
Returns a
Syncer
instance for the given settings name.Parameters:
- str - A settings name.
Raises:
- ValueError - for invalid settings.
sync_in_jira(settings_name, entity_type, entity_id, event, **kwargs)
Sync the given Flow Production Tracking Entity to Jira.
Parameters:
- settings_name (str) - The name of the settings to use for this sync.
- entity_type (str) - The Flow Production Tracking Entity type to sync.
- entity_id (int) - The id of the Flow Production Tracking Entity to sync.
- event - A dictionary with the event meta data for the change.
Returns:
- True if the Entity was actually synced in Jira, False if syncing was skipped for any reason.
sync_in_shotgun(settings_name, resource_type, resource_id, event, **kwargs)
Sync the given Jira Resource to Flow Production Tracking.
Parameters:
- settings_name (str) - The name of the settings to use for this sync.
- resource_type (str) - The type of Jira resource sync, e.g. Issue.
- resource_id (str) - The id of the Jira resource to sync.
- event - A dictionary with the event meta data for the change.
Returns:
- True if the resource was actually synced in Flow Production Tracking, False if syncing was skipped for any reason.
Syncers
Base class in charge of initially determining whether to accept events from Flow Production Tracking and Jira for syncing. If accepted, it then passes on the event to a Handler to process the event.
This must be subclassed to implement a list of Handlers to dispatch events to. Additional parameters can be accepted as well to pass on to Handlers.
from .syncer import Syncer
from .handlers import TaskIssueHandler, NoteCommentHandler, EnableSyncingHandler
class TaskIssueSyncer(Syncer):
"""
Sync Flow Production Tracking Tasks as Jira Issues.
"""
def __init__(self, issue_type="Task", **kwargs):
"""
Instatiate a new Task/Issue syncer for the given bridge.
:param str issue_type: Jira Issue type to use when creating new Issues.
"""
self._issue_type = issue_type
super(TaskIssueSyncer, self).__init__(**kwargs)
self._task_issue_handler = TaskIssueHandler(self, self._issue_type)
self._note_comment_handler = NoteCommentHandler(self)
# A handler combining the Task <-> Issue handler and the Note <-> Comment
# handler. Task syncing to Jira starts if the Task "Sync in Jira" checkbox
# is turned on. Notes linked to a Task being actively synced are automatically
# synced without having to manually select them. A full sync is performed
# when the Task checkbox is turned on.
self._enable_syncing_handler = EnableSyncingHandler(
self, [self._task_issue_handler, self._note_comment_handler]
)
@property
def handlers(self):
"""
Return a list of :class:`~handlers.SyncHandler` instances.
"""
return [
self._enable_syncing_handler,
self._task_issue_handler,
self._note_comment_handler,
]
Syncer
class sg_jira.Syncer(name, bridge, **kwargs)
A class handling syncing between Flow Production Tracking and Jira.
All Syncers should define a list of
SyncHandler
which should reject or accept and process events.Instantiate a new syncer for the given bridge.
Parameters:
__init__(name, *bridge, *kwargs)**
Instantiate a new syncer for the given bridge.
Parameters:
property bridge
Returns the
Bridge
instance used by this syncer.
property shotgun
Return a connected
ShotgunSession
instance.
property jira
Return a connected Jira handle.
property handlers
Needs to be re-implemented in deriving classes and return a list of
SyncHandler
instances.
setup()
Check the Jira and Flow Production Tracking site, ensure that the sync can safely happen and cache any value which is slow to retrieve.
get_jira_project(project_key)
Retrieve the Jira Project with the given key, if any.
Returns:
- A
jira.resources.Project
instance or None.
accept_shotgun_events(entity_type, entity_id, events)
Accept or reject the given event for the given Flow Production Tracking Entity.
Returns:
- A
SyncHandler
instance if the event is accepted for processing, None otherwise.
accept_jira_event (resource_type, resource_id, event)
Accept or reject the given event for the given Jira resource.
Parameters:
resource_type(str) - The type of Jira resource sync, e.g. Issue.
resource_id(str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns:
- A
SyncHandler
instance if the event is accepted for processing, None otherwise.
SyncHandlers
Base class that handles a particular sync instance between Flow Production Tracking and Jira.
Handlers hold the main logic for syncing values between a Flow Production Tracking Entity type and a Jira resource. They are owned by a Syncer instance. This base class defines the interface all handlers should support and provides helpers methods useful to all implementations.
SyncHandlers
class sg_jira.handlers.SyncHandler(syncer)
Base class to handle a particular sync between Flow Production Tracking and Jira.
Handlers typically handle syncing values between a Flow Production Tracking Entity type and a Jira resource and are owned by a
Syncer
instance.This base class defines the interface all handlers should support and provides some helpers which can be useful to all handlers.
Instantiate a handler for the given syncer.
Parameters:
- syncer - A
Syncer
instance.
__init__(syncer)
Instantiate a handler for the given syncer.
Parameters:
- syncer - A
Syncer
instance.
get_jira_project(project_key)
Retrieve the Jira Project with the given key, if any.
Returns:
- A
jira.resources.Project
instance or None.
get_jira_issue(issue_key)
- Retrieve the Jira Issue with the given key, if any.
Parameters:
- issue_key (str) -- A Jira Issue key to look for.
Returns:
- A
jira.Issue
instance or None.Raises:
- RuntimeError -- if the Issue if not bound to any Project.
setup()
This method can be re-implemented in deriving classes to Check the Jira and Flow Production Tracking site, ensure that the sync can safely happen and cache any value which is slow to retrieve.
This base implementation does nothing.
accept_shotgun_event(entity_type, entity_id, event)
Accept or reject the given event for the given Flow Production Tracking Entity.
Must be re-implemented in deriving classes.
Returns:
- True if the event is accepted for processing, False otherwise.
process_shotgun_event(entity_type, entity_id, event)
Process the given Flow Production Tracking event for the given Flow Production Tracking Entity
Must be re-implemented in deriving classes.
Parameters:
entity_type(str) - The Flow Production Tracking Entity type to sync.
entity_id (int) - The id of the Flow Production Tracking Entity to sync.
event - A dictionary with the event for the change.
Returns:
- True if the event was successfully processed, False if the sync didn't happen for any reason.
accept_jira_event(resource_type, resource_id, event)
Accept or reject the given event for the given Jira resource.
Must be re-implemented in deriving classes.
Parameters:
resource_type (str) - The type of Jira resource sync, e.g. Issue.
resource_id (str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns:
- True if the event is accepted for processing, False otherwise.
process_jira_event(resource_type, resource_id, event)
Process the given Jira event for the given Jira resource.
Must be re-implemented in deriving classes.
Parameters:
resource_type (str) - The type of Jira resource sync, e.g. Issue.
resource_id (str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns:
- True if the event was successfully processed, False if the sync didn't happen for any reason.
EntityIssueHandler
Base class for syncing Flow Production Tracking Entities and Jira Issues. This inherits from SyncHandler
.
class sg_jira.handlers.EntityIssueHandler(syncer, issue_type)
Bases:
SyncHandler
Base class for handlers syncing a Flow Production Tracking Entity to a Jira Issue.
Instantiate an Entity Issue handler for the given syncer.
Parameters:
__init__(syncer, issue_type)
Instantiate an Entity Issue handler for the given syncer.
Parameters:
accept_jira_event(resource_type, resource_id, event)
Accept or reject the given event for the given Jira resource.
Parameters:
resource_type (str) - The type of Jira resource sync, e.g. Issue.
resource_id (str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns:
- True if the event is accepted for processing, False otherwise.
process_jira_event(resource_type, resource_id, event)
Process the given Jira event for the given Jira resource.
Parameters:
resource_type (str) - The type of Jira resource to sync, e.g. Issue.
resource_id (str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns: True if the event was successfully processed, False if the sync didn't happen for any reason.
accept_shotgun_event(entity_type, entity_id, event)
Accept or reject the given event for the given Flow Production Tracking Entity.
Must be re-implemented in deriving classes.
Returns:
- True if the event is accepted for processing, False otherwise.
get_jira_issue(issue_key)
Retrieve the Jira Issue with the given key, if any.
Parameters:
- issue_key (str) -- A Jira Issue key to look for.
Returns:
- A
jira.Issue
instance or None.Raises:
- RuntimeError -- if the Issue if not bound to any Project.
get_jira_project(project_key)
Retrieve the Jira Project with the given key, if any.
Returns:
- A
jira.resources.Project
instance or None.
process_shotgun_event(entity_type, entity_id, event)
Process the given Flow Production Tracking event for the given Flow Production Tracking Entity
Must be re-implemented in deriving classes.
Parameters:
entity_type (str) - The Flow Production Tracking Entity type to sync.
entity_id (int) - The id of the Flow Production Tracking Entity to sync.
event- A dictionary with the event for the change.
Returns:
- True if the event was successfully processed, False if the sync didn't happen for any reason.
setup()
This method can be re-implemented in deriving classes to Check the Jira and Flow Production Tracking site, ensure that the sync can safely happen and cache any value which is slow to retrieve.
This base implementation does nothing.
EnableSyncingHandler
A handler that controls the initial sync for a Flow Production Tracking Task and Jira Issue when the "Sync In Jira" checkbox is toggled in Flow Production Tracking. It combines multiple handlers to begin the syncing process by performing a full sync each time the checkbox is toggled on. This allows one to manually force a re-sync if needed by just toggling the checkbox off and then on again.
Inherits from SyncHandler
.
class sg_jira.handlers.EnableSyncingHandler(syncer, handlers)
A handler which combines multiple handlers to start syncing Tasks and Entities linked to them when a Task "Sync In Jira" (sg_sync_in_jira) checkbox field is changed in Flow Production Tracking.
A full sync is performed each time the checkbox is turned on. This allows to manually force a re-sync if needed by just setting off the checkbox, and then back to on.
Instantiate a new handler which combines the provided handlers.
The first handler in the list is assumed to be a primary handler, the others are assumed to be secondary handlers.
Events will be sent to secondary handlers for processing only if the primary handler was able to successfully process them.
This allows to control from the primary handler if a Flow Production Tracking Entity should be synced or not, and then automatically start syncing secondary Entities which are linked to this primary Entity, e.g. Notes on a Task, without having to explicitely enable syncing for the linked Entities.
Combined handlers shouldn't accept the events which are accepted by this handler, but they need to be able to process them.
Parameters:
syncer - A
Syncer
instance.handlers - A non empty list of
SyncHandler
instances.
__init__(syncer, handlers)
Instantiate a new handler which combines the provided handlers.
The first handler in the list is assumed to be a primary handler, the others are assumed to be secondary handlers.
Events will be sent to secondary handlers for processing only if the primary handler was able to successfully process them.
This allows to control from the primary handler if a Flow Production Tracking Entity should be synced or not, and then automatically start syncing secondary Entities which are linked to this primary Entity, e.g. Notes on a Task, without having to explicitely enable syncing for the linked Entities.
Combined handlers shouldn't accept the events which are accepted by this handler, but they need to be able to process them.
Parameters:
syncer - A
Syncer
instance.handlers - A non empty list of
SyncHandler
instances.
setup()
Check the Jira and Flow Production Tracking site, ensure that the sync can safely happen. This can be used as well to cache any value which is slow to retrieve.
Run all handlers setup.
accept_shotgun_event(entity_type, entity_id, event)
Accept or reject the given event for the given Flow Production Tracking Entity.
Returns:
- True if the event is accepted for processing, False otherwise.
process_shotgun_event(entity_type, entity_id, event)
Process the given Flow Production Tracking event for the given Flow Production Tracking Entity
Parameters:
accept_jira_event(resource_type, resource_id, event)/span>
Accept or reject the given event for the given Jira resource.
This handler rejects all Jira events.
Parameters:
resource_type (str) - The type of Jira resource sync, e.g. Issue.
resource_id (str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns:
- True if the event is accepted for processing, False otherwise.
get_jira_issue(issue_key)
Retrieve the Jira Issue with the given key, if any.
Parameters:
- issue_key (str) -- A Jira Issue key to look for.
Returns:
- A
jira.Issue
instance or None.Raises:
- RuntimeError -- if the Issue if not bound to any Project.
get_jira_project(project_key)
Retrieve the Jira Project with the given key, if any.
Returns:
- A
jira.resources.Project
instance or None.
process_jira_event(resource_type, resource_id, event)
Process the given Jira event for the given Jira resource.
Must be re-implemented in deriving classes.
Parameters:
resource_type (str) - The type of Jira resource sync, e.g. Issue.
resource_id (str) - The id of the Jira resource to sync.
event - A dictionary with the event meta data for the change.
Returns:
- True if the event was successfully processed, False if the sync didn't happen for any reason.
Utils
Common utility functions.
sg_jira.utils.utf8_to_unicode(value)
Convert any string in the given input to unicode. Strings are expected to be in utf-8 encoding.
Treat containers by recursively iterating over all the values they contain.
Parameters:
- value -- A string, a list, a tuple, or a dictionary.
Returns:
- The value with all strings converted to unicode.
Raises:
- ValueError -- if a converted UTF-8 decoded key is already present in the original value of a dictionary.
sg_jira.utils.unicode_to_utf8(value)
Convert any unicode in the given input to an utf8 encoded string value.
Treat containers by recursively iterating over all the values they contain.
Parameters:
- value -- A string, a list, a tuple, or a dictionary.
Returns:
- The value with all unicode values converted to strings.
Raises:
- ValueError -- if a converted UTF-8 encoded key is already present in the original value of a dictionary.
Errors
exception sg_jira.errors.InvalidSyncValue(field, value, *args, **kwargs)
Base class for exceptions raised when a value can't be translated to a valid value for a given field.
Parameters:
field (str) -- The Jira or PTR field for which the exception was raised.
value -- The Jira or PTR value for which the exception was raised.
property field
- Return the field for which the exception was raised.
property value
- Return the value for which the exception was raised.
with_traceback()
- Exception.with_traceback(tb) -- set self.traceback to tb and return self.
exception sg_jira.errors.InvalidShotgunValue(field, value, *args, **kwargs)
An exception raised when a Flow Production Tracking value can't be translated to a valid Jira value for a given field.
Parameters:
field (str) -- The Jira or PTR field for which the exception was raised.
value -- The Jira or PTR value for which the exception was raised.
property field
- Return the field for which the exception was raised.
property value
- Return the value for which the exception was raised.
with_traceback()
- Exception.with_traceback(tb) -- set self.traceback to tb and return self.
exception sg_jira.errors.InvalidJiraValue(field, value, args, *kwargs)
An exception raised when a Jira value can't be translated to a valid Flow Production Tracking value for a given field.
Parameters:
field (str) -- The Jira or PTR field for which the exception was raised.
value -- The Jira or PTR value for which the exception was raised.
property field
- Return the field for which the exception was raised.
property value
- Return the value for which the exception was raised.
with_traceback()
- Exception.with_traceback(tb) -- set self.traceback to tb and return self.
Tests & CI
Unit tests are in the /tests
folder. A requirements.txt
file is available in this folder as well to install the required modules to run the tests.
Run the tests from the tests directory with python run_tests.py
.
Continuous Integration (CI)
Azure Pipelines are used for the continuous integration and run the following validations:
Enforce reasonable PEP-8 conventions with Flake8.
Run unit tests on Linux, Mac and Windows with Python 3.9.
Azure Pipelines jobs are defined by the description files in the /azure-pipelines
folder.