diff --git a/client/ayon_core/cli.py b/client/ayon_core/cli.py index 322c294cfb..2340696ad9 100644 --- a/client/ayon_core/cli.py +++ b/client/ayon_core/cli.py @@ -235,6 +235,30 @@ def version(build): print(os.environ["AYON_VERSION"]) +@main_cli.command() +@click.option( + "--project", + type=str, + help="Project name", + required=True) +def create_project_structure( + project, +): + """Create project folder structure as defined in setting + `ayon+settings://core/project_folder_structure` + + Args: + project (str): The name of the project for which you + want to create its additional folder structure. + + """ + + from ayon_core.pipeline.project_folders import create_project_folders + + print(f">>> Creating project folder structure for project '{project}'.") + create_project_folders(project) + + def _set_global_environments() -> None: """Set global AYON environments.""" # First resolve general environment diff --git a/pyproject.toml b/pyproject.toml index c932917224..f4a452a2b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ mdx-gh-links = "^0.4" pymdown-extensions = "^10.14.3" mike = "^2.1.3" mkdocstrings-shell = "^1.0.2" +nxtools = "^1.6" [tool.poetry.group.test.dependencies] attrs = "^25.0.0" diff --git a/server/__init__.py b/server/__init__.py index d60f50f471..620cb3285c 100644 --- a/server/__init__.py +++ b/server/__init__.py @@ -1,6 +1,15 @@ from typing import Any from ayon_server.addons import BaseServerAddon +from ayon_server.actions import ( + ActionExecutor, + ExecuteResponseModel, + SimpleActionManifest, +) +try: + from ayon_server.logging import logger +except ImportError: + from nxtools import logging as logger from .settings import ( CoreSettings, @@ -26,3 +35,67 @@ class CoreAddon(BaseServerAddon): return await super().convert_settings_overrides( source_version, overrides ) + + async def get_simple_actions( + self, + project_name: str | None = None, + variant: str = "production", + ) -> list[SimpleActionManifest]: + """Return a list of simple actions provided by the addon""" + output = [] + + if project_name: + # Add 'Create Project Folder Structure' action to folders. + output.append( + SimpleActionManifest( + identifier="core.createprojectstructure", + label="Create Project Folder Structure", + icon={ + "type": "material-symbols", + "name": "create_new_folder", + }, + order=100, + entity_type="project", + entity_subtypes=None, + allow_multiselection=False, + ) + ) + + return output + + async def execute_action( + self, + executor: ActionExecutor, + ) -> ExecuteResponseModel: + """Execute webactions.""" + + project_name = executor.context.project_name + + if executor.identifier == "core.createprojectstructure": + if not project_name: + logger.error( + f"Can't execute {executor.identifier} because" + " of missing project name." + ) + # Works since AYON server 1.8.3 + if hasattr(executor, "get_simple_response"): + return await executor.get_simple_response( + "Missing project name", success=False + ) + return + + args = [ + "create-project-structure", "--project", project_name, + ] + # Works since AYON server 1.8.3 + if hasattr(executor, "get_launcher_response"): + return await executor.get_launcher_response(args) + + return await executor.get_launcher_action_response(args) + + logger.debug(f"Unknown action: {executor.identifier}") + # Works since AYON server 1.8.3 + if hasattr(executor, "get_simple_response"): + return await executor.get_simple_response( + "Unknown action", success=False + ) diff --git a/server/settings/main.py b/server/settings/main.py index 93cedf2d65..cca885303f 100644 --- a/server/settings/main.py +++ b/server/settings/main.py @@ -319,6 +319,10 @@ class CoreSettings(BaseSettingsModel): "{}", widget="textarea", title="Project folder structure", + description=( + "Defines project folders to create on disk" + " for 'Create project folders' action." + ), section="---" ) project_environments: str = SettingsField(