Introduction
Flow Production Tracking and Jira
Flow Production Tracking is used by studios of all sizes as a production management tool, serving as a central hub for production teams and artists to track, schedule, and review all aspects of a creative project.
Technical staff, including but not limited to software engineers, pipeline TDs, and game developers, often need to use tools in addition to Flow Production Tracking that align more closely to their technical workflows. This is where Jira comes in.
The Flow Production Tracking Jira Bridge allows two-way synchronization of data between Flow Production Tracking and Jira, keeping teams that are using both Flow Production Tracking and Jira connected, and ensuring that Flow Production Tracking can function effectively as the central hub for all project management tracking.
Content
Ready for installation? Check out the Flow Production Tracking Jira Bridge Installation Guide.
How the Flow Production Tracking Jira Bridge works
The Flow Production Tracking Bridge (sg-jira-bridge) provides a simple setup to sync data between Flow Production Tracking and Jira.
At the heart of the workflow is a lightweight web app that handles POST requests to sync data. A request is validated and executed by this module code which handles all the connections, logic, and data translation between Flow Production Tracking and Jira. It then sends a request to update Flow Production Tracking or Jira with the translated data.
Requests to sync data from Flow Production Tracking to Jira are generated by the sg_jira_event_trigger.py plugin running in the Flow Production Tracking Event Daemon Trigger.
Requests to sync data from Jira to Flow Production Tracking are generated by a webhook that is configured in Jira for your Project.
Customizing the workflow
The Flow Production Tracking Jira Bridge is structured so that studios can tailor the workflow to meet their specific needs. Because both Flow Production Tracking and Jira are highly customizable, exposing a handful of settings would not be sufficient. Therefore, the bridge has been structured to allow subclassing the various components that control syncing and handling events to give full control over the logic.
Structure overview
Bridge
The Bridge
is the main class for the sync. It handles the connections to both Flow Production Tracking and Jira, manages sync settings from the settings.py
file, and initiates the calls to sync in Flow Production Tracking and Jira.
This class is intended to be used as-is without requiring customization since the details of the workflow logic are defined in the Syncer
and SyncHandler
. When creating a new instance of Bridge
, typically you'll use the Bridge.get_bridge()
factory method and pass in the full path to the settings file.
Syncers
The Syncer
is in charge of initially determining whether to accept or reject events from Flow Production Tracking and Jira for syncing. This is done with the accept_shotgun_event()
and accept_jira_event()
methods. It performs initial basic checks on the event to determine if it should immediately be rejected without needing to ask the handlers. These checks should be completely independent of the implementation details of the handlers. For example, a Flow Production Tracking event can be inspected to ensure it has the basic required fields in an event like the meta
and project
keys. Without either of these keys in the event, no handlers could process the event anyway.
If nothing in the event immediately disqualifies itself from consideration, the Syncer
then hands the event off to each SyncHandler
to accept the event or not. The first handler that accepts the event is then returned to process the event.
Only one handler may process an event since having multiple handlers process a single event could cause issues where one handler undoes what a previous one did for the same event.
Syncers must be sub-classed from the base Syncer
class in order to implement a list of Handlers to dispatch events to. The handlers()
property must be overridden but additional parameters can be accepted by the class 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
]
Sync Handlers
A SyncHandler
holds the logic for syncing values between a Flow Production Tracking Entity type and a Jira resource and is owned by a Syncer
instance. The base class defines the interface all handlers should support and provides a set of helper methods useful for implementations.
The following methods must be overridden from the Syncer
base class:
# public methods
accept_shotgun_event()
accept_jira_event()
process_shotgun_event()
process_jira_event()
# private property
_sg_jira_status_mapping()
Setup
When a syncer is first loaded, it calls setup()
on each SyncHandler
. This can be used to check the Jira and Flow Production Tracking sites for specific conditions or setup requirements, ensuring that the sync can safely happen.
Additionally, this can be used to cache value(s) from either site if there are queries that might be done repeatedly that slow things down during the sync process.
Accepting the Event
After the Syncer
has done its initial checks to decide whether to accept an event, it then passes the event off to its handlers to check for themselves. Each SyncHandler
must define a accept_shotgun_event()
and accept_jira_event()
which overrides the Syncer
base class. This is where the more specific logic for accepting or rejecting an event can occur. Checks for things like whether the event is for a Flow Production Tracking Entity type or Jira resource type that the handler cares about are appropriate. Or for example, you may wish to check a Flow Production Tracking event to see if the Task field that was changed, is one that is supported by your handler.
The goal of these methods is to quickly determine whether to process the event given the information provided. Queries are expensive. If after checking all of the given event info, there are still more questions to answer that require making additional queries to Flow Production Tracking or Jira, it is perfectly fine for these to be done in the process_shotgun_event()
or process_jira_event()
methods later.
Processing the Event
process_shotgun_event()
and process_jira_event()
process the event data, perform any additional validation required to determine whether to continue with the sync (which may include additional queries to Jira and/or Flow Production Tracking ), and then do the actual update.
Once the event itself has been validated fully, the actual data that has changed is validated and converted to a format appropriate for the recipient of the sync. There are private methods in the base classes that perform some of the heavy lifting for this.
If the event was processed successfully, it returns True
. If the event was not processed for any reason it returns False
.
EntityIssueHandler
In addition to the base SyncHandler
, there is also a EntityIssueHandler
which serves as a base class for handlers that sync between a Flow Production Tracking Entity type and a Jira Issue resource. Since this is probably how a majority of workflows will work, it is provided to add an additional level of convenience.
It inherits from SyncHandler
. When using EntityIssueHander
as a base class, the following methods must be overridden in addition to the ones required by SyncHandler:
_get_jira_issue_field_for_shotgun_field()
_supported_shotgun_fields_for_jira_event()
_get_shotgun_entity_field_for_issue_field()
Want to learn more? Check out the Flow Production Tracking Jira Bridge Developer Resources.