From ae5726edf98b1c0c5e1e2d84e23ac49b82c573f2 Mon Sep 17 00:00:00 2001 From: Enjaileu Date: Thu, 16 Nov 2023 11:34:28 +0100 Subject: [PATCH] folder i18n come back --- docs/user/interface/interface.md | 2 +- docs/user/{ => interface}/shortcuts.md | 0 i18n/fr/code.json | 232 +++++ .../options.json | 14 + .../current.json | 64 ++ .../current/faq.md | 40 + .../current/it/deployment/pipeline-drive.md | 23 + .../current/it/deployment/resilio.md | 45 + .../current/it/deployment/rez.md | 77 ++ .../current/it/deployment/silex-desktop.md | 27 + .../current/it/deployment/wapt.md | 78 ++ .../current/it/observium.md | 16 + .../current/it/portainer.md | 21 + .../current/it/presentation.mdx | 36 + .../current/it/resilio.md | 47 + .../current/it/scripts/blade-tractor.mdx | 22 + .../it/scripts/deploy-package-vray.mdx | 22 + .../current/it/scripts/gokillprocess.mdx | 52 ++ .../current/it/scripts/montage-marvin.mdx | 38 + .../current/it/scripts/presentation.md | 15 + .../current/it/scripts/rez-deployment.mdx | 39 + .../current/it/zammad.md | 32 + .../current/td/Backend/CGWire/zou.md | 108 +++ .../current/td/Backend/backend.md | 32 + .../Renderfarm/Gokillprocess/gokillprocess.md | 48 + .../current/td/Renderfarm/Harvest/harvest.md | 34 + .../td/Renderfarm/Tractor/configuration.md | 206 ++++ .../td/Renderfarm/Tractor/installation.md | 82 ++ .../current/td/Renderfarm/Tractor/issues.md | 107 +++ .../current/td/Renderfarm/Tractor/tractor.md | 14 + .../current/td/Renderfarm/renderfarm.md | 61 ++ .../td/Silex/Architecture/architecture.md | 57 ++ .../Architecture/silex-actions-client.md | 7 + .../td/Silex/Client/action-definition.mdx | 151 +++ .../td/Silex/Client/action-execution.md | 132 +++ .../current/td/Silex/Client/client.md | 36 + .../td/Silex/Client/command-definition.md | 98 ++ .../current/td/Silex/Client/context.md | 29 + .../current/td/Silex/Client/event-loop.md | 42 + .../Submit/implementsubmitter.md | 884 ++++++++++++++++++ .../td/Silex/CommonActions/Submit/submit.md | 158 ++++ .../current/td/Silex/CommonActions/bundle.md | 57 ++ .../td/Silex/CommonActions/commonactions.md | 22 + .../current/td/Silex/CommonActions/conform.md | 102 ++ .../current/td/Silex/CommonActions/publish.md | 272 ++++++ .../current/td/Silex/Plugins/Houdini.md | 28 + .../current/td/Silex/Plugins/Maya.md | 28 + .../current/td/Silex/Plugins/Plugins.md | 103 ++ .../current/td/Silex/Silex.md | 14 + .../td/Silex/SocketService/app-structure.md | 31 + .../current/td/Silex/SocketService/events.md | 81 ++ .../td/Silex/SocketService/listeners.md | 61 ++ .../td/Silex/SocketService/namespace.md | 59 ++ .../current/td/Silex/SocketService/rooms.md | 74 ++ .../current/td/Silex/SocketService/routes.md | 26 + .../td/Silex/SocketService/socket-service.md | 32 + .../current/td/Silex/SocketService/tests.md | 78 ++ .../current/td/Silex/SocketService/usage.md | 31 + .../current/td/Workflow/Rez/Rez.mdx | 202 ++++ .../td/Workflow/continuous-integration.md | 5 + .../current/td/Workflow/git-github.md | 66 ++ .../current/td/Workflow/workflow.md | 5 + .../current/td/design.mdx | 22 + .../current/td/getting-started.md | 236 +++++ .../current/td/introduction.md | 11 + .../user/basic-concepts/actions/actions.md | 5 + .../user/basic-concepts/actions/publish.md | 5 + .../user/basic-concepts/actions/save.md | 5 + .../user/basic-concepts/basic-concepts.md | 7 + .../current/user/basic-concepts/workflow.md | 139 +++ .../current/user/harvest/harvest.md | 5 + .../current/user/interface/file-explorer.md | 43 + .../current/user/interface/interface.md | 88 ++ .../current/user/interface/nimby.md | 7 + .../current/user/interface/statistics.md | 5 + .../current/user/presentation.md | 5 + .../current/user/renderfarm/renderfarm.md | 5 + .../current/user/shortcuts.md | 5 + .../user/trouble-shootinh/trouble-shooting.md | 6 + i18n/fr/docusaurus-theme-classic/footer.json | 122 +++ i18n/fr/docusaurus-theme-classic/navbar.json | 26 + 81 files changed, 5351 insertions(+), 1 deletion(-) rename docs/user/{ => interface}/shortcuts.md (100%) create mode 100644 i18n/fr/code.json create mode 100644 i18n/fr/docusaurus-plugin-content-blog/options.json create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current.json create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/faq.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/pipeline-drive.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/resilio.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/rez.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/silex-desktop.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/wapt.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/observium.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/portainer.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/presentation.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/resilio.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/blade-tractor.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/deploy-package-vray.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/gokillprocess.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/montage-marvin.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/presentation.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/rez-deployment.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/it/zammad.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/CGWire/zou.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/backend.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Gokillprocess/gokillprocess.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Harvest/harvest.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/configuration.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/installation.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/issues.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/tractor.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/renderfarm.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/architecture.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/silex-actions-client.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-definition.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-execution.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/client.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/command-definition.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/context.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/event-loop.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/implementsubmitter.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/submit.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/bundle.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/commonactions.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/conform.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/publish.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Houdini.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Maya.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Plugins.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Silex.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/app-structure.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/events.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/listeners.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/namespace.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/rooms.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/routes.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/socket-service.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/tests.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/usage.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/Rez/Rez.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/continuous-integration.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/git-github.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/workflow.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/design.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/getting-started.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/td/introduction.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/actions.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/publish.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/save.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/basic-concepts.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/workflow.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/harvest/harvest.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/interface/file-explorer.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/interface/interface.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/interface/nimby.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/interface/statistics.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/presentation.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/renderfarm/renderfarm.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/shortcuts.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/user/trouble-shootinh/trouble-shooting.md create mode 100644 i18n/fr/docusaurus-theme-classic/footer.json create mode 100644 i18n/fr/docusaurus-theme-classic/navbar.json diff --git a/docs/user/interface/interface.md b/docs/user/interface/interface.md index 08e3e83..0e52f5f 100644 --- a/docs/user/interface/interface.md +++ b/docs/user/interface/interface.md @@ -43,7 +43,7 @@ This section displays your account avatar, the Nimby status, access to the list 1- Hamberger menu. -2- Update button : Reload the interface (useful if some newly created files don't show or if new features don't appear). You can use the **very precious** CTRL + R [shortcuts](../shortcuts.md)to trigger the same result. +2- Update button : Reload the interface (useful if some newly created files don't show or if new features don't appear). You can use the **very precious** CTRL + R [shortcuts](shortcuts.md) to trigger the same result. 3- List of running software : diff --git a/docs/user/shortcuts.md b/docs/user/interface/shortcuts.md similarity index 100% rename from docs/user/shortcuts.md rename to docs/user/interface/shortcuts.md diff --git a/i18n/fr/code.json b/i18n/fr/code.json new file mode 100644 index 0000000..5becb02 --- /dev/null +++ b/i18n/fr/code.json @@ -0,0 +1,232 @@ +{ + "theme.ErrorPageContent.title": { + "message": "Cette page a planté.", + "description": "The title of the fallback page when the page crashed" + }, + "theme.ErrorPageContent.tryAgain": { + "message": "Réessayer", + "description": "The label of the button to try again when the page crashed" + }, + "theme.NotFound.title": { + "message": "Page introuvable", + "description": "The title of the 404 page" + }, + "theme.NotFound.p1": { + "message": "Nous n'avons pas trouvé ce que vous recherchez.", + "description": "The first paragraph of the 404 page" + }, + "theme.NotFound.p2": { + "message": "Veuillez contacter le propriétaire du site qui vous a lié à l'URL d'origine et leur faire savoir que leur lien est cassé.", + "description": "The 2nd paragraph of the 404 page" + }, + "theme.AnnouncementBar.closeButtonAriaLabel": { + "message": "Fermer", + "description": "The ARIA label for close button of announcement bar" + }, + "theme.BackToTopButton.buttonAriaLabel": { + "message": "Revenez en haut", + "description": "The ARIA label for the back to top button" + }, + "theme.blog.archive.title": { + "message": "Archive", + "description": "The page & hero title of the blog archive page" + }, + "theme.blog.archive.description": { + "message": "Archive", + "description": "The page & hero description of the blog archive page" + }, + "theme.blog.paginator.navAriaLabel": { + "message": "Pagination de la liste des articles du blog", + "description": "The ARIA label for the blog pagination" + }, + "theme.blog.paginator.newerEntries": { + "message": "Nouvelles entrées", + "description": "The label used to navigate to the newer blog posts page (previous page)" + }, + "theme.blog.paginator.olderEntries": { + "message": "Anciennes entrées", + "description": "The label used to navigate to the older blog posts page (next page)" + }, + "theme.blog.post.readingTime.plurals": { + "message": "Une minute de lecture|{readingTime} minutes de lecture", + "description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.blog.post.readMoreLabel": { + "message": "Read more about {title}", + "description": "The ARIA label for the link to full blog posts from excerpts" + }, + "theme.blog.post.readMore": { + "message": "Lire plus", + "description": "The label used in blog post item excerpts to link to full blog posts" + }, + "theme.blog.post.paginator.navAriaLabel": { + "message": "Pagination des articles du blog", + "description": "The ARIA label for the blog posts pagination" + }, + "theme.blog.post.paginator.newerPost": { + "message": "Article plus récent", + "description": "The blog post button label to navigate to the newer/previous post" + }, + "theme.blog.post.paginator.olderPost": { + "message": "Article plus ancien", + "description": "The blog post button label to navigate to the older/next post" + }, + "theme.blog.sidebar.navAriaLabel": { + "message": "Navigation article de blog récent", + "description": "The ARIA label for recent posts in the blog sidebar" + }, + "theme.blog.post.plurals": { + "message": "Un article|{count} articles", + "description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.blog.tagTitle": { + "message": "{nPosts} tagués avec « {tagName} »", + "description": "The title of the page for a blog tag" + }, + "theme.tags.tagsPageLink": { + "message": "Voir tous les tags", + "description": "The label of the link targeting the tag list page" + }, + "theme.colorToggle.ariaLabel": { + "message": "Switch between dark and light mode (currently {mode})", + "description": "The ARIA label for the navbar color mode toggle" + }, + "theme.colorToggle.ariaLabel.mode.dark": { + "message": "dark mode", + "description": "The name for the dark color mode" + }, + "theme.colorToggle.ariaLabel.mode.light": { + "message": "light mode", + "description": "The name for the light color mode" + }, + "theme.docs.DocCard.categoryDescription": { + "message": "{count} items", + "description": "The default description for a category card in the generated index about how many items this category includes" + }, + "theme.docs.sidebar.expandButtonTitle": { + "message": "Déplier le menu latéral", + "description": "The ARIA label and title attribute for expand button of doc sidebar" + }, + "theme.docs.sidebar.expandButtonAriaLabel": { + "message": "Déplier le menu latéral", + "description": "The ARIA label and title attribute for expand button of doc sidebar" + }, + "theme.docs.paginator.navAriaLabel": { + "message": "Pagination des documents", + "description": "The ARIA label for the docs pagination" + }, + "theme.docs.paginator.previous": { + "message": "Précédent", + "description": "The label used to navigate to the previous doc" + }, + "theme.docs.paginator.next": { + "message": "Suivant", + "description": "The label used to navigate to the next doc" + }, + "theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel": { + "message": "Toggle the collapsible sidebar category '{label}'", + "description": "The ARIA label to toggle the collapsible sidebar category" + }, + "theme.docs.tagDocListPageTitle.nDocsTagged": { + "message": "Un document tagué|{count} documents tagués", + "description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.docs.tagDocListPageTitle": { + "message": "{nDocsTagged} avec \"{tagName}\"", + "description": "The title of the page for a docs tag" + }, + "theme.docs.versionBadge.label": { + "message": "Version: {versionLabel}" + }, + "theme.docs.versions.unreleasedVersionLabel": { + "message": "Ceci est la documentation de la prochaine version {versionLabel} de {siteTitle}.", + "description": "The label used to tell the user that he's browsing an unreleased doc version" + }, + "theme.docs.versions.unmaintainedVersionLabel": { + "message": "Ceci est la documentation de {siteTitle} {versionLabel}, qui n'est plus activement maintenue.", + "description": "The label used to tell the user that he's browsing an unmaintained doc version" + }, + "theme.docs.versions.latestVersionSuggestionLabel": { + "message": "Pour une documentation à jour, consultez la {latestVersionLink} ({versionLabel}).", + "description": "The label used to tell the user to check the latest version" + }, + "theme.docs.versions.latestVersionLinkLabel": { + "message": "dernière version", + "description": "The label used for the latest version suggestion link label" + }, + "theme.common.editThisPage": { + "message": "Éditer cette page", + "description": "The link label to edit the current page" + }, + "theme.common.headingLinkTitle": { + "message": "Lien direct vers le titre", + "description": "Title for link to heading" + }, + "theme.lastUpdated.atDate": { + "message": " le {date}", + "description": "The words used to describe on which date a page has been last updated" + }, + "theme.lastUpdated.byUser": { + "message": " par {user}", + "description": "The words used to describe by who the page has been last updated" + }, + "theme.lastUpdated.lastUpdatedAtBy": { + "message": "Dernière mise à jour{atDate}{byUser}", + "description": "The sentence used to display when a page has been last updated, and by who" + }, + "theme.navbar.mobileVersionsDropdown.label": { + "message": "Versions", + "description": "The label for the navbar versions dropdown on mobile view" + }, + "theme.common.skipToMainContent": { + "message": "Aller au contenu principal", + "description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation" + }, + "theme.TOCCollapsible.toggleButtonLabel": { + "message": "Sur cette page", + "description": "The label used by the button on the collapsible TOC component" + }, + "theme.tags.tagsListLabel": { + "message": "Tags :", + "description": "The label alongside a tag list" + }, + "theme.CodeBlock.copied": { + "message": "Copié", + "description": "The copied button label on code blocks" + }, + "theme.CodeBlock.copyButtonAriaLabel": { + "message": "Copier le code", + "description": "The ARIA label for copy code blocks button" + }, + "theme.CodeBlock.copy": { + "message": "Copier", + "description": "The copy button label on code blocks" + }, + "theme.navbar.mobileLanguageDropdown.label": { + "message": "Languages", + "description": "The label for the mobile language switcher dropdown" + }, + "theme.docs.sidebar.collapseButtonTitle": { + "message": "Réduire le menu latéral", + "description": "The title attribute for collapse button of doc sidebar" + }, + "theme.docs.sidebar.collapseButtonAriaLabel": { + "message": "Réduire le menu latéral", + "description": "The title attribute for collapse button of doc sidebar" + }, + "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": { + "message": "← Retour au menu principal", + "description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)" + }, + "theme.tags.tagsPageTitle": { + "message": "Tags", + "description": "The title of the tag list page" + }, + "site.tagline": { + "message": "Guide utilisateur pour TDs et artistes", + "description": "The site title tagline" + }, + "homepage.startButton": { + "message": "Démarrer" + } +} diff --git a/i18n/fr/docusaurus-plugin-content-blog/options.json b/i18n/fr/docusaurus-plugin-content-blog/options.json new file mode 100644 index 0000000..9239ff7 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-blog/options.json @@ -0,0 +1,14 @@ +{ + "title": { + "message": "Blog", + "description": "The title for the blog used in SEO" + }, + "description": { + "message": "Blog", + "description": "The description for the blog used in SEO" + }, + "sidebar.title": { + "message": "Recent posts", + "description": "The label for the left sidebar" + } +} diff --git a/i18n/fr/docusaurus-plugin-content-docs/current.json b/i18n/fr/docusaurus-plugin-content-docs/current.json new file mode 100644 index 0000000..9676a52 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current.json @@ -0,0 +1,64 @@ +{ + "version.label": { + "message": "Next", + "description": "The label for version current" + }, + + "sidebar.td.category.Coding workflow": { + "message": "Codage workflow", + "description": "The label for category Coding workflow in sidebar td" + }, + "sidebar.td.category.Silex": { + "message": "Silex", + "description": "The label for category Silex in sidebar td" + }, + "sidebar.td.category.Architecture": { + "message": "Architecture", + "description": "The label for category Architecture in sidebar td" + }, + "sidebar.td.category.Client": { + "message": "Client", + "description": "The label for category Client in sidebar td" + }, + "sidebar.td.category.Common Actions": { + "message": "Common Actions", + "description": "The label for category Common Actions in sidebar td" + }, + "sidebar.td.category.Submit": { + "message": "Submit", + "description": "The label for category Submit in sidebar td" + }, + "sidebar.td.category.Plugins": { + "message": "Plugins", + "description": "The label for category Plugins in sidebar td" + }, + "sidebar.td.category.SocketService": { + "message": "SocketService", + "description": "The label for category SocketService in sidebar td" + }, + "sidebar.td.category.Backend": { + "message": "Backend", + "description": "The label for category Backend in sidebar td" + }, + "sidebar.td.category.CGWire": { + "message": "CGWire", + "description": "The label for category CGWire in sidebar td" + }, + "sidebar.td.category.Renderfarm": { + "message": "Renderfarm", + "description": "The label for category Renderfarm in sidebar td" + }, + "sidebar.td.category.Tractor": { + "message": "Tractor", + "description": "The label for category Tractor in sidebar td" + }, + + "sidebar.it.category.deployment": { + "message": "Déploiment", + "description": "The label for category Deployment in sidebar it" + }, + "sidebar.it.category.scripts": { + "message": "Scripts", + "description": "The label for category Scripts in sidebar it" + } +} diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/faq.md b/i18n/fr/docusaurus-plugin-content-docs/current/faq.md new file mode 100644 index 0000000..029cfb0 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/faq.md @@ -0,0 +1,40 @@ +--- +id: faq +title: FAQ +sidebar_position: 10 +--- + +--- + +### S'enquérir du bien-être des autres + +
+ Comment vous allez ? +
+
Pas très bien maintenant que vous me le demandez ..
+
+
+ +### Problème doc + +
+ J'ai une question quelconque par rapport à la doc où puis-je la poser ? +
+
Il faut contacter un TD, il vaudrait mieux même si vous venez nous voir de nous envoyer un mail ou un message chat sur google, ou sur discord, cela nous permet de garder une trace écrite des questions récurrentes ou non
+
+
+
+ Pourquoi la doc n'est pas fini ? +
+
'' Une documentation n'est jamais vraiment fini ''
+
+
+ +### Problème Silex/Renderfarm + +
+ J'ai un problème avec Silex ou la renderfarm que faire ? +
+
Il faut contacter un TD, il vaudrait mieux même si vous venez nous voir de nous envoyer un mail ou un message chat sur google, ou sur discord, cela nous permet de garder une trace écrite des bugs récurrents ou non
+
+
diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/pipeline-drive.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/pipeline-drive.md new file mode 100644 index 0000000..bb3d96e --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/pipeline-drive.md @@ -0,0 +1,23 @@ +--- +id: pipeline-drive +title: Pipeline Drive +sidebar_position: 10 +--- + +--- + +Snapin pour montage P: drive pour les projets 5RN. +Seulement pour les machines de 5RN. + +## Pourquoi ? + +Nous avons besoin de créer un alias de drive **_P:_** monté sur **_D:/PIPELINE_**, pour que le repath soit transparent entre farm et machine locale.
+Quand une tache est envoyée à une blade, la première commande exécutée est celle du montage du P: sur tars ou ana, en fonction du projet. + +``` +📦pipeline-drive + ┣ 📜Montage_marvin.bat // ajout du net use for P: + ┣ 📜set-drive-pipeline.bat // exec set-drive-pipeline.ps1 + ┣ 📜set-drive-pipeline.ps1 // remplace marvin dans le dossier shell:startup pour ajouter P: mappé on D:/PIPELINE + ┗ 📜snapin.png // screenshot of fog snapin +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/resilio.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/resilio.md new file mode 100644 index 0000000..952b75e --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/resilio.md @@ -0,0 +1,45 @@ +--- +id: resilio +title: Resilio +sidebar_position: 20 +--- + +--- + +Resilio est l'outil de synchronisation entre tous les groupes et les nas. + +## Accès + +| | | +| ------- | ------------------------- | +| Adresse | `http://172.16.69.2:8443` | + +## Configuration + +L'équipe IT va générer les fichiers de config depuis la console resilio, chaque fichier de config peut avoir des variables par exemple GROUP en clés et en valeur le nom du groupe. + +Avec cette technique l'association des machines dans chaque groupe sera automatique lors du déploiement sera "automatique". + +## Merge fichier .conf et .MSI + +Pour faciliter le déploiement avec fog, on a utilisé [ce script](https://github.com/ArtFXDev/silex_fog_snapin/blob/main/resilio/attach-sync-conf-to-msi.ps1) avec la commande `powershell.exe -ExecutionPolicy Bypass -Noprofile ./attach-sync-conf-to-msi.ps1 -MSIPath .\Resilio-Connect-Agent_x64.msi -SyncConfPath .\sync.conf` + +À la sortie de la commande cela donnera un seul .msi qu'on peut déployer via un fog snapin. + +## Comment désinstaller proprement Resilio + +En supposant que vous avez déployé resilio avec FOG en tant que user SYSTEM. + +L'utilisation de PsExec est disponible uniquement avec une powershell démarrer en administrateur. + +1. Télécharger PsExec: + - PsExec est trouvable ici [PsTools](https://docs.microsoft.com/en-us/sysinternals/downloads/psexec) + - Extraire PsExec qui se trouve dans le .zip et placez-le dans le C:/ (pour que ce soit plus simple, il est aussi disponible ici \\192.168.2.112\rez\windows\PsExec.exe) +2. Ouvrir un powershell en tant qu'administrateur dans C:/. +3. Écrire `.\PsExec.exe -i -s powershell.exe` pour ouvrir un powershell en tant que user system. +4. Lancer le même .msi que celui installé, dans l'interface qui s'ouvre on a l'option pour supprimer le client resilio. + - Quand on désinstalle resilio, la plupart du temps le service windows explorer.exe plante (plus de barre de tâches etc), pour fix ça il faut simplement ouvrir le gestionnaire de tâche (ctrl+shift+echap) puis file > run new process et écrire explorer.exe, tout devrait réapparaitre. +5. Quand on désinstalle resilio il faut également supprimer ce dossier `C:\ProgramData\resilio folder` aprés avoir desinstaller resilio. +6. Quand tout est fait c'est bon resilio est désinstallé, vous pouvez réinstaller un client normalement avec PsExec si vous voulez réinstaller en system. + +Cette "procédure" fonctionne en cas de remplacement d'un disque de PFE5RN. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/rez.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/rez.md new file mode 100644 index 0000000..3d10250 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/rez.md @@ -0,0 +1,77 @@ +--- +id: rez +title: Rez +sidebar_position: 30 +--- + +--- + +Rez est utilisé pour composer des environnements virtuels à la volée. + +## Pourquoi Rez? + +Quand on crée une nouvelle scène avec SilexDesktop, rez est utilisé pour lancer le bon logiciel dans un environnement composé avec le bon contexte.
+Rez est aussi utilisé pour passé dans d'autre environment facilement, (dev, beta, prod).
+les packages dev son stocké localement, beta et prod sont stockés sur un serveur samba (\\192.168.2.112\rez) + +Vous pouvez retrouver REZ sur GitHub [ici](https://github.com/nerdvegas/rez). + +## Packages + +Les packages sont stockés ici : \\192.168.2.112\rez + +![](@site/static/img/it/package_root.png) + +Pour une question de performance, le dossier lib est copié localement en utilisant le snapin `rez-install-from-network`. + +silex-rez est la racine du dosser pour tous les packages REZ du pipeline. + +![](@site/static/img/it/silex_rez_package.png) + +``` +📦silex-rez packages + ┣ 📂5rn // packages des projets 5rn, pour ajouter des dépendances au besoin + ┃ ┣ 📂achromatic + ┃ ┣ 📂fady + ┃ ┣ 📂la_mouche + ┃ ┣ 📂la_tielle_setoise + ┃ ┣ 📂macula + ┃ ┣ 📂my_dog_ate_the_moon + ┃ ┣ 📂nelliebly + ┃ ┣ 📂pek + ┃ ┣ 📂quit_smoking + ┃ ┣ 📂skyrace + ┃ ┣ 📂supower + ┃ ┣ 📂test_pipe + ┃ ┣ 📂watchers + ┃ ┣ 📂what_about_cooking + ┃ ┗ 📜.rez + ┣ 📂dcc // packages dcc, par example, houdini installé au même endroit sur chaque machine. + ┃ ┣ 📂houdini + ┃ ┣ 📂maya + ┃ ┣ 📂nuke + ┃ ┗ 📜.rez + ┣ 📂silex // pipepline packages + ┃ ┣ 📂aiogazu + ┃ ┣ 📂silex_client + ┃ ┃ ┣ 📂beta.0.1.0 + ┃ ┃ ┗ 📂prod.0.1.0 + ┃ ┣ 📂silex_houdini + ┃ ┃ ┣ 📂beta.0.1.0 + ┃ ┃ ┗ 📂prod.0.1.0 + ┃ ┣ 📂silex_maya + ┃ ┃ ┣ 📂beta.0.1.0 + ┃ ┃ ┗ 📂prod.0.1.0 + ┃ ┣ 📂silex_nuke + ┃ ┃ ┣ 📂beta.0.1.0 + ┃ ┃ ┗ 📂prod.0.1.0 + ┃ ┗ 📜.rez + ┣ 📂softwares // les autres logiciel et moteur de rendu, pour faire des variants par dccs + ┃ ┣ 📂aces + ┃ ┣ 📂arnold + ┃ ┣ 📂python + ┃ ┣ 📂tractor + ┃ ┣ 📂vray + ┃ ┗ 📜.rez + ┗ 📜.rez // les fichiers .rez sont utilisés avec la config rezconfig.py modifié pour descendre plus bas dans les arborescences de dossier. +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/silex-desktop.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/silex-desktop.md new file mode 100644 index 0000000..ab53f1e --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/silex-desktop.md @@ -0,0 +1,27 @@ +--- +id: silex-desktop +title: Silex Desktop +sidebar_position: 40 +--- + +--- + +Silex Desktop est le client du pipeline. +Avec ce logiciel on peut exécuter des actions du pipeline ArtFX sur chaque dcc. +Ouvrir des scènes, publish, conform etc. + +## Comment déployer ? + +``` +📦silex-desktop + ┣ 📜silex-desktop-Setup-1.0.10.exe // .exe packages for ArtFX + ┗ 📜SilexDesktopDeploymentFog.png // screenshot des snapin +``` + +Quand ce snapin sera exécuté sur une machine d'ArtFX, une erreur apparaîtra.
+C'est un comportement normal. + +L'erreur apparaît parce que les snapin fog sont exécutés en tant qu'utilisateur system, mais l'application installée s'installe dans **_%appdata%/local_**.
L'utilisateur system n'ayant pas **_d'%appdata%_** une erreur apparaît.
+Mais comme l'installer de l'application l'install pour tous les utilisateurs, l'utilisateur "etudiant" disposera quand meme de Silex Desktop. + +Cet exécutable est a utilisé lors du premier déploiement, après l'installation Silex-Desktop va chercher la dernière mise à jour disponible depuis GitHub et se mettra à jour automatiquement. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/wapt.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/wapt.md new file mode 100644 index 0000000..4435ddc --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/deployment/wapt.md @@ -0,0 +1,78 @@ +--- +id: wapt +title: Wapt +sidebar_position: 50 +--- + +--- + +WAPT sera le nouvel outil de déploiement pour déployer des paquets sur les machines, il remplacera les snapins FOG. + +## Créé un package + +Pour créer un nouveau paquet il faut aller dans l'onglet 'dépôt privé' dans l'interface wapt puis cliquer sur "générer un modèle de paquet". + +![](/img/it/wapt_packages/wapt_packages_create_menu.png) + +Une fenêtre va s'ouvrir pour choisir qu'elle type de paquet on veut créer. + +Pour notre exemple on va partir du principe qu'on veut déployer un script, car c'est le plus "compliqué". +![](/img/it/wapt_packages/wapt_packages_create_template_package.png) + +Il faut choisir ici "paquet vide". + +Une fois le paquet l'éditeur est censé s'ouvrir s'il ne s'ouvre pas vous pouvez lancer l'édition d'un paquet en faisant clique droit puis "modifier le paquet dans l'éditeur". + +![](/img/it/wapt_packages/wapt_packages_edit_package_menu.png) + +Une fois que votre éditeur favori s'ouvre vous pouvez vous rendre compte que le langage de script des paquets est Python3 ! + +Pour exécuter et avoir les logs d'exécution d'un script powershell vous pouvez utiliser ce script python: + +```py +from pathlib import Path +import subprocess + +SMB_SERVER = r"\\\" +SCRIPT_NAME = ".ps1" +def install(): + print("Installing: %s" % control.package) + script_path = Path(SMB_SERVER) / SCRIPT_NAME + print(f"Executing {script_path}") + process = subprocess.Popen(["powershell", "-ExecutionPolicy", "ByPass", "-NoProfile", "-File", script_path], stdout=subprocess.PIPE) + p_out, _ = process.communicate() + print(p_out) +``` + +## Mettre à jour un package + +Une fois vos modifications effectué, vous pouvez mettre à jour le paquet en cliquant sur "importer un paquet" puis "construire et importer un paquet dans le dépôt". + +![](/img/it/wapt_packages/wapt_packages_import_package_menu.png) + +Un explorateur va s'ouvrir et vous devrez sélectionner votre dossier local du paquet. _(par défaut situé sous 'C:\waptdev')._ + +Une fois l'import effectué il faut cliquer en haut à gauche sur "Actualiser les paquets disponibles" et vous devrez voir votre numéro de version s'incrémenter. + +![](/img/it/wapt_packages/wapt_packages_import_package_version.png) + +## Mettre à jour une machine + +Une fois que vous avez créé et/ou mis à jour un paquet, pour lancer son exécution il faut se rendre dans l'onglet "inventaire" dans la barre de recherche, mettre la machine sur laquelle on veut lancer la mise à jour. + +![](/img/it/wapt_packages/wapt_packages_register_package_in_computer_menu.png) + +Si votre paquet n'apparaît pas à droite c'est normal, c'est qu'il n'a pas encore était installé sur cette machine. + +Pour enregistrer le paquet dans la machine cliquer sur "Modifier la machine", sélectionner votre paquet dans la fenêtre de droite puis faite "ajouter des dépendances au paquet". + +![](/img/it/wapt_packages/wapt_packages_register_package_in_computer.png) + +Puis cliquer sur enregistrer et appliquer. + +Ensuite si le status de la machine ne change pas en "TO-UPGRADE" cliquer sur "vérification des mises à jour" puis sur "Actualiser" et là le status devrait changer. + +Pour lancer l'exécution du paquet il suffit alors de cliquer sur "Lancer les installations". + +Une fois le paquet installé vous pourrez retrouver les logs à la fin de l'exécution du paquet (statuts passés sur 'ok'). +![](/img/it/wapt_packages/wapt_packages_end_install_and_log_on_computer.png) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/observium.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/observium.md new file mode 100644 index 0000000..3aa239b --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/observium.md @@ -0,0 +1,16 @@ +--- +id: observium +title: Observium +sidebar_position: 40 +--- + +--- + +Observium est utilisé pour voir l'état des serveurs/nas, voir l'état des équipements réseau. +Utile pour voir la saturation et les limites de l'infrastructure réseau. + +## Accès + +| | | +| ------- | --------------------- | +| Adresse | `http://172.16.2.144` | diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/portainer.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/portainer.md new file mode 100644 index 0000000..10fb6ab --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/portainer.md @@ -0,0 +1,21 @@ +--- +id: portainer +title: Portainer +sidebar_position: 30 +--- + +--- + +Portainer est un outil graphique pour administrer et créer des containers docker sur la preprod et prod. + +## Preprod + +| | | +| ------- | --------------------------- | +| Adresse | `http://192.168.2.111:9000` | + +## Prod + +| | | +| ------- | --------------------------- | +| Adresse | `http://192.168.2.112:9000` | diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/presentation.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/it/presentation.mdx new file mode 100644 index 0000000..48c2f2d --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/presentation.mdx @@ -0,0 +1,36 @@ +--- +id: presentation +title: Présentation +sidebar_position: 10 +--- + +--- + +import { PROD_ROOT } from "@site/src/constants"; + +## Outils déployés + +- Silex desktop: enclencher nimby, file manager. En l'état, problème d'installation avec fog, mais le système de déploiement va changer. + - Pour les étudiants, silex desktop (installé en etudiant), service de kill (GOKILL install systeme), tractor blade (install systeme) pour utiliser l'ordi sur la farm, Rez, ports TCP à ouvrir (GO Kill 5119, pour gérer le nofreeslot, 5118 pour avoir le statut de silex à distance, 9005 port des blades), déploiement de Vray, problème avec les variables d'environnement système (les mettre au niveau etudiant) + - Pour les 5RN, même chose + Resilio, configuration resilio powershell pour merge le msi d'installation et la config (on se retrouve avec 1 msi par groupe), supprimer hrender sur les machines locales pour qu'il prenne celui de rez, montage marvin pour le disque P, copier les packages rez en local (pour aller plus vite) (idéalement utiliser le cache) +- Scripts powershell pour deployer chaque système, a part pour les .msi qui sont déployés directement dans fog (ex Resilio). Les scripts powershells sont stockés sur un serveur samba (192.168.2.112). +- Resilio +- Rez, à déployer, via un script powershell. Ne peut pas se servir de la version embeddable. Ont utilisé la version python de scoop (package manager pour windows) pour avoir un venv et un truc facilement déployable. Il faut une variable d'environnement qui pointe sur la config qui est sur le samba. +- Version python : se baser vfxplatform.com +- Tractor, c'est un peu de la merde. Deadline serait plus pratique. A priori on peut garder tel quel. Il faut que tractor s'authentifie sur kitsu, script perso par joseph. Tractor, quand on se login dessus, lance un script python qui fait un est de login kitsu avec. +- Serveur de preprod (pour faire des tests + contient les conteneurs hotfix et pas très officiels) et prod : containeurs docker, base de données kitsu, api rest et api graphql pour communiquer avec, bdd harvest, api pour communiquer avec harvest, nginx reverse proxy pour les frontend (silex, harvest, kitsu/cgwire), zammad système de tickets, front de la doc de silex (docusaurus) + des trucs temporaires qui vont pas rester. +- Actuellement le serveur de preprod sert aussi de samba pour mettre tous les packages rez (faut-il un serveur spécifique pour ça ?). Olivier y stocke aussi ses scripts powershell, sur le samba. +- Configuration de nginx pour renvoyer vers les différents services + +### Adresse samba : + +\\{PROD_ROOT}\rez +
+
+ +linux, windows : sert au déploiement
+packages : servent pour rez
+houdini : hda custom des étudiants (devrait être un package rez)
+arnold : shaders custom osl des étudiants (devrait être un package rez)
+nuke : guizmo custom (devrait être un package rez)
+transfert : sert à stocker les fichiers à transférer, il y a les docs de prez diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/resilio.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/resilio.md new file mode 100644 index 0000000..9b8632c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/resilio.md @@ -0,0 +1,47 @@ +--- +id: resilio +title: Resilio +sidebar_position: 20 +--- + +--- + +## Présentation + +Resilio est l'outil de synchronisation entre tous les groupes et les nas. + +## Configuration + +L'équipe IT va générer les fichiers de config depuis la console resilio, chaque fichier de config peut avoir des variables par exemple GROUP en clés et en valeur le nom du groupe. + +Avec cette technique l'association des machines dans chaque groupe sera automatique lors du déploiement sera "automatique". + +## Merge fichier .conf et .MSI + +Pour faciliter le déploiement avec fog, on a utilisé [ce script](https://github.com/ArtFXDev/silex_fog_snapin/blob/main/resilio/attach-sync-conf-to-msi.ps1) avec la commande `powershell.exe -ExecutionPolicy Bypass -Noprofile ./attach-sync-conf-to-msi.ps1 -MSIPath .\Resilio-Connect-Agent_x64.msi -SyncConfPath .\sync.conf` + +À la sortie de la commande cela donnera un seul .msi qu'on peut déployer via un fog snapin. + +## Comment désinstaller proprement Resilio + +En supposant que vous avez déployé resilio avec FOG en tant que user SYSTEM. + +L'utilisation de PsExec est disponible uniquement avec une powershell démarrer en administrateur. + +1. Télécharger PsExec: + - PsExec est trouvable ici [PsTools](https://docs.microsoft.com/en-us/sysinternals/downloads/psexec) + - Extraire PsExec qui ce trouve dans le .zip et placez-le dans le C:/ (pour que ce soit plus simple, il est aussi disponible ici \\192.168.2.112\rez\windows\PsExec.exe) +2. Ouvrir un powershell en tant qu'administrateur dans C:/. +3. Écrire `.\PsExec.exe -i -s powershell.exe` pour ouvrir un powershell en tant que user system. +4. Lancer le même .msi que celui installé, dans l'interface qui s'ouvre on a l'option pour supprimer le client resilio. + - Quand on désinstalle resilio, la plupart du temps le service windows explorer.exe plante (plus de barre de tâches etc), pour fix ça il faut simplement ouvrir le gestionnaire de tâche (ctrl+shift+echap) puis file > run new process et écrire explorer.exe, tout devrait réapparaitre. +5. Quand on désinstalle resilio il faut également supprimer ce dossier `C:\ProgramData\resilio folder` aprés avoir desinstaller resilio. +6. Quand tout est fait c'est bon resilio est désinstallé, vous pouvez réinstaller un client normalement avec PsExec si vous voulez réinstaller en system. + +Cette "procédure" fonctionne en cas de remplacement d'un disque de PFE5RN. + +## Accès + +| | | +| ------- | ------------------------- | +| Adresse | `http://172.16.69.2:8443` | diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/blade-tractor.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/blade-tractor.mdx new file mode 100644 index 0000000..f821c7c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/blade-tractor.mdx @@ -0,0 +1,22 @@ +--- +id: blade-tractor +title: Blade Tractor +sidebar_position: 20 +--- + +--- + +import CodeSnippet from "@site/src/components/codeSnippetComponent"; + +# Présentation + +Le déploiement de la blade ce fait via Tractor .msi présent sous `\\192.168.2.112\rez\windows\tractor-blade-patch` +Ensuite il faut déployer ce script qui va mettre à jour certains scripts de la blade qui ont été customisé. + +# Contenu + + diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/deploy-package-vray.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/deploy-package-vray.mdx new file mode 100644 index 0000000..fce2b8c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/deploy-package-vray.mdx @@ -0,0 +1,22 @@ +--- +id: deploy-package-vray +title: Deploy Package Vray +sidebar_position: 30 +--- + +--- + +import CodeSnippet from "@site/src/components/codeSnippetComponent"; + +# Présentation + +Ce script copie simplement le contenu du plugin v-ray présent sur le 192.168.2.112 sur la machine locale. +Le lien entre le dossier sur la machine locale et Houdini est effectué grace au fichier .json a placé dans le dossier 'package' là où est installé Houdini. + +# Contenu + + diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/gokillprocess.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/gokillprocess.mdx new file mode 100644 index 0000000..57a9297 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/gokillprocess.mdx @@ -0,0 +1,52 @@ +--- +id: deploy-gokillprocess +title: Deploy Go killprocess +sidebar_position: 40 +--- + +--- + +import CodeSnippet from "@site/src/components/codeSnippetComponent"; + +## Présentation + +Gokillprocess permet de récupérer la liste des processus, services ainsi que de kill un processus via PID et redémarrer un service via le nom, +à travers des requêtes http. + +| descritpion | route | Verbe HTTP | Utilisation | +| --------------------- | ---------------------------------------- | ---------- | ---------------------------------- | +| Lister les processus | `http://:5119/processes` | GET | | +| Lister les services | `http://:5119/services` | GET | | +| Kill d'un processus | `http://:5119/kill/` | POST | PID dans l'url | +| Redemarrer un service | `http://:5119/restartservice` | POST | Name dans body de la requetes post | + +Ce service est également utilisé pour kill les no free slots sur la farm. +Pour tester vos requêtes http vous pouvez utiliser l'outil [postman](https://www.postman.com). + +## Script de déploiement + + + +## Ouverture de ports + +Pour fonctionner ce service a besoin d'avoir le port 5119 d'ouvert sur toutes les machines. +Ce script contient également d'autres ports, ceux-ci ne sont pas utiles pour gokillprocess mais pour d'autres : + +| Service | Port | protocole | +| --------------- | ---- | ---------- | +| Go killprocess | 5119 | TCP IN/OUT | +| Silex Desktop | 5118 | TCP IN/OUT | +| Tractor service | 9005 | TCP IN/OUT | + +Remove-NetFirewallRule -DisplayName "silex-desktop.exe" est utile car lors de l'installation un pop-up apparaît pour l'autorisation sur le pare-feu local, +si ce pop-up est refusé, siles-desktop.exe est bloqué sur le pare-feu locale. + + diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/montage-marvin.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/montage-marvin.mdx new file mode 100644 index 0000000..76d5cca --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/montage-marvin.mdx @@ -0,0 +1,38 @@ +--- +id: montage-marvin +title: Montage Marvin +type: doc +sidebar_position: 50 +--- + +--- + +import CodeSnippet from "@site/src/components/codeSnippetComponent"; + +# Montage Marvin + +Ce script à était modifié pour les PFE5RN, il est utilisé pour monter un alias "P:" pointant sur "D:/PIPELINE". +C'est alias P: est du coup utilisé pour tous les paths dans les scènes du pipe, ce qui permet d'éviter une étape de repath coté render farm. +Coté render farm, il suffit de changer lors du rendu l'alias "P:" pointant par exemple sur le nas ANA. + +# Script de déploiement + +Ce script est utilisé pour le snapin fog. +Ont copy le fichier montage_marvin.bat dans le dossier de démarrage de la machine locale. +Tous les scripts présents dans le dossier de démarrage seront exécutés au démarrage de la machine. + + + +# Contenu du Script + +Nous avons seulement ajouté la ligne de l'alias P: + + diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/presentation.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/presentation.md new file mode 100644 index 0000000..f73fb1c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/presentation.md @@ -0,0 +1,15 @@ +--- +id: presentation +title: Présentation +type: doc +sidebar_position: 10 +--- + +--- + +# Présentation et détails des scripts utilisés lors du déploiement + +Cette documentation détails le fonctionnement de chaque script. + +La plupart des scripts ont était créé dans la logique de pouvoir être redéployé.
+Seuls certains fichiers comme la blade tractor ne possède pas ce comportement, ce qui nous a obligé à récréer un snapin de `reset_status.ps1` pour redémarrer les services en cas de redéploiement par exemple. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/rez-deployment.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/rez-deployment.mdx new file mode 100644 index 0000000..946d43e --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/scripts/rez-deployment.mdx @@ -0,0 +1,39 @@ +--- +id: rez-deployment +title: Rez Deployment +type: doc +sidebar_position: 60 +--- + +--- + +import CodeSnippet from "@site/src/components/codeSnippetComponent"; + +# Rez + +## Test for py3 + +Dans le pipeline on utilise rez avec la version 3.7.9 de python. +Nous avons donc besoin de la version de python sur chaque machine de la farm. +La première étape de ce script est de tester la version de python installer, et d'installer la bonne version de python au besoin. + +Pour installer python via un script on copie simplement une installation de python embeddable. +Dans les releases python officiel embeddable, les installe ne comprennent pas le package venv qui est indispensable pour rez, nous n'utilisons donc pas les versions embeddable officielles mais une version de python installé depuis scoop. + +## Installation de rez + +Dans chaque machine rez est installé dans C:/rez +./ **install** contient l'install local de rez +./ packages contient les packages locaux, ils sont également copiés grace aux scripts en local. +Le path vers l'exécutable de rez est également ajouté à la variable d'environnement PATH. +Le path vers le fichier de configuration rez est situé ici `\\192.168.2.112\rez\windows\config\rezconfig.py` et est ajouté à la variable REZ_CONFIG_FILE + +## Scripts + +Scripts du snapin: + + diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/it/zammad.md b/i18n/fr/docusaurus-plugin-content-docs/current/it/zammad.md new file mode 100644 index 0000000..ba72de4 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/it/zammad.md @@ -0,0 +1,32 @@ +--- +id: zammad +title: Zammad +sidebar_position: 50 +--- + +--- + +Zammad est l'outil utilisé pour le suivi des tickets. + +| | | +| ------- | --------------------------- | +| Adresse | `http://192.168.2.111:8081` | + +Zammad tourne dans un container sur la preprod. + +## Création du ticket + +Il y a deux moyens de créé un ticket, via l'interface Siles dans le menu ticket, ou par mail à `silex-support@artfx.fr`. + +## Email + +Il existe 2 adresses email associées à Zammad. +La réception des tickets par mail ce fait via `silex-support@artfx.fr` et la sortie par `silex@artfx.fr` +Pour la notification par mail, qu'on peut configurer dans son profil utilisateur zammad, l'email de notification est également envoyé via `silex@artfx.fr` + +Pour administrer les paramètres liés aux emails : `http://192.168.2.111:8081/#channels/email` + +| email | roles | +| ---------------------- | ------------------------- | +| silex-support@artfx.fr | inbound | +| silex@artfx.fr | outbound and notification | diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/CGWire/zou.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/CGWire/zou.md new file mode 100644 index 0000000..177c7ef --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/CGWire/zou.md @@ -0,0 +1,108 @@ +--- +id: zou +title: Zou +sidebar_position: 10 +--- + +--- + +[Zou](https://zou.cg-wire.com/) est la base de données de l'écosystème CGWire. + +Il nous permet de **stocker les données de production** pour les films, y compris les séquences, les shots, les assets, les utilisateurs, les templates de fichiers, les customs entities... + +## Configuration + +### `zou-deploy` + +[`zou-deploy`](https://github.com/ArtFXDev/zou-deploy) est me repository qui contient des scripts pour remplir automatiquement la base de données Zou avec des utilisateurs, des projets et d'autres entités. + +Il s'appuie sur les fichiers de configuration `.csv` et JSON pour remplir la base de données. + +### Arborescence de fichiers + +Chaque chemin du pipeline est défini par une configuration `JSON` qui décrit comment un chemin pour une certaine entité doit être construit. + +Un exemple concerne les fichiers **published** : + +```json +{ + "output": { + "mountpoint": "P:", + "root": "", + "folder_path": { + "shot": "/shots///_/publish/v/", + "asset": "/assets///_/publish/v/", + "sequence": "/sequences//_/publish/v/", + "scene": "/scenes///_/publish/v/", + "rushes": "/rushes///", + "style": "lowercase" + }, + "file_name": { + "shot": "_____publish_v", + "asset": "_____publish_v", + "sequence": "____publish_v", + "scene": "_____publish_v", + "style": "lowercase" + } + } +} +``` + +:::tip +Voir la [documentation](https://zou.cg-wire.com/file_trees/) sur les arbres de fichiers pour voir quelles entités vous pouvez utiliser. +::: + +:::caution +Assurez-vous d'ajouter un champ `nas` dans le champ de `données` d'un projet. Cela contiendra le NAS où le projet est situé. (ceci est ajouté dans `zou-deploy`) + +Par exemple : + +```json +{ + "id": "4142bd7f-d92a-44f0-a5e8-7968b2ed6532", + "name": "MACULA", + "data": "{\"nas\": \"ana\"}" +} +``` + +Il est utilisé lors du rendering sur la [render farm](../../Silex/CommonActions/Submit/implementsubmitter#wrapping-with-the-mount-command). + +::: + +#### Accès réseau direct aux fichiers + +Si vous voulez mettre un projet sur un lecteur réseau et accéder aux fichiers directement, changez la clé `mountpoint` dans le template de fichier `//server/...` comme : + +```json +{ + "working": { + "mountpoint": "//marvin/WIP/PIPELINE", + "root": "" + // ... + } +} +``` + +_(exemple : [`file_tree_marvin.json`](https://github.com/ArtFXDev/zou-deploy/blob/main/data/file_tree_marvin.json) pour le projet spécial FranceTV)_ + +## API + +### REST + +Zou a une API REST disponible à http://kitsu.prod.silex.artfx.fr/api/ (par exemple). + +Voir les [routes disponibles dans la documentation](https://zou.cg-wire.com/api/). + +### GraphQL + +Parce que nous avons forked Zou, nous avons ajouté une [API GraphQL](https://graphql.org/) utilisant [`graphene-python`](https://graphene-python.org/). Il est très utile pour la récupération de données front-end puisque vous pouvez interroger ce que vous voulez. + +Utilisez l'url `/api/graphql` pour obtenir un éditeur [GraphiQL](https://github.com/graphql/graphiql) intégré : + +![](/img/graphiql.png) + +Sinon, vous pouvez utiliser le grand GraphQL IDE appelé [client Altair](https://altair.sirmuel.design/). + +:::info +Notez que l'API GraphQL n'est **disponible que pour la récupération de données** pour l'instant. Le support pour les [mutations](https://graphql.org/learn/queries/#mutations) pourrait être ajouté à l'avenir. +::: diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/backend.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/backend.md new file mode 100644 index 0000000..7d1deb2 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Backend/backend.md @@ -0,0 +1,32 @@ +--- +id: backend +title: Backend +sidebar_position: 50 +--- + +--- + +Le backend de Silex est composé de plusieurs services qui peuvent être déployés à l'aide du repository [`silex-deploy`](https://github.com/ArtFXDev/silex-deploy). + +## Déploiement + +Nous utilisons [Docker](https://www.docker.com/) pour package les applications comme conteneurs isolés et [`docker compose`](https://docs.docker.com/compose/) pour définir une **pile d'application multi-containeurs**. + +C'est génial, car le déploiement de la plupart des applications Silex backend est aussi simple que (voir détails [ici](https://github.com/ArtFXDev/silex-deploy)): + +```shell +$ git clone https://github.com/ArtFXDev/silex-deploy.git +$ cd silex-deploy +$ docker-compose --env-file .env up -d +``` + +_(et la configuration additionnelle...)_ + +## Services + +- [silex-doc](https://github.com/ArtFXDev/silex-doc) +- [silex-front](https://github.com/ArtFXDev/silex-front) +- [zou](https://github.com/ArtFXDev/zou) (ArtFXDev fork) +- [kitsu](https://github.com/ArtFXDev/kitsu) (ArtFXDev fork) +- [harvest-api](https://github.com/ArtFXDev/harvest-api) +- [harvest-ui](https://github.com/ArtFXDev/harvest-ui) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Gokillprocess/gokillprocess.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Gokillprocess/gokillprocess.md new file mode 100644 index 0000000..fc72544 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Gokillprocess/gokillprocess.md @@ -0,0 +1,48 @@ +--- +id: td-gokillprocess +title: Gokillprocess +--- + +## Présentation + +Gokillprocess est utilisé pour obtenir des listes de processus en cours d'exécution, des services, kill un processus en cours avec PID et redémarrer un service avec son nom, via une requête HTTP. + +## Déploiement + +Vous pouvez retrouver la partie déploiement dans la doc IT [ici](/docs/it/scripts/deploy-gokillprocess). + +## Structure de Projet + +``` +📦go_killprocessbywebserver + ┣ 📂middlewares + ┃ ┗ 📜middlewares.go + ┣ 📂responses + ┃ ┗ 📜responses.go + ┣ 📂server + ┃ ┣ 📜controllers.go + ┃ ┣ 📜routes.go + ┃ ┗ 📜server.go + ┣ 📜.gitattributes + ┣ 📜go.mod + ┣ 📜go.sum + ┗ 📜main.go +``` + +## Middlewares Package + +- Définir facilement les en-têtes de demande dans les routes + +## Package Responses + +- Méthodes pour retourner un message formaté + +## Serveur de Package + +- Controllers.go: Recevoir les requêtes http et les traiter. +- Routes.go: Routes http de l'application. +- Server.go: Définit l'objet Server et contient l'exécution de la fonction principale de serveur + +## main.go + +- Main de l'application diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Harvest/harvest.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Harvest/harvest.md new file mode 100644 index 0000000..2a44002 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Harvest/harvest.md @@ -0,0 +1,34 @@ +--- +title: Harvest +sidebar_position: 15 +--- + +![](https://github.com/ArtFXDev/harvest-ui/blob/main/img/harvest_home_page.png?raw=true) + +Harvest est un tableau de bord de statistiques et API pour la [render farm de Tractor de Pixar](../Tractor). + +Harvest se compose de deux repositories principaux : + +- L'application front-end écrite dans React: [`harvest-ui`](https://github.com/ArtFXDev/harvest-ui) +- L'API backend écrite en Typescript avec [Prisma](https://www.prisma.io/): [`harvest-api`](https://github.com/ArtFXDev/harvest-api) + +## API + +Harvest a une API REST accessible à http://harvest.preprod.silex.artfx.fr/api/, voici les routes actuelles : + +```json +{ + "/history/project-usage", + "/history/blade-usage", + "/current/blade-usage", + "/current/project-usage", + "/info/compute-time", + "/info/projects", + "/info/blades", + "/info/running-jobs", + "/info/jobs-per-owner", + "/history/jobs-per-owner", + "/info/jobs-per-project", + "/fog/groups", +} +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/configuration.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/configuration.md new file mode 100644 index 0000000..deeaaeb --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/configuration.md @@ -0,0 +1,206 @@ +--- +title: Configuration +sidebar_position: 20 +--- + +Les fichiers de configuration de Tractor se trouvent dans `/opt/pixar/Tractor-.`. + +Il y a un repository GitHub sur ArtFXDev qui stocke la configuration pour l'année 2022 : https://github.com/ArtFXDev/tractor-config + +Vous pouvez également vérifier la configuration de 2021 : https://github.com/ArtFXDev/tractor-2020 + +## `tractor.config` + +Paramètres globaux pour l'engine. + +Quelques paramètres utiles à modifier : + +- `EngineOwner`: changer le propriétaire de service du processus (mieux en tant qu'utilisateur non-root) +- `EngineDiscovery`: paramètres DNS pour les blades lors de l'interrogation de l'engine, laissez-le vide pour ne pas multicast (peu flood(inonder) le réseau autrement) +- `SiteCmdLogRetrievalURL`: url pour récupérer les logs (voir [logging blade](#blade-log-access)) +- `SiteMaxListReplyCount`: limite le nombre d'enregistrements de liste que vous pouvez obtenir à partir de l'API +- `JobSchedulingMode`: changer le mode de planification des jobs (nous utilisons principalement `P+ATCL+RR`, voir la [documentation](https://rmanwiki.pixar.com/display/TRA/Scheduling+Modes)) +- `CmdAutoRetryAttempts`: définit le nombre de tentatives automatiques pour les commandes qui échouent +- `CmdAutoRetryStopCodes`: exclure le code de retour de réessayer automatiquement la task (utile lorsque vous savez qu'il y a une erreur) +- `EngineWorkerThreads`: définit le nombre de threads et workers de l'engine (conseillé d'être : `10 + (number_of_blades / 100)`) + +## `blade.config` + +Décrit les profils de blade (groupe d'ordinateurs). + +:::info +Les profils sont exclusifs et attribués de haut en bas. Utilisez la liste `Provides` pour attribuer plusieurs tags(étiquettes) aux blades. +::: + +Voici un exemple d'un profil correspondant aux blades qui ont un GPU `NVIDIA` : + +```json +// blade.config +{ + "ProfileName": "GPU", + "Hosts": { + "GPU.label": ["NVIDIA GeForce*"] + }, + "Provides": ["GPU"], + "PathExists": [ + "C:/Maya2022/Maya2022/vray/bin/vray.exe", + "C:/Nuke13.0v3/Nuke13.0.exe", + "C:/Maya2022/Maya2022/bin/render.exe", + "C:/Program Files/Autodesk/Arnold" + ], + "EnvKeys": ["@merge('shared.windows.envkeys')"] +} +``` + +:::tip +Pour plus d'informations, voir la [documentation](https://rmanwiki.pixar.com/display/TRA/Server+Profiles) officielle +::: + +### Accès au log blade + +De la [documentation sur les loggings](https://rmanwiki.pixar.com/display/TRA/Logging#Logging-directwritesLoggingCommandOutputtoaCentralFileserver) : + +> Logging Tractor command output to a central fileserver should be considered a best-practice technique, especially for large production sites. + +> Écrire directement sur un partage de réseau haute performance en utilisant des opérations de fichier "locales" peut être presque aussi bon, et offre de nombreux avantages supplémentaires en termes d'accès et de gestion des logs. + +> Il y a plusieurs avantages à utiliser un serveur web standard pour livrer ces logs de commande à Tractor Dashboard, et d'autres requestors. Le premier est qu'il peut décharger ce type de fichier i/o de Tractor Engine lui-même. Plus important encore, il peut également permettre aux utilisateurs de parcourir les logs directement à partir d'un navigateur web générique en parcourant simplement les listes de répertoires de job fournies par le serveur web. Évidemment, le serveur de fichiers partagés sous-jacents lui-même fournit un accès similaire aux logs à partir d'utilitaires et de scripts arbitraires utilisant des opérations. + +Dans l'objet `ProfileDefaults`, nous avons modifié la key suivante pour indiquer aux blades où elles doivent écrire les logs. + +```json +// blade.config +{ + "ProfileDefaults": { + "CmdOutputLogging": "logfile=//prod.silex.artfx.fr/tractor_logs/%u/J%j/T%t.log" + } +} +``` + +Pour ce faire, le dossier doit être accessible en tant qu'emplacement réseau Samba avec accès en écriture. + +Modifiez également la configuration pour récupérer les logs dans le fichier `tractor.config` pour qu'il soit l'URL du serveur web hébergeant les fichiers statiques : + +```json +// tractor.config +{ + "SiteCmdLogRetrievalURL": "http://prod.silex.artfx.fr:8001/%u/J%j/T%t.log" +} +``` + +## `crews.config` + +Spécifiez Administrateur, Wrangler et ValidLogins. + +- `Administrator` -> peut reload(recharger) la configuration sur l'interface +- `Wrangler` -> peut modifier les jobs des autres (utile pour le responsable technique de l'équipe) +- `ValidLogins` -> pour l'authentification NIMBY + +:::info +Pour utiliser l'authentification utilisateur personnalisée, spécifiez-la : + +```json +{ + "SitePasswordValidator": "python3 ${TractorConfigDirectory}/trSiteLoginValidator.py" +} +``` + +::: + +## `limits.config` + +Spécifiez des limites pour les tasks et les jobs sur la render farm. Vous pouvez limiter un certain type de job à exécuter uniquement sur max X machines. + +Vous précisez également les limites à l'utilisation qu'un projet peut faire de la farm. + +> Consulter : https://rmanwiki.pixar.com/display/TRA/Limits+Configuration + +:::note +Les priorités de job sont parfois plus efficaces que de limiter un projet à un pourcentage maximal d'utilisation à la farm. +::: + +## `shared.xxxxx.envkeys` + +Liste des variables d'environnement pouvant être incluses dans la configuration du profil `blade.config`. + +Un exemple de fichier peut être : + +```json +// shared.windows.envkeys +[ + { + "keys": ["default"], + "environment": { + // Rez configuration file location on the network + "REZ_CONFIG_FILE": "//192.168.2.112/rez/windows/config/rezconfig.py", + + // Ana and tars username and password + "SERVER_USER": "xxxxxx", + "SERVER_PASS": "xxxxxx", + + // Software license server location + "foundry_LICENSE": "4101@centlic", + "ADSKFLEX_LICENSE_FILE": "2080@winlic" + }, + "envhandler": "default" + } +] +``` + +Puis l'utiliser partout sur les profils pour hériter de ceux : + +```json +// blade.config +{ + "BladeProfiles": [ + { + "ProfileName": "DEV", + "EnvKeys": ["@merge('shared.windows.envkeys')"] + } + ] +} +``` + +## `trSiteLoginValidator.py` + +Nous permet de nous authentifier auprès du backend Zou pour la gestion des utilisateurs. + +Nous faisons une demande à l'API en fournissant l'utilisateur brut et mot de passe. + +```python +# trSiteLoginValidator.py +#!/usr/bin/env python + +import requests +import sys + +def main (): + user = input() + challenge = input() + pw_hash = input() + + # Allow the nimby to eject jobs + if user == "nimby": + return 0 + + r = requests.post( + "http://kitsu.prod.silex.artfx.fr/api/auth/login", + {"email": f"{user}@artfx.fr", "password": pw_hash} + ) + + return 0 if r.status_code == 200 else 1; + +if __name__ == "__main__": + rc = main() + + if 0 != rc: + sys.exit(rc) +``` + +:::info +Remarquez la connexion spéciale `"nimby"` pour que le NIMBY se connecte sans mot de passe à l'engine +::: + +:::caution +Les mots de passe ne sont pas actuellement hashed, ils peuvent donc être stockés en texte clair dans la base de données... +::: diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/installation.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/installation.md new file mode 100644 index 0000000..e5df4e3 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/installation.md @@ -0,0 +1,82 @@ +--- +title: Installation +sidebar_position: 10 +--- + +Tractor était destiné à être installé sur une distribution Linux basée sur [RHEL](https://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux) comme [CentOS](https://en.wikipedia.org/wiki/CentOS) qui est couramment utilisé dans les studios VFX. Mais ce guide inclut des instructions pour l'installer sur une machine basée sur Debian. + +### Installer des packages RPM + +Le package que vous obtenez de la [page de téléchargement](https://renderman.pixar.com/forum/download.php) est un package [`.rpm`](https://en.wikipedia.org/wiki/RPM_Package_Manager) que vous ne pouvez installer que sur RHEL distros. +Cependant, si vous prévoyez de l'installer sur une machine basée sur [Debian](https://en.wikipedia.org/wiki/Debian), la configuration est un peu différente. + +Pour convertir un `.rpm` en package `.deb`, utilisez [Alien](https://github.com/mildred/alien) : + +```shell +$ sudo apt install alien + +# Convertir en .deb avec des scripts (-c option) +$ sudo alien -d -c Tractor-2.4_2091325-linuxRHEL6_gcc44icc150.x86_64.rpm + +# Installe le package deb généré en utilisant dpkg de low level +$ sudo dpkg -i tractor_2.42091325-1_amd64.deb +``` + +:::info +Répétez cette procédure pour que le serveur de Licence Pixar (Utilitaires de Licence) installe la licence. (par exemple `PixarLicense-LA-24.0_2172149-linuxRHEL7_gcc63icc190.x86_64.rpm`) +::: + +### Serveur de Licence + +Pour installer le serveur de licence, procédez comme suit (après avoir installé le paquet) : + +```shell +$ cd /opt/pixar/PixarLicense-LA-24.0 +$ sudo ./linux_installService.sh +``` + +:::caution +Vous devez avoir un fichier `pixar.license` dans le répertoire `/opt/pixar` pour que l'installation fonctionne. +::: + +### Configuration des fichiers de service système + +Maintenant le problème est que les services [systemd](https://en.wikipedia.org/wiki/Systemd) ne sont pas installés et configurés. Il permet au service de démarrer/redémarrer au démarrage. +Voir la documentation de Pixar sur la [configuration des services](https://rmanwiki.pixar.com/display/TRA/Setting+Up+Services). + +Les fichiers de service systemd se trouvent dans `/opt/pixar/Tractor-2.4/lib/SystemServices`. Copiez ces fichiers dans le dossier de droite et lancez les services : + +```shell +# Copier le fichier de maintenance dans le répertoire systemd +$ sudo cp /opt/pixar/Tractor-2.4/lib/SystemServices/systemd /etc/systemd/system +$ sudo systemctl start tractor-engine.service + +# Vérifie s'il fonctionne +$ sudo systemctl status tractor-engine.service +``` + +:::note +Vous pouvez modifier la ligne `Environment="OPTIONS=--debug --log /home/td/tractor/engine.log"` dans `tractor-engine.service` pour ajouter un emplacement de log personnalisé. +::: + +### Configuration DNS + +Il doit y avoir une entrée dans le serveur DNS de `tractor` et du `tractor-engine` pointant vers le serveur. Il permet aux futures blades et services de se connecter à l'engine. + +Pour vérifier si cela fonctionne, vous pouvez utiliser `nslookup` : + +```shell +$ nslookup tractor +Server: 172.16.69.160 +Address: 172.16.69.160#53 + +Non-authoritative answer: +Name: tractor.artfx.fr +Address: 192.168.2.120 +``` + +### Se connecter à l'interface du tableau de bord + +Si tout fonctionne comme prévu, vous pouvez aller sur `http://tractor` sur un navigateur pour inspecter l'interface de Tractor. + +Félicitations! Tractor va bien 🚜🚜 diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/issues.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/issues.md new file mode 100644 index 0000000..63bce35 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/issues.md @@ -0,0 +1,107 @@ +--- +title: Problèmes et solutions +sidebar_position: 30 +--- + +## Kill correctement une task sur Windows + +Sur la render farm, nous utilisons [Rez](https://github.com/AcademySoftwareFoundation/rez). Rez est très pratique, mais le problème est que lors du lancement d'une commande, il génère un sous-processus dans un sous-shell. + +Ceci est problématique lorsque Tractor ou le NIMBY veulent kill le processus sur une Blade parce que le PID visible est celui de la Rez, pas le processus worker. Donc on a fini par kill Rez et le processus de V-Ray tournait toujours sur la machine... + +Vous pouvez lire plus de détails sur cette discussion GitHub : https://github.com/AcademySoftwareFoundation/rez/discussions/1250 + +La solution était de modifier le code blade spécifiquement sur Windows pour kill l'arbre de processus en utilisant `Powershell`: + +```python +# TrSubprocess.py + +def send_signal(self, sig): + if subprocess.mswindows: + subprocess.call(['taskkill', '/F', '/T', '/PID', str(self.pid)]) +``` + +Voir les fichiers patchés ici : https://github.com/ArtFXDev/tractor-blade-patch + +:::info +Cette approche est également utilisée du côté de l'utilisateur, le NIMBY s'exécutant dans `silex-desktop`. Il envoie une requête au `silex_GoKillProcess`, un service spécial exécuté sur chaque ordinateur utilisé pour kill un pid dans la session système : + +- https://github.com/ArtFXDev/silex_GoKillProcess/blob/a03a61f31beddc714d87483b51d7ee3fd1391110/utils/terminate.go#L8 +- https://github.com/ArtFXDev/silex-desktop/blob/3676ba99a58f4951ad1cdaad408883448114d31b/src/utils/blade.js#L47 + +::: + +:::note +Il semble résoudre ce problème. J'ai posté : https://renderman.pixar.com/forum/showthread.php?s=&threadid=45707 (plusieurs propriétaires de task même si max slots est à 1) +::: + +## Le problème `"No Free Slots"` + +Le `No Free Slots` question est un classique dans l'histoire du pipeline ArtFX (salut Sylvain et Bruno). + +Par défaut, chaque blade de la farm a une capacité de slot maximale de `1` ce qui signifie qu'elle ne peut exécuter `1` task simultanément. Lorsque cela se produit, le champ de `note` de la blade passe à `no free slots (1) / aucun slot libre (1)`, ce qui signifie que la blade ne peut pas accepter une autre task. + +The issue we saw rising was blades that had the no free slots thing even thought **no tasks were running on the blade**. + +Nous avons corrigé cela en kill les noms de processus spécifiques sur les blades affectées dans [Harvest](../harvest) : + +https://github.com/ArtFXDev/harvest-api/blob/master/src/schedule/nofreeslots.ts + +```js +export async function clearNoFreeSlots() { + const blades = await getNoFreeSlots(); + + blades.forEach(async (b) => { + const result = await getProcessesQuery(b.addr); + const processesToKill = ["rez", "maya", "hrender", "kick", "vray"]; + + processesToKill.forEach(async (p) => { + const process: ResultGoKillProcess = result?.data.find( + (tp: { Name: string }) => tp.Name.toLowerCase().includes(p) + ); + if (process) await killProcessesQuery(b.addr, process.PID); + }); + }); +} +``` + +## Exécution de plusieurs commandes sur la même blade + +Une task a plusieurs commandes. Vous pourriez penser qu'une task signifie un ordinateur et ainsi les commandes sont exécutées sur la même blade, **vous avez tort !** + +Puisque nous voulons monter le NAS du projet avant de faire un rendu, nous voulons le faire en deux commandes. Pendant longtemps, nous avons eu des problèmes parce qu'il montait le lecteur réseau sur une autre machine et donc il n'avait pas accès aux fichiers publish... + +Nous avions aussi des blades bloquées parce qu'elles aillaient NIMBY ON entre les deux commandes. + +Voir ce thread pour plus d'informations : https://renderman.pixar.com/forum/showthread.php?s=&threadid=45603 + +Actuellement ce problème est résolu en utilisant un wrapper de commande que j'ai écrit dans Rust (pour apprendre le langage, si vous voulez aussi [le faire en Python](https://github.com/ArtFXDev/silex-rez/tree/prod/packages/utils/command_wrapper) ça ne devrait pas être trop dur) : + +https://github.com/johhnry/cmd-wrapper/ + +Il est compilé sous forme de `.exe` et mis sur le réseau dans les packages Rez. + +Il nous permet de faire ce qui suit en une seule commande : + +```shell +rez env cmd_wrapper -- cmd-wrapper + --pre="rez env mount_render_drive -- mount_rd_drive ana" + --cmd="rez env houdini pek -- hython -m hrender + scene.hip + -d surface_reflec + -o out.$F4.exr + -v -S + -f 1001;1002;1003;1004;1005;1006;1007;1008" +``` + +En passant des commandes sous forme de strings, il lancera toutes les commandes `--pre`, la commande `--cmd` et même si elle échoue, les commandes `--post`. + +Il résout également ce problème que j'ai posté : https://renderman.pixar.com/forum/showthread.php?s=&threadid=45739 (à propos de l'ajout d'une task de nettoyage sur Tractor utilisant `task.addCleanup`) + +## Clear blade data + +:::caution +Soyez prudent lorsque vous cliquez avec le bouton droit sur les blades dans l'interface et appuyez sur `"Clear earlier blade data"`(`"Effacer les données de la blade précédente"`) car il pourrait mettre toutes les blades en mode `No Free Slots` instantanément lorsque vous **le faites sur une grande quantité de blades**. + +Filed this bug here : https://renderman.pixar.com/forum/showthread.php?s=&threadid=45857 +::: diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/tractor.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/tractor.md new file mode 100644 index 0000000..9847f2e --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/Tractor/tractor.md @@ -0,0 +1,14 @@ +--- +title: Tractor +sidebar_position: 10 +--- + +## Introduction + +[Tractor](https://renderman.pixar.com/tractor) est le logiciel de Pixar pour la distribution des job et le rendering de réseau. Tractor est un logiciel payant. + +Pour en savoir plus, consultez la [documentation](https://rmanwiki.pixar.com/display/TRA/About+Tractor) de Tractor. + +## Forum + +Si vous avez des problèmes et des questions, vous pouvez poster un message sur leur [forum](https://renderman.pixar.com/forum). diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/renderfarm.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/renderfarm.md new file mode 100644 index 0000000..f31279d --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Renderfarm/renderfarm.md @@ -0,0 +1,61 @@ +--- +id: renderfarm +title: Renderfarm +sidebar_position: 60 +--- + +# Render farm + +La render farm est un élément clé du pipeline. Il permet aux artistes de rendre leurs images en utilisant divers moteurs de rendu comme V-Ray, Redshift ou Arnold. + +Après qu'un artiste a [conforme](../Silex/commonactions/conform)/[publish](../Silex/commonactions/publish) tous les fichiers nécessaires liés à une scène et la scène elle-même, il peut **submit** un job à la render farm. + +## Concepts + +### Job + +Un **job** est le top level workload sur une render farm, elle est décrite avec un _nom_, une _priorité_ et la plupart du temps la spécification des ordinateurs à exécuter. + +### Task + +Habituellement, un **job** est composé de **tasks** qui sont de plus petites unités de travail à effectuer. Parr exemple un ordinateur peut rendre les frames de `1-10` et un autre de `11-20`. + +### Commande + +Une **task** a alors des **commandes** qui sont envoyées à l'ordinateur par un [Shell]() (par exemple `bash` dans le cas de Linux or `cmd.exe` pour Windows) ou directement interprétées par l'ordinateur. + +Par exemple: + +```shell +rez env vray test_pipe -- vray + -skipExistingFrames=1 + -display=0 + -progressUseColor=0 + -progressUseCR=0 + -progressIncrement=5 + -verboseLevel=3 + -rtEngine=0 + -sceneFile=scene.vrscene + -imgFile=out_frame.exr + -frames=1;2;3;4;5;6;7;8;9;10 +``` + +:::tip +La commande ci-dessus utilise [Rez](https://github.com/nerdvegas/rez/) qui est utilisé pour résoudre les **environnements**dynamiquement en définissant les **packages** et les variables d'environnement. Il est très utile dans une configuration de render farm puisque nous avons divers software packages et différentes **versions**. +::: + +### Blade + +Un **blade** est un ordinateur qui travaille sur la render farm. Il reçoit une **task** du master engine et exécute des commandes. + +Le blade stocke et envoie les logs et mises à jour à l'engine. + +### Engine + +L'**engine** est le programme fonctionnant sur le serveur principal sur le réseau. Son job est de recevoir des demandes de jobs et d'envoyer et dispatch des tasks aux blades connectées. Il gère la priorité, les logs et une base de données où il stocke des informations sur ce qui se passe. + +## Que lire ensuite + +- Chez ArtFX, nous utilisons [Tractor](./tractor) qui est le système de render farm de Pixar. +- Consultez l'action [Submit](../Silex/commonactions/submit) pour savoir comment nous submittons les jobs. +- [Harvest](./harvest) est une interface statistique et API pour Tractor. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/architecture.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/architecture.md new file mode 100644 index 0000000..0f2ad5b --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/architecture.md @@ -0,0 +1,57 @@ +--- +id: silex-architecture +title: Architecture +sidebar_position: 10 +--- +--- + +![](/img/silex/silex_architecture.png) + +## Espace utilisateur + +Ces parties du pipeline Silex sont disponible sur la machine utilisateur. + +### Silex desktop + +Silex desktop est le principal outil utilisateur. Il contient l'accès utilisateur à la plupart des sercives Silex : + +- Gestionnaire de fichiers +- Accès et action de l'artiste sur les DCC +- Nimby (Not In My BackYard: empêche la renderfarm d'utiliser cet ordinateur) +- Harvest, statistiques des films + +Il communique à la fois avec le backend pour exécuter les requêtes de base de données et avec le service de socket silex pour assurer la communication avec le DCC. + +Il s'agit d'une application électronique qui affiche le contenu à partir du serveur Front. + +### Service Silex socket + +Le service de socket Silex permet une communication en temps réel entre le Silex desktop et les DCC, via les actions client Silex. + +### Client Silex + +Silex client est un système d'action configurable, qui peut lancer des actions autonomes, généralement via des scripts Rez, ou des actions DCC grâce à des plugins. + +### Rez packages + +Rez crée des environnements de travail spécifiques et configurables. Les packages Rez sont chargés pour assurer la création de cet environnement. Lors du lancement d'un DCCs par Silex, les artistes utilisent chaque fois un environnement Rez spécifique. + +### Aiogazu + +Aiogazu est une bibliothèque python qui résume les routes HTTP de la base de données. C'est un fork de Gazu, qui a été rendue asynchrone. + +## Backend + +### Serveur Front (Silex front end) + +Ce serveur est ciblé par Silex desktop. C'est une application React qui contient le contenu affiché de Silex Desktop. + +Il authentifie la base de données CG Wire. La plupart des requêtes passent par l'adaptateur GraphQL au lieu d'attaquer directement la base de données. + +### Base de données du suivi de la production + +Cette base de données contient toutes les données de production, qui est utilisé par le front Silex. + +### Adaptateur GraphQL + +GraphQL sert d'API pour faciliter les requêtes dans une base de données. Les requêtes (Queries) peuvent être configurées. C'est l'outil principal pour obtenir des données de la base de données. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/silex-actions-client.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/silex-actions-client.md new file mode 100644 index 0000000..392f33c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Architecture/silex-actions-client.md @@ -0,0 +1,7 @@ +--- +id: silex-actions-client +title: Serveur client +sidebar_position: 10 +--- + +![](/img/silex/silex_client_architecture.png) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-definition.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-definition.mdx new file mode 100644 index 0000000..ec1ba02 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-definition.mdx @@ -0,0 +1,151 @@ +--- +id: action-definition +title: Définir les action +sidebar_position: 30 +--- + +import { PROD_ROOT } from "@site/src/constants"; + +Les actions sont définies avec les fichiers YAML + +## Où dois-je placer mon yaml ? + +Silex cherchera des définitions d'action à l'aide de la variable d'environment `SILEX_ACTION_CONFIG`. +Le yaml doit être dans une catégorie. La catégorie par défaut est la catégorie `actions`. Lorsque vous appelez une action, si vous ne spécifiez pas une catégorie, silex cherchera le yaml dans le dossier actions + +``` +📦config + ┗ 📂actions + ┗ 📜your_action.yml + 📂action_category + ┗ 📜your_action.yml +``` + +## Schéma de définitions d'action + +L'action est organisée en hiérarchie. Uneaction est composée d'étapes, une étape est composée de commandes et une commande est composée de paramètres. + +- L'`action` contient des `étapes`, c'est l'entité de niveau supérieur avec quelques informations globales +- Les `étapes` sont ici pour grouper les `commandes`. Ils ne détiennent pas beaucoup de données, ils ont un index attributs qui est très important. L'ordre d'exécution dépend de cet index, l'utilisation d'une structure de données clé/valeur au lieu d'un simple tableau permet d'insérer facilement des étapes entre les autres. Lorsqu'une action hérite d'une autre, elle peut insérer une étape en la définissant avec un index qui se trouve entre deux autres étapes. C'est pourquoi nous augmentons habituellement les étapes de 10 ou 100 pour permettre des insertions potentielles plus tard +- La `commande` est liée à un morceau de code à exécuter, elle contient des `paramètres` et est responsable d'appeler le code en fournissant la valeur de ses `paramètres`. Il contient également la sortie de l'exécution +- Le `paramètre` peut soit stocker une valeur brute ou être connecté à une sortie de `commande`. Il a un type et assure-vous que le type fourni est correct. Atention, pour les types invalides, silex va essayer de lancer la valeur, il est utile dans la plupart des cas, mais parfois il peut se traduire par des résultats étranges. + +:::tip +Vous devez être prudant avec YAML, Une indentation peut rendre votre action entière fausse. Et l'erreur est très cryptique +::: + +Voici à quoi devrait ressembler une définition d'action : + +```yml +: + # L’étiquette est juste pour l’affichage, vous pouvez l’omettre, dans ce cas le nom sera utilisé (la clé qui est dans l'action) + label: " (default: value in the key)" + # Spécifiez si cette action doit être affichée sur l’interface utilisateur, certaines actions n’ont pas besoin d’une interface avec une fenêtre contextuelle + hide: " (default: false)" + # Un peu d’aide qui sera affichée sur l’interface utilisateur + tooltip: " || null (default: null)" + + steps: + : + # L’étiquette est juste pour l’affichage, vous pouvez l’omettre, dans ce cas le nom sera utilisé (la clé qui est dans l'étape) + label: " (default: value in the key)" + # Préciser si cette étape doit être affichée sur l’interface utilisateur + hide: " (default: false)" + # Un peu d’aide qui sera affichée sur l’interface utilisateur + tooltip: " || null (default: null)" + # L’index est utilisé pour définir l’ordre d’exécution, on incrémente habituellement 10 par 10 pour pouvoir insérer des étapes plus tard si une autre action hérite de celle-ci + index: " (default: 0)" + + commands: + : + # Le libellé est juste pour l’affichage, vous pouvez l’omettre, dans ce cas le nom sera utilisé (la clé qui est dans cette commande) + label: " (default: value in the key)" + # Spécifier si cette commande doit être affichée sur l’interface utilisateur + hide: " (default: false)" + # Un peu d’aide qui sera affichée sur l’interface utilisateur + tooltip: " || null (default: null)" + # Le chemin qui mène à la commande python à exécuter, le format est comme une important python régulière (ex: 'silex_plugin.commands.my_command.MyCommand'). Voir la page de définition de commande pour plus d'informations) + path: " (default: '')" + # Préciser si l’exécution doit s’arrêter avant cette commande, et demander à l’utilisateur de modifier les paramètres + ask_user: " (default: false)" + + parameters: + : + # L’étiquette est juste pour l’affichage, vous pouvez l’omettre, dans ce cas le nom sera utilisé (la clé qui est dans ce paramètre) + label: " (default: value in the key)" + # Préciser si ce paramètre doit être affiché sur l’interface utilisateur + hide: " (default: false)" + # Un peu d’aide qui sera affichée sur l’interface utilisateur + tooltip: " || null (default: null)" + # La valeur par défaut de ce paramètre + value: " (default: null)" +``` + +## Connexions + +Vous pouvez connecter la sortie d'une commande à l'entrée d'un paramètre. Pour ce faire, utilisez le tag `!command-output` avec un string spécifiant le chemin de la commande (ex: `value: !command-output ":"`) +Si la commande retourne un dictionnaire, vous pouvez obtenir une valeur spécifique de ce dictionnaire en ajoutant plus de clés au chemin. + +Par exemple, si la commande retourne `{"foo": {"bar": "baz"}}` vous pouvez accéder au string `baz` en définissant le chemin sur `"::foo:bar"`. + +:::info +Nous utilisons les dictionnaires comme moyen pour les commandes d'avoir plusieurs sorties, c'est pourquoi il est toujours bon de sortir un dictionnaire dans les commandes même s'il n'y a qu'une sortie, juste au cas où nous le mettions à jour plus tard avec plus de sorties. +::: + +## Héritage + +Certaines actions sont très similaire, pour éviter d'avoir à refaire les même choses encore et encore, vous pouvez utiliser l'héritage. Pour utiliser l'héritage, vous devez d'abord comprendre comment silex résout une action à partir de son nom. Il utilise la variable d'environment `SILEX_ACTION_CONFIG`, qui consiste en une liste de chemin, il suffit de lister la variable `PATH`. + +Par exemple: + +- \\{PROD_ROOT}\rez\packages\test_pipe +- \\{PROD_ROOT}\rez\packages\silex_maya +- \\{PROD_ROOT}\rez\packages\silex_client + +Ici, le [contexte](./context.md) a silex_client chargé et 2 plugins, silex_maya et test_pipe. L'ordre dans lequel les plugins sont chargés importe beaucoup. Lorsque silex cherche une action, il regarde de haut en bas de la liste. Vous devez le savoir si vous utilisez l'héritage parce qu'une action ne peut **hériter que d'une autre action qui est dans le niveau actuel ou inférieur**. + +La syntaxe pour l'héritage est : + +```yml +my_action: !inherit + # Le nom de l'action dont vous voulez hériter. Vous pouvez ajouter un '.' devant le nom si vous voulez que silex commence à chercher des actions au niveau actuel + # Si vous ne mettez pas un . silex commencera à chercher l'action en commençant au niveau sous le niveau actuel. + parent: " (default: null)" + # Si vous souhaitez hériter d’une partie spécifique de l’action, utilisez la clé pour la spécifier + key: " (default: )" + # Le nom de la catégorie de l’action dont vous souhaitez hériter + category: " (default: )" +``` + +Vous n'avez pas à hériter d'une action entière, une partie de votre action peut hériter d'une partie d'une autre action. +Dans l'exemple ci-dessous, le tag `!inherit` est utilisée à la racine de l'action. Mais vous pouvez aussi l'utiliser à la clé d'une étape ou d'une commande. +Si vous le faites, vous devez utiliser l'option `key` et l'utiliser pour spécifier quelle partie de l'action vous voulez insérer (exemple: `action_name.step_name` si vous voulez une étape qui hérite d'une étape spécifique) + +:::info +Le cas d'utilisateur pour l'héritage est généralement de réduire la répétition ou de personnaliser le comportement d'une action pour un [contexte](./context.md) spécifique. Par exemple, vous pouvez créer un plugin pour un projet et personnaliser le comportement de cette action pour les contextes qui incluent spécifiquement ce projet. +::: + +Pour override une valeur, ajoutez seulement les keys pour la valeur que vous voulez override. Par exemple, nous avons ici une action vrscene (un publish vrscene) +qui est personnalisée pour un certain projet, nous définissions le paramètre merge à true (ui est un paramètre caché) uniquement pour les contextes où ce plugin est chargé. + +```yml +vrscene: !inherit + parent: "vrscene" + + steps: + move: + commands: + move: + parameters: + merge: true +``` + +## Ordre d'override de valeur + +Du point où l'action est définie au point où elle est exécutée, la valeur de certains champs peut changer de multiples façons. Voici l'ordre dans lequel une valeur de paramètre sera définie : + +1. La valeur par défaut du paramètre est définie dans la définition de la commande +2. Il peut alors overriden dans la définition YAML de l'action qui uilise cette commande +3. Lorsque l'action est créée, la valeur peut alors être modifiée avec l'argument `set_parameter` ou `--parameter` +4. Lorsque l'action est exécutée, si la commande est définie sur `ask_user: true`, l'utilisateur mettra à jour la valeur avant l'exécution +5. Juste après que l'utilisateur change la valeur, la méthode `setup` est appelée qui pourrait définir une dernière fois la valeur. (voir la page de définition de la commande) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-execution.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-execution.md new file mode 100644 index 0000000..35a6c76 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/action-execution.md @@ -0,0 +1,132 @@ +--- +id: action-execution +title: Exécution d'action +sidebar_position: 20 +--- + +--- + +Une action est un ensemble d'instructions qui seront exécutées séquentiellement. Pour en savoir plus à leur sujet, lisez la page du guide de l'utilisateur sur les actions. + +## Exécution des actions à partir de CLI + +C'est la façon la plus simple d'exécuter une action. Une fois Silex installé, exécutez `silex action `. + +:::tip +Si vous avez installé le client Silex en tant que package Rez, n'oubliez pas d'exécuter cette commande dans l'environnement Rez: `rez env silex_client -- silex action ` +::: + +#### Task ID + +Certaines actions se comportent différement selon le [contexte](./context.md) à partir duquel vous les exécutez (par exemple, le publish définira l'emplacement de publication en utilisant la tâche courante définie dans le contexte). +Vous pouvez spécifier la tâche en utilisant l'argument `--task-id` avec l'ID si l'entité est dans la base de données [CGWire](https://www.cg-wire.com/). + +#### Paramètres + +Les actions Silex invitent parfois l'utilisateur avec des paramètres. Vous pouvez définir les paramètres à l'avance avec l'argument `--parameters`. La valeur attendue est `=` le paramètre sera automatiquement inclus dans le type de paramètre attendu. Pour définir plusieurs paramètres, utilisez cet argument plusieurs fois. + +#### Mode Batch + +Parfois vous voulez exécuter des actions en mode headless (sur la renderfarm ou sur ssh), dans ce cas vous n'avez pas accès à l'interface silex et quand l'utilisateur sera invité, l'exécution de l'action sera bloquée en attendant une entrée dans l'interface. Pour éviter cela, vous pouvez utiliser `--batch` pour dire à Silex de ne pas essayer de se connecter à l'interface utilisateur via websocket. Tous les paramètres qui nécessitent une entrée utilisateur conserveront leurs valeurs par défaut. + +#### Catégories + +Si votre action n'est pas dans la catégorie par défaut (la catégorie `actions`) vous pouvez en spécifier une autre en utilisant l'argument `--category` (pour plus d'informations, voir la page de définition des actions) + +:::tip +Pour obtenir plus d'informations sur l'interface client silex, utilisez `silex action --help` +::: + +## Exécuter des actions à partir de Python + +Lorsque vous exécutez une action à partir d'un dcc (avec un shelf button) vous voulez exécuter l'action à partir de python : + +```python +from silex_client.action.action_query import ActionQuery + +action = ActionQuery("") +action.execute() +``` + +#### Catégories + +Si votre action n'est pas dans la catégorie par défaut (la catégorie `actions`) vous pouvez en spécifier une autre en utilisant le paramètre `category` lors de l'instanciation de l'action (pour plus d'informations voir la page de définition de l'actions) + +#### Méthodes + +L'exécuter d'une action à partir de python est beaucoup plus flexible car l'object ActionQuery vous donne le contrôle à l'exécution. +Voici une liste de méthodes utiles sur ActionQuery, elles peuvent être utilisées pendant l'exécution de l'action. + +```python +# Certaines des méthodes suivanteson une version asynchrone (préfixée par 'async_') +# les utiliser si vous voulez les utiliser depuis la boucle d'événements silex. +# (voir la page de la boucle d'événements) + +# Définir un paramètre +action.set_parameter("", ) + +# Obtenir une commande +action.get_command("") + +# Arrêter l'exécution en cas d'exécution et revenir en arrière sur une commande +action.undo() + +# Suspendre l'exécution +action.stop() + +# Reprendre l'exécution +action.redo() + +# Synchroniser avec l'interface utilisateur, utiliser cette méthode si vous avez modifié +# le tampon (buffer) de l'action directement (comme obtenir une commande et modifier ses données) +action.update_websocket() +``` + +## Débogage d'une action + +Quand une exécution ne va pas bien, vous pouvez déboguer son exécution en utilisant certaines méthodes de requête d'action. Les instructions suivantes ne peuvent pas être utilisées pour les actions exécutées à partir de la CLI. + +- Veiller à régler le niveau de log sur `INFO`, la valeur par défaut est `WARNING` + +```python +from silex_client.utils.log import logger +logger.setLevel("INFO") +``` + +:::caution +`DEBUG` est très verbeux (il enregistre tous les diffs du processus de synchronisation websocket) donc `INFO` est suffisant la plupart du temps +::: + +- Si vous n'avez pas stocké l'instance ActionQuery dans une variable (ou si l'action a été lancée à partir d'un shelf button) vous pouvez obtenir l'instance ActionQuery avec son ID à partir du Contexte : + +```python +# Pour obtenir l'ID, cliquer sur le bouton à côté du contexte dans +# le panneau de l'action sur l'interface utilisateur. Il stockera l'ID dans votre presse-papiers. +from silex_client.core.context import Context +action = Context.get().actions[""] +``` + +- Vous pouvez utiliser la méthode execute avec l'argument step_by_step (`action.execute(step_by_step=True)`). Ceci exécutera une seule commande et mettra en pause directement. A partir de ce point, il sera plus facile de vérifier toutes les valeurs de la sortie et des entrées. Pour passer à la commande suivante, utilisez à nouveau `action.execute(step_by_step=True)`. + +- Certaines commandes / paramètres sont masqués, vous pourriez vouloir les afficher, voici un extrait pour définir chaque commande : + +```python +for command in action.commands: + commands.hide = False + +# Toujours utiliser cette méthode après avoir modifié les buffers directement +# pour rester synchronisé avec l'interface utilisateur +action.update_websocket() +``` + +- Vous pouvez vérifier la sortie d'une commande à tout moment, avec la propriété `output_result`. + +```python +print(action.command[].output_result) +``` + +- Vous pouvez vérifier l'entrée d'un paramètre à tout moment avec la méthode get_value. L'entrée de paramètre peut être un lien vers une sortie de commande. Cette méthode résoudra tous les liens s'il y en a et vous donnera la valeur réelle directement. + +```python +print(action.command[].parameters[""].get_value(action)) +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/client.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/client.md new file mode 100644 index 0000000..1fabb9c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/client.md @@ -0,0 +1,36 @@ +--- +id: client +title: Client +sidebar_position: 20 +--- + +Silex client is responsible for the resolution and execution of actions. These actions represents what the user +can do from the context he is in. + +## Technologies used + +Silex uses various technologies, make sure to learn about them before getting into Silex. + +- Silex core is written in [python](https://www.python.org/). It can be used as a CLI tool or as a Python library. +- [Rez](https://github.com/AcademySoftwareFoundation/rez) is used for the context management. The use of rez allows to make some actions available or not according to the resolved context. +- Silex client connects with [silex-socket-service](https://github.com/ArtFXDev/silex-socket-service) with the WebSocket protocol. For that, it uses the [python-socketio](https://python-socketio.readthedocs.io/en/latest/index.html) library. +- The connection with the [CGWire](https://www.cg-wire.com/) database is made possible with [aiogazu](https://github.com/ArtFXDev/aiogazu), a simple python library that abstracts the HTTP queries of the backend. +- Actions are defined using the [YAML](https://fr.wikipedia.org/wiki/YAML) file format. + +## Installation + +Silex client can be installed with pip. + +```bash +# Simple global install +$ pip install git+https://github.com/ArtFXDev/silex_client.git + +# Rez package install (require rez installed) +$ rez pip -i git+https://github.com/ArtFXDev/silex_client.git +# or simply clone the repo and place it into your rez package path manually +$ git clone https://github.com/ArtFXDev/silex_client.git +``` + +:::caution +For production, `silex_client` should be used as a rez package (using the rez pip method or git clone method). It should be installed on a network storage with the rez configuration pointing to it. +::: diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/command-definition.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/command-definition.md new file mode 100644 index 0000000..1bfcc73 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/command-definition.md @@ -0,0 +1,98 @@ +--- +id: command-definition +title: Définition de commande +sidebar_position: 40 +--- + +Les commandes sont définies comme des classes python qui héritent de [`CommandBase`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/action/command_base.py) + +## Où dois-je placer mes commandes ? + +Où vous voulez tant que c'est importable par python. Donc pour rendre votre classe importable, vous devez ajouter le dossier racine à la variable d'environnement `PYTHONPATH`, comme une bibliothèque python normale. Cependant, nous utilisons une convention uniquement à des fins d'organisation : + +``` +📦my_plugin + ┗ 📂commands + ┣ 📂command_category + ┃ ┗ 📜your_command.py + ┣ 📂command_category + ┃ ┗ 📜your_command.py +``` + +## Schéma de définition des commandes + +La définition de commande suivante n'a pas d'indice de type pour simplifier. En production, vous devez taper tous les paramètres. +Tous les attributs/méthodes qui sont définis sont optionnels, si vous ne les implémentez pas, ils ne feront rien et auront des valeurs vides + +```python +from silex_client.action.command_base import CommandBase + +class MyCommand(CommandBase): + """ + Small description about my command + """ + + # L’attribut parameters définit la liste des paramètres de la commande + parameters = { + "my_parameter": { + # Le label est juste pour l'affichage, vous pouvez l’omettre, dans ce cas le nom sera utilisé (la key de cette commande) + "label": " (default: value in the key)", + # Le type de valeur attendu pour ce paramètre (voir la section types de paramètres plus bas) + "type": " (default: NoneType)", + # La valeur par défaut de ce paramètre + "value": " (default: None)", + # Un peu d’aide qui sera affichée sur l’interface utilisateur + "tooltip": " || null (default: null)" + # Préciser si ce paramètre doit être affiché sur l’interface utilisateur + hide: " (default: false)" + }, + } + + @CommandBase.conform_command() + async def __call__(self, parameters, action_query, logger): + # Code à exécuter lorsque la commande sera exécutée + + async def undo(self, parameters, action_query, logger): + # Code à exécuter lorsque la commande est annulée + + async def setup(self, parameters, action_query, logger): + # Code à exécuter chaque fois qu’un paramètre change +``` + +Les trois méthodes disponibles prennent les mêmes trois paramètres : + +- parameter: Un dictionnaire contenant le nom et une **copie** de la valeur du paramètre (Le fait qu'il s'agisse d'une copie est très important). +- action_query: La requête d'action qui appelle cette commande, vous pouvez accéder à toutes les commandes de celui-ci +- logger: Utilisez cet enregistreur au lieu de l'enregistreur global. Cet enregistreur stocke les logs dans la commande elle-même et l'affiche à l'utilisateur dans la section de debug de l'interface utilisateur + +La méthode de configuration, doit être rapide à exécuter, il est utilisé pour les entrées utilisateur de post-traitement ou pour modifier dynamiquement certaines valeurs en fonction de l'entrée. Par exemple : + +```python +async def setup(self, parameters, action_query, logger): + task_parameter = self.command_buffer.parameters["task"] + task_parameter.hide = parameters.["use_current_context"] +``` + +Ici, lorsque l'utilisateur bascule sur le paramètre `use_current_context`, le paramètre `task` se cachera dynamiquement + +## Types de paramètres + +Le type de paramètre peut être n'importe quelle définition de classe, `"type": str`, `"type": list`, `"type": int` sont tous des types valides. +Cependant, pour des paramètres plus complexes comme un menu déroulant ou un sélecteur de fichiers, vous pouvez utiliser certains paramètres spéciaux trouvés dans le [module des types de paramètres](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/parameter_types.py). + +```python +from silex_client.utils.parameter_types import SelectParameterMeta + +class MyCommand(CommandBase): + parameters = { + "my_parameter": { + "type": SelectParameterMeta("foo", "bar", "baz") + } + } +``` + +Ici nous utilisons le SelectParameterMeta, qui est une liste déroulante qui renvoie un string (la valeur sélectionnée). Ces paramètres sont différents car ce sont en fait des fonctions qui prennent des paramètres. La liste complète ne sera pas détaillée ici, vous pouvez jeter un oeil au [module des types de paramètres](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/parameter_types.py) pour la liste complète des types de paramètres spéciaux. + +## Héritage de commande + +Il est possible d'hériter d'une autre commande. Il fonctionne comme un héritage normal en python, sauf que le paramètre sera fusionné (merge) avec les paramètres des enfants. Pour les overrides de méthode, vous pouvez simplement utiliser `super()` comme dans l'héritage python normal. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/context.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/context.md new file mode 100644 index 0000000..cb917b3 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/context.md @@ -0,0 +1,29 @@ +--- +id: context +title: Contexte +sidebar_position: 10 +--- +--- + +Silex est sensible au contexte, le point de toutes les actions est que la même action dépendra de l'endroit d'où vous l'exécutez. Le contexte est défini par deux facteurs : + +- L'environnement Rez, qui définit les actions et commandes disponibles. +- L'ID de la tâche, qui définira les variables stockées dans les métadonnées du contexte comme le nom du projet, le nom de la tâche, le nom de l'utilisateur, le nom du shot... + +## L'environnement Rez + +Silex peut charger des plugins dynamiquement grâce à Rez. Chaque plugins enregistrera une liste d'actions et de commandes. L'ordre est important parce que les actions régies peuvent outrepasser et hériter des actions enfants. + +## L'ID de la tâche + +Vous pouvez accéder à diverses informations sur le contexte actuel avec la classe globale instanciée `Context`. Cette classe se comporte comme un dictionnaire en lecture seule qui vous donne accès à toutes ces informations. + +```python +from silex client.core.context import Context + +print(Context.get()["task"]) +``` + +Si vous voulez recalculer toutes les métadonnées, vous pouvez utiliser la méthode `compute_metadata()`. Vous pouvez définir la variable d'environnement `SILEX_TASK_ID` avant si vous voulez recalculer les métadonnées pour un contexte différent. (C'est ce que fait l'action set-context.) + +Ces métadonnées sont utilisées dans de nombreuses actions pour s'adapter à la scène actuelle. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/event-loop.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/event-loop.md new file mode 100644 index 0000000..4aa9a77 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Client/event-loop.md @@ -0,0 +1,42 @@ +--- +id: event-loop +title: Boucle d'événement +sidebar_position: 50 +--- + +Silex exécute une boucle d'événement dans un thread secondaire. Cette boucle d'événement est utilisée pour exécuter la connexion websocket, et les multiples actions en cours d'exécution. + +## Problèmes que vous pourriez rencontrer + +- Puisque les actions silex et la connexion websocket sont exécutées dans la même boucle d'événement, si une action retient l'attention + de la boucle d'événement pendant trop longtemps, la connexion websocket pourrait se rompre. Ce n'est en fait pas un problème puisque socketio gère la déconnexion + et la reconnexion automatiquement, mais vous recevrez un message d'avertissement dans l'interface silex. Pour éviter cela, assurez-vous de séparer votre logique + d'action en plusieurs coroutines. + +- Certaines instructions peuvent prendre du temps et ne sont pas attendues (comme les appels système). Pour éviter cela, + silex a la fonction [execute_in_thread](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/thread.py). + L'utilisation de [execute_in_thread](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/thread.py) exécutera + l'exécution dans un thread différent et retournera un futur avec le résultat. + +## Intéraction avec les DCCs + +La plupart des DCCs ne gèrent pas très bien la lecture réciproque, et aucun d'eux n'est utilisable avec asyncio. Pour rendre toutes les fonctions DCCs attendues, nous avons fait de la classe +[ExecutionInThread](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/thread.py) une classe appelable afin que chaque DCC +puisse la personnaliser pour travailler avec ses fonctionnalités de threading. (voir la page Silex Plugins pour plus d'infos) + +Par exemple, maya fournit la méthode [`executeDefered` et `executeInMainThreadWithResult`](https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-Scripting/files/GUID-9B5AECBB-B212-4C92-959A-22599760E91A-htm.html) qui prend un callable comme paramètre. + +- `executeDefered` n'est pas bloquant, il s'agit simplement d'ajouter la boucle d'événement propre à maya sans renvoyer le résultat. +- `executeInMainThreadWithResult` bloque, l'appel bloque la boucle d'événement jusqu'à ce que la fonction soit exécutée et renvoie le résultat. + +Dans notre cas, nous ne voulons pas utiliser `executeInMainThreadWithResult`, puisqu'il est bloquant, si la commande prend du temps il n'y a aucun moyen pour la boucle d'événement de faire autre chose en attendant le résultat, la connexion websocket se cassera, et si d'autres actions sont exécutées en même temps elle seront toutes bloquées. + +C'est pourquoi nous utilisons `executeDefered`. De cette façon, l'appel n'est pas bloquant, mais il y a toujours un problème : comment obtenir le résultat ? + +La class [ExecutionInThread](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/thread.py) est en fait en train de wrapping `executeDefered` dans une fonction qui renvoie un futur asyncio stockant le résultat. +The future peut alors être attendu pour que la boucle d'événements continue à fonctionner sur d'autres task jusqu'à ce que le résultat soit prêt. + +:::info +Si vous implémentez un nouveau DCC qui ne supporte pas l'asyncio dans son API (ce qui est le plus susceptible de se produire), vous devrez réimplanter cette classe [ExecutionInThread](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/thread.py) pour l'API de threading de ce DCC. +Pour plus de détails, consultez [l'implémentation faite pour maya](https://github.com/ArtFXDev/silex_maya/blob/dev/silex_maya/utils/thread.py) +::: diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/implementsubmitter.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/implementsubmitter.md new file mode 100644 index 0000000..bf6340c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/implementsubmitter.md @@ -0,0 +1,884 @@ +--- +title: Implémenter notre propre submitter +--- + +Dans ce tutoriel, nous allons implémenter notre propre submitter dans Silex pour le logiciel de composition [Natron](https://natrongithub.github.io/). + +Natron est un **logiciel de compositing open source** très similaire à Nuke. Le but est de submit des scène de compositing et des images de sortie avec un node d'écriture. + +## Paquet Rez et exécutable + +La première chose à faire est de s'assurer que la **même version** de Natron sera utilisée partout sur la farm. Ceci est utile car nous ne voulons pas d'incohérences entre les rendus. + +Pour ce faire, nous devons ajouter un paquet `natron` [Rez](../../../Workflow/Rez). + +[Téléchargez d'abord l'exécutable de Natron](https://github.com/NatronGitHub/Natron/releases/download/v2.4.3/Natron-2.4.3-Windows-x86_64.zip) pour Windows. Actuellement, la dernière version est `2.4.3`. + +**Nous mettrons l'exécutable dans le réseau** afin qu'il nesoit pas nécessaire de l'installer sur chaque machine. C'est bien puisqu'il n'est pas si grand et fonctionne sur la render farm. + +Puis créer un package dans `\\rez-network-location\silex-rez\packages\dcc`: + +``` +natron +├── platform-windows +│   ├── natron_env.py +│ └── Natron-2.4.3-Windows-x86_64 +│ ├── bin +│ └── ... +└── package.py +``` + +```python title=package.py +name = "natron" +version = "2.4.3" + +tools = [ + "Natron", + "NatronRenderer" +] + +variants = [ + ["platform-windows"] +] + +def commands(): + import sys + sys.path.append(root) + import natron_env + natron_env.commands(env, root) +``` + +```python title=platform-windows/natron_env.py +def commands(env, root): + env.PATH.prepend("{root}/Natron-2.4.3-Windows-x86_64/bin") +``` + +:::tip +Nous utilisons `env.PATH.prepend` ici parce que nous voulons que l'exécutable ait priorité sur une version installée localement. +::: + +:::info +`platform-windows` est un package implicite, c'est pourquoi nous utilisons une variante dans le package afin qu'il soit résolu automatiquement lorsque nous disons `rez env natron` sur Windows. Il ajoutera au chemin le chemin exécutable sur le réseau. +::: + +Vous devriez maintenant pouvoir lancer l'interface graphique de Natron avec : + +```shell +$ rez env natron -- natron +``` + +## Utilisation de la ligne de commande 🖥️ + +La prochaine étape consiste à voir comment Natron peut-être utilisé comme **outil de ligne de commande** sans interface. + +Consultez la documentation : https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + +> Natron dispose de 3 modes d'exécution différents : +> +> - L'exécution des projets Natron (.ntp) +> - L'exécution de scripts Python contenant des commandes pour Natron +> - Une mode interpréteur où les commandes peuvent être données directement à l'interpréteur Python + +Nous pouvons voir qu'il y a un exécutable spécial `NatronRenderer` qui fait automatiquement `Natron -background`. C'est parfait puisqu'on veut faire du batch rendering sur la farm. + +Une commande de base serait : + +``` +$ rez env natron -- natronrenderer -w WriteNode out.####.exr 1-10 project.ntp +``` + +Nous devons préciser : + +- Le nom du **node d'écriture** (`WriteNode`) +- Le **chemin de destination** des images rendues (`out.####.exr`). Remarquez les quatre `#` pour indiquer la numérotation des frames comme `out.0001.exr`. +- La **plage de frames** à rendre (`1-10`) +- La **scène** à rendre (`project.ntp`) + +
+ +Avec un exemple réel (télécharger le fichier de test [ici](/files/natron_test_project.ntp)): + +![](/img/natron_test_project.png) + +``` +$ rez env natron -- natronrenderer -w Write1 ./out.####.exr 1-10 .\project.ntp + +Restoring the image cache... +Loading plugin cache... +Info: init.py script not loaded (this is not an error) +Loading PyPlugs... +Loading project: C:/Users/etudiant/Desktop/project.ntp +Write1 ==> Rendering started +Write1 ==> Frame: 1, Progress: 10.0%, 7.4 Fps, Time Remaining: 1 seconds +Write1 ==> Frame: 3, Progress: 20.0%, 7.0 Fps, Time Remaining: 1 seconds +Write1 ==> Frame: 2, Progress: 30.0%, 10.3 Fps, Time Remaining: 0 second +Write1 ==> Frame: 4, Progress: 40.0%, 8.9 Fps, Time Remaining: 0 second +Write1 ==> Frame: 5, Progress: 50.0%, 9.9 Fps, Time Remaining: 0 second +Write1 ==> Frame: 6, Progress: 60.0%, 11.3 Fps, Time Remaining: 0 second +Write1 ==> Frame: 7, Progress: 70.0%, 9.4 Fps, Time Remaining: 0 second +Write1 ==> Frame: 8, Progress: 90.0%, 10.5 Fps, Time Remaining: 0 second +Write1 ==> Frame: 9, Progress: 90.0%, 11.8 Fps, Time Remaining: 0 second +Write1 ==> Frame: 10, Progress: 100.0%, 13.1 Fps, Time Remaining: 0 second +Write1 ==> Rendering finished +``` + +## Création de l'action ✔️ + +Lorsque l'utilisateur clique sur l'action [`Submit`](../Submit), il lance l'action définie par [`silex_client/config/action/submit.yml`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/config/action/submit.yml) qui insère ensuite l'action de submit appropriée pour le logiciel choisi. + +### Action simple + +Nous allons d'abord définir une nouvelle action dans le répertoire `silex_client/config/submit`. + +Cela va être une action simple sans entrée de l'utilisateur. Nous allons juste créer des tasks et les donner à la commande `SubmitToTractorCommand` : + +```yaml title="silex_client/config/submit/natron.yml" +natron: + label: "Submit Natron scene" + steps: + natron_render: + label: "Setup render parameters" + index: 20 + commands: + build_natron_tasks: + path: "silex_client.commands.farm.natron_render_tasks.NatronRenderTasksCommand" + label: "Natron Job parameters" + + submit_to_tractor: + label: "Submit" + path: "silex_client.commands.farm.submit_to_tractor.SubmitToTractorCommand" + ask_user: true + parameters: + tasks: + value: !command-output "natron_render:build_natron_tasks:tasks" + job_title: + value: !command-output "natron_render:build_natron_tasks:file_name" + job_tags: + value: + - "natron" +``` + +```python title="silex_client/commands/farm/natron_render_tasks.py" +from __future__ import annotations + +import logging +import typing +from typing import Any, Dict + +from silex_client.action.command_base import CommandBase +from silex_client.utils import farm + +# Forward references +if typing.TYPE_CHECKING: + from silex_client.action.action_query import ActionQuery + + +class NatronRenderTasksCommand(CommandBase): + """ + Construct Natron render commands + See: https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + """ + + @CommandBase.conform_command() + async def __call__( + self, + parameters: Dict[str, Any], + action_query: ActionQuery, + logger: logging.Logger, + ): + # Utilisez la commande utilisée précédemment avec Rez + command = r"rez env natron -- natronrenderer -w Write1 P:\test_pipe\test\render\out.####.exr 1-10 P:\test_pipe\test\project.ntp" + + # Créer une Task de farm en passant une liste d'arguments + tasks = [farm.Task("1-10", argv=command.split(" "))] + + # Renvoyer les résultats de la commande + return {"tasks": tasks, "file_name": "project.ntp"} +``` + +:::info +Remarquez que la scène Natron a été mise sur le lecteur `P:` parce qu'elle doit être syncronisée pour que les **ordinateurs de la farm aient accès aux fichiers**. +::: + +Pour l'instant, nous fournissons manuellement une commande qui sera exécutée en une seule task sur la farm. Nous utilisons la classe [`silex_client.utils.farm.Task`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/farm.py#L21) qui accepte directement une liste d'arguments et crée une commande. + +Cela équivaut à : + +```python +task = farm.Task("1-10") +task.addCommand(farm.Command(argv=command.split(" "))) +tasks = [task] +``` + +#### Lancement du job + +Après avoir lancer une action `Submit` (depuis le shelf Maya par exemple), appuyer sur `Continuer` jusqu'à ce que l'action soit terminée. + +Si tout se passe bien, rendez-vous sur le [tableau de bord de Tractor](http://tractor/tv) pour voir le résultat : + +![](/img/farm_test_natron.png) + +En double-cliquant sur la Task (rectangle rouge), vous obtenez quelque chose comme ceci : + +```s +====[2022/06/08 11:54:23 /J8451/T1/C1.2/jhenry@i7-mk8-2017-38 on md12-2021-002 ]==== + +Error while loading OpenGL: WGL: The driver does not appear to support OpenGL +OpenGL rendering is disabled. +WGL: The driver does not appear to support OpenGL +WGL: The driver does not appear to support OpenGL +# highlight-next-line +ERROR: Natron: P:\test_pipe\test\project.ntp: No such file. +Restoring the image cache... +Loading plugin cache... +Info: init.py script not loaded (this is not an error) +Loading PyPlugs... +``` + +:::danger Pourquoi y a-t-il une erreur ? + +Il y a une _error_ parce que l'ordinateur de la farm (`md12-2021-002`) **ne peut pas accéder aux fichiers** sur le lecteur `P:`. + +Selon le NAS où se trouvent les fichiers du projet, **nous devons monter un lecteur réseau pointant vers cet emplacement**. + +::: + +#### Wrapping avec la commande mount + +Pour monter le lecteur réseau, nous utilisons le [package Rez](https://github.com/ArtFXDev/silex-rez/blob/prod/packages/utils/mount_render_drive/1.0.0/platform-windows/mount_rd.ps1) : + +```shell +$ rez env mount_render_drive -- mount_rd_drive ana +``` + +Le problème est que la [création de dex commandes sur Tractor cause des problèmes...](../../../Renderfarm/Tractor/issues#running-multiple-commands-on-the-same-blade) + +Nous utilisons donc un helper pour wrap la commande avec la commande mount. Pour cela, nous devons d'abord utiliser la classe [`CommandBuilder`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/command_builder.py#L5) qui utilise le [modèle du builder](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html) : + +```python title="silex_client/commands/farm/natron_render_tasks.py" +# highlight-next-line +from silex_client.utils import command_builder, farm + +class NatronRenderTasksCommand(CommandBase): + """ + Construct Natron render commands + See: https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + """ + + @CommandBase.conform_command() + async def __call__( + self, + parameters: Dict[str, Any], + action_query: ActionQuery, + logger: logging.Logger, + ): + # highlight-start + command = ( + command_builder.CommandBuilder( + "natronrenderer", rez_packages=["natron"], delimiter=None + ) + .param("w", ["Write1", r"P:\test_pipe\test\render\out.####.exr", "1-10"]) + .value(r"P:\test_pipe\test\project.ntp") + ) + + command = farm.wrap_with_mount(command, "ana") + + task = farm.Task("1-10") + task.addCommand(command) + + return {"tasks": [task], "file_name": "project.ntp"} + # highlight-end +``` + +Il en résulte la commande suivante : + +```shell +$ rez env cmd_wrapper -- cmd-wrapper "--pre=\"rez env mount_render_drive -- mount_rd_drive ana\"" "--cmd=\"rez env natron -- natronrenderer -w Write1 P:\\test_pipe\\test\\render\\out.####.exr 1-10 P:\\test_pipe\\test\\project.ntp\"" +``` + +et les logs : + +``` +====[2022/06/08 14:10:23 /J8459/T1/C1.1/jhenry@i7-mk8-2017-38 on md7-2016-048 ]==== + +----------------------------- PRE COMMAND 0 BEGIN ----------------------------- +DELETE * +Vous poss�dez les connexions � distance suivantes�: + P: \\tars\PIPELINE +La poursuite de cette op�ration va rompre les connexions. +La commande s'est termin�e correctement. +--------------------------------- +NET USE P +La commande s'est termin�e correctement. +--------------------------------- +net use successful +AFTER MOUNT P +Les nouvelles connexions ne seront pas m�moris�es. +�tat Local Distant R�seau +------------------------------------------------------------------------------- + +OK P: \\ana\PIPELINE Microsoft Windows Network + +La commande s'est termin�e correctement. + +----------------- PRE COMMAND 0 END in 0h 0m 1s (exit code: 0) ----------------- + +------------------------------ MAIN COMMAND BEGIN ------------------------------ +Error while loading OpenGL: WGL: The driver does not appear to support OpenGL +OpenGL rendering is disabled. +WGL: The driver does not appear to support OpenGL +WGL: The driver does not appear to support OpenGL +Clearing the image cache... +Loading plugin cache... +Info: init.py script not loaded (this is not an error) +Loading PyPlugs... +Loading project: P:/test_pipe/test/project.ntp + +Write1 ==> Rendering started +Write1 ==> Frame: 1, Progress: 10.0%, 8.0 Fps, Time Remaining: 1 seconds +Write1 ==> Frame: 2, Progress: 20.0%, 8.0 Fps, Time Remaining: 0 second +Write1 ==> Frame: 3, Progress: 30.0%, 11.3 Fps, Time Remaining: 0 second +Write1 ==> Frame: 7, Progress: 40.0%, 8.8 Fps, Time Remaining: 0 second +Write1 ==> Frame: 4, Progress: 50.0%, 10.7 Fps, Time Remaining: 0 second +Write1 ==> Frame: 6, Progress: 60.0%, 12.4 Fps, Time Remaining: 0 second +Write1 ==> Frame: 5, Progress: 70.0%, 14.5 Fps, Time Remaining: 0 second +Write1 ==> Frame: 10, Progress: 80.0%, 12.5 Fps, Time Remaining: 0 second +Write1 ==> Frame: 8, Progress: 90.0%, 13.7 Fps, Time Remaining: 0 second +Write1 ==> Frame: 9, Progress: 100.0%, 15.2 Fps, Time Remaining: 0 second +Write1 ==> Rendering finished +----------------- MAIN COMMAND END in 0h 0m 8s (exit code: 0) ----------------- + +====[2022/06/08 14:10:33 process complete, exit code: 0]==== +``` + +Ça fonctionne!!!! 🎉🎉🎉 + +### Ajout de paramètres + +#### Paramètre unique + +Le fait est que notre submitter ne fait que la même scène et les même frames tout le temps... 🤔 + +Il faut d'abord que l'utilisateur sélectionne son fichier de projet dans le submitter. Pour cela on spécifie un dictionnaire de `paramètres` et on utilise le type de paramètre `TaskFileParameterMeta` : + +```python title="silex_client/commands/farm/natron_render_tasks.py" +# highlight-next-line +from silex_client.utils.parameter_types import TaskFileParameterMeta + +# Forward references +if typing.TYPE_CHECKING: + from silex_client.action.action_query import ActionQuery + + +class NatronRenderTasksCommand(CommandBase): + """ + Construct Natron render commands + See: https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + """ + + # highlight-start + parameters = { + "scene_file": { + "label": "Project file", + "type": TaskFileParameterMeta(extensions=[".ntp"]), + }, + } + # highlight-end +``` + +Dans l'intercace, il affiche un composant d'explorateur de fichier afin que l'utilisateur puisse sélectionner sa scène à submit. **Il affiche seulement les fichiers `.ntp` comme spécifié dans le type de paramètre**. + +![](/img/natron_file_explorer.png) + +Ensuite, nous utilisons ce paramètre dans la commande de code : + +```python title="silex_client/commands/farm/natron_render_tasks.py" +# highlight-next-line +scene_file: pathlib.Path = parameters["scene_file"] + +command = ( + command_builder.CommandBuilder( + "natronrenderer", rez_packages=["natron"], delimiter=None + ) + .param("w", ["Write1", r"P:\test_pipe\test\render\out.####.exr", "1-10"]) + # highlight-next-line + .value(scene_file.as_posix()) +) +``` + +:::info +Notez que nous avons spécifié le type `scene_file: pathlib.Path`. Les paramètres sont automatiquement cast dans leurs propres typess lorsqu'ils sont données à une commande. +::: + +:::caution +Utilisez la méthode [`PurePath.as_posix()`](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.as_posix) pour convertir un chemin Windows en chemin POSIX standard avec des **slashes**. Cela peut causer des problèmes sur la farm lors de l'analyse de la commande autrement. +::: + +#### Chemin de sortie d'image + +Maintenant que nous pouvons fournir la scène, la destination de l'image rendue dépendra de la task de la même manière. Pour cela, nous utilisons la commande [`BuildOutputPath`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/commands/build_output_path.py#L28). Nous devons l'ajouter à la définition de l'action YAML : + +```yaml title="silex_client/config/submit/natron.yml" +natron: + label: "Submit Natron scene" + steps: + # highlight-start + build_output_path: + label: "Build output path" + index: 10 + commands: + select_extension: + label: "Output extension" + path: "silex_client.commands.select_list.SelectList" + parameters: + param_name: "Output extension" + parameters_list: + - "exr" + - "png" + - "jpg" + - "tiff" + + build_output_path: + label: "Build output path" + path: "silex_client.commands.build_output_path.BuildOutputPath" + ask_user: true + parameters: + create_temp_dir: false + create_output_dir: false + output_type: + value: !command-output "build_output_path:select_extension" + hide: true + use_current_context: + value: true + hide: true + name: + value: "render" + # highlight-end + + # ... +``` + +Il va d'abord demande une extension, puis construire le chemin. Utilisez-le en connectant les sorties et les entrées avec la directive YAML `!command-output` : + +```yaml title="silex_client/config/submit/natron.yml" +natron: + steps: + natron_render: + commands: + build_natron_tasks: + # highlight-start + ask_user: true + parameters: + output_directory: + value: !command-output "build_output_path:build_output_path:directory" + output_filename: + value: !command-output "build_output_path:build_output_path:file_name" + output_extension: + value: !command-output "build_output_path:select_extension" + # highlight-end +``` + +```python title="silex_client/commands/farm/natron_render_tasks.py" +class NatronRenderTasksCommand(CommandBase): + """ + Construct Natron render commands + See: https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + """ + + parameters = { + # highlight-start + "output_directory": {"type": pathlib.Path, "hide": True}, + "output_filename": {"type": str, "hide": True}, + "output_extension": {"type": str, "hide": True}, + # highlight-end + "scene_file": { + "label": "Project file", + "type": TaskFileParameterMeta(extensions=[".ntp"]), + }, + # highlight-next-line + "write_node": {"type": str}, + } + + @CommandBase.conform_command() + async def __call__( + self, + parameters: Dict[str, Any], + action_query: ActionQuery, + logger: logging.Logger, + ): + # highlight-start + output_directory: pathlib.Path = parameters["output_directory"] + output_filename: str = parameters["output_filename"] + output_extension: str = parameters["output_extension"] + # highlight-end + + scene_file: pathlib.Path = parameters["scene_file"] + # highlight-start + write_node: str = parameters["write_node"] + + output_path = ( + output_directory + / write_node + / f"{output_filename}_{write_node}.####.{output_extension}" + ) + # highlight-end + + command = ( + command_builder.CommandBuilder( + "natronrenderer", rez_packages=["natron"], delimiter=None + ) + # highlight-next-line + .param("w", [write_node, output_path, "1-10"]) + .value(scene_file.as_posix()) + ) + + command = farm.wrap_with_mount(command, "ana") + + task = farm.Task("1-10") + task.addCommand(command) + + # highlight-next-line + return {"tasks": [task], "file_name": scene_file.stem} +``` + +Ce qui donnera ce chemin de sortie (en sélectionnant `png` par exemple) : + +``` +P:\test_pipe\shots\s03\p060\layout_main\publish\v000\png\render\Write1\test_pipe_s03_p060_layout_main_publish_v000_render_Write1.####.png +``` + +### Fractionnement de la plage de frame + +La dernière chose à faire est d'utiliser toute la puissance de la render farm: **la parallélisation**. + +En bref : répartir le calcul sur plusieurs ordinateurs et les faire fonctionner **simultanément**. + +Pour ce faire, nous devons **diviser la plage de frame** que l'artiste veut rendre, disons `1-500` dans des morceaux de frames. Comme `10` frames sur chaque ordinateur. + +Pour représenter les expressions de plage de frame , nous utilisons la classe `FrameSet` de la bibliothèque [Fileseq](https://github.com/justinfx/fileseq/) Python. Il permet de représenter des expressions de range complexes comme `1-10, 50-80x2` (avec des paddings...). + +Nous fournissons un paramètre `FrameSet` et un `task_size` qui définira le **nombre de frames par task/ordinateur**: + +```python title="silex_client/commands/farm/natron_render_tasks.py" +from __future__ import annotations + +import logging +import pathlib +import typing +from typing import Any, Dict, List + +# highlight-next-line +from fileseq import FrameSet +from silex_client.action.command_base import CommandBase +# highlight-next-line +from silex_client.utils import command_builder, farm, frames +from silex_client.utils.parameter_types import TaskFileParameterMeta + +# Forward references +if typing.TYPE_CHECKING: + from silex_client.action.action_query import ActionQuery + + +class NatronRenderTasksCommand(CommandBase): + """ + Construct Natron render commands + See: https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + """ + + parameters = { + "scene_file": { + "label": "Project file", + "type": TaskFileParameterMeta(extensions=[".ntp"]), + }, + "output_directory": {"type": pathlib.Path, "hide": True}, + "output_filename": {"type": str, "hide": True}, + "output_extension": {"type": str, "hide": True}, + # highlight-start + "frame_range": { + "label": "Frame range", + "type": FrameSet, + "value": "1-50x1", + }, + "task_size": { + "label": "Task size", + "tooltip": "Number of frames per computer", + "type": int, + "value": 10, + }, + # highlight-end + "write_node": {"type": str}, + } + + @CommandBase.conform_command() + async def __call__( + self, + parameters: Dict[str, Any], + action_query: ActionQuery, + logger: logging.Logger, + ): + output_directory: pathlib.Path = parameters["output_directory"] + output_filename: str = parameters["output_filename"] + output_extension: str = parameters["output_extension"] + + scene_file: pathlib.Path = parameters["scene_file"] + write_node: str = parameters["write_node"] + # highlight-start + frame_range: FrameSet = parameters["frame_range"] + task_size: int = parameters["task_size"] + # highlight-end + + output_path = ( + output_directory + / write_node + / f"{output_filename}_{write_node}.####.{output_extension}" + ) + + # highlight-start + natron_cmd = command_builder.CommandBuilder( + "natronrenderer", rez_packages=["natron"], delimiter=None + ) + + tasks: List[farm.Task] = [] + frame_chunks = frames.split_frameset(frame_range, task_size) + + for chunk in frame_chunks: + # Copier la commande initiale + chunk_cmd = natron_cmd.deepcopy() + + chunk_cmd.param("w", [write_node, output_path, str(chunk)]) + chunk_cmd.value(scene_file.as_posix()) + + command = farm.wrap_with_mount( + chunk_cmd, action_query.context_metadata["project_nas"] + ) + + task = farm.Task(str(chunk)) + task.addCommand(command) + tasks.append(task) + + return {"tasks": tasks, "file_name": scene_file.stem} + # highlight-end +``` + +![](/img/natron_frame_split.png) + +:::tip +Nous utilisons [`frames.split_frameset`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/frames.py#L16) pour diviser une expression `FrameSet` en morceaux égaux. +::: + +:::info +Notez que nous avons utilisé `action_query.context_metadata["project_nas"]` dans l'appel de fonction `wrap_with_mount`. **Le NAS du projet est stocké dans le contexte d'action**, donc nous l'utilisons au lieu d'une valeur explicite. +::: + +#### Handling frame padding + +Lorsque vous utilisez une plage de frame avec un frame padding : `1-10x2` et une taille de task de `3` qui donnera `["1-5x2", "7,9"]` mais le problème est que **Natron ne comprends pas** `-w Write1 out.###.exr 1-5x2 ...`. + +En utilisant `rez env natron -- natronrenderer -h`, nous pouvons voir la syntaxe requise : + +> Une ou plusieurs plage de frame, séparées par des virgules. +> Chaque plage de frame doit être l'une des suivantes : +> +> - <frame> (un seul numéro de frame, ex. 57) +> - <firstFrame>-<lastFrame> (ex. 10-40) +> - <firstFrame>-<lastFrame>:<frameStep> (ex. 1-10:2 rendrait 1,3,5,7,9) +> Exemples: +> 1-10:1,20-30:2,40-50 +> 1329,2450,123,1-10:2 + +Ainsi, nous pouvons facilement remplacer n'importe quel caractère `x` par `:` en `1-50x2` -> `1-50:2`. + +```python title="silex_client/commands/farm/natron_render_tasks.py" +chunk_range = str(chunk).replace("x", ":") +chunk_cmd.param("w", [write_node, output_path, chunk_range]) +``` + +Maintenant, il fonctionne parfaitement!! 👌👌 + +
Fichier final de définition d'actionnatron.yml + +

+ +```yml +natron: + label: "Submit Natron scene" + steps: + build_output_path: + label: "Build output path" + index: 10 + commands: + select_extension: + label: "Output extension" + path: "silex_client.commands.select_list.SelectList" + parameters: + param_name: "Output extension" + parameters_list: + - "exr" + - "png" + - "jpg" + - "tiff" + + build_output_path: + label: "Build output path" + path: "silex_client.commands.build_output_path.BuildOutputPath" + ask_user: true + parameters: + create_temp_dir: false + create_output_dir: false + output_type: + value: !command-output "build_output_path:select_extension" + hide: true + use_current_context: + value: true + hide: true + name: + value: "render" + + natron_render: + label: "Setup render parameters" + index: 20 + commands: + build_natron_tasks: + path: "silex_client.commands.farm.natron_render_tasks.NatronRenderTasksCommand" + label: "Natron Job parameters" + ask_user: true + parameters: + output_directory: + value: !command-output "build_output_path:build_output_path:directory" + output_filename: + value: !command-output "build_output_path:build_output_path:file_name" + output_extension: + value: !command-output "build_output_path:select_extension" + + submit_to_tractor: + label: "Submit" + path: "silex_client.commands.farm.submit_to_tractor.SubmitToTractorCommand" + ask_user: true + parameters: + tasks: + value: !command-output "natron_render:build_natron_tasks:tasks" + job_title: + value: !command-output "natron_render:build_natron_tasks:file_name" + job_tags: + value: + - "natron" +``` + +

+
+ +
Fichier de commande natron_render_tasks.py final + +

+ +```python +from __future__ import annotations + +import logging +import pathlib +import typing +from typing import Any, Dict, List + +from fileseq import FrameSet +from silex_client.action.command_base import CommandBase +from silex_client.utils import command_builder, farm, frames +from silex_client.utils.parameter_types import TaskFileParameterMeta + +# Forward references +if typing.TYPE_CHECKING: + from silex_client.action.action_query import ActionQuery + + +class NatronRenderTasksCommand(CommandBase): + """ + Construct Natron render commands + See: https://natron.readthedocs.io/en/rb-2.5/devel/natronexecution.html + """ + + parameters = { + "scene_file": { + "label": "Project file", + "type": TaskFileParameterMeta(extensions=[".ntp"]), + }, + "output_directory": {"type": pathlib.Path, "hide": True}, + "output_filename": {"type": str, "hide": True}, + "output_extension": {"type": str, "hide": True}, + "frame_range": { + "label": "Frame range", + "type": FrameSet, + "value": "1-50x1", + }, + "task_size": { + "label": "Task size", + "tooltip": "Number of frames per computer", + "type": int, + "value": 10, + }, + "write_node": {"type": str, "value": "Write1"}, + } + + @CommandBase.conform_command() + async def __call__( + self, + parameters: Dict[str, Any], + action_query: ActionQuery, + logger: logging.Logger, + ): + output_directory: pathlib.Path = parameters["output_directory"] + output_filename: str = parameters["output_filename"] + output_extension: str = parameters["output_extension"] + + scene_file: pathlib.Path = parameters["scene_file"] + write_node: str = parameters["write_node"] + frame_range: FrameSet = parameters["frame_range"] + task_size: int = parameters["task_size"] + + output_path = ( + output_directory + / write_node + / f"{output_filename}_{write_node}.####.{output_extension}" + ) + + natron_cmd = command_builder.CommandBuilder( + "natronrenderer", rez_packages=["natron"], delimiter=None + ) + + tasks: List[farm.Task] = [] + frame_chunks = frames.split_frameset(frame_range, task_size) + + for chunk in frame_chunks: + # Copier la commande initiale + chunk_cmd = natron_cmd.deepcopy() + + chunk_range = str(chunk).replace("x", ":") + chunk_cmd.param("w", [write_node, output_path, chunk_range]) + chunk_cmd.value(scene_file.as_posix()) + + command = farm.wrap_with_mount( + chunk_cmd, action_query.context_metadata["project_nas"] + ) + + task = farm.Task(str(chunk)) + task.addCommand(command) + tasks.append(task) + + return {"tasks": tasks, "file_name": scene_file.stem} +``` + +

+ +
+ +## Aller plus loin 🚀 + +Quelques idées pour améliorer le submitter : + +- Gérez plusieurs nodes d'écriture. Utilisez des subtasks pour atteindre cet objectif dans Tractor. Voyez le [submitter V-Ray avec les render layers](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/commands/farm/vray_render_tasks.py#L103) pour un exemple complet. + +- Une fois le fichier projet `.ntp` sélectionné, ouvrez-le en arrière-plan et remplissez le paramètre `write_node` avec tous les nodes d'écriture de la scène. Nous l'avons fait [dans le submitter Houdini](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/commands/farm/houdini_render_tasks.py#L235). + +- Parcourez le graphique des nodes et construisez un graphique de dépendance des nodes d'écriture et construisez-le pour Tractor. En fait, les nodes d'écriture peuvent être utilisés comme nodes de lecture + +- Quand un node de lecture ne peut trouver un fichier, Natron ne retournera pas un code de retour différent de `0`. Il y a donc une erreur dans le rendu mais Tractor le voit comme terminé. Vous pouvez soit [l'ajouter dans des messages d'erreur personnalisées dans le code blade](https://github.com/ArtFXDev/tractor-blade-patch#bladetractorsitestatusfilterpy) ou déposer un problème sur GitHub pour demander pourquoi. + + > Voir ce fil sur le code de retour de Natron : https://discuss.pixls.us/t/error-while-rendering-rendering-failed-return-code-is-0/31155 diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/submit.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/submit.md new file mode 100644 index 0000000..dd06aad --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/Submit/submit.md @@ -0,0 +1,158 @@ +--- +title: Submit +--- + +**Submit** est l'action de lancer un job sur la [render farm](../../../Renderfarm). + +## Objectif + +Le but du submitter est de pouvoir lancer des jobs de rendu avec **différents moteur de rendu (render engines)** et outils. + +Il doit être suffisamment **flexible** pour construire différents types de commandes utilisées pour le rendu. + +Nous soutenons actuellement : + +- V-Ray `.vrscene` files +- Blender `.blend` files +- [Husk](https://www.sidefx.com/docs/houdini/ref/utils/husk.html) (rendu fichier USD avec Houdini Karma ou un autre délégué Hydra) +- [Kick](https://docs.arnoldrenderer.com/pages/viewpage.action?pageId=36110428) (ligne de commande Arnold) `.ass` sequences +- Houdini scenes `.hip*` +- Maya scenes `.ma/mb` +- Nuke scripts `.nk` + +## Architecture + +Voici un exemple d'un submitter de **V-Ray** : + +![](/img/silex/vray_submit_action.jpg) + +
submit.yml définition de l’action + +

+ +```yaml +submit: + shelf: "output" + thumbnail: "submit.svg" + + steps: + setup: + lavel: "Setup" + index: 50 + commands: + get_submiter: + label: "Select submiter" + path: "silex_client.commands.select_submit.SelectSubmit" + tooltip: "Select the type of conform you want to make" + ask_user: true + + append_submit_actions: + label: "Append selected submit action" + path: "silex_client.commands.insert_action.InsertAction" + tooltip: "Append the selected submit to the list of commands to execute" + parameters: + category: "submit" + action: + value: !command-output "setup:get_submiter:action" + hide: true + + silex_coins: + index: 500 + hide: true + commands: + add_silex_coins: + path: "silex_client.commands.user.silex_coins.AddSilexCoinsCommand" + parameters: + amount: + value: 3 +``` + +

+ +
+ +
vray.ymldéfinition de l’action + +

+ +```yaml +vray: + label: "Submit V-Ray scene" + steps: + build_output_path: + label: "Build output path" + index: 10 + commands: + select_extension: + label: "Output extension" + path: "silex_client.commands.select_list.SelectList" + parameters: + param_name: "Output extension" + parameters_list: + - "exr" + - "png" + - "jpg" + - "tiff" + + build_output_path: + label: "Build output path" + path: "silex_client.commands.build_output_path.BuildOutputPath" + tooltip: "Build the complete output path" + ask_user: true + parameters: + output_type: + value: !command-output "build_output_path:select_extension" + hide: true + create_temp_dir: false + create_output_dir: false + task: + hide: true + use_current_context: + value: true + hide: true + frame_set: + hide: true + name: + value: "render" + + vray_render: + label: "Setup render parameters" + index: 20 + commands: + build_vray_tasks: + path: "silex_client.commands.farm.vray_render_tasks.VrayRenderTasksCommand" + label: "V-Ray Job parameters" + ask_user: true + parameters: + output_directory: + value: !command-output "build_output_path:build_output_path:directory" + output_filename: + value: !command-output "build_output_path:build_output_path:file_name" + output_extension: + value: !command-output "build_output_path:select_extension" + + submit_to_tractor: + label: "Submit" + path: "silex_client.commands.farm.submit_to_tractor.SubmitToTractorCommand" + ask_user: true + parameters: + tasks: + value: !command-output "vray_render:build_vray_tasks:tasks" + job_title: + value: !command-output "vray_render:build_vray_tasks:file_name" + job_tags: + value: + - "vray" +``` + +

+ +
+ +Les étapes sont les suivantes : + +1. Nous lançons l'action définie par `submit.yml`. C'est l'action de base +2. `append_submit_actions` utilise la commande [`InsertAction`](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/commands/insert_action.py#L21) pour insérer le submitter approprié en fonction de la saisie de l'utilisateur. Nous indiquons la catégorie de `submit` pour regarder les définitions d'action du submitter [`config/submit/xxxx.yml`](https://github.com/ArtFXDev/silex_client/tree/dev/silex_client/config/submit). +3. Le submitter est inséré et nous construisons le chemin de sortie des fichiers images pour le rendu +4. `build_vray_tasks` construit des tâches et des commandes en fonction de la `task_size` et d'autres entrées de l'utilisateur. Il renvoie une liste de tasks dans un [modèle de données abstrait](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/farm.py). +5. `submit_to_tractor` reçoit ces tasks et [les convertit dans son propre modèle de données Tractor](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/utils/tractor.py#L14). Il [envoie ensuite le job](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/commands/farm/submit_to_tractor.py#L130) avec l'utilisateur, les pools, les besoins en RAM et la priorité. Pour cela, nous utilisons notre propre [bibliothèque Python de Tractor](https://github.com/ArtFXDev/tractor_lib) mais patché pour Python 3.x. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/bundle.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/bundle.md new file mode 100644 index 0000000..6062d68 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/bundle.md @@ -0,0 +1,57 @@ +--- +id: bundle +title: Bundle +--- + +--- + +## Intro : + +L'action **Bundle** est mise en oeuvre pour _Maya_ et _Houdini_. Il est basé sur un concept similaire à l'action **Conform**, je recommande donc de lire également [l'action conform](./conform.md). + +**Le Bundle se trouve dans** le dossier **config\bundle\\** du repository DCC. + +![](/img/bundle_location.png) + +--- + +## Utilisation : + +L'action **Bundle** est similaire à la fonction _archive_ dans maya, mais au lie d'exporter la scène et ses références, elle trouve aussi **récursivement** toutes les références dans les fichiers référencés, puis copie toutes les références dans un seul dossier avec la scène, et refait tout avec une variable d'environnement : **BUNDLE_ROOT** dans ce dossier. + +Vous avez juste besoin de définir la variable dans votre Windows et vous pouvez utiliser le dossier bundle pour rendre à partir de la render farm externe ou à la maison. + +--- + +## Étapes : + +### étape 1 + +Le bundle trouve toutes les références dans la scène sélectionnée. + +### étape 2 + +Les références sont copiées, une par une, dans le dossier d'exportation (Par défaut, ce dossier sera créé en dehirs de la scène), si un fichier référencé a des références propre, ils passeront par le même processus. + +Si une référence ne fait pas partie de la structure du fichier pipeline, ou ne suit pas la même convention d'appelation, le fichier copié sera renommé avec une version **Hashed**. + +### étape 3 + +Les références sont sont repensées dans la scène d'origine avec une variable d'environnement, **BUNDLE_ROOT** vers le nouvel emplacement. + +### étape 4 + +La scène est copiée dans le dossier export. + +:::caution + +Actuellement, il n'y a aucun moyen de sélectionner un dossier dans l'interface utilisateur, donc les actions n'ont pas besoin d'être spécifiées un répertoire d'exportation, et créera son propre dossier dans le même répertoire que la scène sélectionnée. Si la scène est dans un dossier de **publish** (Signifiant, un dossier qui est synchronisé sur le serveur), le dossier nouvellement créé sera synchronisé et remplira la mémoire. + +Il est conseillé de copier la scène dans un lecteur local avant de la bundling, de sorte que le nouveau "dossier BUNDLE" sera également placé dans le lecteur local. +::: + +--- + +Documentation utilisateur : + +[Bundle documentation utilisateur](@site/docs/user/basic-concepts/actions/actions.md) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/commonactions.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/commonactions.md new file mode 100644 index 0000000..a9b9d1b --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/commonactions.md @@ -0,0 +1,22 @@ +--- +id: commonactions +title: Actions Communes +sidebar_position: 30 +--- + +Certaines actions sont communes à tous les DCCs. Elles sont mise en œuvre directement dans `Silex Client`, puis personnalisées pour chaque DCCs grâce au contexte. + +:::info +Les actions sont définies avec les fichiers YAML. Si vous ne savez pas comment définir une action, consultez la [page de définition des actions](../Client/action-definition.mdx) +::: + +## Insertion d'action + +Un point commun à ces actions est qu'elles insèrent toutes des actions à l'exécution en utilisant la [commande insert action](https://github.com/ArtFXDev/silex_client/blob/dev/silex_client/commands/insert_action.py). +Cette commande résoudra les actions spécifiées et insérera toutes ses étapes et commandes juste après l'étape en cours. +Cela permet d'avoir une action qui s'adapte dynamiquement lors de son exécution. + +![](/img/silex/silex_insert_action.gif) + +Pour séparer les actionsà insérer et celles à exécuter directement, nous utilisons des [catégories](../Client/action-definition.mdx#where-do-i-place-my-yaml-). +Par exemple, l'action publish permettra à l'utilisateur d'insérer une action parmi les possibles présent dans la catégorie `publish`. Vous pouvez rendre certaines publishes accessible dans certains [contextes](../Client/context.md) ou non en définissant vos publishes dans le plugin que vous souhaitez. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/conform.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/conform.md new file mode 100644 index 0000000..80fb566 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/conform.md @@ -0,0 +1,102 @@ +--- +id: conform +title: Conform +--- + +Le conform est utilisée pour déplacer un fichier de l'extérieur du pipeline dans le pipeline. +Il vérifie d'abord toutes les dépendances possibles de ce fichier (textures, références...) et s'assure que le fichier et toutes ses dépendances sont accessibles sur le pipeline. + +## Objectif + +Le conform est différente selon le type du fichier. Nous pouvons diviser ces types de fichiers en deux catégories : + +- Le fichier qui ne peut pas avoir de dépendances de fichiers externes (comme un fichier PNG) +- Le fichier qui pourrait avoir des dépendances de fichiers externes (comme un fichier de scène houdini) + +:::tip +La première catégorie est la plus simple, il n'y a presque rien à faire pour implémenter un nouveau type de fichier qui ne peut pas avoir de dépendances de fichier externes. Toutefois, la première catégorie nécessite un traitement spécial. +::: + +Le conform peut être séparée en 6 étapes : + +1. Sélectionner un fichier conform +2. Build le chemin de sortie pour ce fichier +3. Trouver toutes les dépendances du fichier qui ne sont pas dans le pipeline +4. Appeler le conform pour chaque dépendance trouvée +5. Repath les dépendances à leur nouveau chemin conformé +6. Déplacer le fichier à son emplacement de sortie + +Lorsque vous implémentez une nouvelle conform, vous devrez implémenter les étapes `3` et `4` car la façon dont ces étapes sont implémentées est généralement spécifique à chaque types de fichier. + +Une partie importante est qu'à l'étape `4` les appels conform un autre se conform à chaque dépendances du fichier, ce qui rend le conform récursif. + +:::info +Dans le cas d'un type de fichier qui ne peut pas avoir de dépendances externes, ces étapes n'existent pas, c'est pourquoi elles sont si faciles à implémenter. +::: + +## Architecture + +Voici un exemple de la conformité Maya : + +![](/img/silex/vray_conform_action.jpg) + +- L'utilisateur exécute le conform et sélectionne un fichier de scène maya. +- Le conform maya est insérée, et le chemin de sortie de cette scène maya est construit +- Nous trouvons les dépendances de cette scènne maya qui ne sont pas sur le pipeline +- Pour chacune de ces dépendances, nous insérons un autre conform pour chaque dépendances (un seul conform PNG est montré ici) +- Nous rassemblons tous les nouveaux chemins et repath toutes les dépendances de la scène maya pour leur faire pointer leur nouvel emplacement +- Nous copions le fichier de scène maya à son nouvel emplacement et le renommons correctement + +:::info +Dans cet exemple nous voyons seulement qu'un png conform a été inséré pour la simplicité. En réalité, un png conform sera inséré pour chaque png qui doit être conforme. Il en va de même pour toutes les dépendances externes comme les VDB, les alembics... +L'action final pourrait finir très grosses pour les grandes scènes avec beaucoup de dépendances. +::: + +:::caution +Dans cet exemple, nous avons une profondeur de 2 (un fichier qui fait référence à un autre fichier) mais puisque les fichiers de scène maya peuvent faire référence +à d'autres fichiers de scène maya, le depht peut aller très loin. +::: + +## Rédigez votre propre conform + +Lorsque vous exécutez l'action conform, la première étape est de sélectionner le fichier que vous voulez conform et ensuite un conform appropriée sera insérée. +Lors de l'insertion du conform appropriée, la commande cherchera les fichiers yaml dans la catégorie `conform`. Ainsi, votre implémentation conform doit être dans un dossier `conform` d'un emplacement `SILEX_ACTION_CONFIG` (voir la section définition de l'action). + +The command can auto selecte the conform using the extention of the given file, for that to work your conform must have the same +name as the extension it is made for. For example if you implement a conform for USD files you should organize your file like this: + +``` +📦config + ┗ 📂conform + ┗ 📜usd.yml +``` + +### Fichier qui ne peut pas avoir de dépendances externes + +Ces fichiers n'ont pas besoin d'un traitement spécial, tout ce qui vous avez à faire est d'hériter du conform `default` et de de remplacer le paramètre `output_type` de la commande `build_output_path` : + +```yml +vdb: !inherit + parent: ".default" + + steps: + conform: + commands: + build_output_path: + parameters: + output_type: + value: "vdb" +``` + +### Fichier pouvant avoir des dépendances externes + +WIP + +:::tip +Si vous vérifier les fichiers yaml du conform par défaut, vous verrez qu'ils ont plus d'étapes que montré dans l'architecture. +Ces étapes ne servent qu'à stocker globaly les fichiers conforme, et à empêcher le conforming du même fichier à nouveau s'il est référencé plusieurs fois. +::: + +:::caution +L'action **.ass conform** utilise une api Maya Arnold qui n'est accessible que depuis Maya. Donc les fichiers **.ass** doivent être conform depuis le shelf d'une scène maya ouverte ! +::: diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/publish.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/publish.md new file mode 100644 index 0000000..069f314 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/CommonActions/publish.md @@ -0,0 +1,272 @@ +--- +id: publish +title: Publish +--- + +--- + +## Intro : + +Le publish est l'une des actions les plus importante dans Silex. + +Chaque scène envoyée à la renderfarm doit être dans un dossier de publish (qui est synchronisé avec le serveur : voir [introduction Silex](../Silex.md)) ainsi que ses références. De cette façon, les _blades_ (ordinateurs dans la renderfarm) peuvent accéder à tous les fichiers nécessaire au rendering. + +## Objectif : + +L'action **Publish** est le moyen de sauvegarder vos scènes et références dans le **dossier de publish**. Il exporte plusieurs formats, vérifie que toutes les références sont dans un dossier de publish et renomme le fichier exporté en conséquence avec la convention de nommage. + +Le but du **publish** est de s'assurer que chaque job soumis à la [Renderfarm](../../Renderfarm/renderfarm.md) est restituable, et que toutes les références et textures peuvent être atteintes par n'importe quelle _blade_ du réseau. Pour ce faire, l'action appelle l'action [Conform](./conform.md) action. Si les références trouvées dans la scène doivent être [conformes](./conform.md) au pipeline, et ne peuvent pas être accessibles depuis le serveur. L'action **Publish** vous demandera de vous [conformer](./conform.md) à ces références. + +### Utilisation étape par étape du publish : + +1- Sélectionnez un type de publish. + +2- Sélectionner ou taper un nom de fichier. + +3- Paramètres de processus spécifiques à la commande appelée pour le type de publish choisi. + +4- La commande exporte la scène ou la sélection dans un dossier temporaire. + +5- Une commande de **déplacement** à partir de silex_client est appelée pour déplacer le fichier exporté vers le bon emplacement. + +--- + +## Architecture : + +Le publish vous permet d'exporter dans un large éventail de formats. Vous pouvez trouver la liste dans le code dans le dossier : + +- command + - config + - publish + +(voir plus d'infos sur l'architecture du repository : [Plugins](../Plugins/Plugins.md)) 🧭 + +--- + +### Yummy YAMLs : 🎂 + +Le publish du fichier [YAML](../Client/action-definition.mdx) dans [silex_client](../Client/client.md) appelle d'autres [YAML](../Client/action-definition.mdx) depuis le dossier commande **command/config/publish** dans les repositories de plugin. Ici, les [YAML](../Client/action-definition.mdx) ont le même nom que l'extension associée au type de publish. + +Par exemple, dans [silex_maya](../Plugins/Maya.md) dans **command/config/publish** : + +- publish + - abc.yaml + - ass.yaml + - fbx.yaml + - ma.yaml + - ... + - xgen.yaml + +Un fichier [YAML](../Client/action-definition.mdx) de publish ressemble à ceci : + +```yaml title="ma.yaml" +# Le root doit avoir le même nom que le fichier YAML. +ma: + steps: + # Cherche des références et vérifie que tout est conform. + # Sinon, utilise une action conform + check_references: + label: "Check references" + index: 30 + commands: + cleanup: + label: "Cleanup scene" + path: "silex_maya.commands.cleanup_scene.CleanupScene" + get_references: + label: "Get referenced files" + path: "silex_maya.commands.get_references.GetReferences" + parameters: + excluded_extensions: + value: + - ".wav" + conform_references: + label: "Conform references found" + path: "silex_client.commands.iterate_action.IterateAction" + parameters: + values: + value: !command-output "check_references:get_references:file_paths" + hide: true + actions: + - "conform" + categories: + - "action" + parameter: "setup:get_conform_output:file_paths" + label_key: "file_paths" + output: "setup:append_conform_actions" + + conform_references: + label: "Repath references" + index: 40 + commands: + repath_attributes: + label: "Repath attributes" + path: "silex_maya.commands.set_references.SetReferences" + tooltip: "Set the new path on the attributes" + parameters: + attributes: + value: !command-output "check_references:get_references:attributes" + hide: true + values: + value: !command-output "check_references:conform_references" + hide: true + + # Exporte dans le bon format, dans un dossier temporaire à côté de l'emplacement final. + export: + label: "Export" + index: 50 + commands: + export_ma: + label: "Export as ma" + path: "silex_maya.commands.export_ma.ExportMa" + parameters: + directory: + value: !command-output "setup:build_output_path:temp_directory" + hide: true + file_name: + value: !command-output "setup:build_output_path:file_name" + hide: true + + # Déplace le fichier exporté de l'emplacement temporaire à l'emplacement final + move: + label: "Move" + index: 60 + commands: + move: + label: "Move" + path: "silex_client.commands.move.Move" + parameters: + src: + value: !command-output "export:export_ma" + hide: true + dst: + value: !command-output "setup:build_output_path:directory" + hide: true + remove: + label: "Remove temp directory" + path: "silex_client.commands.remove.Remove" + parameters: + file_path: + value: !command-output "setup:build_output_path:temp_directory" + hide: true + + # Invite l'utilisateur à prévisualiser l'image dans l'explorateur Silex. + preview: + label: "Upload Preview" + index: 70 + commands: + step_exit: + label: "Prompt preview" + path: "silex_client.commands.exit_step.ExitStep" + parameters: + enable: + label: "Skip preview capture" + value: false + ask_user: True + + capture_preview: + label: "Capture preview" + path: "silex_maya.commands.capture_preview.CapturePreview" + + upload_preview: + label: "Upload preview" + path: "silex_maya.commands.upload_preview.UploadPreview" + parameters: + preview_path: + value: !command-output "preview:capture_preview:thumbnail" + hide: true +``` + +Comme vous pouvez le voir, il y a plusieurs étapes que le publish, comme le contrôle de conform, comme mentionné précédemment, et la capture d'aperçu. + +Parfois, vous pouvez voir un chemin avec un root **setup** comme : `"setup:build_output_path:directory"` + +Cela fait référence au fichier publish.yaml dans le repository [silex_client](../Client/client.md), qui appelle le YAML spécifique (dans ce cas ma.yaml) dans le repository plugin. Dans notre exemple, avant d'exécuter le fichier ma.yaml, le fichier publish exécute un tas d'autres commandes, dont la plus importante est **build_output_path**. + +Voici le fichier publish.yaml dans **silex_lcient/command/config/action/** : + +```yaml title="publish.yaml" +publish: !inherit + parent: ".pull" + shelf: "output" + + thumbnail: "publish.svg" + steps: + setup: + lavel: "Setup" + index: 50 + commands: + get_publish_type: + label: "Select publish type" + path: "silex_client.commands.select_publish.SelectPublish" + tooltip: "Select the type of publish you want to make" + ask_user: true + build_output_path: + label: "Build output path" + path: "silex_client.commands.build_output_path.BuildOutputPath" + tooltip: "Build the complete output path" + ask_user: True + parameters: + output_type: + value: !command-output "setup:get_publish_type:publish_type" + hide: true + use_current_context: + value: true + hide: true + task: + hide: true + frame_set: + hide: true + name: + value: "main" + label: "Publish name" + + pull: + index: 100 + commands: + select_pull: + parameters: + prompt: true + publish: + value: !command-output "setup:build_output_path:directory" + hide: true + + insert: + index: 150 + hide: true + commands: + append_publish_actions: + label: "Append selected publish action" + path: "silex_client.commands.insert_action.InsertAction" + tooltip: "Append the selected publish to the list of commands to execute" + parameters: + category: "publish" + action: + value: !command-output "setup:get_publish_type:publish_type" + hide: true + + silex_coins: + index: 500 + hide: true + commands: + add_silex_coins: + path: "silex_client.commands.user.silex_coins.AddSilexCoinsCommand" +``` + +La commande **build_output_path.py** retourne le chemin de sortie du publish en suivant la convention de nommage. + +## Rédigez votre propre publish : 🏆 + +Habituellement, pour implémenter un nouveau publish, vous pouvez écrire une nouvelle [commande](../Client/command-definition.md) pour exporter votre format et utiliser cet exemple YAML comme template. Vous n'avez qu'à changer la [commande](../Client/command-definition.md) dans l'étape **Export** pour le nom de votre nouvelle [commande](../Client/command-definition.md) d'export. + +:::tip 🦉 +Dans de nombreux cas, une commande exportera le fichier published vers un dossier temporaire passé à partir du chemin **build_output_path**. Par la suite, il devra passer le ou les fichiers nouvellement crées à l'étape de déplacement afin que la fonction de déplacement puisse les copier à l'emplacement final. +**Ainsi, les exigences de commande sont :** + +1- Prendre un répertoire export comme paramètre. + +2- Retourne la liste de tous les fichiers dans le dossier temporaire. +::: + +Si vous le souhaitez, vous pouvez personnaliser ce template de publish en ajoutant ou en supprimant des étapes. + +Si vous n'avez pas lu la documentation sur la définition de YAML, vous pouvez cliquer ici [action definition](../Client/action-definition.mdx). 🧭 diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Houdini.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Houdini.md new file mode 100644 index 0000000..b24393d --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Houdini.md @@ -0,0 +1,28 @@ +--- +id: houdini +title: Houdini +--- + +[Repository](https://github.com/ArtFXDev/silex_maya) + +--- + +### Démarrage + +Toutes les features et tools sont ajoutés au démarrage. + +Les scripts Houdini _123.py_ et _456.py_ sont dans le dossier **startup\script\\**. _123.py_ importe et appelle plusieurs scripts localisés dans la même root. _456.py_ importe actuellement _123.py_. + +- startup + - scripts + - 123.py + - 456.py + - create_shelf.py + - custom_save.py + +Si vous devez ajouter un nouveau au démarrage, ajoutez-le au dossier **startup\script\\** et **importez**-le en _123.py_ ou _456.py_. Silex utilise le gestionnaire d'environnement [REZ](../../Workflow/Rez/Rez.mdx), et exécute les scripts dans le dossier **startup** au lieu de celui localisé dans le dossier d'installation Houdini. + +### Scripts de démarrage + +1. Crée et remplit le shelf **Silex**. +2. Ajoute des raccourcis pour enregistrer. (Appelle des actions silex au lieu de Maya save). diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Maya.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Maya.md new file mode 100644 index 0000000..0e5ec70 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Maya.md @@ -0,0 +1,28 @@ +--- +id: maya +title: Maya +--- + +[Repository](https://github.com/ArtFXDev/silex_houdini) + +--- + +### Démarrage + +Toutes les features sont ajoutées au démarrage. + +Le script Maya _userSetup.py_ se trouve dans le dossier **startup**. Il importe et appelle plusieurs scripts localisés dans la même root. + +- startup + - create_shelf.py + - custom_save.py + - load_plugins.py + - userSetup.py + +Si vous devez ajouter un nouveau script au démarrage, ajoutez-le au dossier **startup** et **importez**-le dans _userSetup.py_. Silex utilise le gestionnaire d'environnement [REZ](../../Workflow/Rez/Rez.mdx), et exécute les scripts dans le dossier **startup** au lieu de celui localisé dans le dossier d'installation Maya. + +### Scripts de démarrage + +1. _create_shelf.py_ : Crée et remplit le shelf **Silex**. +2. _custom_save.py_ : Ajout de raccourcis pour l'enregistrement. (Appelle des actions silex au lieu de Maya save) +3. _load_plugins.py_ : Charge les plugins nécessaires. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Plugins.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Plugins.md new file mode 100644 index 0000000..252ef85 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Plugins/Plugins.md @@ -0,0 +1,103 @@ +--- +id: plugins +title: Plugins +--- + +--- + +## Intro : + +Silex utilise différents plugins. Un pour chaque DCC ajouter au pipeline. + +Alors que le noyau de **Silex** est codé dans le repository git [silex_client](../Client/client.md), chaque DCC a son propre repository. + +Maya --> _silex_maya_ + +Houdini --> _silex_houdini_ + +Lorsque vous ouvrez un DCC à partir de silex, le repository du DCC's est utilisé. Il ajoute des features spéciales dans un shelf **Silex**, et combine toutes les features de silex_client en plus des features spécifique au DCC. + +--- + +## Dans le ventre du repository : 🐋 + +Un repository contient essentiellement des commandes et des actions à déclencher dans le DCC. + +### Structure du repository : + +Voici un exemple avec le repository maya : + +- silex_maya + - commands + - config + - utils +- startup + +Contenu : + +_silex_maya/commands_ : Contient les commandes relatives au DCC. Les [commandes](../Client/command-definition.md) peuvent utiliser l'API DCC, donc certaines [commandes](../Client/command-definition.md) peuvent avoir un nom identique dans d'autres plugins, mais le code est différent. + +_silex_maya/config_ : Celui-ci contient des **actions** (voir : [définition des actions](../Client/action-definition.mdx)). Certaines actions, comme le _publish_, nécessitent plusieurs yaml à des fins multiples. + +_silex_maya/utils_ : Contient des constantes, des fonctions, des wrappers... utilisés dans les commandes. + +_startup_ : Il contient des scripts de démarrage exécutés dans le DCC au démarrage, y compris le shelf silex pour le DCC et les icônes pour les outils. + +:::note +Vous trouverez aussi un package.py, qio est un package [REZ](../../Workflow/Rez/Rez.mdx). +::: + +--- + +### Ajouter un nouveau plugin : 🏆 + +Pour ajouter un nouveau dcc, c'est facile. Vous devez : + +1. Un repository, comme décrit précédemment, avec son package.py [REZ](../../Workflow/Rez/Rez.mdx). +2. Un package [REZ](../../Workflow/Rez/Rez.mdx) pour le plugin (dcc) que vous shouhaitez implémenter. +3. Ajoutez un accès dans le silex_front. + +Voici l'exemple du package.py **silex_maya** : + +```python title="silex_maya/package.py" +# pylint: skip-file +name = "silex_maya" +version = "0.1.0" + +authors = ["ArtFx TD gang"] + +description = """ + Ensemble de module python et de configuration maya pour intégrer maya dans le pipeline silex + Part of the Silex ecosystem + """ + +vcs = "git" + +build_command = "python {root}/script/build.py {install}" + + +def commands(): + """ + Définir les variables d'environment pour silex_maya + """ + env.SILEX_ACTION_CONFIG.prepend("{root}/silex_maya/config") + env.PYTHONPATH.append("{root}") + env.PYTHONPATH.append("{root}/startup") + env.XBMLANGPATH.append("{root}/startup/icons") + + parser_module = ".".join(["silex_maya", "cli", "parser"]) + alias("silex", f"mayapy -m {parser_module}") + + +@late() +def requires(): + major = str(this.version.major) + silex_requirement = ["silex_client"] + if major in ["dev", "beta", "prod"]: + silex_requirement = [f"silex_client-{major}"] + + return ["maya", "python-3.7"] + silex_requirement + +``` + +Vous trouverez plus de détails dans la documentation [REZ](../../Workflow/Rez/Rez.mdx). 🧭 diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Silex.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Silex.md new file mode 100644 index 0000000..e82c690 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/Silex.md @@ -0,0 +1,14 @@ +--- +id: silex +title: Silex +sidebar_position: 40 +--- +--- + +## Intro : + +generalités sur le pipeline + +organisation des fichiers, resilio, seperation work / publish. + +(expliquer la synchronisation sur les publish uniquement...) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/app-structure.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/app-structure.md new file mode 100644 index 0000000..560ada8 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/app-structure.md @@ -0,0 +1,31 @@ +--- +id: app-structure +title: Structure App +sidebar_position: 20 +--- + +La structure d'app est assez simple. + +Le point d'entrée est /index.js, il va scanner et exécuter tous les fichiers .js sous /src/listeners + +``` +📦src + ┣ 📂events + ┃ ┣ 📂dcc + ┃ ┃ ┗ 📜yourdccevent.js + ┃ ┗ 📂ui + ┃ ┃ ┗ 📜youreventui.js + ┣ 📂listeners + ┃ ┣ 📜yourlistener.js + ┣ 📂namespaces + ┃ ┣ 📂dcc + ┃ ┃ ┣ 📜yourdccnamespace.js + ┃ ┗ 📂ui + ┃ ┃ ┣ 📜youruinamespace.js + ┣ 📂rooms + ┃ ┣ 📜dcc.js + ┃ ┗ 📜ui.js + ┣ 📂store + ┃ ┗ 📜index.js + ┗ 📜index.js +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/events.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/events.md new file mode 100644 index 0000000..8512197 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/events.md @@ -0,0 +1,81 @@ +--- +id: events +title: Events +sidebar_position: 30 +--- + +Event n'est pas un objet socket.io, c'est juste un object personnalisé pour structurer cette application. + +Un event contient le code "réel" exécuté, est le noyau principal de chaque comportement. + +## Structure de fichier + +``` +📦events + ┣ 📂dcc + ┃ ┣ 📂actions + ┃ ┃ ┣ 📜query.js + ┃ ┃ ┣ 📜request.js + ┃ ┃ ┗ 📜update.js + ┃ ┣ 📜disconnect.js + ┃ ┗ 📜initialization.js + ┗ 📂ui + ┃ ┣ 📜disconnect.js + ┃ ┣ 📜getclients.js + ┃ ┗ 📜initialization.js +``` + +Pour ajouter un nouvel event, il vous suffit de créer votre event.js ci-dessous /events. + +## Exemple de Code + +```javascript +// events/dcc/disconnect/js + +const store = require("../../store"); // <== main storage of app +const { uiRoomTo } = require("../../rooms/ui"); // <== require/import here + +const disconnect = (socket, io) => { + // <== Body of your event + socket.on("disconnect", (data) => { + // get uuid from data + const uuid = data.uuid; + if (uuid && store.dccs[uuid]) { + delete store.dccs[uuid]; + } + uiRoomTo(io).emit("dccDisconnect", { uuid: socket.data.uuid }); + }); +}; +module.exports = disconnect; +``` + +## Utilisation + +```javascript + +// listeners/dcc.js + +... +/** EVENTS */ +const initializationEvent = require("../events/dcc/initialization") // <== import your event +const queryEvent = require("../events/dcc/actions/query") +const requestEvent = require("../events/dcc/actions/request") +const updateEvent = require("../events/dcc/actions/update") +const diconnectEvent = require("../events/dcc/disconnect") +... + + +module.exports = function (io) { + dccNamespace(io).on("connection", function (socket) { + dccRoomJoin(socket) // <== events arehere + initializationEvent(socket, io) + diconnectEvent(socket, io) + }) + + dccActionNamespace(io).on("connection", function (socket) { + queryEvent(socket, io) // <== events are here + requestEvent(socket, io) + updateEvent(socket, io) + }) +} +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/listeners.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/listeners.md new file mode 100644 index 0000000..f4baef2 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/listeners.md @@ -0,0 +1,61 @@ +--- +id: listeners +title: Listeners +sidebar_position: 40 +--- + +Lien entre les routes et les events. Ils sont automatiquement exécutés à partir de index.js. + +Donc, si vous voulez ajouter un nouvel listeners, il vous suffit de créer un nouveau fichier js sous le répertoire listener. + +## Structure des Fichiers + +``` +📦listeners + ┣ 📜dcc.js + ┣ 📜index.js + ┗ 📜ui.js +``` + +## Exemple de Code + +```javascript +module.exports = function (io) { // <== le code commence ici + myNamespace(io).on("connection", function (socket) { // <== dccNamespace(io)... sera exécuté par index.js + myevent(socket) // Sur l'event "connection", nous exécutons sur socket object tous les events ci-dessous + mySecondEvent(socket, io) + myLastEvent(socket, io) + }) +``` + +**Deuxième exemple d'utilisation réel :** + +```javascript +/** NAMESPACE */ +const dccNamespace = require("../namespaces/dcc/dcc"); +const dccActionNamespace = require("../namespaces/dcc/action"); + +/** EVENTS */ +const initializationEvent = require("../events/dcc/initialization"); +const queryEvent = require("../events/dcc/actions/query"); +const requestEvent = require("../events/dcc/actions/request"); +const updateEvent = require("../events/dcc/actions/update"); +const diconnectEvent = require("../events/dcc/disconnect"); + +/** ROOMS */ +const { dccRoomJoin } = require("../rooms/dcc"); + +module.exports = function (io) { + dccNamespace(io).on("connection", function (socket) { + dccRoomJoin(socket); + initializationEvent(socket, io); + diconnectEvent(socket, io); + }); + + dccActionNamespace(io).on("connection", function (socket) { + queryEvent(socket, io); + requestEvent(socket, io); + updateEvent(socket, io); + }); +}; +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/namespace.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/namespace.md new file mode 100644 index 0000000..5b4f945 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/namespace.md @@ -0,0 +1,59 @@ +--- +id: namespace +title: Namespace +sidebar_position: 50 +--- + +Pour des explication sur l'utilisation des namespace pour Socket.io voir : [Socket.io/namespaces](https://socket.io/docs/v4/namespaces/) + +De manière simple : Namespaces est comme une route pour votre requête, pour les trier. + +## Structure des Fichiers + +``` +📦namespaces + ┣ 📂dcc + ┃ ┣ 📜action.js + ┃ ┗ 📜dcc.js + ┗ 📂ui + ┃ ┣ 📜action.js + ┃ ┗ 📜ui.js +``` + +Pour ajouter de nouveaux namespaces, vous devez créer un fichier .js sous le répertoire namespaces du projet. Dans l'exemple de structure de fichier, nous avons 4 namespaces : + +- /dcc +- /dcc/action +- /ui +- /ui/action + +## Exemple de Code + +```javascript +const ui = (io) => { + return io.of("/ui"); +}; + +module.exports = ui; +``` + +Cela retournera simplement l'objet de sortie de io.of("/ui") + +## Utilisation : + +```javascript +// listeners/dcc.js + +/** NAMEPSACE */ +const dccNamespace = require("../namespaces/dcc/dcc") // <== Import Here +const dccActionNamespace = require("../namespaces/dcc/action") + + +module.exports = function (io) { + dccNamespace(io).on("connection", function (socket) { // <== Use Here + dccRoomJoin(socket) + ... +``` + +**Côté client pour la connexion au Namespace**: +clientDcc = new Client(`http://localhost:${port}/dcc`) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/rooms.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/rooms.md new file mode 100644 index 0000000..09e5e31 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/rooms.md @@ -0,0 +1,74 @@ +--- +id: rooms +title: Rooms +sidebar_position: 60 +--- + +Pour des explication sur l'utilisation des namespace pour Socket.io voir : [Socket.io/rooms](https://socket.io/docs/v4/rooms/) + +Les rooms sont utilisées ici pour diviser les socket d'interface client et les socket DCC client. + +Vous pouvez diffuser l'event à tous les clients présents dans les rooms, ce qui est très utile. + +## Structure de Fichier + +``` +📦rooms + ┣ 📜dcc.js + ┗ 📜ui.js +``` + +Pour créer une nouvelle room, il vous suffit de créer des fichers .js sous le répertoire /rooms + +## Exemple de Code + +```javascript +const dccNamespace = require("../namespaces/dcc/dcc"); + +const dccRoomJoin = (socket) => { + // vous avez 2 fonction principale pour une room : join et to + console.log("join dccRoom"); // join need the socket client + return socket.join("dccRoom"); +}; + +const dccRoomTo = (io) => { + // <== "to" need the object server : io + return dccNamespace(io).to("dccRoom"); // <== vous pouvez lier votre room à un namespace comme ceci +}; + +module.exports = { dccRoomJoin, dccRoomTo }; // <== exporter ces 2 méthodes +``` + +## Utilisation + +```javascript +// listeners/dcc.js +... +/** ROOMS */ +const { dccRoomJoin } = require("../rooms/dcc") // <== room are import here + +module.exports = function (io) { + dccNamespace(io).on("connection", function (socket) { + dccRoomJoin(socket) // <== join are called here + initializationEvent(socket, io) + diconnectEvent(socket, io) // code of this below ... + }) + + +// events/dcc/disconnect.js +const store = require("../../store") +const { uiRoomTo } = require("../../rooms/ui") // <== To are import here + +const disconnect = (socket, io) => { + socket.on("disconnect", (data) => { + // get uuid from data + const uuid = data.uuid + if (uuid && store.dccs[uuid]) { + delete store.dccs[uuid] + } + uiRoomTo(io).emit("dccDisconnect", { uuid: socket.data.uuid }) // <== to emit on all socket client in the namespaces+rooms + }) +} +module.exports = disconnect + +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/routes.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/routes.md new file mode 100644 index 0000000..0ab39bf --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/routes.md @@ -0,0 +1,26 @@ +--- +id: routes +title: Routes +sidebar_position: 70 +--- + +## Structure de Routing Apps Socket + +``` +📦namespaces + ┣ /auth + ┃ ┣ 🔧login: params: ({ email: myemail@mail.com, password: mypassword }, callback) # Login and set kitsuToken in store + ┃ ┗ 🔧token: params: (callback) # Return kitsuToken in callback + ┣ /dcc + ┃ ┣ 🔧disconnect: params: empty # remove dccUuid from store + ┃ ┗ 🔧initialization: params: (data, callback) # data is the current context + ┣ /dcc/action + ┃ ┣ 🔧query: params: (data, callback) => emit data on event query on /ui + ┃ ┣ 🔧request: params: (data, callback) => emit data on event request on /ui + ┃ ┗ 🔧update: params: (data, callback) => emit data on event update on /ui + ┗ /ui + ┣ 🔧disconnect: params: empty # remove uiUuid from store + ┣ 🔧getclients: params: (callback) # return store.dccs + ┣ 🔧initialization: params: (data, callback) # get uiUuid from data and save it in store + ┗ 🔧submit: params: (data, callback) => emit data to /dcc/[dccSocketId] # use to send reponse to dcc, dccSocketId in data params +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/socket-service.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/socket-service.md new file mode 100644 index 0000000..1fd7ea5 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/socket-service.md @@ -0,0 +1,32 @@ +--- +id: socket-service +title: Présentation générale +sidebar_position: 10 +--- + +WebSocket serveur est un pont entre DCCs et frontend. + +Les interfaces DCCs et Silex doivent communiquer en temps réel, et nous utilisons un serveur socket pour cela. Vous pouvez imaginer un serveur socket comme une chat room, où chaque client est connecté et peut envoyer des requêtes. Comme Silex desktop frontend et les DCCs sont connectés sur le même service de socket, ils peuvent intéragir. + +Afin de réaliser la Séparation des Préoccupations (Separation of Concerns), ce n'est ni l'interface de bureau Silex ni les DCCs qui effectuent les actions de fichier, mais le Service Silexsocket lui-même. + +Silex Socket Service utilise la bibliothèque Socket-io. +Socket-io est un protocole qui utilise WebSocket. + +## Pour commencer + +En autonome : + +- obtenir la dernière version +- `yarn` +- `yarn start` + +Dans le projet du bureau : + +- Créez .npmrc à côté de package.json et mettez ça dans : +- ``` + //npm.pkg.github.com/:_authToken= # only if your repository is private + @ArtFXDev:registry=https://npm.pkg.github.com/ + ``` + **Ne pas oublier de remplacer par votre token d'accès github**, réf : [ici](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry) +- `npm install @artfxdev/silex-socket-service` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/tests.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/tests.md new file mode 100644 index 0000000..f24576e --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/tests.md @@ -0,0 +1,78 @@ +--- +id: tests +title: Tests +sidebar_position: 80 +--- + +Le [mocha](https://mochajs.org/#hooks) est utilisé pour les test unitaires. + +## Structure de Fichiers + +``` +📦test + ┣ 📂dcc + ┃ ┣ 📜action.js + ┃ ┗ 📜dcc.js + ┣ 📂ui + ┃ ┗ 📜ui.js + ┗ 📜index.js +``` + +La commande mocha dans package.json scanne et exécute tous les fichiers dans /test. Par conséquent, pour créer un nouveau test, il vous suffit de créer votre nouveau testfile.js sous /test. + +/index.js est utilisé pour démarrer l'application principale avant tous les tests. + +## Exemple de Code + +```javascript +const Client = require("socket.io-client"); // <== import socket.io-client lib +const assert = require("chai").assert; // <== used for assert + +/** test cases */ +// eslint-disable-next-line no-undef +describe("silex_socket_service_dcc", () => { + // <== describe function is the name of your test + let clientSocket; + const port = 5118; + + // eslint-disable-next-line no-undef + before((done) => { + // <== run before your tests + clientSocket = new Client(`http://localhost:${port}/dcc`); + clientSocket.on("connect", () => { + console.log("connected"); + }); + done(); + }); + + // eslint-disable-next-line no-undef + after(() => { + // <== run after your tests + clientSocket.close(); + }); + + // eslint-disable-next-line no-undef + it("Test dcc initialization ok", (done) => { + // <== it function is the container four your test + clientSocket.emit( + "initialization", + { + name: "untilted", + dcc: "undefined", + user: "undefined", + project: "undefined", + asset: "undefined", + uuid: -1, + }, + (response) => { + assert.equal(response.status, 200); // validate reception + done(); // <== done() are called to validate your test + } + ); + }); +}); +``` + +## Utilisation + +`npm run mocha ` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/usage.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/usage.md new file mode 100644 index 0000000..3d3f511 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Silex/SocketService/usage.md @@ -0,0 +1,31 @@ +--- +id: usage +title: Usage +sidebar_position: 90 +--- + +## Exemple d'Utilisation + +Exemple d'utilisation de Silex Socket Service dans Silex-front. + +Créer une connexion Socket-io avec Socket-io (sur 5118 par défaut pour le service silex socket) + +Tout d'abord, dans la connexion Socket-io, vous devez mettre le bon namespace que vous voulez utiliser comme ceci. + +```js +export const socketInstance = io( + "http://localhost:5118/ui", // <== pass the namespace here + { reconnectionDelay: 2000 } +); +``` + +Par exemple si vous voulez envoyer l'event 'clearAction' sur SilexSocketService : + +```js +// Cancel or clear the action +const handleClearAction = () => { + socketInstance.emit("clearAction", { uuid: action.uuid }, () => { + // then here + }); +}; +``` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/Rez/Rez.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/Rez/Rez.mdx new file mode 100644 index 0000000..6f34002 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/Rez/Rez.mdx @@ -0,0 +1,202 @@ +--- +id: rez +title: Rez +sidebar_position: 10 +--- + +import { PROD_ROOT, PROD_SSH } from "@site/src/constants"; + +--- + +Rez est un gestionnaire d'environment qui nous permet de lancer des DCCs dans des contextes isolés, y compris les bibliothèques obligatoires, de définir des variables d'environment propres à cet environment ou de définir des cas spéciaux pour chaque équipe de l'école. + +Tout se trouve dans la documentation sur GitHub : [https://github.com/AcademySoftwareFoundation/rez](https://github.com/AcademySoftwareFoundation/rez) + + + Dans le pipeline, les packages REZ sont localisés sur le serveur dans{" "} + + \\{PROD_ROOT} + \rez\{" "} + + + +
+
+ + + Les packages DCC et ceux d'équipe se trouvent dans{" "} + + \\{PROD_ROOT} + \rez\packages\silex-rez\packages\ + + + +
+
+ +- packages + - 5rn + - dcc + +:::tip 🦉 +Les packages d'équipe (5rn) sont généralement des shells vides, ils nécessitent initialement le package render engine utilisé par l'équipe et la config aces. Mais vous pouvez ajouter des outils ou des environnements spécifiques à leurs besoins spécifiques. + +**Exemple** : + +Dans ce cas, nous associons une nouvelle configuration à la variable d'environment SILEX_ACTION_CONFIG afin que l'équipe **Quit_smoking** ait un vrscene spécial [action YAML](../../Silex/Client/action-definition.mdx) spécifique à ses besoins. + +```python +# -*- coding: utf-8 -*- +name = 'quit_smoking' +version = '1.0' + +authors = ['ArtFx TD gang'] + +variants = [["maya"], ["houdini"], ["nuke"], ["silex_client"], ["silex_maya"], ["silex_houdini"]] + +requires = [ + 'vray', + 'aces', + "texturetotx", +] + +timestamp = 1635410671 + +vcs = 'git' + +format_version = 2 + +def commands(): + env.SILEX_ACTION_CONFIG.prepend("{root}/config") + + +``` + +::: + +Voici un exemple de package REZ pour Maya [Plugin](../../Silex/Plugins/Maya.md) : + +```python title="dcc/maya/package.py" +name = "maya" +version = "2022.0" + +requires = [ + "python-3.7", +] + + +tools = [ + "fcheck", + "imgcvt", + "maya", + "mayabatch", + "mayapy", + "rcc", + "uic", +] + +variants = [ + ["platform-windows"] +] + +def commands(): + import sys + sys.path.append(root) + import mayaenv + mayaenv.commands(env, root) + +``` + +Les repositories [Plugins](../../Silex/Plugins/Plugins.md) et [silex_client](../../Silex/Client/client.md) se trouvent dans : + + + \\{PROD_ROOT}\rez\packages\silex-rez\packages\silex\ + + +
+
+ +- silex + + - aiogazu + - silex_client + - silex_houdini + - silex_maya + - silex_nuke + + Voici un exemple de package du repository package.py : + + La variable d'environment SILEX_ACTION_CONFIG est expliquée dans la documentation [Action definition](../../Silex/Client/action-definition.mdx). + +```python title="silex/silex_maya:package.py" +# pylint: skip-file +name = "silex_maya" +version = "0.1.0" + +authors = ["ArtFx TD gang"] + +description = """ + Ensemble de module python et de configuration maya pour intégrer maya dans le pipeline silex + Partie de l’écosystème Silex + """ + +vcs = "git" + +build_command = "python {root}/script/build.py {install}" + +def commands(): + """ + Définir les variables d’environnement pour silex_maya + """ + env.SILEX_ACTION_CONFIG.prepend("{root}/silex_maya/config") + env.PYTHONPATH.append("{root}") + env.PYTHONPATH.append("{root}/startup") + env.XBMLANGPATH.append("{root}/startup/icons") + + parser_module = ".".join(["silex_maya", "cli", "parser"]) + alias("silex", f"mayapy -m {parser_module}") + + +@late() +def requires(): + """ + Gestion des versions + """ + major = str(this.version.major) + silex_requirement = ["silex_client"] + if major in ["dev", "beta", "prod"]: + silex_requirement = [f"silex_client-{major}"] + + return ["maya", "python-3.7"] + silex_requirement + + +``` + +### Mise à jour des repositories + +Les repositories sont la base de Silex. Si vous modifiez les plugins ou le [silex_client](../../Silex/Client/client.md) vous pouvez vous connecter au serveur prod en utilisant ssh : + + + ssh {PROD_SSH} + + +
+
+ +Puis mettre à jour les repositories en utilisant la commande git : + +git submodule update --remote + +
+
+ +L'élève sera en mesure de profiter de vos nouvelles features ! \_(^^)/ + +### Beta et Prod + + + Dans \\{PROD_ROOT}\rez\packages\silex-rez\packages\silex\ + +, si vous regardez dans l'un des silex_folder, vous pourrez voir un dossier **beta** +et un **prod**. Ils contiennent tous les deux la branche du même nom dans le repository, +et sont mis à jour en fonction de ces branches. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/continuous-integration.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/continuous-integration.md new file mode 100644 index 0000000..748577a --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/continuous-integration.md @@ -0,0 +1,5 @@ +--- +id: continuous-integration +title: Intégration continue +sidebar_position: 0 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/git-github.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/git-github.md new file mode 100644 index 0000000..b474bd4 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/git-github.md @@ -0,0 +1,66 @@ +--- +id: github +title: Git & GitHub +sidebar_position: 20 +--- +--- + +Tout le code de Silex est hébergé sur GitHub dans l'organisation [ArtFXDev](https://github.com/ArtFXDev) : + +![](/img/silex_repositories.png) + +## Conventions + +### `README.md` + +Silex est censé être **open-source** donc les repositories doivent être bien présentés et propre. Nous utilisons une structure similaire pour chaque ligne de fichiers `README.md` sur [`silex-front`](https://github.com/ArtFXDev/silex-front#readme). + +### Nom du repository + +- Pour les package Rez, nous utilisons des underscores `_` parce qu'un trait d'union désigne une version pour Rez. (exemples: `silex_houdini`, `silex_client`) + +- Pour les autres repositories c'est habituellement `silex-*` avec des traits d'union (`-`). (exemples: `silex-front`, `silex-socket-service`) + +## Branches et Pull requests + +Pour les repositories critiques, nous avons habituellement des branches `dev`, `beta` et `prod` branches. C'est le cas de [`silex_client`](https://github.com/ArtFXDev/silex_client). + +Un développeur qui travaille sur le repository peut faire comme ceci: + +``` +feature-branch1 -> dev -> beta -> prod +``` + +1. Allez sur la branche `dev` : `git checkout dev` +2. Créer une branche de feature: `git checkout -b feature-branch1` +3. Apporter des modifications et commit: `git add ... && git commit -m "my feature"` +4. Push ces modifications sur GitHub: `git push origin feature-branch1` +5. Créer une pull request sur GitHub +6. Un autre TD review votre code et approuve les changements +7. Vous mergez la pull request en `dev` +8. Lorsque les changements sont prêts, faites une pull request de `dev` à `beta` +9. Les bêta-testeurs utilisent cette feature +10. Enfin, merge `beta` en `prod` pour que tout le monde puisse l'utiliser + +## Registre des dockers GitHub + +Afin d'utiliser les images dans le [deployment repository](https://github.com/ArtFXDev/silex-deploy) en utilisant `docker-compose`, il y a une action GitHub sur certains repositories **pour construire une image automatiquement lorsqu'un tag est push**. + +Pour créer et push un tag, faire ce qui suit: + +```shell +$ git tag v # Use semantic versionning +$ git push origin --tags +``` + +:::tip +Assurez-vous que la version du tag correspond à n'importe quelle version de `package.json` version. + +Utilisez également [semantic versionning](https://semver.org/) (semver). +::: + +Il va construire l'image et la publier sur le registre GitHub Docker: + +![](/img/docker_build.png) + +Vous pouvez ensuite **pull les dernières images** pour mettre à jour les conteneurs. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/workflow.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/workflow.md new file mode 100644 index 0000000..bf76440 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/Workflow/workflow.md @@ -0,0 +1,5 @@ +--- +id: workflow +title: Codage workflow +sidebar_position: 30 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/design.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/td/design.mdx new file mode 100644 index 0000000..8548def --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/design.mdx @@ -0,0 +1,22 @@ +--- +id: design +title: Directives de conception +sidebar_position: 70 +--- + +--- + +import ColorRect from "@site/src/components/ColorRect"; + +L'interface utilisateur Silex est contruite en utilisant les règles d'interface utilisateur Material avec la [bilbiothèque MUI](https://mui.com/) + +## Couleurs + +
+ + +
+ +## Polices + +- [Karrik](http://karrik.phantom-foundry.com/) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/getting-started.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/getting-started.md new file mode 100644 index 0000000..4510620 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/getting-started.md @@ -0,0 +1,236 @@ +--- +id: getting-started +title: Mise en route +sidebar_position: 20 +--- + +Ce guide vous guidera dans l'installation de Silex en étant un nouveau développeur. + +Cela signifie être en mesure de **contribuer** et de mettre ne œuvre de **nouvelles fonctionnalités**. + +:::info +Ce guide suppose que vous travaillez dans un **environnement Windows**. +::: + +## Prérequis + +- Faire partie de l'organisation [ArtFXDev](https://github.com/ArtFXDev) Github +- Les services backend fonctionnent soit sur un serveur partagé soit [localement](./Backend) (`zou`, `silex-front`) +- Avoir un compte sur la base pipeline (Zou) en allant sur http://kitsu.prod.silex.artfx.fr + +## Installer Scoop + +Nous allons commencer par installer [Scoop](https://scoop.sh/), un gestionnaire de paquets qui peut facilement installer, supprimer et mettre à jour le logiciel **sans casser les choses**. + +À partir d'un terminal PowerShell terminal, exécuter : + +```powershell +$ Set-ExecutionPolicy RemoteSigned -Scope CurrentUser +$ irm get.scoop.sh | iex +$ scoop --version +``` + +## Installer Python et Rez + +Si ce n'est pas déjà fait, vous pouvez installer **git** avec Scoop (vous en aurez besoin pour les prochaines étapes): + +```shell +$ scoop install git +``` + +### Python + +En ce qui concerne le pipeline 2021-2022, Python **3.7.x** est nécessaire. Voir [VFX Reference Platform](http://vfxplatform.com/) pour la version Windows Python. + +Installez-le avec Scoop: + +```shell +$ scoop bucket add versions # Ajout version bucket +$ scoop install python37 +$ scoop reset python37 # Vérfier que les shims sont créées +$ python --version +``` + +### Rez + +Rez est le résolveur d'environnement de paquet, pour l'installer cloner le GitHub: + +```shell +$ git clone https://github.com/AcademySoftwareFoundation/rez +$ cd rez +$ python ./install.py -v C:/rez/__install__ # spécifie le répertoire d'installation, -v : verbose +``` + +Ajoutez ensuite ce chemin à la variable d'environnement `$PATH` afin que l'exécutable soit reconnu : + +``` +C:\rez\__install__\Scripts\rez +``` + +Lancez un nouveau terminal et vous devriez pouvoir exécuter Rez: + +```shell +$ rez --version +# Rez 2.111.1 from c:\rez\__install__\lib\site-packages\rez (python 3.7) +``` + +Rez a besoin d'un fichier de configuration, puisque nous voulons qu'il soit sur le réseau, dites à Rez où le trouver en créant un `REZ_CONFIG_FILE` pointant vers : `\\prod.silex.artfx.fr/rez/windows/config/rezconfig.py` (changez-le avec l'emplacement réel). + +Il devrait changer la façon dont les paquets sont recherchés sur le réseau : + +```shell +$ rez config packages_path +# - D:\rez\dev_packages +# - C:\rez\packages +# - C:\rez\packages\lib +# - C:\rez\packages\silex +# - \\192.168.2.112\rez\packages +# - \\192.168.2.112\rez\packages\lib +# - \\192.168.2.112\rez\packages\plugins +# - \\192.168.2.112\rez\packages\silex-rez +# - \\192.168.2.112\rez\packages\silex-rez\packages +# - \\192.168.2.112\rez\packages\silex-rez\packages\5rn +# - \\192.168.2.112\rez\packages\silex-rez\packages\dcc +# - \\192.168.2.112\rez\packages\silex-rez\packages\projects +# - \\192.168.2.112\rez\packages\silex-rez\packages\silex +# - \\192.168.2.112\rez\packages\silex-rez\packages\softwares +# - \\192.168.2.112\rez\packages\silex-rez\packages\tools +# - \\192.168.2.112\rez\packages\silex-rez\packages\utils +# - \\192.168.2.112\rez\packages\tools + +$ rez config local_packages_path +# C:\rez\packages +``` + +:::caution +Les chemins ci-dessus peuvent changer en fonction de la configuration du réseau et des chemins `rezconfig.py`. +::: + +## Configurer Rez + +Le fichier de configuration `rezconfig.py` décrit l'emplacement où Rez doit trouver les packages. + +Dans la configuration actuelle, voici les principaux emplacements : + +```python +root_packages_path = [ + r"D:\rez\dev_packages", # Pour vos propres packages Silex dev + r"C:\rez\packages", # Pour les packages de production locale + r"\\prod.silex.artfx.fr\rez\packages", # Package réseau +] +``` + +:::tip +Lorsque Rez résout un package, les packages ont la priorité sur les autres en fonction de l'ordre du `root_packages_path`. Les packages dev sont donc les premiers. +::: + +### Packages de base : `silex-rez` + +Clonez d'abord le dépôt [`silex-rez`](https://github.com/ArtFXDev/silex-rez) pour obtenir les packages de base : + +```powershell +$ mkdir D:\rez\dev_packages +$ cd D:\rez\dev_packages +$ New-Item -ItemType File -Name .rez # Dites à Rez de chercher dans ce répertoire +$ git clone --recurse-submodules -j8 https://github.com/ArtFXDev/silex-rez.git # Cloner récursivement +``` + +Maintenant, la résolution de `houdini` en tant que package devrait utiliser la version locale: + +```shell +$ rez env houdini + +# resolved packages: +# houdini-18.5.596 d:\rez\dev_packages\silex-rez\packages\dcc\houdini\18.5.596\platform-windows +# platform-windows c:\rez\packages\lib\platform\windows +``` + +### Configuration de développement pour `silex_client` + +Pour développer localement et utiliser vos propres packages, procédez comme suit : + +```shell +$ cd D:\rez\dev_packages +$ mkdir silex; cd silex +$ New-Item -ItemType File -Name .rez +$ mkdir silex_client; cd silex_client +$ git clone https://github.com/ArtFXDev/silex_client.git dev.1.0.0 +``` + +Cela clonera une version locale de `silex_client` dans un dossier de version `dev`, de sorte que vous devriez avoir cette structure : + +``` +. +├── .rez +├── silex +│   ├── .rez +│   └── silex_client +│   └── dev.1.0.0 +│   └── ... +└── silex-rez + └── ... +``` + +Et maintenant Rez devrait résoudre vos packages local : + +```shell +$ rez env silex_client-dev + +# ... +# silex_client-dev.1.0.0 d:\rez\dev_packages\silex\silex_client\dev.1.0.0 +# ... +``` + +## Installer `silex-desktop` + +`silex-desktop` est l'application de bureau qui utilise Electron. Elle utilise JavaScript. + +Installer Node.JS en utilisant scoop: + +```shell +$ scoop install nodejs-lts +$ npm install --global yarn # Installer le gestionnaire de package Yarn +``` + +Puis cloner le repository `silex-desktop` : + +```shell +$ git clone git@github.com:ArtFXDev/silex-desktop.git +``` + +Puisque `silex-desktop` utilise [`silex-socket-service`](https://github.com/ArtFXDev/silex-socket-service) comme dépendance directe et qu'il héberge dans le registre NPM de GitHub, vous avez besoin d'un token d'accès personnel pour le récupérer. + +Créer un fichier `.npmrc` dans le dossier racine `silex-desktop` avec ce contenu : + +```text title="silex-desktop/.npmrc" +//npm.pkg.github.com/:_authToken= +@artfxdev:registry=https://npm.pkg.github.com/ +``` + +Remplacez `` par votre token d'accès GitHub. +(Voir [ici](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) pour obtenir des instructions.) + +Enfin installer les dépendances avec Yarn: + +```shell +$ yarn install +``` + +## Exécuter and tester + +1. Lancer l'application de bureau: + +```shell +$ cd silex-desktop +$ yarn start +``` + +2. Ensuite, connectez-vous avec votre compte Silex. + +3. Lancer l'action `tester` depuis un autre terminal : + +```shell +$ rez env silex_client-dev -- silex action tester -c dev +``` + +> Félicitation vous êtes maintenant prêt à contribuer à Silex! 🎉🎉 diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/td/introduction.md b/i18n/fr/docusaurus-plugin-content-docs/current/td/introduction.md new file mode 100644 index 0000000..828bdac --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/td/introduction.md @@ -0,0 +1,11 @@ +--- +id: introduction +title: Introduction +sidebar_position: 10 +--- + +**Silex** est le nom donné à un ensemble d'applications de pipeline ici à ArtFX. + +Il comprend une [bibliothèque d'exécution d'action Python](https://github.com/ArtFXDev/silex_client/), une [application de bureau](https://github.com/ArtFXDev/silex-desktop), une [interface utilisateur](https://github.com/ArtFXDev/silex-front) et [diverses intégrations DCC](https://github.com/ArtFXDev/?q=silex_&type=all&language=python&sort=)... + +Il a été créé à l'origine par les TD pour la promotion 2021-2022. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/actions.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/actions.md new file mode 100644 index 0000000..3157c25 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/actions.md @@ -0,0 +1,5 @@ +--- +id: actions +title: Actions +sidebar_position: 20 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/publish.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/publish.md new file mode 100644 index 0000000..faf1733 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/publish.md @@ -0,0 +1,5 @@ +--- +id: publish +title: Publish +sidebar_position: 10 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/save.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/save.md new file mode 100644 index 0000000..64259ff --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/actions/save.md @@ -0,0 +1,5 @@ +--- +id: save +title: Save +sidebar_position: 20 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/basic-concepts.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/basic-concepts.md new file mode 100644 index 0000000..7843f5d --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/basic-concepts.md @@ -0,0 +1,7 @@ +--- +id: basic-concepts +title: Concepts de base +sidebar_position: 20 +--- + +Silex est UNIQUE ! 🙏, et utilise sa propre architecture, mais le vocabulaire est assez basique. Silex applique certains des concepts les plus importants d'un pipeline, comme l'outil de publish, ou le submit à la render farm. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/workflow.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/workflow.md new file mode 100644 index 0000000..eea850f --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/basic-concepts/workflow.md @@ -0,0 +1,139 @@ +--- +id: workflow +title: Workflow +sidebar_position: 10 +--- + +## publish / work + +### Qu'est-ce qu'un dossier Work ? : + +Le dossier Work est accessible depuis l'interface comme vous pouvez le voir [ici](../interface/file-explorer.md). +Il s'agit d'un espace libre pour enregistrer les scènes en cours. C'est un dossier qui n'est pas sauvegardé(backup) sur le serveur, et n'existe que dans votre ordinateur. C'est là que vous enregistrez votre scène et les versions incrémentées. + +### Un choix dans le dossier Publish : + +Le **Publish** est probablement le concept le plus important à saisir dans un pipeline. Quand une scène est publish, cela signifie que la scène est "finie", ou dans sa "version final" et prête pour la prochaine étape dans le pipeline. Cela vaut pour tous les departement, mais un dossier publish est un peu lus que cela et si nous voulons comprendre ce qu'il en est vraiment, nous avons besoin de plus de connaissances sur son fonctionnement. + +Il s'agit de connaissances importantes à avoir, et sera utile pour d'autres concepts et services sur Silex ou dans d'autres pipelines. Alors lisez attentivement 👀. + +Travaillez dans un pipeline signifie généralement, **travailler avec un serveur**. Pour que ce soit simple, je vais aller droit au but et essayer d'éviter les détails inutiles. Dans Silex, nous utilisons un serveur "connecté" à tous les ordinateurs de l'école ( il y a en fait 2 serveurs, mais pour cette explication, disons qu'il n'y en a qu'un seul ok ? :) ). Puisque le serveur est accessible par tous les ordinateurs dans Artfx, tous les fichiers stockés dans celui-ci peuvent être accessible de **n'importe où** 🌍 + +Lorsque vous mettez un fichier dans un dossier de **publish**, ce dossier est synchronisé sur le serveur et peut être consulté par n'importe quel ordinateur. Vous comprenez ? Cela signifie aussi que la [renderfarm](../renderfarm/renderfarm.md) sait où se trouve le fichier et peut le rendre dans le cas de la scène Maya, de la scène Houdini, vrscene... + +( J'encourage la lecture de la documentation sur la [renderfarm](../renderfarm/renderfarm.md) 🚜 pour plus détails. ) + +EN OUTRE ! Pour pouvoir rendre une scène sur la [renderfarm](../renderfarm/renderfarm.md), il faut aussi que toutes les textures ou références soient accessible sur le serveur. C'est la partie délicate, et [l'outil de publish](./actions/publish.md) assure que tous les fichiers liés, de quelque façon que ce soit, au fichier publish est également copié sur le serveur. C'est un deuxième aspect important du **Publish**. + +:::note +Donc, pour résumer : + +- Un fichier publish (un fichier exporté vers le dossier de publish par [l'outil de publish](./actions/publish.md)Silex) est accessible **partout** ainsi que ses références, textures, etc... . + +- Un fichier publish n'est que la version finale de votre travail. + +(il y aura une, étape par étape complète, exemple plus loin.) +::: + +## Contexte et Tasks + +Un autre concept important dans Silex est le concept de **task** et de **contexte**. + +![](/img/user_guide/workflow/workflow_tasks.png) + +Ici dans cette photo, nous venons de cliquer sur le shot 330 (comme vous pouvez le voir dans le rouge). A l'intérieur, vous pouvez voir toutes les différentes **tasks** assignées à ce shot. (Les **tasks** sont l'équivalent de departements dans un studio vfx/3D 🦉) + +Par exemple : Layout, lookdev... + +Vous pouvez ajouter une nouvelle task personnalisée à la liste en cliquant sur le bouton "+" près du nom du shot. Remplissez ensuite la fenêtre pop up window : + +![](/img/user_guide/workflow/workflow_custom_task.png) + +:::caution +La liste des tasks est définie par les superviseurs avant le début du projet. +::: + +Disons que vous êtes layout artist. Après avoir sélectionné votre Shot ou Asset dans l'exploreur, vous pouvez sélectionner la task **Layout**, et [ouvrir une nouvelle scène](../interface/file-explorer.md) dans la fenêtre de lancement. La nouvelle scène est maintenant ouverte dans un **Contexte** spécifique à cette task. Cela signifie qque les [outils du shelf Silex](./actions/actions.md) prendrons en compte que vous êtes dans une scène de layout pour le shot que vous avez sélectionnée. En d'autres termes, Silex SAIT où vous êtes et l'utilisera pour publishing des fichiers. + +Comme mentionné précédemment, [l'outil de publish](./actions/publish.md) exporte la scène ou la sélection dans un dossier publish. Puisque vous travaillez dans une scène de **Layout**, si vous utilisez [l'outil de publish](./actions/publish.md), les fichiers exportés seront accessibles dans le dossier de publish. Vous pourrez y accéder SEULEMENT dans cette task particulière, dans ce shot particulier. + +( Pour voir les fichiers publiés, voir la section correspondante dans [Parcourir les fichiers](../interface/file-explorer.md) ) + +## Exemple de workflow étape par étape : + +Avant d'entrer dans le vif du sujet, vous devez lire la documentation sur l'[interface](../interface/interface.md) et [l'explorateur de fichiers](../interface/file-explorer.md) + +**Créons un scénario :** + +Vous fabriquez une car asset dans Maya et vous travaillez avec un artiste lookDev et un spécialiste du render/lighting. + +Vous devez d'abord créer la task et l'asset. Allez à l'asset dans [l'explorateur de fichiers](../interface/file-explorer.md), et ajoutez une catégorie de **Props** de task si elle n'existe pas. + +1 : + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_click_asset.png) + +2 : + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_new_asset.png) + +3 : + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_select_asset_type.png) + +Donnez-lui un nom et cliquez sur **créer**. L'accès au nouveau asset et créer un nouveau **prop**. Appelez-le Car. + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_new_props.png) + +Cliquez sur le nouveau **Prop**. + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_click_car.png) + +Cliquez sur Modeling (ou créez la task si elle n'existe pas en cliquant sur le button "+") + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_click_modeling.png) + +Ouvrir une nouvelle scène + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_open_scene.png) + +Ensuite, travaillez sur votre modeling et enregistrez en utilisant l'action [save (enregistrer)](./actions/save.md) dans le shelf silex, et [l'incrément save](./actions/save.md). + +Chaque fois que vous sauvegardez, votre scène sera enregistrée dans le dossier **Work**. + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_work.png) + +Maintenant, vous devez tranférer ce work à l'artiste lookDev. C'est là que l'[action Publish](./actions/publish.md) entre dans le ring 🥊🥊. + +Dans le shelf Silex, cliquez sur Publish, et suivez les instructions dans la documentation ici : [Publish](./actions/publish.md) + +Lorsque c'est fait, vous pouvez passer à la section de publish dans Silex. + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_publish.png) + +Vous pouvez voir tous les fichiers de publish ici, les artistes de votre projet peuvent les voir aussi 🤩. Incroyable pas vrai ? +Les fichiers sont dans le dossier **Publish**, il est donc synchronisé sur le serveur et kes autres étudiants y ont accès. + +Maintenant, le lookDev artiste peut prendre la scène publish dans son propre dossier work, sur son propre ordinateur. Il suffit de cliquer sur le bouton d'import du fichier publish : + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_pull.png) + +Et maintenant, il peut l'ouvrir à partir du dossier work pour travailler dessus. + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_open_pulled_scene.png) + +⚠️ SI VOUS TRAVAILLEZ AVEC DES REFERENCES (ce qui est probablement le cas dans cette exemple), VOUS POUVEZ REFERENCER LE FICHIER PUBLISH SANS LE DEPLACER DANS LE DOSSIER WORK. DE CETTE FACON, SI UNE NOUVELLE VERSION EST PUBLISH, ELLE REMPLACEMENT LA REFERENCE ET L'ARTISTE LOOKDEV N'AURA QU'A RECHARGER LA REFERENCE DANS SA SCENE.⚠️ + +:::tip + +- Si les fichiers ne s'affichent pas sur l'interface, avant d'appeler un TD essayez d'utiliser CTRL + R pour recharger l'affichage. Vous pouvez également cliquer sur le bouton recharger ici. + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_reload.png) + +- Si vous souhaitez ouvrir le dossier work dans l'explorateur Windows, vous pouvez y accéder en activant le bouton "More details..." ON, en cliquant ici : + +![](/img/user_guide/workflow/tutorial/workflow_tutrorial_open_work.png) + +::: + +Si vous avez besoin de changer votre model et de donner une nouvelle version, vous pouvez publish la nouvelle scène et il remplacera celle dans le publish diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/harvest/harvest.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/harvest/harvest.md new file mode 100644 index 0000000..6248808 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/harvest/harvest.md @@ -0,0 +1,5 @@ +--- +id: harvest +title: Harvest +sidebar_position: 50 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/file-explorer.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/file-explorer.md new file mode 100644 index 0000000..b9e1ae7 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/file-explorer.md @@ -0,0 +1,43 @@ +--- +id: file-explorer +title: Explorateur de fichiers +sidebar_position: 10 +--- + +L'explorateur de fichiers vous permet de parcourir vos projets. + +Voici à quoi cela ressemble : + +![](/img/user_guide/file_explorer/file_explorer_shots.png) + +C'est la vue de vos séquences mais vous pouvez aussi accéder à vos assets dans le menu : + +![](/img/user_guide/file_explorer/file_explorer_assets.png) + +Pour les étudiants spécialisés avec plusieurs projets, vous pouvez également changer de projets. + +![](/img/user_guide/file_explorer/file_explorer_projects.png) + +## Parcourir les fichiers : + +Lorsque vous cliquez sur une séquence, vous serez "à l'intérieur" et accéderez à vos shots. Exactement comme un explorateur de fichiers Windows. + +![](/img/user_guide/file_explorer/file_explorer_structure.png) + +Lors de la sélection d'un **Shot** ou d'un **Asset**, une fenêtre s'affiche sur votre écran. Cette fenêtre affiche le contenu de votre fichier work et publish, ainsi qu'une capture d'écran de votre scène (si vous en avez pris une lors du publish) + +![](/img/user_guide/file_explorer/file_explorer_work.png) + +Vous pouvez passer du dossier **Work** au dossier **Publish** ici : + +![](/img/user_guide/file_explorer/file_explorer_switch_publish.png) + +Et Pull un fichier publish du dossier **Publish** dans le dossier **Work** (si jamais vous n'avez pas d'arbo rendering par exemple, pour continuer à travailler sur cette task) : + +![](/img/user_guide/file_explorer/file_explorer_pull.png) + +(pour plus d'informations sur le work et publish, voir : workflow) + +Dans le dossier **Work**, vous pouvez ouvrir une nouvelle scène ou une scène déjà existante. + +![](/img/user_guide/file_explorer/file_explorer_open_scene.png) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/interface.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/interface.md new file mode 100644 index 0000000..d0f887c --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/interface.md @@ -0,0 +1,88 @@ +--- +id: interface +title: Interface +sidebar_position: 30 +--- + +## Page d'accueil + +![](/img/silex_logo.png) + +--- + +Salut les newbies ! 🖖 + +Bienvenue sur Silex, une application pipeline qui vous donne accès à la render farm et vous permet de parcourir vos shots et vos assets, et bien d'autres choses ! (vous verrez, c'est très amusant) + +Lors de l'ouverture de Silex, il vous suffit de vous connecter à votre compte Kitsu. +Après cela, la page d'accueil sera affichée. + +![](/img/user_guide/home_page/silex_home_page.png) + +Cette page d'accueil comporte trois parties principales. + +### La partie inférieure : + +Il affiche les raccourcis vers les shots / assets / projets : + +![](/img/user_guide/home_page/silex_home_page_frame_bottom.png) + +- Le côté **gauche** est pour le projet dont vous faites partie. En cliquant sur l'un d'eux, vous serez redirigé vers l'[explorateur de fichiers](file-explorer.md) dans Silex, où vous pourrez parcourir le projet. + +- Le **centre** et le côté **droit**, sont des raccourcis vers les tasks et les scènes récemment ouvertes. + +:::tip +Si vous êtes un spécialiste, vous avez probablement plusieurs projets sur la gauche. Si vous avez besoin d'être ajouté à un autre projet au cours de l'année, allez demander à un TD de vous ajouter à un groupe (Ils sont très gentils, vous verrez). +::: + +### La partie centrale : + +Il s'agit d'un accès rapide au menu _hamburger_ en haut à gauche (en jaune sur l'image). Sur le côté droit, vous pouvez également accéder à l'action [conforme](../basic-concepts/actions/actions.md) pour les fichiers simple comme les textures. ( ⚠️Cette action conform ne fonctionnera pas avec les fichiers Houdini et Maya ⚠️ ) + +![](/img/user_guide/home_page/silex_home_page_frame_middle.png) + +Ces icones représente différentes applications accessibles dans Silex. Elles seront expliquées dans les sous-sections dédiées à la **fin** de ce document. + +### La barre supérieure : + +Cette section affiche votre avatar de compte, le statut Nimby, l'accès à la liste des applications en cours d'exécution, un bouton de mise à jour et le menu hamuerger (précédemment mentionné). + +![](/img/user_guide/home_page/silex_home_page_frame_top.png) + +1- Menu Hamburger. + +2- Bouton de mise à jour : Recharger l'interface (utile si certains fichiers nouvellement créés ne s'affichent pas ou si de nouvelles fonctionnalités n'apparaissent pas). Vous pouvez utiliser le **très précieux** [raccourci](../shortcuts.md) CTRL + R pour déclencher le même résultat. + +3- Liste des logiciels en cours d'exécution : + +![](/img/user_guide/home_page/silex_home_page_running_software.png) + +4- Nimby : permet d'activer/d'éteindre le [nimby](nimby.md). + +5- Profil du compte : + +![](/img/user_guide/home_page/silex_home_page_profile.png) + +Silex a un système de pièce. Ce sont des points que vous pouvez recueillir lors du publish, du conform... + +## Menu hamburger : + +Ce menu vous donne accès à tous les services sur Silex. + +![](/img/user_guide/home_page/silex_home_page_hamburger.png) + +- **Accueil** : Page d'accueil + +- **Explorateur de projets** : Il s'agit d'un [explorateur de fichiers](file-explorer.md) qui vous permet de parcourir les fichiers de vos projets. + +- **Actions** : Affiche toutes les [actions](../basic-concepts/actions/actions.md) en cours sur votre ordinateur. + +- **Statistiques** : Cela représente la progression des frames rendues de chaque équipe tout au long de l'année. Essayez d'atteindre le sommet aussi vite que possible 📈. + +- **Arcade** : Ici vous pouvez trouver des jeux de type flappy-bird, inspirés par les films de la promo2022. Jouez y pour gagner des Silex coins ! (Mais pas trop non plus) + +- **Tractor** : Tractor est la [renderfarm](../renderfarm/renderfarm.md) de l'école. + +- **Harvest** : Vous serez redirigé vers [Harvest](../harvest/harvest.md). Un outil statistique relatant différentes informations sur la renderfarm. + +- **Ticket** : Accès au système de ticket. Voir avec les TDs s'ils l'utilisent. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/nimby.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/nimby.md new file mode 100644 index 0000000..e0858c0 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/nimby.md @@ -0,0 +1,7 @@ +--- +id: nimby +title: Nimby +sidebar_position: 40 +--- + +![](/img/user_guide/home_page/silex_home_page_nimby.png) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/statistics.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/statistics.md new file mode 100644 index 0000000..da0f359 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/interface/statistics.md @@ -0,0 +1,5 @@ +--- +id: statistics +title: Statistiques +sidebar_position: 40 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/presentation.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/presentation.md new file mode 100644 index 0000000..be37994 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/presentation.md @@ -0,0 +1,5 @@ +--- +id: presentation +title: Présentation +sidebar_position: 10 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/renderfarm/renderfarm.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/renderfarm/renderfarm.md new file mode 100644 index 0000000..8cee82d --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/renderfarm/renderfarm.md @@ -0,0 +1,5 @@ +--- +id: renderfarm +title: Renderfarm +sidebar_position: 40 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/shortcuts.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/shortcuts.md new file mode 100644 index 0000000..fc812c4 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/shortcuts.md @@ -0,0 +1,5 @@ +--- +id: shortcuts +title: Raccourcis +sidebar_position: 50 +--- diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/user/trouble-shootinh/trouble-shooting.md b/i18n/fr/docusaurus-plugin-content-docs/current/user/trouble-shootinh/trouble-shooting.md new file mode 100644 index 0000000..e89b14a --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/user/trouble-shootinh/trouble-shooting.md @@ -0,0 +1,6 @@ +--- +id: trouble-shooting +title: Mesures de dépannage +--- + +## Mon Dieu ! Nous avons des ennuis ... diff --git a/i18n/fr/docusaurus-theme-classic/footer.json b/i18n/fr/docusaurus-theme-classic/footer.json new file mode 100644 index 0000000..16a9b12 --- /dev/null +++ b/i18n/fr/docusaurus-theme-classic/footer.json @@ -0,0 +1,122 @@ +{ + "link.title.User Guide": { + "message": "Guide Utilisateur", + "description": "The title of the footer links column with title=Guide Utilisateur in the footer" + }, + "link.item.label.Shots and assets": { + "message": "Shots and assets", + "description": "The label of footer link with label=Shots and assets linking to /docs/user/shots-assets" + }, + "link.item.label.Action": { + "message": "Action", + "description": "The label of footer link with label=Action linking to /docs/user/action" + }, + "link.item.label.Actions in Maya": { + "message": "Actions in Maya", + "description": "The label of footer link with label=Actions in Maya linking to /docs/user/action-maya" + }, + "link.item.label.Actions in Houdini": { + "message": "Actions in Houdini", + "description": "The label of footer link with label=Actions in Houdini linking to /docs/user/action-houdini" + }, + "link.item.label.Actions in Nuke": { + "message": "Actions in Nuke", + "description": "The label of footer link with label=Actions in Nuke linking to /docs/user/action-nuke" + }, + "link.item.label.The render farm and tractor": { + "message": "The render farm and tractor", + "description": "The label of footer link with label=The render farm and tractor linking to /docs/user/renderfarm-tractor" + }, + "link.item.label.Install": { + "message": "Install", + "description": "The label of footer link with label=Install linking to /docs/user/getting-started" + }, + "link.item.label.Shots & assets": { + "message": "Shots & assets", + "description": "The label of footer link with label=Shots & assets linking to /docs/user/shots-assets" + }, + "link.item.label.Silex Action": { + "message": "Silex Action", + "description": "The label of footer link with label=Silex Action linking to /docs/user/action" + }, + + "link.title.TD": { + "message": "TD", + "description": "The title of the footer links column with title=TD in the footer" + }, + "link.item.label.Presentation": { + "message": "Présentation", + "description": "The label of footer link with label=Presentation linking to /docs/td/introduction" + }, + "link.item.label.Install Silex": { + "message": "Installer Silex", + "description": "The label of footer link with label=Install Silex linking to /docs/td/getting-started" + }, + "link.item.label.Coding Workflow": { + "message": "Coding Workflow", + "description": "The label of footer link with label=Coding Workflow linking to /docs/td/workflow" + }, + "link.item.label.Backend": { + "message": "Backend", + "description": "The label of footer link with label=Backend linking to /docs/td/backend/CGWire/zou" + }, + "link.item.label.Renderfarm": { + "message": "Renderfarm", + "description": "The label of footer link with label=Renderfarm linking to /docs/td/renderfarm" + }, + "link.item.label.Silex": { + "message": "Silex", + "description": "The label of footer link with label=Silex linking to /docs/td/silex" + }, + "link.item.label.Design Guidelines": { + "message": "Design Guidelines", + "description": "The label of footer link with label=Design Guidelines linking to /docs/td/design" + }, + + "link.title.IT": { + "message": "IT", + "description": "The title of the footer links column with title=IT in the footer" + }, + "link.item.label.Présentation": { + "message": "Présentation", + "description": "The label of footer link with label=Présentation linking to /docs/it/presentation" + }, + "link.item.label.Resilio": { + "message": "Résilio", + "description": "The label of footer link with label=Resilio linking to /docs/it/resilio" + }, + "link.item.label.Portainer": { + "message": "Portainer", + "description": "The label of footer link with label=Portainer linking to /docs/it/portainer" + }, + "link.item.label.Observium": { + "message": "Observium", + "description": "The label of footer link with label=Observium linking to /docs/it/observium" + }, + "link.item.label.Zammad": { + "message": "Zammad", + "description": "The label of footer link with label=Présentation linking to /docs/it/zammad" + }, + "link.item.label.Deployment": { + "message": "Déploiment", + "description": "The label of footer link with label=Présentation linking to /docs/it/deployment/pipeline-drive" + }, + "link.item.label.Scripts": { + "message": "Scripts", + "description": "The label of footer link with label=Scripts linking to /docs/it/scripts/presentation" + }, + + "link.title.FAQ": { + "message": "FAQ", + "description": "The title of the footer links column with title=FAQ in the footer" + }, + "link.item.label.faq": { + "message": "FAQ", + "description": "The label of footer link with label=faq linking to /docs/faq" + }, + + "copyright": { + "message": "Copyright © 2022 ArtFX TDs", + "description": "The footer copyright" + } +} diff --git a/i18n/fr/docusaurus-theme-classic/navbar.json b/i18n/fr/docusaurus-theme-classic/navbar.json new file mode 100644 index 0000000..1c39a5f --- /dev/null +++ b/i18n/fr/docusaurus-theme-classic/navbar.json @@ -0,0 +1,26 @@ +{ + "title": { + "message": "Silex Docs", + "description": "The title in the navbar" + }, + + "item.label.User Guide": { + "message": "Guide utilisateur", + "description": "Navbar item with label User Guide" + }, + + "item.label.TD": { + "message": "TD", + "description": "Navbar item with label TD" + }, + + "item.label.IT": { + "message": "IT", + "description": "Navbar item with label IT" + }, + + "item.label.FAQ": { + "message": "FAQ", + "description": "Navbar item with label FAQ" + } +}