WIP: Pipeline Release: Bundle all Add-Ons in a Zip #268
@ -112,20 +112,21 @@ export default defineConfig({
|
|||||||
|
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
items: [
|
items: [
|
||||||
{ text: 'Anim Cupboard', link: '/addons/anim_cupboard'},
|
{ text: 'Anim Cupboard', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/anim_cupboard/README.md'},
|
||||||
{ text: 'Asset Pipeline', link: '/addons/asset_pipeline'},
|
{ text: 'Asset Pipeline', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/asset_pipeline/README.md'},
|
||||||
{ text: 'Blender Kitsu', link: '/addons/blender_kitsu'},
|
{ text: 'Blender Kitsu', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_kitsu/README.md'},
|
||||||
{ text: 'Blender SVN', link: '/addons/blender_svn'},
|
{ text: 'Blender Log', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_log/README.md'},
|
||||||
{ text: 'Blender Gizmos', link: '/addons/bone_gizmos'},
|
{ text: 'Blender SVN', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_svn/README.md'},
|
||||||
{ text: 'Cache Manager', link: '/addons/cache_manager'},
|
{ text: 'Bone Gizmos', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/bone_gizmos/README.md'},
|
||||||
{ text: 'Contact Sheet', link: '/addons/contactsheet'},
|
{ text: 'Cache Manager', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/cache_manager/README.md'},
|
||||||
{ text: 'Easy Weights', link: '/addons/easy_weights'},
|
{ text: 'Contact Sheet', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/contactsheet/README.md'},
|
||||||
{ text: 'Geonode Shapekeys', link: '/addons/geonode_shapekeys'},
|
{ text: 'Easy Weights', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/easy_weights/README.md'},
|
||||||
{ text: 'Grase Converter', link: '/addons/grease_converter'},
|
{ text: 'Geonode Shapekeys', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/geonode_shapekeys/README.md'},
|
||||||
{ text: 'Lattice Magic', link: '/addons/lattice_magic'},
|
{ text: 'Grase Converter', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/grease_converter/README.md'},
|
||||||
{ text: 'Lighting Overrider', link: '/addons/lighting_overrider'},
|
{ text: 'Lattice Magic', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lattice_magic/README.md'},
|
||||||
{ text: 'Pose Shape Keys', link: '/addons/pose_shape_keys'},
|
{ text: 'Lighting Overrider', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lighting_overrider/README.md'},
|
||||||
{ text: 'Render Review', link: '/addons/render_review'},
|
{ text: 'Pose Shape Keys', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/pose_shape_keys/README.md'},
|
||||||
|
{ text: 'Render Review', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/render_review/README.md'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/anim_cupboard/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/anim_cupboard/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/asset_pipeline/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/asset_pipeline/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/blender_kitsu/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/blender_kitsu/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/blender_svn/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/blender_svn/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/bone_gizmos/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/bone_gizmos/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/cache_manager/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/cache_manager/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/contactsheet/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/contactsheet/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/easy_weights/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/easy_weights/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/geonode_shapekeys/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/geonode_shapekeys/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/grease_converter/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/grease_converter/CHANGELOG.md-->
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/lattice_magic/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/lattice_magic/CHANGELOG.md-->
|
|
@ -1,4 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/lighting_overrider/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/lighting_overrider/CHANGELOG.md-->
|
|
@ -1 +1 @@
|
|||||||
<!--@include: ../../scripts/pipeline-release/overview.md-->
|
<!--@include: ../../scripts-blender/README.md-->
|
@ -1,4 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/pose_shape_keys/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/pose_shape_keys/CHANGELOG.md-->
|
|
@ -1,4 +0,0 @@
|
|||||||
<!--@include: ../../scripts-blender/addons/render_review/README.md-->
|
|
||||||
##
|
|
||||||
# Changelog
|
|
||||||
<!--@include: ../../scripts-blender/addons/render_review/CHANGELOG.md-->
|
|
BIN
docs/media/addons/easy_weights/custom_wp_context_menu.png
(Stored with Git LFS)
BIN
docs/media/addons/easy_weights/custom_wp_context_menu.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/media/addons/easy_weights/toggle_wp_shortcut.png
(Stored with Git LFS)
BIN
docs/media/addons/easy_weights/toggle_wp_shortcut.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/media/addons/easy_weights/vg_context_menu.png
(Stored with Git LFS)
BIN
docs/media/addons/easy_weights/vg_context_menu.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/media/addons/easy_weights/weight_islands.png
(Stored with Git LFS)
BIN
docs/media/addons/easy_weights/weight_islands.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/media/addons/easy_weights/wp_context_menu_shortcut.png
(Stored with Git LFS)
BIN
docs/media/addons/easy_weights/wp_context_menu_shortcut.png
(Stored with Git LFS)
Binary file not shown.
@ -136,32 +136,8 @@ python rollback_blender_local.py
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Install/Update Add-Ons
|
## Install/Update Add-Ons
|
||||||
Blender Add-ons can be packaged directly from the [Blender Studio Pipeline](https://projects.blender.org/studio/blender-studio-pipeline) repository. Personal Add-Ons can be installed [normally](https://docs.blender.org/manual/en/latest/editors/preferences/addons.html#installing-add-ons).
|
|
||||||
|
|
||||||
1. Enter Directory
|
<!--@include: ../../../scripts/pipeline-release/README.md-->
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ~/data/blender-studio-pipeline/scripts/pipeline-release # Linux/Mac
|
|
||||||
```
|
|
||||||
```bash
|
|
||||||
cd %HOMEPATH%\data\blender-studio-pipeline\scripts\pipeline-release # Windows
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Update Git
|
|
||||||
```bash
|
|
||||||
# Windows & Linux/Mac
|
|
||||||
git checkout main # Checkout main branch
|
|
||||||
git reset --hard # Remove any changes stored in your branch
|
|
||||||
git pull --rebase origin # Pull to update to latest commit
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Run Package Local Script
|
|
||||||
```bash
|
|
||||||
./package_local.py ~/data/your_project_name/shared/artifacts/addons # Linux/Mac
|
|
||||||
```
|
|
||||||
```bash
|
|
||||||
python package_local.py %HOMEPATH%\data\your_project_name\shared\artifacts\addons # Windows
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
::: info Blender Studio Users
|
::: info Blender Studio Users
|
||||||
|
@ -4,22 +4,18 @@ Add-ons used by the Blender Studio pipeline. To review or report issues visit th
|
|||||||
|
|
||||||
| Add-on | Description |
|
| Add-on | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
|Anim Cupboard |Miscellaneous tools for animators.
|
|[Anim Cupboard](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/anim_cupboard) |Miscellaneous tools for animators.
|
||||||
|Asset Pipeline |Manages the Asset Pipeline, used by Modeling, Shading and Rigging departments.
|
|[Asset Pipeline](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/asset_pipeline) |Manages the Asset Pipeline, used by Modeling, Shading and Rigging departments.
|
||||||
|Blender Kitsu |Enforce conventions, build shots, manage production files and update data on kitsu server.
|
|[Blender Kitsu](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_kitsu) |Enforce conventions, build shots, manage production files and update data on kitsu server.
|
||||||
|Blender Log |A place for add-ons to report issues to the user in a persistent UI element.
|
|[Blender Log](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_log) |A place for add-ons to report issues to the user in a persistent UI element.
|
||||||
|Blender SVN |UI for the SVN (Subversion) file versioning system.
|
|[Blender SVN](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_svn) |UI for the SVN (Subversion) file versioning system.
|
||||||
|Blender Gizmos |Attempt to prototype a system for using meshes for the manipulation of armatures.
|
|[Blender Gizmos](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/bone_gizmos) |Attempt to prototype a system for using meshes for the manipulation of armatures.
|
||||||
|Cache Manager |Streamline the Alembic cache workflow of assets.
|
|[Cache Manager](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/cache_manager) |Streamline the Alembic cache workflow of assets.
|
||||||
|Contact Sheet |Create a contactsheet from sequence editor strips.
|
|[Contact Sheet](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/contactsheet) |Create a contactsheet from sequence editor strips.
|
||||||
|Easy Weights |Quality of life improvements for weight painting.
|
|[Easy Weights](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/easy_weights) |Quality of life improvements for weight painting.
|
||||||
|Geonode Shapekeys |Enable animators to sculpt on linked and overridden meshes.
|
|[Geonode Shapekeys](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/geonode_shapekeys) |Enable animators to sculpt on linked and overridden meshes.
|
||||||
|Grease Converter |Convert annotations to Grease Pencil objects and vise versa.
|
|[Grease Converter](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/grease_converter) |Convert annotations to Grease Pencil objects and vise versa.
|
||||||
|Lattice Magic |Lattice-based utilities.
|
|[Lattice Magic](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lattice_magic) |Lattice-based utilities.
|
||||||
|Lighting Overrider |Create, manage and apply python overrides in a flexible and reliable way.
|
|[Lighting Overrider](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lighting_overrider) |Create, manage and apply python overrides in a flexible and reliable way.
|
||||||
|Pose Shape Keys |Manage and maintain shapekeys for rigging.
|
|[Pose Shape Keys](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/pose_shape_keys) |Manage and maintain shapekeys for rigging.
|
||||||
|Render Review |Review renders from Flamenco with the sequence editor.
|
|[Render Review](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/render_review) |Review renders from Flamenco with the sequence editor.
|
||||||
|
|
||||||
Download release packages of the above add-ons from the [Add-on Release Table](https://studio.blender.org/pipeline/addons/overview) page.
|
|
||||||
|
|
||||||
Download previous release of the above add-ons from the [Releases](https://projects.blender.org/studio/blender-studio-pipeline/releases) page.
|
|
@ -43,7 +43,7 @@ If Kitsu is up and running and you can successfully log in via the web interface
|
|||||||
|
|
||||||
###### **Setup Login Data**
|
###### **Setup Login Data**
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/prefs_login.jpg)
|
![image info](docs_media/prefs_login.jpg)
|
||||||
|
|
||||||
>**Host**: The web address of your kitsu server (e.g., https://kitsu.mydomain.com)<br/>
|
>**Host**: The web address of your kitsu server (e.g., https://kitsu.mydomain.com)<br/>
|
||||||
**Email**: The email you use to log in to kitsu<br/>
|
**Email**: The email you use to log in to kitsu<br/>
|
||||||
@ -53,7 +53,7 @@ Press the login button. If the login was successful, the next step is..
|
|||||||
|
|
||||||
###### **Setup Project Settings**
|
###### **Setup Project Settings**
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/prefs_project.jpg)
|
![image info](docs_media/prefs_project.jpg)
|
||||||
|
|
||||||
>**Project Root Directory**: Path to the root of your project. Will later be used to configure the addon on a per project basis<br/>
|
>**Project Root Directory**: Path to the root of your project. Will later be used to configure the addon on a per project basis<br/>
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ Press the login button. If the login was successful, the next step is..
|
|||||||
###### **Setup Animation Tools**
|
###### **Setup Animation Tools**
|
||||||
|
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/prefs_anim_tools.jpg)
|
![image info](docs_media/prefs_anim_tools.jpg)
|
||||||
|
|
||||||
|
|
||||||
>**Playblast Root Directory**: Path to a directory in which playblasts will be saved to<br/>
|
>**Playblast Root Directory**: Path to a directory in which playblasts will be saved to<br/>
|
||||||
@ -71,19 +71,19 @@ Press the login button. If the login was successful, the next step is..
|
|||||||
|
|
||||||
###### **Setup Lookdev Tools**
|
###### **Setup Lookdev Tools**
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/prefs_lookdev.jpg)
|
![image info](docs_media/prefs_lookdev.jpg)
|
||||||
|
|
||||||
>**Render Presets Directory**: Path to a directory in which you can save .py files that will be displayed in render preset dropdown. More info in: How to use render presets.<br/>
|
>**Render Presets Directory**: Path to a directory in which you can save .py files that will be displayed in render preset dropdown. More info in: How to use render presets.<br/>
|
||||||
|
|
||||||
###### **Setup Media Search Paths**
|
###### **Setup Media Search Paths**
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/prefs_outdated_media.jpg)
|
![image info](docs_media/prefs_outdated_media.jpg)
|
||||||
|
|
||||||
>**Path List**: List of paths to top level directory. Only media that is a child (recursive) of one of these directories will be scanned for outdated media.<br/>
|
>**Path List**: List of paths to top level directory. Only media that is a child (recursive) of one of these directories will be scanned for outdated media.<br/>
|
||||||
|
|
||||||
###### **Setup Miscellaneous**
|
###### **Setup Miscellaneous**
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/prefs_misc.jpg)
|
![image info](docs_media/prefs_misc.jpg)
|
||||||
|
|
||||||
>**Thumbnail Directory**: Directory where thumbnails will be saved before uploading them to kitsu. Cannot be edited.<br/>
|
>**Thumbnail Directory**: Directory where thumbnails will be saved before uploading them to kitsu. Cannot be edited.<br/>
|
||||||
**Sequence Editor Render Directory**: Directory where sequence editor renderings will be saved before uploading them to kitsu. Cannot be edited<br/>
|
**Sequence Editor Render Directory**: Directory where sequence editor renderings will be saved before uploading them to kitsu. Cannot be edited<br/>
|
||||||
@ -102,7 +102,7 @@ blender-kitsu sequence editor tools were constructed with the idea in mind to ha
|
|||||||
##### Metadata Strips
|
##### Metadata Strips
|
||||||
Metadata Strips are regular Movie Strips that can be linked to a shot in kitsu. It is a good idea to create a separate metadata strip in a separate channel that represents the shot. That gives you the freedom to assemble a shot out of multiple elements, like multiple storyboard pictures, and still have one metadata strip that contains the full shot range.
|
Metadata Strips are regular Movie Strips that can be linked to a shot in kitsu. It is a good idea to create a separate metadata strip in a separate channel that represents the shot. That gives you the freedom to assemble a shot out of multiple elements, like multiple storyboard pictures, and still have one metadata strip that contains the full shot range.
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/metadata_strip.001.jpg)
|
![image info](docs_media/metadata_strip.001.jpg)
|
||||||
|
|
||||||
>**Good to know**: A metadata strip can have 3 states. It can be **initialized** but **not** linked yet. That means the movie strips knows I am a metadata strip but I don't have a relationship to a shot on Kitsu yet. It can be **linked**, which means the strip is already initialized and is linked to a sequence_id and shot_id on Kitsu. Only if a strip is linked you can exchange metadata, push thumbnails etc. The last state is **uninitialized** which basically means it's a regular movie strips and has nothing to do with kitsu.
|
>**Good to know**: A metadata strip can have 3 states. It can be **initialized** but **not** linked yet. That means the movie strips knows I am a metadata strip but I don't have a relationship to a shot on Kitsu yet. It can be **linked**, which means the strip is already initialized and is linked to a sequence_id and shot_id on Kitsu. Only if a strip is linked you can exchange metadata, push thumbnails etc. The last state is **uninitialized** which basically means it's a regular movie strips and has nothing to do with kitsu.
|
||||||
|
|
||||||
@ -112,7 +112,8 @@ This will create a blank movie strip. The metadata strip will be placed one chan
|
|||||||
|
|
||||||
###### Initialize a Shot
|
###### Initialize a Shot
|
||||||
1. Select a metadata strip and open the `Kitsu` tab in the sidebar of the sequence editor. You will find multiple ways on how to initialize your strip.
|
1. Select a metadata strip and open the `Kitsu` tab in the sidebar of the sequence editor. You will find multiple ways on how to initialize your strip.
|
||||||
![image info](/media/addons/blender_kitsu/sqe_init_shot.jpg)
|
|
||||||
|
![image info](docs_media/sqe_init_shot.jpg)
|
||||||
|
|
||||||
2. Case A: Shot does **already exist** on Kitsu
|
2. Case A: Shot does **already exist** on Kitsu
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ This will create a blank movie strip. The metadata strip will be placed one chan
|
|||||||
|
|
||||||
2.2 Alternatively you can also link a shot by pasting the URL. (e.G: https://kitsu.yourdomain.com/productions/fc77c0b9-bb76-41c3-b843-c9b156f9b3ec/shots/e7e6be02-5574-4764-9077-965d57b1ec12) <br/>
|
2.2 Alternatively you can also link a shot by pasting the URL. (e.G: https://kitsu.yourdomain.com/productions/fc77c0b9-bb76-41c3-b843-c9b156f9b3ec/shots/e7e6be02-5574-4764-9077-965d57b1ec12) <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_link_shot.jpg)
|
![image info](docs_media/sqe_link_shot.jpg)
|
||||||
|
|
||||||
3. Case B: Shot **does not exist** on Kitsu yet
|
3. Case B: Shot **does not exist** on Kitsu yet
|
||||||
|
|
||||||
@ -133,12 +134,12 @@ This will create a blank movie strip. The metadata strip will be placed one chan
|
|||||||
3.4 Execute the `Submit New Shot` operator in the `Push` Panel (Will warn you if the shot already exists on Kitsu). This operator can optionally populate each 'Shot' with a task set to the project's default task status.
|
3.4 Execute the `Submit New Shot` operator in the `Push` Panel (Will warn you if the shot already exists on Kitsu). This operator can optionally populate each 'Shot' with a task set to the project's default task status.
|
||||||
|
|
||||||
>**Note**: Most of the operator are selection sensitive. So you can do these operations for a batch of sequence strips. If you have nothing selected it will usually try to operate on all strips in the sequence editor. <br/>
|
>**Note**: Most of the operator are selection sensitive. So you can do these operations for a batch of sequence strips. If you have nothing selected it will usually try to operate on all strips in the sequence editor. <br/>
|
||||||
![image info](/media/addons/blender_kitsu/sqe_init_selection.jpg)
|
![image info](docs_media/sqe_init_selection.jpg)
|
||||||
|
|
||||||
##### Metadata
|
##### Metadata
|
||||||
If you select a single linked strip you will see a `Metadata` panel that shows you the information that is related to the sequence and shot the strip is linking to.
|
If you select a single linked strip you will see a `Metadata` panel that shows you the information that is related to the sequence and shot the strip is linking to.
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_metadata.jpg)
|
![image info](docs_media/sqe_metadata.jpg)
|
||||||
|
|
||||||
The frame range will be updated by using the Blender editing tools on the strip. (trimming, sliding, etc.). <br/>
|
The frame range will be updated by using the Blender editing tools on the strip. (trimming, sliding, etc.). <br/>
|
||||||
If you execute the `Initialize Shot Start Frame` operator (refresh icon) the current in point of the strip will be remapped so the shot starts at 101 in the current editing state. <br/>
|
If you execute the `Initialize Shot Start Frame` operator (refresh icon) the current in point of the strip will be remapped so the shot starts at 101 in the current editing state. <br/>
|
||||||
@ -146,7 +147,7 @@ You can reassign the shot to another sequence by executing the `Link Sequence` O
|
|||||||
|
|
||||||
If you linked in a sequence that has no `["data"]["color"]` attribute on Kitsu yet the gpu overlay line will be white. In order to add a new sequence color execute the `Add Sequence Color` operator. <br/>
|
If you linked in a sequence that has no `["data"]["color"]` attribute on Kitsu yet the gpu overlay line will be white. In order to add a new sequence color execute the `Add Sequence Color` operator. <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_sequence_color_init.jpg)
|
![image info](docs_media/sqe_sequence_color_init.jpg)
|
||||||
|
|
||||||
|
|
||||||
All this information and more can be `pushed` to kitsu which bring us to the next panel. <br/>
|
All this information and more can be `pushed` to kitsu which bring us to the next panel. <br/>
|
||||||
@ -155,7 +156,7 @@ All this information and more can be `pushed` to kitsu which bring us to the nex
|
|||||||
|
|
||||||
In the `Push` panel you will find all the operators that push data to Kitsu. <br/>
|
In the `Push` panel you will find all the operators that push data to Kitsu. <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_push.jpg)
|
![image info](docs_media/sqe_push.jpg)
|
||||||
|
|
||||||
>**Metadata**: Pushes metadata of shot: sequence, shot name, frame range, sequence_color
|
>**Metadata**: Pushes metadata of shot: sequence, shot name, frame range, sequence_color
|
||||||
>>**Note**: Global edit frame range will be saved in `"frame_in"` `"frame_out"` kitsu shot attribute <br/>
|
>>**Note**: Global edit frame range will be saved in `"frame_in"` `"frame_out"` kitsu shot attribute <br/>
|
||||||
@ -168,42 +169,42 @@ If you select multiple metadata strips it will always use the middle frame to cr
|
|||||||
##### Pull
|
##### Pull
|
||||||
In the `Pull` panel you will find all the operators that pull data from Kitsu to a metadata strip. <br/>
|
In the `Pull` panel you will find all the operators that pull data from Kitsu to a metadata strip. <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_pull.jpg)
|
![image info](docs_media/sqe_pull.jpg)
|
||||||
|
|
||||||
>**Metadata**: Pulls metadata of shot: sequence, shot name, shot description and updates the strip name to match the shot name.
|
>**Metadata**: Pulls metadata of shot: sequence, shot name, shot description and updates the strip name to match the shot name.
|
||||||
>>**Note**: Frame ranges will **never** be updated when pulling data from Kitsu. They belong to the edit and will only be pushed to Kitsu.<br/>
|
>>**Note**: Frame ranges will **never** be updated when pulling data from Kitsu. They belong to the edit and will only be pushed to Kitsu.<br/>
|
||||||
|
|
||||||
If you have not sequence selected the `Pull Entire Edit` Operator will appear in the `Pull` panel.<br/>
|
If you have not sequence selected the `Pull Entire Edit` Operator will appear in the `Pull` panel.<br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_pull_entire_edit.jpg)
|
![image info](docs_media/sqe_pull_entire_edit.jpg)
|
||||||
|
|
||||||
After you selected the channel it will go through all shots on Kitsu, create a metadata strip which will be linked to the respective shot and pulls all metadata. <br/>
|
After you selected the channel it will go through all shots on Kitsu, create a metadata strip which will be linked to the respective shot and pulls all metadata. <br/>
|
||||||
It will use te `frame_in` and `frame_out` attribute on Kitsu to determine the in and out points in the edit. So make sure these are up to date and don't overlap. <br/>
|
It will use te `frame_in` and `frame_out` attribute on Kitsu to determine the in and out points in the edit. So make sure these are up to date and don't overlap. <br/>
|
||||||
|
|
||||||
As a result a bigger edit with nice sequence_colors can look pretty cool:
|
As a result a bigger edit with nice sequence_colors can look pretty cool:
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_sequence_colors.jpg)
|
![image info](docs_media/sqe_sequence_colors.jpg)
|
||||||
|
|
||||||
|
|
||||||
##### Multi Edit
|
##### Multi Edit
|
||||||
|
|
||||||
The `Multi Edit` panel only appears when you select multiple metadata strips that are all `initialized` but not `linked` yet. <br/>
|
The `Multi Edit` panel only appears when you select multiple metadata strips that are all `initialized` but not `linked` yet. <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_multi_edit.jpg)
|
![image info](docs_media/sqe_multi_edit.jpg)
|
||||||
|
|
||||||
It is meant to be way to quickly setup lots of shots if they don't exist on Kitsu yet. You specify the sequence all shots should belong to and adjust the `Shot Counter Start` value. In the preview property you can see how all shots will be named when you execute the `Multi Edit Strip` operator. <br/>
|
It is meant to be way to quickly setup lots of shots if they don't exist on Kitsu yet. You specify the sequence all shots should belong to and adjust the `Shot Counter Start` value. In the preview property you can see how all shots will be named when you execute the `Multi Edit Strip` operator. <br/>
|
||||||
|
|
||||||
##### Shot as Image Sequence
|
##### Shot as Image Sequence
|
||||||
The `Shot as Image Sequence` Operator will replace a playblast from your Playblast Root directory with an image sequence located in the Frames Root directory. The Shots Directory and the Frames Directory should have matching folder structures. Typically the format is `/{sequence_name}/{shot_name}/{shot_name}-{shot_task}/`
|
The `Shot as Image Sequence` Operator will replace a playblast from your Playblast Root directory with an image sequence located in the Frames Root directory. The Shots Directory and the Frames Directory should have matching folder structures. Typically the format is `/{sequence_name}/{shot_name}/{shot_name}-{shot_task}/`
|
||||||
|
|
||||||
![Shot as Image Sequence](/media/addons/blender_kitsu/Shot_as_Image_Sequence.jpg)
|
![Shot as Image Sequence](docs_media/Shot_as_Image_Sequence.jpg)
|
||||||
|
|
||||||
Use this operator to replace playblasts with image sequences that have been approved via the [Render Review Add-On](/addons/render_review) Image Sequences can be loaded as either `EXR` or `JPG` sequences.
|
Use this operator to replace playblasts with image sequences that have been approved via the [Render Review Add-On](/addons/render_review) Image Sequences can be loaded as either `EXR` or `JPG` sequences.
|
||||||
|
|
||||||
###### Advanced Settings
|
###### Advanced Settings
|
||||||
If you check the `Advanced` checkbox next to the counter value, you have access to advance settings to customize the operator even more.
|
If you check the `Advanced` checkbox next to the counter value, you have access to advance settings to customize the operator even more.
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_multi_edit_advanced.jpg)
|
![image info](docs_media/sqe_multi_edit_advanced.jpg)
|
||||||
|
|
||||||
You can adjust the number of counter digits, the increment size and also the `Pattern` it will use to generate the shot name. <br/>
|
You can adjust the number of counter digits, the increment size and also the `Pattern` it will use to generate the shot name. <br/>
|
||||||
>**Pattern**: supports 3 wildcards. `<Sequence>`, `<Counter>`, `<Project>` that can be used multiple times in any order. <br/>
|
>**Pattern**: supports 3 wildcards. `<Sequence>`, `<Counter>`, `<Project>` that can be used multiple times in any order. <br/>
|
||||||
@ -213,15 +214,15 @@ You can adjust the number of counter digits, the increment size and also the `Pa
|
|||||||
##### General Sequence Editor Tools
|
##### General Sequence Editor Tools
|
||||||
In the general tab you can find some tools that don't directly relate to Kitsu but are useful for editing.
|
In the general tab you can find some tools that don't directly relate to Kitsu but are useful for editing.
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_outdated_scan.jpg)
|
![image info](docs_media/sqe_outdated_scan.jpg)
|
||||||
|
|
||||||
`Scan for outdated media` will scan the selected / all sequence strips for their source media file. It searches for a later version in the same directory as the source media. If the current media file is outdated it will highlight that strip with a red line in the sequence editor:
|
`Scan for outdated media` will scan the selected / all sequence strips for their source media file. It searches for a later version in the same directory as the source media. If the current media file is outdated it will highlight that strip with a red line in the sequence editor:
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_outdated_overlay.jpg)
|
![image info](docs_media/sqe_outdated_overlay.jpg)
|
||||||
|
|
||||||
To update the outdated strips you can select them individually and by clicking the `Arrow Up` or `Arrow Down` you cycle through the available versions on disk. You will be prompted with an information if you reached the latest or oldest version.
|
To update the outdated strips you can select them individually and by clicking the `Arrow Up` or `Arrow Down` you cycle through the available versions on disk. You will be prompted with an information if you reached the latest or oldest version.
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/sqe_outdated_update.jpg)
|
![image info](docs_media/sqe_outdated_update.jpg)
|
||||||
|
|
||||||
|
|
||||||
>**Note**: The operator searches for a version string e.G `v001` and checks files that are named the same but have a different version. <br/>
|
>**Note**: The operator searches for a version string e.G `v001` and checks files that are named the same but have a different version. <br/>
|
||||||
@ -232,7 +233,7 @@ blender-kitsu context features were constructed with the idea in mind to create
|
|||||||
|
|
||||||
To create 'context' you can find the `Context Browser` in the `Kitsu` panel in the sidebar of the 3D Viewport. <br/>
|
To create 'context' you can find the `Context Browser` in the `Kitsu` panel in the sidebar of the 3D Viewport. <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/context_browser.jpg)
|
![image info](docs_media/context_browser.jpg)
|
||||||
|
|
||||||
By selecting the different drop down menus you can browse through the Kitsu file structure and set e.G the active sequence, active shot and task type you want to work on. <br/>
|
By selecting the different drop down menus you can browse through the Kitsu file structure and set e.G the active sequence, active shot and task type you want to work on. <br/>
|
||||||
|
|
||||||
@ -245,7 +246,7 @@ Depending on which `Task Type` you select different tool sets will be available.
|
|||||||
The animation tools will show up when you selected a `Task Type` with the name `Animation`. <br/>
|
The animation tools will show up when you selected a `Task Type` with the name `Animation`. <br/>
|
||||||
|
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/context_animation_tools.jpg)
|
![image info](docs_media/context_animation_tools.jpg)
|
||||||
|
|
||||||
>**Create Playblast**: Will create a openGL viewport render of the viewport from which the operator was executed and uploads it to Kitsu. The `+` button increments the version of the playblast. If you would override an older version you will see a warning before the filepath. The `directory` button will open a file browser in the playblast directory. The playblast will be uploaded to the `Animation` Task Type of the active shot that was set in the `Context Browser`. The web browser will be opened after the playblast and should point to the respective shot on Kitsu. <br/>
|
>**Create Playblast**: Will create a openGL viewport render of the viewport from which the operator was executed and uploads it to Kitsu. The `+` button increments the version of the playblast. If you would override an older version you will see a warning before the filepath. The `directory` button will open a file browser in the playblast directory. The playblast will be uploaded to the `Animation` Task Type of the active shot that was set in the `Context Browser`. The web browser will be opened after the playblast and should point to the respective shot on Kitsu. <br/>
|
||||||
**Push Frame Start**: Will Push the current scene's frame start to Kitsu. This will set the `['data']['3d_start]` attribute of the Kitsu shot.
|
**Push Frame Start**: Will Push the current scene's frame start to Kitsu. This will set the `['data']['3d_start]` attribute of the Kitsu shot.
|
||||||
@ -257,7 +258,7 @@ The animation tools will show up when you selected a `Task Type` with the name `
|
|||||||
##### Lookdev Tools
|
##### Lookdev Tools
|
||||||
The lookdev tools will show up when you selected a `Task Type` with the name `Lighting` | `Rendering` | `Compositing`. <br/>
|
The lookdev tools will show up when you selected a `Task Type` with the name `Lighting` | `Rendering` | `Compositing`. <br/>
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/context_lookdev_tools.jpg)
|
![image info](docs_media/context_lookdev_tools.jpg)
|
||||||
|
|
||||||
>**Apply Render Preset**: Consists of a dropdown menu that displays all `.py` files which are present in the `Render Presets Directory` (defined in the add-on preferences). Select the `.py` file you want to execute. When you hit the `Play` button the `main()` function of the python file will be executed. Very useful to quickly switch between different render settings.
|
>**Apply Render Preset**: Consists of a dropdown menu that displays all `.py` files which are present in the `Render Presets Directory` (defined in the add-on preferences). Select the `.py` file you want to execute. When you hit the `Play` button the `main()` function of the python file will be executed. Very useful to quickly switch between different render settings.
|
||||||
|
|
||||||
@ -266,7 +267,7 @@ The lookdev tools will show up when you selected a `Task Type` with the name `Li
|
|||||||
blender-kitsu has different checks that are performed during file load or during editing. If it detects an error that prevents other operators to run it will display an error in the ui. <br/>
|
blender-kitsu has different checks that are performed during file load or during editing. If it detects an error that prevents other operators to run it will display an error in the ui. <br/>
|
||||||
|
|
||||||
|
|
||||||
![image info](/media/addons/blender_kitsu/error_animation.jpg)
|
![image info](docs_media/error_animation.jpg)
|
||||||
|
|
||||||
## Shot Builder
|
## Shot Builder
|
||||||
Shot Builder is a Feature of the Blender Kitsu Add-on To automatically build shot files, using the data from Kitsu server and the file structures defined on the [Blender Studio](https://studio.blender.org/pipeline/naming-conventions/svn-folder-structure) website.
|
Shot Builder is a Feature of the Blender Kitsu Add-on To automatically build shot files, using the data from Kitsu server and the file structures defined on the [Blender Studio](https://studio.blender.org/pipeline/naming-conventions/svn-folder-structure) website.
|
||||||
|
@ -18,12 +18,12 @@ After the add-on is installed you have 2 new operators available.
|
|||||||
- **grease_converter.convert_to_grease_pencil**:
|
- **grease_converter.convert_to_grease_pencil**:
|
||||||
- Located in the 3DView Side Panel (N)-> View -> Annotations Panel
|
- Located in the 3DView Side Panel (N)-> View -> Annotations Panel
|
||||||
- Converts active annotation to Grease Pencil Object and link it in the active Scene.
|
- Converts active annotation to Grease Pencil Object and link it in the active Scene.
|
||||||
![drawing](/media/addons/grease_converter/convert_to_grease_pencil.jpg)
|
![drawing](docs_media/convert_to_grease_pencil.jpg)
|
||||||
|
|
||||||
|
|
||||||
- **grease_converter.convert_to_annotation**:
|
- **grease_converter.convert_to_annotation**:
|
||||||
- Located in the 3DView Header -> Object -> Convert
|
- Located in the 3DView Header -> Object -> Convert
|
||||||
- Active objects needs to be grease pencil object. Will convert it to Annotation Grease Pencil Object. Uses Tint Color and Stroke Thickness attribute found in the Adjustments Panel for final annotation color and stroke thickness. (Annotations are a simple version of GreasePencil and only support **one* color and stoke thickness per layer)
|
- Active objects needs to be grease pencil object. Will convert it to Annotation Grease Pencil Object. Uses Tint Color and Stroke Thickness attribute found in the Adjustments Panel for final annotation color and stroke thickness. (Annotations are a simple version of GreasePencil and only support **one* color and stoke thickness per layer)
|
||||||
|
|
||||||
![drawing](/media/addons/grease_converter/adjustments_panel.jpg)
|
![drawing](docs_media/adjustments_panel.jpg)
|
||||||
- >**Note**: If the grease pencil object has it's transforms not applied or a parent you will be prompted with a warning as these are not taken in to account yet
|
- >**Note**: If the grease pencil object has it's transforms not applied or a parent you will be prompted with a warning as these are not taken in to account yet
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Lattice Magic
|
# Lattice Magic
|
||||||
This addon adds some Lattice-based utilities to Blender.
|
This addon adds some Lattice-based utilities to Blender.
|
||||||
|
|
||||||
![Lattice Magic UI](/media/addons/lattice_magic/lattice_magic.png)
|
![Lattice Magic UI](docs_media/lattice_magic.png)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ This addon adds some Lattice-based utilities to Blender.
|
|||||||
## Tweak Lattice
|
## Tweak Lattice
|
||||||
Tweak Lattice lets you create a lattice setup at the 3D cursor to make deformation adjustments to the selected objects.
|
Tweak Lattice lets you create a lattice setup at the 3D cursor to make deformation adjustments to the selected objects.
|
||||||
|
|
||||||
![How to Tweak Lattice](/media/addons/lattice_magic/tweak_lattice.mp4)
|
[VIDEO: How to Tweak Lattice](docs_media/tweak_lattice.mp4)
|
||||||
|
|
||||||
### Parenting
|
### Parenting
|
||||||
This is meant to be possible to be used in conjunction with a character rig: Before pressing the "Create Tweak Lattice" button, simply select the desired parent rig object and bone in the UI.
|
This is meant to be possible to be used in conjunction with a character rig: Before pressing the "Create Tweak Lattice" button, simply select the desired parent rig object and bone in the UI.
|
||||||
@ -47,7 +47,7 @@ With the lattice control selected, you can see a "Helper Objects" section in the
|
|||||||
## Camera Lattice
|
## Camera Lattice
|
||||||
Camera Lattice lets you create a lattice in a camera's view frame and deform a character (or any collection) with the lattice.
|
Camera Lattice lets you create a lattice in a camera's view frame and deform a character (or any collection) with the lattice.
|
||||||
|
|
||||||
![Camera Lattice Demo](/media/addons/lattice_magic/camera_lattice.mp4)
|
[VIDEO: Camera Lattice Demo](docs_media/camera_lattice.mp4)
|
||||||
|
|
||||||
### Creation
|
### Creation
|
||||||
Add an entry to the Camera Lattice list with the + icon. Each entry corresponds to deforming a single collection with a single lattice object from the perspective of a single camera.
|
Add an entry to the Camera Lattice list with the + icon. Each entry corresponds to deforming a single collection with a single lattice object from the perspective of a single camera.
|
||||||
|
@ -71,7 +71,7 @@ If the addon has been used to manage the settings, the JSON setting data-blocks
|
|||||||
|
|
||||||
Whether the JSON data is stored as an external file or packed in the blend file is displayed with an icon:
|
Whether the JSON data is stored as an external file or packed in the blend file is displayed with an icon:
|
||||||
|
|
||||||
![json icons](/media/addons/lighting_overrider/json_icon_example.png)
|
![json icons](docs_media/json_icon_example.png)
|
||||||
|
|
||||||
#### Specifiers
|
#### Specifiers
|
||||||
|
|
||||||
@ -82,14 +82,14 @@ The specifier can either refer to a single item by specifying its name or it can
|
|||||||
E.g.: `HLP-sprite_settings` refers only to the one sprite character whose settings object has this name, while `HLP-sprite_settings:all` refers to all sprite characters in the file. `HLP-:all` even refers to all helper objects in general.
|
E.g.: `HLP-sprite_settings` refers only to the one sprite character whose settings object has this name, while `HLP-sprite_settings:all` refers to all sprite characters in the file. `HLP-:all` even refers to all helper objects in general.
|
||||||
|
|
||||||
Settings marked with the `:all` suffix are displayed with the world icon when this functionality is available for the category.
|
Settings marked with the `:all` suffix are displayed with the world icon when this functionality is available for the category.
|
||||||
![suffixes](/media/addons/lighting_overrider/lighting_override_suffixes.png)
|
![suffixes](docs_media/lighting_override_suffixes.png)
|
||||||
|
|
||||||
#### Override Picker
|
#### Override Picker
|
||||||
|
|
||||||
Based on the Override Master addon by Andy and Sybren, the Lighting Overrider addon adds the functionality to override any given property (names excluded) on the fly to the `O` hotkey.
|
Based on the Override Master addon by Andy and Sybren, the Lighting Overrider addon adds the functionality to override any given property (names excluded) on the fly to the `O` hotkey.
|
||||||
|
|
||||||
This automatically adds an entry to the RNA overrides and is added to the settings that run on file-load.
|
This automatically adds an entry to the RNA overrides and is added to the settings that run on file-load.
|
||||||
![rna ovrrides](/media/addons/lighting_overrider/rna_override.png)
|
![rna ovrrides](docs_media/rna_override.png)
|
||||||
|
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
@ -1,71 +1,26 @@
|
|||||||
Pipeline release is a script to package addons in the pipeline repo.
|
Blender Add-ons can be packaged directly from the [Blender Studio Pipeline](https://projects.blender.org/studio/blender-studio-pipeline) repository. Personal Add-Ons can be installed [normally](https://docs.blender.org/manual/en/latest/editors/preferences/addons.html#installing-add-ons).
|
||||||
|
|
||||||
# Features
|
1. Enter Directory
|
||||||
- Automatically Find Commits since last version for each addon in `scripts-blender/addons/`
|
|
||||||
- Appends changelog to existing `CHANGELOG.md` per addon
|
|
||||||
- Bump Version on `__init__.py` file
|
|
||||||
- Commits `__init__.py` and `CHANGELOG.md` to current branch (user must manually push changes)
|
|
||||||
- Creates Archive with Checksum in `dist` folder
|
|
||||||
|
|
||||||
## Prerequisite
|
```bash
|
||||||
In order to use this tool you need:
|
cd ~/data/blender-studio-pipeline/scripts/pipeline-release # Linux/Mac
|
||||||
- GIT
|
|
||||||
- Python 3.11+
|
|
||||||
- [Requests Module](https://requests.readthedocs.io/en/latest/)
|
|
||||||
|
|
||||||
## Generate Token
|
|
||||||
A Gitea API token is required to generate a pipeline release.
|
|
||||||
1. Navigate to https://projects.blender.org/user/settings/applications while logged in
|
|
||||||
2. Under Select Permissions, Set `repository` and `package` scopes to "Read & Write"
|
|
||||||
3. Save the provided API key in the root of the pipeline-release directory with the name `api_token.env`
|
|
||||||
|
|
||||||
## Run
|
|
||||||
This folder contains a command line tool that doesn't require installation to use properly. To run `pipeline_release` without installation follow the steps below.
|
|
||||||
1. Clone this repository with `git clone https://projects.blender.org/studio/blender-studio-pipeline.git`
|
|
||||||
2. Run `cd blender-studio-pipeline/scripts/pipeline_release` to enter directory
|
|
||||||
3. Run program with `python -m pipeline_release`
|
|
||||||
|
|
||||||
## How to get started
|
|
||||||
|
|
||||||
| Command | Description |
|
|
||||||
| ----------- | ----------- |
|
|
||||||
| -m, --major|Bump the major version number, otherwise bump minor version|
|
|
||||||
| -n --name| Name of addon(s) folder to update. All addons will be checked if flag is not provided|
|
|
||||||
| -c --commit| Title of commit to consider basis of latest release, otherwise the last commit called 'Version Bump:' will be used|
|
|
||||||
| -f --force|Bump version even if no commits are found|
|
|
||||||
| -t, --test |Test release system by only running locally and skip committing|
|
|
||||||
| -h, --help| show the above help message and exit|
|
|
||||||
|
|
||||||
|
|
||||||
## Changelog Conventions
|
|
||||||
|Changelog Title| Commit Prefix|
|
|
||||||
| ----------- | ----------- |
|
|
||||||
|ADD |add|
|
|
||||||
|BUG FIX |fix|
|
|
||||||
|CHANGED |change|
|
|
||||||
|REMOVED |remove|
|
|
||||||
|MERGED |merge|
|
|
||||||
|DOCUMENTED|doc|
|
|
||||||
|BREAKING|breaking|
|
|
||||||
|
|
||||||
|
|
||||||
This tool will automatically generate changelog messages based on the "changelog categories" below. Commit's subject line convention is `{Name of Addon}: {category} commit content` for example:
|
|
||||||
### Commit Subject Line:
|
|
||||||
```
|
```
|
||||||
Blender Kitsu: Fix naming conventions
|
```bash
|
||||||
````
|
cd %HOMEPATH%\data\blender-studio-pipeline\scripts\pipeline-release # Windows
|
||||||
|
|
||||||
### Changelog Output:
|
|
||||||
```
|
|
||||||
### Fixes
|
|
||||||
- Fix naming conventions
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example Usage
|
2. Update Git
|
||||||
| Action | Command |
|
```bash
|
||||||
| ----------- | ----------- |
|
# Windows & Linux/Mac
|
||||||
|Create a new minor version if available of all addons|`python -m pipeline_release`|
|
git checkout main # Checkout main branch
|
||||||
|Create a new major version if available of all addons|`python -m pipeline_release -m`|
|
git reset --hard # Remove any changes stored in your branch
|
||||||
|Create a new version even no new commits are found|`python -m pipeline_release` -f|
|
git pull --rebase origin # Pull to update to latest commit
|
||||||
|Only check if addon has this name(s) |`python -m pipeline_release -n "blender_kitsu, blender_svn"`|
|
```
|
||||||
|Find a commit that matches this message and uses as version basis otherwise the last commit called 'Version Bump:' will be used |`python -m pipeline_release -c "Commit MSG"`|
|
|
||||||
|
3. Run Package Local Script
|
||||||
|
```bash
|
||||||
|
./package_local.py ~/data/your_project_name/shared/artifacts/addons # Linux/Mac
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
python package_local.py %HOMEPATH%\data\your_project_name\shared\artifacts\addons # Windows
|
||||||
|
```
|
@ -1,21 +0,0 @@
|
|||||||
# Blender Add-ons
|
|
||||||
|
|
||||||
Add-ons used by the Blender Studio pipeline. Download the latest addons releases from the table below. To review or report issues visit the [Blender-Studio-Pipeline](https://projects.blender.org/studio/blender-studio-pipeline/issues) issues board.
|
|
||||||
|
|
||||||
|
|
||||||
| Add-on | Description | Latest Version | Checksum |
|
|
||||||
|---|---|---|---|
|
|
||||||
|[Anim Cupboard](../addons/anim_cupboard) |Miscellaneous tools for animators. |[↓ v0.0.6](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/anim_cupboard-0.0.6.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/anim_cupboard-0.0.6.sha256)|
|
|
||||||
|[Asset Pipeline](../addons/asset_pipeline ) |Manages the Asset Pipeline, used by Modeling, Shading and Rigging departments. |[↓ v0.2.1](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/asset_pipeline-0.2.1.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/asset_pipeline-0.2.1.sha256)|
|
|
||||||
|[Blender Kitsu](../addons/blender_kitsu )|Enforce conventions, build shots, manage production files and update data on kitsu server. |[↓ v0.1.6](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.4/blender_kitsu-0.1.6.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.4/blender_kitsu-0.1.6.sha256)|
|
|
||||||
|[Blender SVN](../addons/blender_svn ) |UI for the SVN (Subversion) file versioning system. |[↓ v1.0.3](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/blender_svn-1.0.3.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/blender_svn-1.0.3.sha256)|
|
|
||||||
|[Blender Gizmos](../addons/bone_gizmos )|Attempt to prototype a system for using meshes for the manipulation of armatures. |[↓ v0.0.3](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/bone_gizmos-0.0.3.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/bone_gizmos-0.0.3.sha256)|
|
|
||||||
|[Cache Manager](../addons/cache_manager ) |Streamline the Alembic cache workflow of assets. |[↓ v0.1.2](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/cache_manager-0.1.2.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/cache_manager-0.1.2.sha256)|
|
|
||||||
|[Contact Sheet](../addons/contactsheet ) |Create a contactsheet from sequence editor strips. |[↓ v0.1.2](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/contactsheet-0.1.2.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/contactsheet-0.1.2.sha256)|
|
|
||||||
|[Easy Weights](../addons/easy_weights ) |Quality of life improvements for weight painting. |[↓ v0.1.4](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.2/easy_weights-0.1.4.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.2/easy_weights-0.1.4.sha256)|
|
|
||||||
|[Geonode Shapekeys](../addons/geonode_shapekeys ) |Enable animators to sculpt on linked and overridden meshes. |[↓ v0.0.5](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/geonode_shapekeys-0.0.5.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/geonode_shapekeys-0.0.5.sha256)|
|
|
||||||
|[Grease Converter](../addons/grease_converter ) |Convert annotations to Grease Pencil objects and vise versa. |[↓ v0.1.2](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/grease_converter-0.1.2.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.1/grease_converter-0.1.2.sha256)|
|
|
||||||
|[Lattice Magic](../addons/lattice_magic ) |Lattice-based utilities. |[↓ v0.1.3](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/lattice_magic-0.1.3.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/lattice_magic-0.1.3.sha256)|
|
|
||||||
|[Lighting Overrider](../addons/lighting_overrider ) |Create, manage and apply python overrides in a flexible and reliable way. |[↓ v0.1.3](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/lighting_overrider-0.1.3.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/lighting_overrider-0.1.3.sha256)|
|
|
||||||
|[Pose Shape Keys](../addons/pose_shape_keys )|Manage and maintain shapekeys for rigging. |[↓ v0.0.4](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/pose_shape_keys-0.0.4.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/pose_shape_keys-0.0.4.sha256)|
|
|
||||||
|[Render Review](../addons/render_review ) |Review renders from Flamenco with the sequence editor. |[↓ v0.1.4](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/render_review-0.1.4.zip) |[↓ SHA256](https://projects.blender.org/studio/blender-studio-pipeline/releases/download/0.0.3/render_review-0.1.4.sha256)|
|
|
@ -1,21 +0,0 @@
|
|||||||
# Blender Add-ons
|
|
||||||
|
|
||||||
Add-ons used by the Blender Studio pipeline. Download the latest addons releases from the table below. To review or report issues visit the [Blender-Studio-Pipeline](https://projects.blender.org/studio/blender-studio-pipeline/issues) issues board.
|
|
||||||
|
|
||||||
|
|
||||||
| Add-on | Description | Latest Version | Checksum |
|
|
||||||
|---|---|---|---|
|
|
||||||
|[Anim Cupboard](../addons/anim_cupboard) |Miscellaneous tools for animators. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Asset Pipeline](../addons/asset_pipeline ) |Manages the Asset Pipeline, used by Modeling, Shading and Rigging departments. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Blender Kitsu](../addons/blender_kitsu )|Enforce conventions, build shots, manage production files and update data on kitsu server. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Blender SVN](../addons/blender_svn ) |UI for the SVN (Subversion) file versioning system. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Blender Gizmos](../addons/bone_gizmos )|Attempt to prototype a system for using meshes for the manipulation of armatures. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Cache Manager](../addons/cache_manager ) |Streamline the Alembic cache workflow of assets. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Contact Sheet](../addons/contactsheet ) |Create a contactsheet from sequence editor strips. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Easy Weights](../addons/easy_weights ) |Quality of life improvements for weight painting. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Geonode Shapekeys](../addons/geonode_shapekeys ) |Enable animators to sculpt on linked and overridden meshes. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Grease Converter](../addons/grease_converter ) |Convert annotations to Grease Pencil objects and vise versa. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Lattice Magic](../addons/lattice_magic ) |Lattice-based utilities. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Lighting Overrider](../addons/lighting_overrider ) |Create, manage and apply python overrides in a flexible and reliable way. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Pose Shape Keys](../addons/pose_shape_keys )|Manage and maintain shapekeys for rigging. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
||||||
|[Render Review](../addons/render_review ) |Review renders from Flamenco with the sequence editor. |[↓ v<VERSION>](<ZIP_URL>) |[↓ SHA256](<CHECKSUM_URL>)|
|
|
58
scripts/pipeline-release/package_release.py
Executable file
58
scripts/pipeline-release/package_release.py
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
import hashlib
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
name = "blender_studio_pipeline_release"
|
||||||
|
zipped_release, checksum_file = get_pipeline_release(name)
|
||||||
|
# TODO Upload zipped release to blender studio pipeline website
|
||||||
|
|
||||||
|
|
||||||
|
def get_pipeline_release(name: str):
|
||||||
|
temp_dir = Path(tempfile.mkdtemp(prefix=name + "_"))
|
||||||
|
output_dir = Path(temp_dir).joinpath(name)
|
||||||
|
output_dir.mkdir()
|
||||||
|
|
||||||
|
cmd_list = ("./package_local.py", str(output_dir))
|
||||||
|
process = subprocess.Popen(cmd_list, shell=False)
|
||||||
|
if process.wait() != 0:
|
||||||
|
print("Add-On Package Locally Failed!")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
zipped_release = shutil.make_archive(
|
||||||
|
temp_dir.joinpath(name),
|
||||||
|
'zip',
|
||||||
|
temp_dir,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
checksum = generate_checksum(zipped_release)
|
||||||
|
chechsum_name = name + ".zip.sha256"
|
||||||
|
checksum_path = temp_dir / chechsum_name
|
||||||
|
checksum_file = write_file(
|
||||||
|
checksum_path,
|
||||||
|
f"{checksum} {name}.zip",
|
||||||
|
)
|
||||||
|
return zipped_release, checksum_file
|
||||||
|
|
||||||
|
|
||||||
|
def write_file(file_path, content):
|
||||||
|
file = open(file_path, 'w')
|
||||||
|
file.writelines(content)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
|
||||||
|
def generate_checksum(archive_path):
|
||||||
|
with open(archive_path, 'rb') as file:
|
||||||
|
digest = hashlib.file_digest(file, "sha256")
|
||||||
|
return digest.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -1,583 +0,0 @@
|
|||||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
#
|
|
||||||
# ***** END GPL LICENCE BLOCK *****
|
|
||||||
#
|
|
||||||
# (c) 2021, Blender Foundation
|
|
||||||
|
|
||||||
import zipfile
|
|
||||||
import hashlib
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List
|
|
||||||
import shutil
|
|
||||||
import argparse
|
|
||||||
import re
|
|
||||||
from typing import Pattern
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
REPO_ROOT_DIR = Path(__file__).parent.parent.parent
|
|
||||||
# BORROWED FROM https://github.com/pawamoy/git-changelog/blob/master/src/git_changelog/commit.py
|
|
||||||
TYPES: dict[str, str] = {
|
|
||||||
"add": "Added",
|
|
||||||
"fix": "Fixed",
|
|
||||||
"change": "Changed",
|
|
||||||
"remove": "Removed",
|
|
||||||
"merge": "Merged",
|
|
||||||
"doc": "Documented",
|
|
||||||
"breaking": "Breaking",
|
|
||||||
}
|
|
||||||
|
|
||||||
# GITEA LOGIN SETTINGS
|
|
||||||
api_token_file = Path(__file__).parent.joinpath("api_token.env")
|
|
||||||
if not api_token_file.exists():
|
|
||||||
print("API Token File not Found")
|
|
||||||
api_token = open(api_token_file, 'r').read()
|
|
||||||
base_url = 'https://projects.blender.org'
|
|
||||||
api_path = f"{base_url}/api/v1"
|
|
||||||
repo_path = '/studio/blender-studio-pipeline'
|
|
||||||
release_path = f'/repos{repo_path}/releases'
|
|
||||||
tag_path = f'/repos{repo_path}/tags'
|
|
||||||
|
|
||||||
|
|
||||||
def parse_commit(commit_message: str) -> dict[str, str]:
|
|
||||||
"""
|
|
||||||
Parse the type of the commit given its subject.
|
|
||||||
Arguments:
|
|
||||||
commit_subject: The commit message subject.
|
|
||||||
Returns:
|
|
||||||
Dict containing commit message and type
|
|
||||||
"""
|
|
||||||
type = ""
|
|
||||||
# Split at first colon to remove prefix from commit
|
|
||||||
if ": " in commit_message:
|
|
||||||
message_body = commit_message.split(': ')[1]
|
|
||||||
else:
|
|
||||||
message_body = commit_message
|
|
||||||
type_regex: Pattern = re.compile(r"^(?P<type>(%s))" % "|".join(TYPES.keys()), re.I)
|
|
||||||
breaking_regex: Pattern = re.compile(
|
|
||||||
r"^break(s|ing changes?)?[ :].+$",
|
|
||||||
re.I | re.MULTILINE,
|
|
||||||
)
|
|
||||||
|
|
||||||
type_match = type_regex.match(message_body)
|
|
||||||
if type_match:
|
|
||||||
type = TYPES.get(type_match.groupdict()["type"].lower(), "")
|
|
||||||
if bool(breaking_regex.search(message_body)):
|
|
||||||
type = "Breaking"
|
|
||||||
return {
|
|
||||||
"message": message_body,
|
|
||||||
"type": type,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"-c",
|
|
||||||
"--commit",
|
|
||||||
help="Find commit with this message and use it as the last version.",
|
|
||||||
type=str,
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-n",
|
|
||||||
"--name",
|
|
||||||
help="Only update the addon corrisponding to this name(s).",
|
|
||||||
type=str,
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-o",
|
|
||||||
"--output",
|
|
||||||
help="Provide a string for the output path of generated zips",
|
|
||||||
type=str,
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-m",
|
|
||||||
"--major",
|
|
||||||
help="Bump the major version number, otherwise bump minor version number",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-t",
|
|
||||||
"--test",
|
|
||||||
help="Test release system by only running locally and skip committing/uploading to release",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-r",
|
|
||||||
"--reuse_lastest_release",
|
|
||||||
help="Add new packages to the lastest avaliable release",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-f",
|
|
||||||
"--force",
|
|
||||||
help="Bump version even if no commits are found",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def cli_command(command: str) -> subprocess:
|
|
||||||
"""Run command in CLI and capture it's output
|
|
||||||
Arguments:
|
|
||||||
command: String of command to run in CLI.
|
|
||||||
"""
|
|
||||||
output = subprocess.run(command.split(' '), capture_output=True, encoding="utf-8")
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
def exit_program(message: str):
|
|
||||||
print(message)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
def write_file(file_path: Path, content):
|
|
||||||
file = open(file_path, 'w')
|
|
||||||
file.writelines(content)
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
|
|
||||||
def replace_line(file_path: Path, new_line: str, line_number: int):
|
|
||||||
file = open(
|
|
||||||
file_path,
|
|
||||||
)
|
|
||||||
lines = file.readlines()
|
|
||||||
lines[line_number] = new_line
|
|
||||||
out = open(file_path, 'w')
|
|
||||||
out.writelines(lines)
|
|
||||||
out.close()
|
|
||||||
|
|
||||||
|
|
||||||
def get_directory(repo_root: Path, folder_name: str) -> Path:
|
|
||||||
"""Returns directory PATH, creates one if none exists"""
|
|
||||||
path = repo_root.joinpath(folder_name)
|
|
||||||
if not os.path.exists(path):
|
|
||||||
os.makedirs(path)
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def clean_str(string: str) -> str:
|
|
||||||
"""Returns string with qoutes and line breaks removed"""
|
|
||||||
return string.replace('\n', '').replace("'", "").replace('"', '')
|
|
||||||
|
|
||||||
|
|
||||||
def generate_checksum(archive_path: str) -> str:
|
|
||||||
"""
|
|
||||||
Generate a checksum for a zip file
|
|
||||||
Arguments:
|
|
||||||
archive_path: String of the archive's file path
|
|
||||||
Returns:
|
|
||||||
sha256 checksum for the provided archive as string
|
|
||||||
"""
|
|
||||||
sha256 = hashlib.sha256()
|
|
||||||
with open(archive_path, 'rb') as file:
|
|
||||||
# Read the file in chunks to handle large files efficiently
|
|
||||||
chunk = file.read(4096)
|
|
||||||
while len(chunk) > 0:
|
|
||||||
sha256.update(chunk)
|
|
||||||
chunk = file.read(4096)
|
|
||||||
return sha256.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
def changelog_category_get(changelog_messages: dict[str, str], title: str, key: str):
|
|
||||||
"""
|
|
||||||
Generate changelog messages for a specific category.
|
|
||||||
Types are defined in global variable 'TYPES'
|
|
||||||
Arguments:
|
|
||||||
changelog_messages: dict contaning commit message & type
|
|
||||||
title: Title of the changelog category
|
|
||||||
key: Key for category/type as defined in global variable TYPES
|
|
||||||
Returns:
|
|
||||||
changelog entry for the given category/type as a string
|
|
||||||
"""
|
|
||||||
entry = ''
|
|
||||||
if not any(commit for commit in changelog_messages if commit["type"] == key):
|
|
||||||
return entry
|
|
||||||
entry += f"### {title} \n"
|
|
||||||
for commit in changelog_messages:
|
|
||||||
if commit["type"] == key:
|
|
||||||
entry += f'- {commit["message"]}'
|
|
||||||
entry += "\n"
|
|
||||||
return entry
|
|
||||||
|
|
||||||
|
|
||||||
def changelog_generate(commit_hashes: list[str], version: str) -> str:
|
|
||||||
"""
|
|
||||||
Generate Changelog Entries from a list of commits hashes
|
|
||||||
Arguments:
|
|
||||||
commit_hashes: A list of commit hashes to include in Changelog
|
|
||||||
version: Latest addon version number
|
|
||||||
Returns:
|
|
||||||
complete changelog for latest version as string
|
|
||||||
"""
|
|
||||||
|
|
||||||
log_entry = f'## {version} - {datetime.date.today()} \n \n'
|
|
||||||
changelog_messages = []
|
|
||||||
if commit_hashes is not None:
|
|
||||||
for commit in commit_hashes:
|
|
||||||
message = (
|
|
||||||
f"{cli_command(f'git log --pretty=format:%s -n 1 {commit}').stdout}\n"
|
|
||||||
)
|
|
||||||
changelog_messages.append(parse_commit(message))
|
|
||||||
|
|
||||||
for type in TYPES:
|
|
||||||
log_entry += changelog_category_get(
|
|
||||||
changelog_messages, TYPES.get(type).upper(), TYPES.get(type)
|
|
||||||
)
|
|
||||||
|
|
||||||
log_entry += "### UN-CATEGORIZED \n"
|
|
||||||
for commit in changelog_messages:
|
|
||||||
if commit["message"] not in log_entry:
|
|
||||||
log_entry += f"- {commit['message']}"
|
|
||||||
log_entry += "\n"
|
|
||||||
return log_entry
|
|
||||||
|
|
||||||
|
|
||||||
def changelog_commits_get(directory: Path, commit_message: str) -> list[str]:
|
|
||||||
"""
|
|
||||||
Get list of commit hashes, that affect a given directory
|
|
||||||
Arguments:
|
|
||||||
directory: Name of directory/folder to filter commits
|
|
||||||
commit_message: Prefix of commit to use as base for latest release
|
|
||||||
Returns:
|
|
||||||
list of commit hashes
|
|
||||||
"""
|
|
||||||
last_version_commit = None
|
|
||||||
commits_in_folder = cli_command(
|
|
||||||
f'git log --format=format:"%H" {directory}/*'
|
|
||||||
).stdout.split('\n')
|
|
||||||
# Find Last Version
|
|
||||||
for commit in commits_in_folder:
|
|
||||||
commit = clean_str(commit)
|
|
||||||
commit_msg = cli_command(f'git log --format=%B -n 1 {commit}')
|
|
||||||
if commit_message in commit_msg.stdout:
|
|
||||||
last_version_commit = commit
|
|
||||||
if last_version_commit is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
commits_since_release = cli_command(
|
|
||||||
f'git rev-list {clean_str(last_version_commit)[0:9]}..HEAD'
|
|
||||||
).stdout.split('\n')
|
|
||||||
commit_hashes = []
|
|
||||||
|
|
||||||
for commit in commits_in_folder:
|
|
||||||
if any(clean_str(commit) in x for x in commits_since_release):
|
|
||||||
commit_hashes.append(clean_str(commit))
|
|
||||||
return commit_hashes
|
|
||||||
|
|
||||||
|
|
||||||
def changelog_file_write(file_path: Path, content: str):
|
|
||||||
"""
|
|
||||||
Append changelog to existing changelog file or create a new
|
|
||||||
changelog file if none exists
|
|
||||||
Arguments:
|
|
||||||
file_path: PATH to changelog
|
|
||||||
content: changelog for latest version as string
|
|
||||||
"""
|
|
||||||
if file_path.exists():
|
|
||||||
dummy_file = str(file_path._str) + '.bak'
|
|
||||||
with open(file_path, 'r') as read_obj, open(dummy_file, 'w') as write_obj:
|
|
||||||
write_obj.write(content)
|
|
||||||
for line in read_obj:
|
|
||||||
write_obj.write(line)
|
|
||||||
os.remove(file_path)
|
|
||||||
os.rename(dummy_file, file_path)
|
|
||||||
else:
|
|
||||||
write_file(file_path, content)
|
|
||||||
return file_path
|
|
||||||
|
|
||||||
|
|
||||||
def update_release_table(addon_dir: Path, version: str, release_version: str):
|
|
||||||
directory = Path(__file__).parent
|
|
||||||
template_file = directory.joinpath("overview.md.template")
|
|
||||||
table_file = directory.joinpath("overview.md")
|
|
||||||
with open(template_file, 'r') as readme_template:
|
|
||||||
for num, line in enumerate(readme_template):
|
|
||||||
if addon_dir.name in line:
|
|
||||||
line_to_replace = num
|
|
||||||
break # Use first line found
|
|
||||||
line = line.replace("<VERSION>", f"{version}")
|
|
||||||
line = line.replace(
|
|
||||||
"<ZIP_URL>",
|
|
||||||
f"{base_url}{repo_path}/releases/download/{release_version}/{addon_dir.name}-{version}.zip",
|
|
||||||
)
|
|
||||||
new_line = line.replace(
|
|
||||||
"<CHECKSUM_URL>",
|
|
||||||
f"{base_url}{repo_path}/releases/download/{release_version}/{addon_dir.name}-{version}.sha256",
|
|
||||||
)
|
|
||||||
replace_line(table_file, new_line, line_to_replace)
|
|
||||||
return table_file
|
|
||||||
|
|
||||||
|
|
||||||
def addon_package(
|
|
||||||
directory: Path,
|
|
||||||
commit_prefix: str,
|
|
||||||
is_major=False,
|
|
||||||
force=False,
|
|
||||||
test=False,
|
|
||||||
output_path=None,
|
|
||||||
to_upload=[],
|
|
||||||
release_version="",
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
For a give directory, if new commits are found after the commit matching 'commit_prefix',
|
|
||||||
bump addon version, generate a changelog, commit changes and package addon into an archive.
|
|
||||||
Print statements indicate if addon was version bumped, or if new version was found.
|
|
||||||
Arguments:
|
|
||||||
directory: Name of directory/folder to filter commits
|
|
||||||
commit_prefix: Prefix of commit to use as base for latest release
|
|
||||||
is_major: if major 2nd digit in version is updated, else 3rd digit
|
|
||||||
"""
|
|
||||||
commit_msg = 'Version Bump:' if commit_prefix is None else commit_prefix
|
|
||||||
commits_in_folder = changelog_commits_get(directory, commit_msg)
|
|
||||||
dist_dir = get_directory(REPO_ROOT_DIR, "dist")
|
|
||||||
|
|
||||||
if commits_in_folder or force:
|
|
||||||
init_file, version = addon_version_bump(directory, is_major)
|
|
||||||
change_log = changelog_generate(commits_in_folder, version)
|
|
||||||
table_file = update_release_table(directory, version, release_version)
|
|
||||||
change_log_file = changelog_file_write(
|
|
||||||
directory.joinpath("CHANGELOG.md"), change_log
|
|
||||||
)
|
|
||||||
if not test:
|
|
||||||
cli_command(f'git reset')
|
|
||||||
cli_command(f'git stage {change_log_file}')
|
|
||||||
cli_command(f'git stage {init_file}')
|
|
||||||
cli_command(f'git stage {table_file}')
|
|
||||||
subprocess.run(
|
|
||||||
['git', 'commit', '-m', f"Version Bump: {directory.name} {version}"],
|
|
||||||
capture_output=True,
|
|
||||||
encoding="utf-8",
|
|
||||||
)
|
|
||||||
print(f"Version Bump: {directory.name} {version}")
|
|
||||||
name = directory.name
|
|
||||||
if output_path is None:
|
|
||||||
addon_output_dir = get_directory(dist_dir, directory.name)
|
|
||||||
else:
|
|
||||||
addon_output_dir = get_directory(Path(output_path), directory.name)
|
|
||||||
|
|
||||||
zipped_addon = shutil.make_archive(
|
|
||||||
addon_output_dir.joinpath(f"{name}-{version}"),
|
|
||||||
'zip',
|
|
||||||
directory.parent,
|
|
||||||
directory.name,
|
|
||||||
)
|
|
||||||
checksum = generate_checksum(zipped_addon)
|
|
||||||
checksum_path = addon_output_dir.joinpath(f"{name}-{version}.sha256")
|
|
||||||
checksum_file = write_file(
|
|
||||||
checksum_path,
|
|
||||||
f"{checksum} {name}-{version}.zip",
|
|
||||||
)
|
|
||||||
to_upload.append(zipped_addon)
|
|
||||||
to_upload.append(checksum_path._str)
|
|
||||||
else:
|
|
||||||
print(f"No New Version: {directory.name}")
|
|
||||||
|
|
||||||
|
|
||||||
def addon_version_set(version_line: str, is_major: bool) -> str:
|
|
||||||
"""
|
|
||||||
Read bl_info within addon's __init__.py file to get new version number
|
|
||||||
Arguments:
|
|
||||||
version_line: Line of bl_info containing version number
|
|
||||||
is_major: if major 2nd digit in version is updated, else 3rd digit
|
|
||||||
Returns
|
|
||||||
Latest addon version number
|
|
||||||
"""
|
|
||||||
version = version_line.split('(')[1].split(')')[0]
|
|
||||||
# Bump either last digit for minor versions and second last digit for major
|
|
||||||
if is_major:
|
|
||||||
new_version = version[:-4] + str(int(version[3]) + 1) + version[-3:]
|
|
||||||
else:
|
|
||||||
new_version = version[:-1] + str(int(version[-1]) + 1)
|
|
||||||
return new_version
|
|
||||||
|
|
||||||
|
|
||||||
def addon_version_bump(directory: Path, is_major: bool):
|
|
||||||
"""
|
|
||||||
Update bl_info within addon's __init__.py file to indicate
|
|
||||||
version bump. Expects line to read as '"version": (n, n, n),\n'
|
|
||||||
Arguments:
|
|
||||||
directory: Name of directory/folder containing addon
|
|
||||||
is_major: if major 2nd digit in version is updated, else 3rd digit
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
init_file: PATH to init file that has been updated with new version
|
|
||||||
version: Latest addon version number
|
|
||||||
"""
|
|
||||||
|
|
||||||
version_line = None
|
|
||||||
str_find = "version"
|
|
||||||
init_file = directory.joinpath("__init__.py")
|
|
||||||
with open(init_file, 'r') as myFile:
|
|
||||||
for num, line in enumerate(myFile):
|
|
||||||
if str_find in line and "(" in line and line[0] != "#":
|
|
||||||
version_line = num
|
|
||||||
break # Use first line found
|
|
||||||
|
|
||||||
file = open(
|
|
||||||
init_file,
|
|
||||||
)
|
|
||||||
lines = file.readlines()
|
|
||||||
version = addon_version_set(lines[version_line], is_major)
|
|
||||||
repl_str = f' "version": ({version}),\n'
|
|
||||||
replace_line(init_file, repl_str, version_line)
|
|
||||||
return init_file, version.replace(', ', '.').replace(',', '.')
|
|
||||||
|
|
||||||
|
|
||||||
### GITEA UPLOAD RELEASE
|
|
||||||
import requests # TODO ADD PRINT STATEMENT IF UNABLE TO IMPORT
|
|
||||||
import json
|
|
||||||
|
|
||||||
"""
|
|
||||||
API token must be created under user>settings>application
|
|
||||||
- Use browser to 'INSPECT' the Generate Token button
|
|
||||||
- Find the property 'GTHidden Display' and remove the element of 'None' to nothing
|
|
||||||
- Then Set the correct scope for the key using the new dropdown menu before creating tag
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def upload_file_to_release(url, api_token, release_id, file):
|
|
||||||
file_name = Path(file.name).name
|
|
||||||
file_content = [
|
|
||||||
('attachment', (file_name, file, 'application/zip')),
|
|
||||||
]
|
|
||||||
response = requests.post(
|
|
||||||
url=f"{url}/{release_id}/assets?name={file_name}&token={api_token}",
|
|
||||||
files=file_content,
|
|
||||||
)
|
|
||||||
if not response.status_code == 201:
|
|
||||||
print(f"{file_name} failed to upload")
|
|
||||||
else:
|
|
||||||
print(f"Uploaded {file_name}")
|
|
||||||
|
|
||||||
|
|
||||||
def send_post_request(url, api_token, data):
|
|
||||||
header_cont = {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
}
|
|
||||||
response = requests.post(
|
|
||||||
url=f"{url}?token={api_token}",
|
|
||||||
headers=header_cont,
|
|
||||||
data=json.dumps(data),
|
|
||||||
)
|
|
||||||
response_json = response.json()
|
|
||||||
if response.status_code != 201:
|
|
||||||
print(response_json["message"])
|
|
||||||
return response_json
|
|
||||||
|
|
||||||
|
|
||||||
def create_new_release(tag_url, base_release_url, release_version, api_token):
|
|
||||||
release_description = "Latest Release of Blender Studio Pipeline"
|
|
||||||
# Create New Tag
|
|
||||||
tag_content = {
|
|
||||||
"message": f"{release_description}",
|
|
||||||
"tag_name": f"{release_version}",
|
|
||||||
"target": f"main",
|
|
||||||
}
|
|
||||||
|
|
||||||
send_post_request(tag_url, api_token, tag_content)
|
|
||||||
|
|
||||||
# Create New Release
|
|
||||||
release_content = {
|
|
||||||
"body": f"{release_description}",
|
|
||||||
"draft": False,
|
|
||||||
"name": f"Pipeline Release {release_version}",
|
|
||||||
"prerelease": False,
|
|
||||||
"tag_name": f"{release_version}",
|
|
||||||
"target_commitish": "string", # will default to latest
|
|
||||||
}
|
|
||||||
|
|
||||||
return send_post_request(base_release_url, api_token, release_content)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
args = parser.parse_args()
|
|
||||||
commit = args.commit
|
|
||||||
major = args.major
|
|
||||||
test = args.test
|
|
||||||
user_names = args.name
|
|
||||||
output_path = args.output
|
|
||||||
force = args.force
|
|
||||||
reuse_latest_relase = args.reuse_lastest_release
|
|
||||||
addon_folder = REPO_ROOT_DIR.joinpath(REPO_ROOT_DIR, "scripts-blender/addons")
|
|
||||||
addon_to_upload = []
|
|
||||||
base_release_url = f"{api_path}{release_path}"
|
|
||||||
base_tag_url = f"{api_path}{tag_path}"
|
|
||||||
latest_release = requests.get(url=f"{base_release_url}/latest?token={api_token}")
|
|
||||||
# Exception for intial release
|
|
||||||
if latest_release.status_code == 404:
|
|
||||||
release_version = '0.0.1'
|
|
||||||
else:
|
|
||||||
latest_tag = latest_release.json()["tag_name"]
|
|
||||||
release_version = latest_tag.replace(
|
|
||||||
latest_tag[-1], str(int(latest_tag[-1]) + 1)
|
|
||||||
)
|
|
||||||
|
|
||||||
addon_dirs = [
|
|
||||||
name
|
|
||||||
for name in os.listdir(addon_folder)
|
|
||||||
if os.path.isdir(addon_folder.joinpath(name))
|
|
||||||
]
|
|
||||||
if user_names:
|
|
||||||
addon_dirs = [
|
|
||||||
name
|
|
||||||
for name in os.listdir(addon_folder)
|
|
||||||
if os.path.isdir(addon_folder.joinpath(name)) and name in user_names
|
|
||||||
]
|
|
||||||
|
|
||||||
for dir in addon_dirs:
|
|
||||||
addon_to_package = addon_folder.joinpath(addon_folder, dir)
|
|
||||||
addon_package(
|
|
||||||
addon_to_package,
|
|
||||||
commit,
|
|
||||||
major,
|
|
||||||
force,
|
|
||||||
test,
|
|
||||||
output_path,
|
|
||||||
addon_to_upload,
|
|
||||||
release_version,
|
|
||||||
)
|
|
||||||
|
|
||||||
if not test:
|
|
||||||
# Release Script
|
|
||||||
if reuse_latest_relase:
|
|
||||||
release_id = latest_release.json()["id"]
|
|
||||||
else:
|
|
||||||
response = create_new_release(
|
|
||||||
base_tag_url, base_release_url, release_version, api_token
|
|
||||||
)
|
|
||||||
release_id = response["id"]
|
|
||||||
|
|
||||||
for file in addon_to_upload:
|
|
||||||
payload = open(file, 'rb')
|
|
||||||
upload_file_to_release(
|
|
||||||
base_release_url,
|
|
||||||
api_token,
|
|
||||||
release_id,
|
|
||||||
payload,
|
|
||||||
)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -4,45 +4,78 @@ import glob
|
|||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
from pathlib import Path
|
||||||
import requests
|
import requests
|
||||||
|
import tempfile
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
def download_file(url, out_folder, filename):
|
def main():
|
||||||
print("Downloading: " + url)
|
# TODO Replace download path with actual download from studio.blender.org
|
||||||
local_filename = out_folder / filename
|
downloads_path = pathlib.Path(__file__).parent.joinpath("downloads")
|
||||||
|
release_zip = downloads_path.joinpath("blender_studio_pipeline_release.zip")
|
||||||
|
release_checksum = downloads_path.joinpath("blender_studio_pipeline_release.zip.sha256")
|
||||||
|
|
||||||
# TODO Can't check any shasums before downloading so always remove and redownload everything for now
|
# TODO make script work from SVN directory, maybe add warning if not in corect directory
|
||||||
prev_downloaded_files = glob.glob(f"{local_filename}*")
|
# current_file_folder_path = pathlib.Path(__file__).parent
|
||||||
for file in prev_downloaded_files:
|
# download_folder_path = (current_file_folder_path / "../../shared/artifacts/addons/").resolve()
|
||||||
os.remove(file)
|
download_folder_path = Path(
|
||||||
|
"/data/my_project/shared/artifacts/addons/"
|
||||||
|
) # TEMP while developing script
|
||||||
|
|
||||||
# NOTE the stream=True parameter below
|
# Ensure that the download directory exists
|
||||||
with requests.get(url, stream=True) as r:
|
os.makedirs(download_folder_path, exist_ok=True)
|
||||||
r.raise_for_status()
|
|
||||||
with open(local_filename, 'wb') as f:
|
|
||||||
for chunk in r.iter_content(chunk_size=None):
|
|
||||||
if chunk:
|
|
||||||
f.write(chunk)
|
|
||||||
|
|
||||||
local_hash_filename = local_filename.with_suffix(".zip.sha256")
|
extract_release_zip(release_zip, download_folder_path)
|
||||||
with open(local_filename, "rb") as f:
|
|
||||||
digest = hashlib.file_digest(f, "sha256")
|
|
||||||
with open(local_hash_filename, "w") as hash_file:
|
|
||||||
hash_file.write(digest.hexdigest())
|
|
||||||
|
|
||||||
return local_filename
|
|
||||||
|
|
||||||
|
|
||||||
current_file_folder_path = pathlib.Path(__file__).parent
|
def extract_release_zip(file_path: Path, dst_path: Path):
|
||||||
download_folder_path = (current_file_folder_path / "../../shared/artifacts/addons/").resolve()
|
temp_dir = tempfile.mkdtemp()
|
||||||
|
with zipfile.ZipFile(file_path, 'r') as zip_ref:
|
||||||
|
zip_ref.extractall(temp_dir)
|
||||||
|
|
||||||
# Ensure that the download directory exists
|
try:
|
||||||
os.makedirs(download_folder_path, exist_ok=True)
|
src_path = [subdir for subdir in Path(temp_dir).iterdir()][0]
|
||||||
|
except IndexError:
|
||||||
|
print("The archive %s does not contain any directory" % file_path.name)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
print("This script currently does nothing. If you want to update the 'studio-pipeline' addons, run the 'package_local.py' script in the studio-pipline repo.")
|
for file in src_path.iterdir():
|
||||||
|
# TODO use checksum to skip files that are already updated?
|
||||||
|
original_file = dst_path / file.name
|
||||||
|
if original_file.exists():
|
||||||
|
os.remove(original_file)
|
||||||
|
shutil.move(file, dst_path)
|
||||||
|
|
||||||
#download_file(
|
shutil.rmtree(temp_dir)
|
||||||
# "https://projects.blender.org/studio/blender-studio-pipeline/archive/main.zip",
|
|
||||||
# download_folder_path,
|
|
||||||
# "blender-studio-pipeline-main.zip",
|
# def download_file(url, out_folder, filename):
|
||||||
#)
|
# print("Downloading: " + url)
|
||||||
|
# local_filename = out_folder / filename
|
||||||
|
|
||||||
|
# # TODO Can't check any shasums before downloading so always remove and redownload everything for now
|
||||||
|
# prev_downloaded_files = glob.glob(f"{local_filename}*")
|
||||||
|
# for file in prev_downloaded_files:
|
||||||
|
# os.remove(file)
|
||||||
|
|
||||||
|
# # NOTE the stream=True parameter below
|
||||||
|
# with requests.get(url, stream=True) as r:
|
||||||
|
# r.raise_for_status()
|
||||||
|
# with open(local_filename, 'wb') as f:
|
||||||
|
# for chunk in r.iter_content(chunk_size=None):
|
||||||
|
# if chunk:
|
||||||
|
# f.write(chunk)
|
||||||
|
|
||||||
|
# local_hash_filename = local_filename.with_suffix(".zip.sha256")
|
||||||
|
# with open(local_filename, "rb") as f:
|
||||||
|
# digest = hashlib.file_digest(f, "sha256")
|
||||||
|
# with open(local_hash_filename, "w") as hash_file:
|
||||||
|
# hash_file.write(digest.hexdigest())
|
||||||
|
|
||||||
|
# return local_filename
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user