WIP: Pipeline Release: Bundle all Add-Ons in a Zip #268

Closed
Nick Alberelli wants to merge 14 commits from TinyNick/blender-studio-pipeline:feature/bundle-pipeline-addons into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
68 changed files with 210 additions and 896 deletions

View File

@ -112,20 +112,21 @@ export default defineConfig({
collapsed: true,
items: [
{ text: 'Anim Cupboard', link: '/addons/anim_cupboard'},
{ text: 'Asset Pipeline', link: '/addons/asset_pipeline'},
{ text: 'Blender Kitsu', link: '/addons/blender_kitsu'},
{ text: 'Blender SVN', link: '/addons/blender_svn'},
{ text: 'Blender Gizmos', link: '/addons/bone_gizmos'},
{ text: 'Cache Manager', link: '/addons/cache_manager'},
{ text: 'Contact Sheet', link: '/addons/contactsheet'},
{ text: 'Easy Weights', link: '/addons/easy_weights'},
{ text: 'Geonode Shapekeys', link: '/addons/geonode_shapekeys'},
{ text: 'Grase Converter', link: '/addons/grease_converter'},
{ text: 'Lattice Magic', link: '/addons/lattice_magic'},
{ text: 'Lighting Overrider', link: '/addons/lighting_overrider'},
{ text: 'Pose Shape Keys', link: '/addons/pose_shape_keys'},
{ text: 'Render Review', link: '/addons/render_review'},
{ 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: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/asset_pipeline/README.md'},
{ text: 'Blender Kitsu', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_kitsu/README.md'},
{ text: 'Blender Log', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_log/README.md'},
{ text: 'Blender SVN', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/blender_svn/README.md'},
{ text: 'Bone Gizmos', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/bone_gizmos/README.md'},
{ text: 'Cache Manager', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/cache_manager/README.md'},
{ text: 'Contact Sheet', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/contactsheet/README.md'},
{ text: 'Easy Weights', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/easy_weights/README.md'},
{ text: 'Geonode Shapekeys', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/geonode_shapekeys/README.md'},
{ text: 'Grase Converter', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/grease_converter/README.md'},
{ text: 'Lattice Magic', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lattice_magic/README.md'},
{ text: 'Lighting Overrider', link: 'https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lighting_overrider/README.md'},
{ 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'},
]
},
{

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/anim_cupboard/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/anim_cupboard/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/asset_pipeline/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/asset_pipeline/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/blender_kitsu/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/blender_kitsu/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/blender_svn/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/blender_svn/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/bone_gizmos/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/bone_gizmos/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/cache_manager/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/cache_manager/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/contactsheet/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/contactsheet/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/easy_weights/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/easy_weights/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/geonode_shapekeys/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/geonode_shapekeys/CHANGELOG.md-->

View File

@ -1,5 +0,0 @@
<!--@include: ../../scripts-blender/addons/grease_converter/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/grease_converter/CHANGELOG.md-->

View File

@ -1,4 +0,0 @@
<!--@include: ../../scripts-blender/addons/lattice_magic/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/lattice_magic/CHANGELOG.md-->

View File

@ -1,4 +0,0 @@
<!--@include: ../../scripts-blender/addons/lighting_overrider/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/lighting_overrider/CHANGELOG.md-->

View File

@ -1 +1 @@
<!--@include: ../../scripts/pipeline-release/overview.md-->
<!--@include: ../../scripts-blender/README.md-->

View File

@ -1,4 +0,0 @@
<!--@include: ../../scripts-blender/addons/pose_shape_keys/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/pose_shape_keys/CHANGELOG.md-->

View File

@ -1,4 +0,0 @@
<!--@include: ../../scripts-blender/addons/render_review/README.md-->
##
# Changelog
<!--@include: ../../scripts-blender/addons/render_review/CHANGELOG.md-->

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -136,32 +136,8 @@ python rollback_blender_local.py
```
## 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
```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
```
<!--@include: ../../../scripts/pipeline-release/README.md-->
::: info Blender Studio Users

View File

@ -4,22 +4,18 @@ Add-ons used by the Blender Studio pipeline. To review or report issues visit th
| Add-on | Description |
|---|---|
|Anim Cupboard |Miscellaneous tools for animators.
|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 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 Gizmos |Attempt to prototype a system for using meshes for the manipulation of armatures.
|Cache Manager |Streamline the Alembic cache workflow of assets.
|Contact Sheet |Create a contactsheet from sequence editor strips.
|Easy Weights |Quality of life improvements for weight painting.
|Geonode Shapekeys |Enable animators to sculpt on linked and overridden meshes.
|Grease Converter |Convert annotations to Grease Pencil objects and vise versa.
|Lattice Magic |Lattice-based utilities.
|Lighting Overrider |Create, manage and apply python overrides in a flexible and reliable way.
|Pose Shape Keys |Manage and maintain shapekeys for rigging.
|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.
|[Anim Cupboard](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/anim_cupboard) |Miscellaneous tools for animators.
|[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](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](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](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](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](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](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/contactsheet) |Create a contactsheet from sequence editor strips.
|[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](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](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](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/lattice_magic) |Lattice-based utilities.
|[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](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](https://projects.blender.org/studio/blender-studio-pipeline/src/branch/main/scripts-blender/addons/render_review) |Review renders from Flamenco with the sequence editor.

View File

@ -43,7 +43,7 @@ If Kitsu is up and running and you can successfully log in via the web interface
###### **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/>
**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**
![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/>
@ -61,7 +61,7 @@ Press the login button. If the login was successful, the next step is..
###### **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/>
@ -71,19 +71,19 @@ Press the login button. If the login was successful, the next step is..
###### **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/>
###### **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/>
###### **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/>
**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 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.
@ -112,7 +112,8 @@ This will create a blank movie strip. The metadata strip will be placed one chan
###### 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.
![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
@ -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/>
![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
@ -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.
>**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
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/>
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/>
![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/>
@ -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/>
![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
>>**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
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.
>>**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/>
![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/>
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:
![image info](/media/addons/blender_kitsu/sqe_sequence_colors.jpg)
![image info](docs_media/sqe_sequence_colors.jpg)
##### Multi Edit
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/>
##### 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}/`
![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.
###### 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.
![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/>
>**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
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:
![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.
![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/>
@ -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/>
![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/>
@ -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/>
![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/>
**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
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.
@ -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/>
![image info](/media/addons/blender_kitsu/error_animation.jpg)
![image info](docs_media/error_animation.jpg)
## 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.

View File

@ -18,12 +18,12 @@ After the add-on is installed you have 2 new operators available.
- **grease_converter.convert_to_grease_pencil**:
- Located in the 3DView Side Panel (N)-> View -> Annotations Panel
- 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**:
- 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)
![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

View File

@ -1,7 +1,7 @@
# Lattice Magic
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
@ -27,7 +27,7 @@ This addon adds some Lattice-based utilities to Blender.
## Tweak Lattice
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
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 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
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.

View File

@ -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:
![json icons](/media/addons/lighting_overrider/json_icon_example.png)
![json icons](docs_media/json_icon_example.png)
#### 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.
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
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.
![rna ovrrides](/media/addons/lighting_overrider/rna_override.png)
![rna ovrrides](docs_media/rna_override.png)
## Structure

View File

@ -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
- 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
1. Enter Directory
## Prerequisite
In order to use this tool you need:
- 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:
```bash
cd ~/data/blender-studio-pipeline/scripts/pipeline-release # Linux/Mac
```
Blender Kitsu: Fix naming conventions
````
### Changelog Output:
```
### Fixes
- Fix naming conventions
```bash
cd %HOMEPATH%\data\blender-studio-pipeline\scripts\pipeline-release # Windows
```
## Example Usage
| Action | Command |
| ----------- | ----------- |
|Create a new minor version if available of all addons|`python -m pipeline_release`|
|Create a new major version if available of all addons|`python -m pipeline_release -m`|
|Create a new version even no new commits are found|`python -m pipeline_release` -f|
|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"`|
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
```

View File

@ -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)|

View File

@ -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>)|

View 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()

View File

@ -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()

View File

@ -4,45 +4,78 @@ import glob
import hashlib
import os
import pathlib
from pathlib import Path
import requests
import tempfile
import sys
import zipfile
import shutil
def download_file(url, out_folder, filename):
print("Downloading: " + url)
local_filename = out_folder / filename
def main():
# TODO Replace download path with actual download from studio.blender.org
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
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
current_file_folder_path = pathlib.Path(__file__).parent
download_folder_path = (current_file_folder_path / "../../shared/artifacts/addons/").resolve()
# TODO make script work from SVN directory, maybe add warning if not in corect directory
# current_file_folder_path = pathlib.Path(__file__).parent
# download_folder_path = (current_file_folder_path / "../../shared/artifacts/addons/").resolve()
download_folder_path = Path(
"/data/my_project/shared/artifacts/addons/"
) # TEMP while developing script
# Ensure that the download directory exists
os.makedirs(download_folder_path, exist_ok=True)
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.")
extract_release_zip(release_zip, download_folder_path)
#download_file(
# "https://projects.blender.org/studio/blender-studio-pipeline/archive/main.zip",
# download_folder_path,
# "blender-studio-pipeline-main.zip",
#)
def extract_release_zip(file_path: Path, dst_path: Path):
temp_dir = tempfile.mkdtemp()
with zipfile.ZipFile(file_path, 'r') as zip_ref:
zip_ref.extractall(temp_dir)
try:
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)
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)
shutil.rmtree(temp_dir)
# 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()