# Testing, packaging, installing, and releasing Blender extensions

The goal is to test the same artifact a user installs, while keeping local
Blender preferences and production scenes out of the test.

## Test layers

### 1. Syntax and registration

Import/register the extension in Blender's Python, not system Python. Ordinary
Python usually has no compatible `bpy` module.

A useful smoke test should:

1. start from `--factory-startup --background`;
2. register or enable the extension;
3. build its own minimal scene and data-blocks;
4. invoke the public operator/API;
5. assert outputs and persistent results;
6. assert selection, active object, render state, and source data restoration;
7. assert temporary objects/materials/meshes/images were removed;
8. print one unmistakable success marker.

The current extension test is:

```bash
./blender/scripts/test.sh
```

When more extensions are added, give each one a focused test file and make the
shared test helper run each in a fresh Blender process. Fresh processes prevent
registration and global-state leakage between tests.

### 2. Manifest validation

Validate source metadata before packaging:

```bash
blender --factory-startup --command extension validate \
  blender/material_id_baker
```

Then validate the actual ZIP:

```bash
VERSION=1.2.0
blender --factory-startup --command extension validate \
  "dist/material_id_baker-${VERSION}.zip"
```

ZIP validation catches package-root and build-exclusion mistakes that source
validation cannot.

### 3. Installed-package test

Build all packages:

```bash
./build-all.sh
```

Install into an isolated Blender profile on Linux/macOS:

```bash
test_profile="$(mktemp -d)"
BLENDER_USER_RESOURCES="$test_profile" ./install-all.sh
```

Then launch Blender with the same `BLENDER_USER_RESOURCES` and assert registered
operators/classes are present. Do not point install tests at the developer's real
profile unless the user explicitly wants to update it.

On Windows, set `BLENDER_USER_RESOURCES` to a temporary directory before running
`install-all.bat` from the same Command Prompt.

### 4. Manual UI test

Headless tests do not prove layout quality or interactive behavior. Before a
release, install the ZIP and check:

- panel location, labels, spacing, disabled states, and tooltips;
- behavior with no object, wrong object type, wrong mode, missing UV/material,
  linked data, shared data, and unsaved `.blend` paths as relevant;
- Undo/Redo for scene changes;
- disabling and re-enabling without restarting Blender;
- saving/reopening the `.blend` when properties or generated data persist;
- output in the Image Editor, Shader Editor, Outliner, and exporter as relevant.

## Build helpers in this repository

`build-all.sh` recursively discovers `blender_manifest.toml` under `blender/`
and writes versioned packages to `dist/`:

```bash
BLENDER_BIN=/path/to/blender-5.2 ./build-all.sh
```

`install-all.sh` builds, installs, and enables only the packages produced by
that invocation:

```bash
BLENDER_EXTENSION_REPO=user_default ./install-all.sh
```

Windows:

```bat
set "BLENDER_BIN=C:\Program Files\Blender Foundation\Blender 5.2\blender.exe"
set "BLENDER_EXTENSION_REPO=user_default"
install-all.bat
```

Close open Blender processes before replacing an extension. Reinstalling files
does not reload a module already imported by a running process.

## Versioning and release checklist

Use semantic versions in `blender_manifest.toml`:

- patch: compatible bug fix or internal improvement;
- minor: backward-compatible user-visible feature;
- major: breaking behavior/configuration/workflow change.

Release sequence:

1. Finish source and documentation changes.
2. Update/add automated tests and run them.
3. Bump the manifest version.
4. Validate the source directory.
5. Run `./build-all.sh`.
6. Validate the new versioned ZIP.
7. Install the ZIP into an isolated profile and confirm it enables.
8. Perform the relevant manual UI/export test in the target Blender version.
9. Inspect ZIP contents; source/tests/repository files must not leak into it.
10. Distribute the immutable ZIP. Do not replace a published ZIP without also
    changing its version.

Inspect package contents on Unix-like systems with:

```bash
unzip -l dist/<id>-<version>.zip
```

An add-on extension ZIP should normally contain `blender_manifest.toml`,
`__init__.py`, its internal modules/assets, and declared wheels—nothing from
other extensions or repository-level tests.

## Headless installation scopes

For the current Blender user, the supported CLI operation is:

```bash
blender --factory-startup --command extension install-file \
  -r user_default -e dist/<id>-<version>.zip
```

`-e` enables the extension and updates that user's preferences.

For a machine-wide deployment, extract packages into the read-only system
repository layout:

```text
$BLENDER_SYSTEM_EXTENSIONS/
  system/
    <id>/
      blender_manifest.toml
      __init__.py
```

System-repository availability is separate from per-user enablement. Managed
deployments can use a startup script under `BLENDER_SYSTEM_SCRIPTS/startup/` to
enable required packages. See Blender's
[production deployment guide](https://docs.blender.org/manual/en/dev/advanced/deploying_blender.html).

## Official references

- [Creating extensions](https://docs.blender.org/manual/en/dev/advanced/extensions/getting_started.html)
- [Extension CLI](https://docs.blender.org/manual/en/dev/advanced/command_line/extension_arguments.html)
- [Production/system extension deployment](https://docs.blender.org/manual/en/dev/advanced/deploying_blender.html)
- [Python wheels](https://docs.blender.org/manual/en/dev/advanced/extensions/python_wheels.html)
