Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Add validator to check correct version of extension for PS and AE #2387

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions openpype/hosts/aftereffects/plugins/publish/closeAE.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
"""Close AE after publish. For Webpublishing only."""
import pyblish.api

from avalon import aftereffects


class CloseAE(pyblish.api.ContextPlugin):
"""Close AE after publish. For Webpublishing only.
"""

order = pyblish.api.IntegratorOrder + 14
label = "Close AE"
optional = True
active = True

hosts = ["aftereffects"]
targets = ["remotepublish"]

def process(self, context):
self.log.info("CloseAE")

stub = aftereffects.stub()
self.log.info("Shutting down AE")
stub.save()
stub.close()
self.log.info("AE closed")
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class CollectCurrentFile(pyblish.api.ContextPlugin):
"""Inject the current working file into context"""

order = pyblish.api.CollectorOrder - 0.5
order = pyblish.api.CollectorOrder - 0.49
label = "Current File"
hosts = ["aftereffects"]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import os
import re
import pyblish.api

from avalon import aftereffects


class CollectExtensionVersion(pyblish.api.ContextPlugin):
""" Pulls and compares version of installed extension.

It is recommended to use same extension as in provided Openpype code.

Please use Anastasiy’s Extension Manager or ZXPInstaller to update
extension in case of an error.

You can locate extension.zxp in your installed Openpype code in
`repos/avalon-core/avalon/aftereffects`
"""
# This technically should be a validator, but other collectors might be
# impacted with usage of obsolete extension, so collector that runs first
# was chosen
order = pyblish.api.CollectorOrder - 0.5
label = "Collect extension version"
hosts = ["aftereffects"]

optional = True
active = True

def process(self, context):
installed_version = aftereffects.stub().get_extension_version()

if not installed_version:
raise ValueError("Unknown version, probably old extension")

manifest_url = os.path.join(os.path.dirname(aftereffects.__file__),
"extension", "CSXS", "manifest.xml")

if not os.path.exists(manifest_url):
self.log.debug("Unable to locate extension manifest, not checking")
return

expected_version = None
with open(manifest_url) as fp:
content = fp.read()
found = re.findall(r'(ExtensionBundleVersion=")([0-9\.]+)(")',
content)
if found:
expected_version = found[0][1]

if expected_version != installed_version:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be in a validator

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but "It should be technically validator, but it could miss some failing collectors which would result in non understandable errors."

msg = (
"Expected version '{}' found '{}'\n Please update"
" your installed extension, it might not work properly."
).format(expected_version, installed_version)

raise ValueError(msg)
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ def process(self, instance):
staging_dir = instance.data["stagingDir"]
self.log.info("staging_dir::{}".format(staging_dir))

stub.render(staging_dir)

# pull file name from Render Queue Output module
render_q = stub.get_render_info()
stub.render(staging_dir)
if not render_q:
raise ValueError("No file extension set in Render Queue")
_, ext = os.path.splitext(os.path.basename(render_q.file_name))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class CollectCurrentFile(pyblish.api.ContextPlugin):
"""Inject the current working file into context"""

order = pyblish.api.CollectorOrder - 0.5
order = pyblish.api.CollectorOrder - 0.49
label = "Current File"
hosts = ["photoshop"]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
import re
import pyblish.api

from avalon import photoshop


class CollectExtensionVersion(pyblish.api.ContextPlugin):
""" Pulls and compares version of installed extension.

It is recommended to use same extension as in provided Openpype code.

Please use Anastasiy’s Extension Manager or ZXPInstaller to update
extension in case of an error.

You can locate extension.zxp in your installed Openpype code in
`repos/avalon-core/avalon/photoshop`
"""
# This technically should be a validator, but other collectors might be
# impacted with usage of obsolete extension, so collector that runs first
# was chosen
order = pyblish.api.CollectorOrder - 0.5
label = "Collect extension version"
hosts = ["photoshop"]

optional = True
active = True

def process(self, context):
installed_version = photoshop.stub().get_extension_version()

if not installed_version:
raise ValueError("Unknown version, probably old extension")

manifest_url = os.path.join(os.path.dirname(photoshop.__file__),
"extension", "CSXS", "manifest.xml")

if not os.path.exists(manifest_url):
self.log.debug("Unable to locate extension manifest, not checking")
return

expected_version = None
with open(manifest_url) as fp:
content = fp.read()

found = re.findall(r'(ExtensionBundleVersion=")([0-10\.]+)(")',
content)
if found:
expected_version = found[0][1]

if expected_version != installed_version:
msg = "Expected version '{}' found '{}'\n".format(
expected_version, installed_version)
msg += "Please update your installed extension, it might not work "
msg += "properly."

raise ValueError(msg)
46 changes: 46 additions & 0 deletions openpype/lib/remote_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@
from openpype.lib.plugin_tools import parse_json


def headless_publish(log, close_plugin_name=None, is_test=False):
"""Runs publish in a opened host with a context and closes Python process.

Host is being closed via ClosePS pyblish plugin which triggers 'exit'
method in ConsoleTrayApp.
"""
if not is_test:
dbcon = get_webpublish_conn()
_id = os.environ.get("BATCH_LOG_ID")
if not _id:
log.warning("Unable to store log records, "
"batch will be unfinished!")
return

publish_and_log(dbcon, _id, log, close_plugin_name)
else:
publish(log, close_plugin_name)


def get_webpublish_conn():
"""Get connection to OP 'webpublishes' collection."""
mongo_client = OpenPypeMongoConnection.get_mongo_client()
Expand All @@ -38,6 +57,33 @@ def start_webpublish_log(dbcon, batch_id, user):
}).inserted_id


def publish(log, close_plugin_name=None):
"""Loops through all plugins, logs to console. Used for tests.

Args:
log (OpenPypeLogger)
close_plugin_name (str): name of plugin with responsibility to
close host app
"""
# Error exit as soon as any error occurs.
error_format = "Failed {plugin.__name__}: {error} -- {error.traceback}"

close_plugin = _get_close_plugin(close_plugin_name, log)

for result in pyblish.util.publish_iter():
for record in result["records"]:
log.info("{}: {}".format(
result["plugin"].label, record.msg))

if result["error"]:
log.error(error_format.format(**result))
uninstall()
if close_plugin: # close host app explicitly after error
context = pyblish.api.Context()
close_plugin().process(context)
sys.exit(1)


def publish_and_log(dbcon, _id, log, close_plugin_name=None):
"""Loops through all plugins, logs ok and fails into OP DB.

Expand Down
17 changes: 17 additions & 0 deletions openpype/settings/defaults/system_settings/applications.json
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,23 @@
"linux": []
},
"environment": {}
},
"2022": {
"enabled": true,
"variant_label": "2022",
"executables": {
"windows": [
"C:\\Program Files\\Adobe\\Adobe After Effects 2022\\Support Files\\AfterFX.exe"
],
"darwin": [],
"linux": []
},
"arguments": {
"windows": [],
"darwin": [],
"linux": []
},
"environment": {}
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion repos/avalon-core
3 changes: 2 additions & 1 deletion start.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,14 @@ def set_avalon_environments():
os.environ.get("AVALON_MONGO")
or os.environ["OPENPYPE_MONGO"]
)
avalon_db = os.environ.get("AVALON_DB") or "avalon" # for tests
os.environ.update({
# Mongo url (use same as OpenPype has)
"AVALON_MONGO": avalon_mongo_url,

"AVALON_SCHEMA": schema_path,
# Mongo DB name where avalon docs are stored
"AVALON_DB": "avalon",
"AVALON_DB": avalon_db,
# Name of config
"AVALON_CONFIG": "openpype",
"AVALON_LABEL": "OpenPype"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ def startup_scripts(self, monkeypatch_session, download_test_data):
def test_db_asserts(self, dbcon, publish_finished):
"""Host and input data dependent expected results in DB."""
print("test_db_asserts")
assert 3 == dbcon.count_documents({"type": "version"}), \

assert 2 == dbcon.count_documents({"type": "version"}), \
"Not expected no of versions"

assert 0 == dbcon.count_documents({"type": "version",
Expand All @@ -81,18 +82,18 @@ def test_db_asserts(self, dbcon, publish_finished):
"modelMain subset must be present"

assert 1 == dbcon.count_documents({"type": "subset",
"name": "workfileTesttask"}), \
"name": "workfileTest_task"}), \
"workfileTesttask subset must be present"

assert 1 == dbcon.count_documents({"type": "subset",
"name": "reviewTesttask"}), \
"reviewTesttask subset must be present"

assert 6 == dbcon.count_documents({"type": "representation"}), \
assert 4 == dbcon.count_documents({"type": "representation"}), \
"Not expected no of representations"

assert 1 == dbcon.count_documents({"type": "representation",
"context.subset": "imageMainBackgroundcopy", #noqa E501
"context.subset": "renderTestTaskDefault", # noqa E501
"context.ext": "png"}), \
"Not expected no of representations with ext 'png'"

Expand Down
10 changes: 10 additions & 0 deletions tests/integration/hosts/photoshop/test_publish_in_photoshop.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ class TestPublishInPhotoshop(PhotoshopTestClass):
- IS_TEST - this differentiate between regular webpublish
- PYBLISH_TARGETS

Always pulls and uses test data from GDrive!

Test zip file sets 3 required env vars:
- HEADLESS_PUBLISH - this triggers publish immediately app is open
- IS_TEST - this differentiate between regular webpublish
- PYBLISH_TARGETS

Then checks content of DB (if subset, version, representations were
created.
Checks tmp folder if all expected files were published.
Expand All @@ -33,8 +40,11 @@ class TestPublishInPhotoshop(PhotoshopTestClass):
# keep empty to locate latest installed variant or explicit
APP_VARIANT = ""

APP_NAME = "{}/{}".format(APP, APP_VARIANT)

TIMEOUT = 120 # publish timeout


def test_db_asserts(self, dbcon, publish_finished):
"""Host and input data dependent expected results in DB."""
print("test_db_asserts")
Expand Down