orionis-installer 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. orionis_installer-0.1.0/.github/workflows/ci.yml +68 -0
  2. orionis_installer-0.1.0/.python-version +1 -0
  3. orionis_installer-0.1.0/LICENCE +21 -0
  4. orionis_installer-0.1.0/MANIFEST.in +8 -0
  5. orionis_installer-0.1.0/PKG-INFO +286 -0
  6. orionis_installer-0.1.0/README.md +266 -0
  7. orionis_installer-0.1.0/pyproject.toml +68 -0
  8. orionis_installer-0.1.0/scripts/verify_distribution.py +132 -0
  9. orionis_installer-0.1.0/setup.cfg +4 -0
  10. orionis_installer-0.1.0/src/orionis_installer/__init__.py +3 -0
  11. orionis_installer-0.1.0/src/orionis_installer/__main__.py +6 -0
  12. orionis_installer-0.1.0/src/orionis_installer/cli.py +343 -0
  13. orionis_installer-0.1.0/src/orionis_installer/configuration.py +397 -0
  14. orionis_installer-0.1.0/src/orionis_installer/exceptions.py +31 -0
  15. orionis_installer-0.1.0/src/orionis_installer/installer.py +391 -0
  16. orionis_installer-0.1.0/src/orionis_installer/messages.py +241 -0
  17. orionis_installer-0.1.0/src/orionis_installer/models.py +223 -0
  18. orionis_installer-0.1.0/src/orionis_installer/post_install.py +431 -0
  19. orionis_installer-0.1.0/src/orionis_installer/prerequisites.py +167 -0
  20. orionis_installer-0.1.0/src/orionis_installer/processes.py +767 -0
  21. orionis_installer-0.1.0/src/orionis_installer/py.typed +0 -0
  22. orionis_installer-0.1.0/src/orionis_installer/skeleton.py +282 -0
  23. orionis_installer-0.1.0/src/orionis_installer/ui/__init__.py +177 -0
  24. orionis_installer-0.1.0/src/orionis_installer/ui/messages.py +109 -0
  25. orionis_installer-0.1.0/src/orionis_installer/ui/output.py +228 -0
  26. orionis_installer-0.1.0/src/orionis_installer/ui/prompts.py +299 -0
  27. orionis_installer-0.1.0/src/orionis_installer/ui/theme.py +37 -0
  28. orionis_installer-0.1.0/src/orionis_installer/validation.py +151 -0
  29. orionis_installer-0.1.0/src/orionis_installer.egg-info/PKG-INFO +286 -0
  30. orionis_installer-0.1.0/src/orionis_installer.egg-info/SOURCES.txt +58 -0
  31. orionis_installer-0.1.0/src/orionis_installer.egg-info/dependency_links.txt +1 -0
  32. orionis_installer-0.1.0/src/orionis_installer.egg-info/entry_points.txt +2 -0
  33. orionis_installer-0.1.0/src/orionis_installer.egg-info/requires.txt +6 -0
  34. orionis_installer-0.1.0/src/orionis_installer.egg-info/top_level.txt +1 -0
  35. orionis_installer-0.1.0/tests/fixtures/skeleton/.env.example +14 -0
  36. orionis_installer-0.1.0/tests/fixtures/skeleton/.gitignore +5 -0
  37. orionis_installer-0.1.0/tests/fixtures/skeleton/LICENCE +2 -0
  38. orionis_installer-0.1.0/tests/fixtures/skeleton/README.md +9 -0
  39. orionis_installer-0.1.0/tests/fixtures/skeleton/bootstrap/app.py +1 -0
  40. orionis_installer-0.1.0/tests/fixtures/skeleton/config/database.py +28 -0
  41. orionis_installer-0.1.0/tests/fixtures/skeleton/config/filesystems.py +19 -0
  42. orionis_installer-0.1.0/tests/fixtures/skeleton/database/.gitkeep +1 -0
  43. orionis_installer-0.1.0/tests/fixtures/skeleton/pyproject.toml +19 -0
  44. orionis_installer-0.1.0/tests/fixtures/skeleton/reactor +1 -0
  45. orionis_installer-0.1.0/tests/integration/test_offline.py +436 -0
  46. orionis_installer-0.1.0/tests/integration/test_real_smoke.py +76 -0
  47. orionis_installer-0.1.0/tests/unit/test_cli.py +703 -0
  48. orionis_installer-0.1.0/tests/unit/test_configuration.py +625 -0
  49. orionis_installer-0.1.0/tests/unit/test_contract_regressions.py +533 -0
  50. orionis_installer-0.1.0/tests/unit/test_documentation.py +43 -0
  51. orionis_installer-0.1.0/tests/unit/test_installer.py +555 -0
  52. orionis_installer-0.1.0/tests/unit/test_messages.py +61 -0
  53. orionis_installer-0.1.0/tests/unit/test_models.py +192 -0
  54. orionis_installer-0.1.0/tests/unit/test_post_install.py +647 -0
  55. orionis_installer-0.1.0/tests/unit/test_prerequisites.py +380 -0
  56. orionis_installer-0.1.0/tests/unit/test_processes.py +641 -0
  57. orionis_installer-0.1.0/tests/unit/test_skeleton.py +590 -0
  58. orionis_installer-0.1.0/tests/unit/test_ui.py +311 -0
  59. orionis_installer-0.1.0/tests/unit/test_validation.py +275 -0
  60. orionis_installer-0.1.0/uv.lock +576 -0
@@ -0,0 +1,68 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ checks:
13
+ name: Python 3.14 / ${{ matrix.os }}
14
+ runs-on: ${{ matrix.os }}
15
+ timeout-minutes: 20
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [ubuntu-latest, windows-latest, macos-latest]
20
+ env:
21
+ NO_COLOR: "1"
22
+ UV_NO_PROGRESS: "1"
23
+ ORIONIS_REAL_SMOKE: "0"
24
+ steps:
25
+ # Official revisions in uv's GitHub guide, inspected 2026-10-06.
26
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27
+ with:
28
+ persist-credentials: false
29
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
30
+ with:
31
+ python-version: "3.14"
32
+ - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
33
+ with:
34
+ version: "0.11.30"
35
+ enable-cache: true
36
+ - name: Sync development environment
37
+ run: uv sync --locked --python 3.14
38
+ - name: Ruff and format
39
+ run: |
40
+ uv run --no-sync ruff check .
41
+ uv run --no-sync ruff format --check .
42
+ - name: Static types
43
+ run: uv run --no-sync mypy
44
+ - name: Offline and unit tests
45
+ run: uv run --no-sync pytest --cov=orionis_installer --cov-report=term-missing --cov-report=xml
46
+ - name: Build wheel and source distribution
47
+ run: uv build
48
+ - name: Clean wheel environment and entry point
49
+ shell: bash
50
+ run: |
51
+ python - <<'PY'
52
+ import os
53
+ import pathlib
54
+ import subprocess
55
+ import tempfile
56
+
57
+ wheel, = pathlib.Path("dist").glob("*.whl")
58
+ with tempfile.TemporaryDirectory(prefix="orionis-wheel-") as temporary:
59
+ environment = pathlib.Path(temporary) / "clean"
60
+ subprocess.run(["uv", "venv", str(environment), "--python", "3.14"], check=True)
61
+ scripts = environment / ("Scripts" if os.name == "nt" else "bin")
62
+ python = scripts / ("python.exe" if os.name == "nt" else "python")
63
+ entry = scripts / ("orionis.exe" if os.name == "nt" else "orionis")
64
+ subprocess.run(["uv", "pip", "install", "--python", str(python), str(wheel.resolve())], check=True)
65
+ for arguments in (["--version"], ["--help"], ["new", "--help"]):
66
+ subprocess.run([str(entry), *arguments], cwd=temporary, check=True)
67
+ subprocess.run(["uvx", "--python", "3.14", "--from", str(wheel.resolve()), "orionis", "--version"], cwd=temporary, check=True)
68
+ PY
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 - 2025 RAÚL MAURICIO UÑATE CASTRO
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ include README.md LICENCE pyproject.toml uv.lock .python-version
2
+ recursive-include src *.py py.typed
3
+ recursive-include tests *.py *.toml *.md *.example .gitignore .gitkeep LICENCE reactor
4
+ recursive-include docs *.md *.patch
5
+ recursive-include scripts *.py
6
+ recursive-include .github *.yml
7
+ global-exclude *.py[cod]
8
+ global-exclude __pycache__
@@ -0,0 +1,286 @@
1
+ Metadata-Version: 2.4
2
+ Name: orionis-installer
3
+ Version: 0.1.0
4
+ Summary: Create Orionis applications with isolated Python environments.
5
+ License-Expression: MIT
6
+ Classifier: Environment :: Console
7
+ Classifier: Programming Language :: Python :: 3.14
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Typing :: Typed
10
+ Requires-Python: >=3.14
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENCE
13
+ Requires-Dist: typer<0.28,>=0.27.3
14
+ Requires-Dist: rich<16,>=15.0.0
15
+ Requires-Dist: prompt-toolkit<4,>=3.0.53
16
+ Requires-Dist: tomlkit<0.16,>=0.15.1
17
+ Requires-Dist: packaging<27,>=26.3
18
+ Requires-Dist: python-dotenv<2,>=1.2.4
19
+ Dynamic: license-file
20
+
21
+ # Orionis Installer
22
+
23
+ `orionis-installer` creates applications from the official Orionis skeleton on
24
+ `master`, with Python **3.14.x**, a project-local `.venv` and `uv.lock`. Its Python
25
+ module is `orionis_installer` and its executable is **`orionis`**.
26
+
27
+ The installer depends on CLI and configuration libraries. Orionis, database
28
+ drivers, cloud SDKs and Faker belong to the generated application's environment.
29
+ The English wizard supports arrow keys, Enter, visible defaults and immediate
30
+ validation. Its ASCII banner adapts to narrow terminals; `NO_COLOR` and
31
+ `--no-color` disable colors.
32
+
33
+ ## Installation
34
+
35
+ Install [uv](https://docs.astral.sh/uv/getting-started/installation/) and
36
+ [Git](https://git-scm.com/downloads). Python 3.14 or newer runs the installer; uv
37
+ selects stable Python 3.14.x for the application and can obtain it according to
38
+ its download and network policies.
39
+
40
+ When this distribution is available on your package index:
41
+
42
+ ```bash
43
+ uvx --from orionis-installer orionis new
44
+ uvx --from orionis-installer orionis new blog
45
+ uvx --python 3.14 --from orionis-installer orionis new
46
+ uv tool install --python 3.14 orionis-installer
47
+ orionis new blog
48
+ orionis --help
49
+ orionis --version
50
+ ```
51
+
52
+ `uvx --python 3.14` selects the **installer's** interpreter. The application has an
53
+ independent environment. The framework can also provide an `orionis` executable;
54
+ invoke the installer through `uvx --from orionis-installer orionis ...` and use
55
+ Reactor through the application's Python. Do not overwrite existing executables
56
+ with force flags.
57
+
58
+ For a local build:
59
+
60
+ ```bash
61
+ uv build
62
+ uvx --python 3.14 --from ./dist/orionis_installer-0.1.0-py3-none-any.whl orionis --version
63
+ uvx --python 3.14 --from ./dist/orionis_installer-0.1.0-py3-none-any.whl orionis new blog
64
+ ```
65
+
66
+ ## Interactive wizard
67
+
68
+ After checking prerequisites, the wizard requests:
69
+
70
+ 1. Application name, defaulting to `orionis-app`; `new blog` supplies it directly.
71
+ 2. Description, defaulting to `A modern application built with Orionis Framework.`
72
+ 3. Optional author name and email.
73
+ 4. File storage drivers and, for `all`, the default disk.
74
+ 5. Database drivers and, for `all`, the default connection.
75
+ 6. Confirmation of the absolute destination, Python target, extras and source.
76
+
77
+ Explicit options skip their corresponding questions. After installation, the
78
+ wizard asks about Git initialization (Yes), migrations and initial seeders (No),
79
+ and Visual Studio Code (Yes), in that order. Ctrl+C cancels with exit code 130.
80
+ Without a TTY, use `--no-interaction`; help and version remain available.
81
+
82
+ Names use 1–100 ASCII letters, digits, dots, hyphens and underscores, with
83
+ alphanumeric endpoints. Path separators, traversal, controls and reserved
84
+ Windows names are rejected. Author names and descriptions support Unicode;
85
+ `--path` supports spaces and Unicode. Invalid names are diagnosed without silent
86
+ normalization. An existing destination is always rejected, even when empty.
87
+
88
+ ## Non-interactive use
89
+
90
+ ```bash
91
+ orionis new blog --no-interaction
92
+ orionis new blog --no-interaction --git --no-migrate --no-open
93
+ orionis new analytics --no-interaction --storage s3 --database redshift
94
+ orionis new team --no-interaction --storage all --database all
95
+ orionis new blog --no-interaction --path "./Project with spaces" --author-name "Jane Doe" --author-email jane@example.com
96
+ ```
97
+
98
+ Defaults are `orionis-app`, the description above, no author, local storage and
99
+ SQLite. Aggregate driver selections default to local storage and SQLite unless
100
+ specified otherwise. Git, migrations and the editor are skipped unless their
101
+ positive flags are provided. This mode never requests credentials.
102
+
103
+ ## CLI options
104
+
105
+ `--version`, `--no-color` and `--verbose` are global options. `--no-color` and
106
+ `--verbose` also work after `new`. Other options belong to `new`:
107
+
108
+ | Option | Behavior |
109
+ | --- | --- |
110
+ | `new [NAME]` | Application name and default folder name. |
111
+ | `--path PATH` | Final project location; its parent must exist. |
112
+ | `--description TEXT` | Application description. |
113
+ | `--author-name TEXT`, `--author-email TEXT` | Optional author metadata; empty values omit a field. |
114
+ | `--storage local\|s3\|azure\|gcs\|all` | File storage drivers to install. |
115
+ | `--default-storage local\|s3\|azure\|gcs` | Active disk with `all`; defaults to local. |
116
+ | `--database sqlite\|mysql\|pgsql\|oracle\|sqlserver\|redshift\|all` | Database drivers to install. |
117
+ | `--default-database sqlite\|mysql\|pgsql\|oracle\|sqlserver\|redshift` | Active connection with `all`; defaults to SQLite. |
118
+ | `--git / --no-git` | Initialize Git or skip it. |
119
+ | `--migrate / --no-migrate` | Request migrations and initial seeders or skip them. |
120
+ | `--open / --no-open` | Open Visual Studio Code or skip it. |
121
+ | `--no-interaction` | Apply safe defaults without reading input. |
122
+ | `--no-color` | Disable colors; also respects `NO_COLOR`, including an empty value. |
123
+ | `--verbose` | Show plan diagnostics without raw subprocess output or secrets. |
124
+
125
+ A default driver must be concrete. Without `all`, it can only repeat the selected
126
+ driver. There is no destructive `--force` option.
127
+
128
+ ## Drivers and configuration
129
+
130
+ | Storage selection | Orionis extra |
131
+ | --- | --- |
132
+ | `local` | None |
133
+ | `s3` | `s3` |
134
+ | `azure` | `azure` |
135
+ | `gcs` | `gcs` |
136
+ | `all` | `storage` |
137
+
138
+ | Database selection | Orionis extra |
139
+ | --- | --- |
140
+ | `sqlite` | None |
141
+ | `mysql` | `mysql` |
142
+ | `pgsql` | `pgsql` |
143
+ | `oracle` | `oracle` |
144
+ | `sqlserver` | `sqlserver` |
145
+ | `redshift` | `redshift` |
146
+ | `all` | `database` |
147
+
148
+ Every application includes `factories`. Extras are sorted and deduplicated:
149
+ local + SQLite uses `factories`; S3 + Redshift uses `factories,redshift,s3`; both
150
+ aggregate selections use `database,factories,storage`. Aggregate extras install
151
+ drivers while migrations use one concrete connection. Installing an SDK creates
152
+ no buckets, accounts, permissions or infrastructure.
153
+
154
+ The installer preserves TOML comments, valid dependency groups, the application's
155
+ version and the skeleton's Orionis requirement. The application remains
156
+ unpackaged through `tool.uv.package = false`. `.env.example` is preferred;
157
+ `env.example` is supported. Only verified configuration keys are changed, and the
158
+ example remains intact. External connections and cloud storage require subsequent
159
+ credential configuration. See the [inspected contract](docs/sources.md).
160
+
161
+ APP_KEY is generated by the framework using the project interpreter, without
162
+ `--force`; existing keys are preserved. The official skeleton's administrative
163
+ seeder uses static example credentials, so automatic `--migrate` is blocked
164
+ before data changes. Review the [separate hardening patch](docs/seeder-hardening.patch)
165
+ and configure independent administrator credentials before manually running
166
+ Reactor. The installer does not automatically certify modified seeder code.
167
+
168
+ ## Installation and recovery
169
+
170
+ The installer clones only the official `master` branch into a sibling staging
171
+ area, validates it, records its SHA and removes only that clone's `.git`. It
172
+ configures files before publication and then runs one main
173
+ `uv sync --python 3.14` at the final location. `.venv` is never moved from staging.
174
+ Python, the installed Orionis distribution, extras, lockfile, APP_KEY and effective
175
+ configuration are checked before reporting success.
176
+
177
+ Failures before publication clean only owned staging files. Failures after
178
+ publication preserve the project and report recovery steps. The operation is not
179
+ fully atomic across files, dependencies and database changes. An inherited uv
180
+ workspace or custom `UV_CONFIG_FILE` is rejected to protect isolation; use uv's
181
+ conventional configuration or documented environment variables for network,
182
+ index and download policies. See [security and isolation](docs/security.md).
183
+
184
+ | Exit code | Meaning |
185
+ | --- | --- |
186
+ | `0` | Application ready; requested operations completed or skipped, or confirmation declined. |
187
+ | `1` | Critical download, configuration, publication or installation failure. |
188
+ | `2` | Invalid arguments, missing prerequisites or an incompatible contract. |
189
+ | `3` | Project created, but a requested post-install operation failed. |
190
+ | `130` | User cancellation or end of input. |
191
+
192
+ Git runs only `git init`. It creates no commit, remote or push. Git and editor
193
+ failures preserve the project; independent post-install operations still run
194
+ unless cancelled. A failed migration may have changed data: inspect the database
195
+ before retrying. No automatic rollback or `migrate:fresh` is performed.
196
+
197
+ For a preserved project, review its configuration before recovering:
198
+
199
+ ```bash
200
+ cd blog
201
+ uv sync --python 3.14
202
+ uv run python -B reactor key:generate
203
+ ```
204
+
205
+ Start a ready application:
206
+
207
+ ```bash
208
+ cd blog
209
+ uv run python -B reactor serve
210
+ ```
211
+
212
+ After reviewing the connection and securing the seeders:
213
+
214
+ ```bash
215
+ uv run python -B reactor migrate --seed
216
+ ```
217
+
218
+ ## Development
219
+
220
+ ```bash
221
+ uv sync --locked --python 3.14
222
+ uv run --no-sync ruff check .
223
+ uv run --no-sync ruff format --check .
224
+ uv run --no-sync mypy
225
+ uv run --no-sync pytest --cov=orionis_installer --cov-report=term-missing
226
+ uv build
227
+ uv run --no-sync python scripts/verify_distribution.py
228
+ ```
229
+
230
+ Normal tests use controlled terminal input, disposable processes and explicit
231
+ fixtures. Offline integration uses a local Git repository with simulated uv and
232
+ framework responses; it does not require Orionis or a network connection. The
233
+ distribution verification script installs the wheel into a clean temporary
234
+ environment and creates a disposable application through real uvx.
235
+
236
+ Enable the real smoke test explicitly. It uses the official skeleton, uv and a
237
+ disposable SQLite database, without running the example administrator seeder:
238
+
239
+ ```bash
240
+ ORIONIS_REAL_SMOKE=1 uv run --no-sync pytest -m smoke -v
241
+ ```
242
+
243
+ ```powershell
244
+ $env:ORIONIS_REAL_SMOKE = '1'
245
+ uv run --no-sync pytest -m smoke -v
246
+ Remove-Item Env:ORIONIS_REAL_SMOKE
247
+ ```
248
+
249
+ [CI](.github/workflows/ci.yml) checks Python 3.14 on Ubuntu, Windows and macOS,
250
+ including lint, formatting, types, tests, build and the clean-wheel entry point.
251
+ Runtime checks on an individual machine do not verify the other platforms or
252
+ external cloud/database services. CI does not publish the package.
253
+
254
+ Follow the English, typed documentation style of
255
+ [Orionis commands](https://github.com/orionis-framework/framework/blob/1.x/orionis/console/commands/support/key_generate.py)
256
+ and [configuration entities](https://github.com/orionis-framework/framework/blob/1.x/orionis/foundation/config/database/entities/connections.py).
257
+ Use concise triple-double-quoted NumPy docstrings for every function and method,
258
+ including private helpers and callbacks. Start with an imperative sentence;
259
+ include relevant Parameters, Returns, Yields and Raises sections, without an
260
+ Examples section. Ruff enforces the NumPy convention and D401; an AST-based test
261
+ checks documentation coverage for nested and private functions as well.
262
+
263
+ Source lives in `src/orionis_installer`; unit and integration tests live in
264
+ `tests`; technical contracts and policies live in `docs`; distribution verification
265
+ lives in `scripts`. Message catalogs remain centralized in `messages.py` and
266
+ `ui/messages.py`. Dependency constraints are declared in [pyproject.toml](pyproject.toml)
267
+ and development resolutions in [uv.lock](uv.lock). License: [MIT](LICENCE).
268
+
269
+ ## Releasing to PyPI
270
+
271
+ Update the version in `pyproject.toml` and `src/orionis_installer/__init__.py`
272
+ together before a release. Configure PyPI authentication through
273
+ `UV_PUBLISH_TOKEN` or another [supported uv authentication method](https://docs.astral.sh/uv/guides/package/#publishing-your-package).
274
+ Run the root release script from PowerShell:
275
+
276
+ ```powershell
277
+ .\release.ps1
278
+ ```
279
+
280
+ The script requires `main` and an `origin` remote. It reads the manifest version,
281
+ cleans old builds, synchronizes Python 3.14, builds wheel/sdist, publishes to PyPI,
282
+ stages all changes, commits the release and pushes `main`. Versions with a major
283
+ component of at least 1 also create and push `v<version>` after checking for tag
284
+ conflicts. Successful releases clean generated builds. Failures stop the remaining
285
+ steps and retain artifacts for inspection or retry; completed uploads and Git
286
+ operations are not rolled back.
@@ -0,0 +1,266 @@
1
+ # Orionis Installer
2
+
3
+ `orionis-installer` creates applications from the official Orionis skeleton on
4
+ `master`, with Python **3.14.x**, a project-local `.venv` and `uv.lock`. Its Python
5
+ module is `orionis_installer` and its executable is **`orionis`**.
6
+
7
+ The installer depends on CLI and configuration libraries. Orionis, database
8
+ drivers, cloud SDKs and Faker belong to the generated application's environment.
9
+ The English wizard supports arrow keys, Enter, visible defaults and immediate
10
+ validation. Its ASCII banner adapts to narrow terminals; `NO_COLOR` and
11
+ `--no-color` disable colors.
12
+
13
+ ## Installation
14
+
15
+ Install [uv](https://docs.astral.sh/uv/getting-started/installation/) and
16
+ [Git](https://git-scm.com/downloads). Python 3.14 or newer runs the installer; uv
17
+ selects stable Python 3.14.x for the application and can obtain it according to
18
+ its download and network policies.
19
+
20
+ When this distribution is available on your package index:
21
+
22
+ ```bash
23
+ uvx --from orionis-installer orionis new
24
+ uvx --from orionis-installer orionis new blog
25
+ uvx --python 3.14 --from orionis-installer orionis new
26
+ uv tool install --python 3.14 orionis-installer
27
+ orionis new blog
28
+ orionis --help
29
+ orionis --version
30
+ ```
31
+
32
+ `uvx --python 3.14` selects the **installer's** interpreter. The application has an
33
+ independent environment. The framework can also provide an `orionis` executable;
34
+ invoke the installer through `uvx --from orionis-installer orionis ...` and use
35
+ Reactor through the application's Python. Do not overwrite existing executables
36
+ with force flags.
37
+
38
+ For a local build:
39
+
40
+ ```bash
41
+ uv build
42
+ uvx --python 3.14 --from ./dist/orionis_installer-0.1.0-py3-none-any.whl orionis --version
43
+ uvx --python 3.14 --from ./dist/orionis_installer-0.1.0-py3-none-any.whl orionis new blog
44
+ ```
45
+
46
+ ## Interactive wizard
47
+
48
+ After checking prerequisites, the wizard requests:
49
+
50
+ 1. Application name, defaulting to `orionis-app`; `new blog` supplies it directly.
51
+ 2. Description, defaulting to `A modern application built with Orionis Framework.`
52
+ 3. Optional author name and email.
53
+ 4. File storage drivers and, for `all`, the default disk.
54
+ 5. Database drivers and, for `all`, the default connection.
55
+ 6. Confirmation of the absolute destination, Python target, extras and source.
56
+
57
+ Explicit options skip their corresponding questions. After installation, the
58
+ wizard asks about Git initialization (Yes), migrations and initial seeders (No),
59
+ and Visual Studio Code (Yes), in that order. Ctrl+C cancels with exit code 130.
60
+ Without a TTY, use `--no-interaction`; help and version remain available.
61
+
62
+ Names use 1–100 ASCII letters, digits, dots, hyphens and underscores, with
63
+ alphanumeric endpoints. Path separators, traversal, controls and reserved
64
+ Windows names are rejected. Author names and descriptions support Unicode;
65
+ `--path` supports spaces and Unicode. Invalid names are diagnosed without silent
66
+ normalization. An existing destination is always rejected, even when empty.
67
+
68
+ ## Non-interactive use
69
+
70
+ ```bash
71
+ orionis new blog --no-interaction
72
+ orionis new blog --no-interaction --git --no-migrate --no-open
73
+ orionis new analytics --no-interaction --storage s3 --database redshift
74
+ orionis new team --no-interaction --storage all --database all
75
+ orionis new blog --no-interaction --path "./Project with spaces" --author-name "Jane Doe" --author-email jane@example.com
76
+ ```
77
+
78
+ Defaults are `orionis-app`, the description above, no author, local storage and
79
+ SQLite. Aggregate driver selections default to local storage and SQLite unless
80
+ specified otherwise. Git, migrations and the editor are skipped unless their
81
+ positive flags are provided. This mode never requests credentials.
82
+
83
+ ## CLI options
84
+
85
+ `--version`, `--no-color` and `--verbose` are global options. `--no-color` and
86
+ `--verbose` also work after `new`. Other options belong to `new`:
87
+
88
+ | Option | Behavior |
89
+ | --- | --- |
90
+ | `new [NAME]` | Application name and default folder name. |
91
+ | `--path PATH` | Final project location; its parent must exist. |
92
+ | `--description TEXT` | Application description. |
93
+ | `--author-name TEXT`, `--author-email TEXT` | Optional author metadata; empty values omit a field. |
94
+ | `--storage local\|s3\|azure\|gcs\|all` | File storage drivers to install. |
95
+ | `--default-storage local\|s3\|azure\|gcs` | Active disk with `all`; defaults to local. |
96
+ | `--database sqlite\|mysql\|pgsql\|oracle\|sqlserver\|redshift\|all` | Database drivers to install. |
97
+ | `--default-database sqlite\|mysql\|pgsql\|oracle\|sqlserver\|redshift` | Active connection with `all`; defaults to SQLite. |
98
+ | `--git / --no-git` | Initialize Git or skip it. |
99
+ | `--migrate / --no-migrate` | Request migrations and initial seeders or skip them. |
100
+ | `--open / --no-open` | Open Visual Studio Code or skip it. |
101
+ | `--no-interaction` | Apply safe defaults without reading input. |
102
+ | `--no-color` | Disable colors; also respects `NO_COLOR`, including an empty value. |
103
+ | `--verbose` | Show plan diagnostics without raw subprocess output or secrets. |
104
+
105
+ A default driver must be concrete. Without `all`, it can only repeat the selected
106
+ driver. There is no destructive `--force` option.
107
+
108
+ ## Drivers and configuration
109
+
110
+ | Storage selection | Orionis extra |
111
+ | --- | --- |
112
+ | `local` | None |
113
+ | `s3` | `s3` |
114
+ | `azure` | `azure` |
115
+ | `gcs` | `gcs` |
116
+ | `all` | `storage` |
117
+
118
+ | Database selection | Orionis extra |
119
+ | --- | --- |
120
+ | `sqlite` | None |
121
+ | `mysql` | `mysql` |
122
+ | `pgsql` | `pgsql` |
123
+ | `oracle` | `oracle` |
124
+ | `sqlserver` | `sqlserver` |
125
+ | `redshift` | `redshift` |
126
+ | `all` | `database` |
127
+
128
+ Every application includes `factories`. Extras are sorted and deduplicated:
129
+ local + SQLite uses `factories`; S3 + Redshift uses `factories,redshift,s3`; both
130
+ aggregate selections use `database,factories,storage`. Aggregate extras install
131
+ drivers while migrations use one concrete connection. Installing an SDK creates
132
+ no buckets, accounts, permissions or infrastructure.
133
+
134
+ The installer preserves TOML comments, valid dependency groups, the application's
135
+ version and the skeleton's Orionis requirement. The application remains
136
+ unpackaged through `tool.uv.package = false`. `.env.example` is preferred;
137
+ `env.example` is supported. Only verified configuration keys are changed, and the
138
+ example remains intact. External connections and cloud storage require subsequent
139
+ credential configuration. See the [inspected contract](docs/sources.md).
140
+
141
+ APP_KEY is generated by the framework using the project interpreter, without
142
+ `--force`; existing keys are preserved. The official skeleton's administrative
143
+ seeder uses static example credentials, so automatic `--migrate` is blocked
144
+ before data changes. Review the [separate hardening patch](docs/seeder-hardening.patch)
145
+ and configure independent administrator credentials before manually running
146
+ Reactor. The installer does not automatically certify modified seeder code.
147
+
148
+ ## Installation and recovery
149
+
150
+ The installer clones only the official `master` branch into a sibling staging
151
+ area, validates it, records its SHA and removes only that clone's `.git`. It
152
+ configures files before publication and then runs one main
153
+ `uv sync --python 3.14` at the final location. `.venv` is never moved from staging.
154
+ Python, the installed Orionis distribution, extras, lockfile, APP_KEY and effective
155
+ configuration are checked before reporting success.
156
+
157
+ Failures before publication clean only owned staging files. Failures after
158
+ publication preserve the project and report recovery steps. The operation is not
159
+ fully atomic across files, dependencies and database changes. An inherited uv
160
+ workspace or custom `UV_CONFIG_FILE` is rejected to protect isolation; use uv's
161
+ conventional configuration or documented environment variables for network,
162
+ index and download policies. See [security and isolation](docs/security.md).
163
+
164
+ | Exit code | Meaning |
165
+ | --- | --- |
166
+ | `0` | Application ready; requested operations completed or skipped, or confirmation declined. |
167
+ | `1` | Critical download, configuration, publication or installation failure. |
168
+ | `2` | Invalid arguments, missing prerequisites or an incompatible contract. |
169
+ | `3` | Project created, but a requested post-install operation failed. |
170
+ | `130` | User cancellation or end of input. |
171
+
172
+ Git runs only `git init`. It creates no commit, remote or push. Git and editor
173
+ failures preserve the project; independent post-install operations still run
174
+ unless cancelled. A failed migration may have changed data: inspect the database
175
+ before retrying. No automatic rollback or `migrate:fresh` is performed.
176
+
177
+ For a preserved project, review its configuration before recovering:
178
+
179
+ ```bash
180
+ cd blog
181
+ uv sync --python 3.14
182
+ uv run python -B reactor key:generate
183
+ ```
184
+
185
+ Start a ready application:
186
+
187
+ ```bash
188
+ cd blog
189
+ uv run python -B reactor serve
190
+ ```
191
+
192
+ After reviewing the connection and securing the seeders:
193
+
194
+ ```bash
195
+ uv run python -B reactor migrate --seed
196
+ ```
197
+
198
+ ## Development
199
+
200
+ ```bash
201
+ uv sync --locked --python 3.14
202
+ uv run --no-sync ruff check .
203
+ uv run --no-sync ruff format --check .
204
+ uv run --no-sync mypy
205
+ uv run --no-sync pytest --cov=orionis_installer --cov-report=term-missing
206
+ uv build
207
+ uv run --no-sync python scripts/verify_distribution.py
208
+ ```
209
+
210
+ Normal tests use controlled terminal input, disposable processes and explicit
211
+ fixtures. Offline integration uses a local Git repository with simulated uv and
212
+ framework responses; it does not require Orionis or a network connection. The
213
+ distribution verification script installs the wheel into a clean temporary
214
+ environment and creates a disposable application through real uvx.
215
+
216
+ Enable the real smoke test explicitly. It uses the official skeleton, uv and a
217
+ disposable SQLite database, without running the example administrator seeder:
218
+
219
+ ```bash
220
+ ORIONIS_REAL_SMOKE=1 uv run --no-sync pytest -m smoke -v
221
+ ```
222
+
223
+ ```powershell
224
+ $env:ORIONIS_REAL_SMOKE = '1'
225
+ uv run --no-sync pytest -m smoke -v
226
+ Remove-Item Env:ORIONIS_REAL_SMOKE
227
+ ```
228
+
229
+ [CI](.github/workflows/ci.yml) checks Python 3.14 on Ubuntu, Windows and macOS,
230
+ including lint, formatting, types, tests, build and the clean-wheel entry point.
231
+ Runtime checks on an individual machine do not verify the other platforms or
232
+ external cloud/database services. CI does not publish the package.
233
+
234
+ Follow the English, typed documentation style of
235
+ [Orionis commands](https://github.com/orionis-framework/framework/blob/1.x/orionis/console/commands/support/key_generate.py)
236
+ and [configuration entities](https://github.com/orionis-framework/framework/blob/1.x/orionis/foundation/config/database/entities/connections.py).
237
+ Use concise triple-double-quoted NumPy docstrings for every function and method,
238
+ including private helpers and callbacks. Start with an imperative sentence;
239
+ include relevant Parameters, Returns, Yields and Raises sections, without an
240
+ Examples section. Ruff enforces the NumPy convention and D401; an AST-based test
241
+ checks documentation coverage for nested and private functions as well.
242
+
243
+ Source lives in `src/orionis_installer`; unit and integration tests live in
244
+ `tests`; technical contracts and policies live in `docs`; distribution verification
245
+ lives in `scripts`. Message catalogs remain centralized in `messages.py` and
246
+ `ui/messages.py`. Dependency constraints are declared in [pyproject.toml](pyproject.toml)
247
+ and development resolutions in [uv.lock](uv.lock). License: [MIT](LICENCE).
248
+
249
+ ## Releasing to PyPI
250
+
251
+ Update the version in `pyproject.toml` and `src/orionis_installer/__init__.py`
252
+ together before a release. Configure PyPI authentication through
253
+ `UV_PUBLISH_TOKEN` or another [supported uv authentication method](https://docs.astral.sh/uv/guides/package/#publishing-your-package).
254
+ Run the root release script from PowerShell:
255
+
256
+ ```powershell
257
+ .\release.ps1
258
+ ```
259
+
260
+ The script requires `main` and an `origin` remote. It reads the manifest version,
261
+ cleans old builds, synchronizes Python 3.14, builds wheel/sdist, publishes to PyPI,
262
+ stages all changes, commits the release and pushes `main`. Versions with a major
263
+ component of at least 1 also create and push `v<version>` after checking for tag
264
+ conflicts. Successful releases clean generated builds. Failures stop the remaining
265
+ steps and retain artifacts for inspection or retry; completed uploads and Git
266
+ operations are not rolled back.