[This post is part of a series of articles about working from home in Shotgun.]
When using a distributed pipeline setup, with users working in remote locations, there can arise a need to be able to not only distribute your Toolkit configuration and your work, but also any other tools/plugins that usually sit outside of the Toolkit pipeline.
This post aims to provide an example of how you can set up a way to distribute your Software plugins along with your Toolkit config. It will focus on the distribution part rather than the setup of the plugins, and some plugins which require running an installer might be hard to setup.
However, for plugins that just require a folder to be downloaded and included in some way to your environment, this should work well enough.
Please note that the code provided in this example is not tested in production and is not guaranteed to work, it is intended as an example that can be built upon.
Overview
The process described below will set up a custom entity on your Shotgun site, where you will upload your plugin payload as a zip. Your Toolkit configuration will then contain a hook that will be run when a user tries to launch software, which will check for plugins and download and set up any that are found on your Shotgun site.
Steps
-
First, you need to enable your custom entity that will represent the software plugins. Navigate to the site preferences and enable a
CustomNonProjectEntity
and create a new page to view it on:
-
Create a new
File
field called Payload on your new entity type.
Feel free to create a new entity to test with, but don’t upload anything to it yet. Also, theSoftware
field shown will be created in the next step. -
Navigate to your
Software
entity page, and create a new multi entity field calledSoftware Plugins
(field codesg_software_plugin
) which links to your new custom entity.
This relationship will allow us to know what plugins are required when launching certain software. -
Now you need to add a hook to your config to download these plugins when launching. Copy the
before_app_launch.py
hook from thetk-multi-launchapp
to your config’s hooks folder:
-
Modify your app launch environment settings to use this hook, and also request the
sg_software_plugin
field to be included with the Software entity that gets passed to the hook.software_entity_extra_fields: [sg_software_plugins] hook_before_app_launch: "{config}/tk-multi-launchapp/before_app_launch.py"
Advanced/tk-config-default2:
Basic/tk-config-basic:
-
Next replace the contents of your
before_app_launch.py
file with this: before_app_launch.py (7.8 KB)
The code is commented so I won’t go through it line by line here, but essentially what it does is:- Finds the plugins associated with the
Software
entity. - Before downloading, it will check to see if that version of the plugin has already been downloaded.
- If not it will download and unzip it, to a folder in the Shotgun cache (
{Shotgun Cache}/{your site}/site/tm-launchapp/plugins/
), or you can specify a plugin root folder with theSOFTWARE_PLUGIN_ROOT
environment variable. - It expects each plugin zip to contain a single folder which contains the plugin, and will rename it to be the id of the attachment.
- It then looks for an
sg_setup.py
file inside the root of the plugin folder which will be called to setup the plugin. Each plugin is responsible for its own setup.
- Finds the plugins associated with the
-
Preparing a plugin payload. As mentioned above all the plugin files must be contained within a single folder, and that folder must contain a
sg_setup.py
file. Here is asg_setup.py
file that contains only the required code: sg_setup.py (242 Bytes). You will need to implement code in there that enables the plugin to be used by the software. -
Zip up your plugin and upload it to the
payload
field on your Shotgun Plugin entity. Ensure that your plugin has been added to aSoftware
as well via the software field.
And that is everything you need to do.
Real-world example
Whilst I was testing, I picked the first free Maya plugin I could find on the internet and attempted to set this up. The plugin I picked contained mostly python files and an install.mel
script. I decided to replicate the behavior of the install script and implement it into a userSetup.py
script (which Maya runs on startup.) I then implemented the following code in the sg_setup.py
so that the userSetup.py
would be run on startup.
import sys
import os
import sgtk
def execute(
plugin_path,
software_plugin,
app_path,
app_args,
version,
engine_name,
software_entity,
**kwargs
):
# There may be a better way of doing this, but you can't use
# `__file__` in the `userSetup.py` so we are getting the current
# plugin location here and setting it in an env var so that the
# `userSetup.py` can access it when it runs.
os.environ["STUDIO_LIBRARY_PATH"] = plugin_path
# Append the root plugin path to the PYTHONPATH env var
# so that the userSetup.py file will be run when Maya
# launches.
sgtk.util.append_path_to_env_var("PYTHONPATH", plugin_path)
My plugin before being zipped then looked like this:
There are many other approaches you could use, and ways to improve this example:
- Pulling your plugins from a location other than Shotgun.
- Showing a splash screen whilst it downloads so the user knows why it’s taking a while.
- Bundling the plugins in a framework, uploading the framework to Shotgun, and then referencing the framework with a Shotgun descriptor. Then you could call the framework from the hook. This approach would mean you wouldn’t need to handle the downloading plugins your self, as this would be done when the config is bootstrapped.
Feel free to share any suggestions or approaches you may have!