|
| 1 | +# Extension package lifecycle |
| 2 | + |
| 3 | +Takes [`templates/extension-addon-template`](../../templates/extension-addon-template/) |
| 4 | +through what an extension meets after its first run: validate, build, a |
| 5 | +repository listing, install, an upgrade over the top, removal, and the |
| 6 | +online-access gate. Every step runs a child Blender against a throwaway user |
| 7 | +directory (`BLENDER_USER_RESOURCES`), so the real install is never touched. |
| 8 | +Check-only: the witnesses are exit codes, zip members and paths, so a render |
| 9 | +would look the same whether the contract held or broke. |
| 10 | + |
| 11 | +Follows [`extension-runtime-and-packaging`](../../skills/extension-runtime-and-packaging/SKILL.md), |
| 12 | +whose snippet is [`extension-user-data.py`](../../snippets/extension-user-data.py). |
| 13 | +Scaffolding matches [`eval-mesh-datablock-name`](../eval-mesh-datablock-name/) |
| 14 | +(`check()` steps return codes, argparse falsifier flags, FATAL wrapper). |
| 15 | + |
| 16 | +**What it witnesses:** |
| 17 | + |
| 18 | +- `blender --command extension validate` and `build` accept the template, and |
| 19 | + the zip carries `blender_manifest.toml` and `__init__.py` at its root. |
| 20 | +- **`validate` is not a release gate.** With `wheels = ["./wheels/not_shipped-1.0-py3-none-any.whl"]` |
| 21 | + appended and no such file, `validate` exits 0 and `build` exits 1 with no |
| 22 | + zip. Only the build opens the files the manifest names. |
| 23 | +- `extension server-generate --repo-dir` writes `index.json` listing the |
| 24 | + package with `archive_url` `./example_addon-0.1.0.zip`. |
| 25 | +- Installed with `extension install-file -r user_default`, the add-on imports |
| 26 | + as `bl_ext.user_default.example_addon`, and |
| 27 | + `bpy.utils.extension_path_user(__package__)` names |
| 28 | + `extensions/.user/user_default/example_addon`, beside the install tree |
| 29 | + `extensions/user_default/example_addon`, not inside it. |
| 30 | +- Installing 0.2.0 over 0.1.0 replaces the install tree (a file written |
| 31 | + beside `__file__` is gone) and keeps the user directory (`settings.json` |
| 32 | + survives). `extension remove` deletes the user directory too. |
| 33 | +- `bpy.app.online_access` is `False` in a factory-startup child and `True` |
| 34 | + under `--online-mode`. |
| 35 | + |
| 36 | +**What failure each check would catch:** |
| 37 | + |
| 38 | +- exit 3 — the template stopped validating or building, or the zip lost its manifest |
| 39 | +- exit 4 — a package whose wheel does not exist passed the release gate |
| 40 | + (`--validate-only` lands here: it gates on `validate` alone); also exit 4 if |
| 41 | + `validate` starts rejecting the missing wheel, because the trap this example |
| 42 | + names would then be gone |
| 43 | +- exit 5 — `server-generate` wrote no listing, or the listing does not name the package |
| 44 | +- exit 6 — install, import, upgrade or remove failed, or `__package__` is not |
| 45 | + `bl_ext.user_default.example_addon` |
| 46 | +- exit 7 — user data lives inside the install tree, did not survive the |
| 47 | + upgrade, or survived removal (`--data-next-to-file` lands here: it stores |
| 48 | + data beside `__file__`) |
| 49 | +- exit 8 — `online_access` is not `False` by default and `True` under `--online-mode` |
| 50 | + |
| 51 | +## Re-verified |
| 52 | + |
| 53 | +| Measurement | 4.5.11 | 5.1.2 | 5.2.1 | |
| 54 | +| --- | --- | --- | --- | |
| 55 | +| validate / build, template | 0 / 0 | 0 / 0 | 0 / 0 | |
| 56 | +| validate / build, missing wheel | 0 / 1 | 0 / 1 | 0 / 1 | |
| 57 | +| `__package__` | `bl_ext.user_default.example_addon` | same | same | |
| 58 | +| user data kept by 0.2.0 upgrade | yes | yes | yes | |
| 59 | +| file beside `__file__` kept by upgrade | no | no | no | |
| 60 | +| user data after `remove` | deleted | deleted | deleted | |
| 61 | +| `online_access` default / `--online-mode` | False / True | False / True | False / True | |
| 62 | +| default exit | 0 | 0 | 0 | |
| 63 | +| `--validate-only` / `--data-next-to-file` exit | 4 / 7 | 4 / 7 | 4 / 7 | |
| 64 | + |
| 65 | +## API reference |
| 66 | + |
| 67 | +- [`bpy.utils.extension_path_user`](https://docs.blender.org/api/current/bpy.utils.html#bpy.utils.extension_path_user) |
| 68 | + ([4.5 LTS](https://docs.blender.org/api/4.5/bpy.utils.html#bpy.utils.extension_path_user)) |
| 69 | +- [`bpy.app.online_access`](https://docs.blender.org/api/current/bpy.app.html#bpy.app.online_access) |
| 70 | +- [Extensions command line arguments](https://docs.blender.org/manual/en/latest/advanced/command_line/extension_arguments.html) |
| 71 | + |
| 72 | +## Run |
| 73 | + |
| 74 | +```bash |
| 75 | +blender --background --python extension_package_lifecycle.py -- |
| 76 | +blender --background --python extension_package_lifecycle.py -- --validate-only |
| 77 | +blender --background --python extension_package_lifecycle.py -- --data-next-to-file |
| 78 | +``` |
| 79 | + |
| 80 | +The script starts about a dozen child Blender processes, so it takes longer |
| 81 | +than most examples. |
| 82 | + |
| 83 | +## Exit codes |
| 84 | + |
| 85 | +| Code | Meaning | |
| 86 | +| --- | --- | |
| 87 | +| 0 | Success | |
| 88 | +| 1 | Uncaught exception (FATAL wrapper) | |
| 89 | +| 2 | argparse / usage | |
| 90 | +| 3 | Template does not validate or build, or the zip lacks its manifest | |
| 91 | +| 4 | Missing-wheel package passed the release gate (`--validate-only` lands here) | |
| 92 | +| 5 | `server-generate` listing missing or wrong | |
| 93 | +| 6 | Install, import, upgrade or remove failed, or `__package__` wrong | |
| 94 | +| 7 | User data inside the install tree, lost on upgrade, or kept after removal (`--data-next-to-file` lands here) | |
| 95 | +| 8 | `online_access` default or `--online-mode` value wrong | |
| 96 | + |
| 97 | +The `blender-smoke` workflow runs the check on Blender 5.2 LTS and 4.5 LTS |
| 98 | +(5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch). |
| 99 | +Smoke passes no extra flags on the happy path. Its catalog falsifiers are |
| 100 | +`--validate-only` (expects exit 4) and `--data-next-to-file` (expects exit 7). |
0 commit comments