# Contributing > Project layout, build, and release flow. **If you only want to use the tool — read [README](README.md) instead.** ## Repo layout ``` vrcx/ ├── .github/ │ ├── workflows/release.yml ← CI: tag-driven build + GitHub Release │ └── ISSUE_TEMPLATE/ ← bug / feature / security routing ├── dev/ ← current work (everything code-related lives here) │ ├── src/vrcx/ │ │ ├── __init__.py ← single source of truth for __version__ │ │ ├── __main__.py ← entry: python -m vrcx │ │ ├── app.py ← orchestration: config, prompts, threads, packaging │ │ ├── config.py ← config.ini next to the exe (first-run prompt) │ │ ├── i18n.py ← EN/RU translation table + t() helper │ │ ├── platform_win.py ← VT enable │ │ ├── update_check.py ← GitHub /releases/latest poll (returns tag) │ │ ├── commands.py ← BMC artefacts table │ │ ├── bmc.py ← BmcSession (SSH + Redfish helper) │ │ ├── collector.py ← per-host BMC collect loop │ │ ├── os_commands.py ← SDS-host artefacts table │ │ ├── sds.py ← SdsSession (SSH + sudo -S + SFTP) │ │ ├── os_collector.py ← per-host OS collect loop │ │ ├── discover.py ← Redfish-MAC → ARP → SDS IP │ │ ├── tarball.py ← layout, per-host & session tar.gz │ │ └── ui.py ← rich-based TUI │ ├── assets/icon.ico ← embedded app icon │ ├── tools/make_icon.ps1 ← regenerate the icon │ ├── vrcx-launcher.py ← PyInstaller entry (absolute import) │ ├── vrcx.spec ← PyInstaller spec (gitignored) │ └── pyproject.toml ├── prod/ ← last stable portable build (gitignored) ├── old/ ← previous portable builds, kept for rollback ├── CHANGELOG.md / CONTRIBUTING.md / LICENSE / README.md / README.ru.md / SECURITY.md └── .gitignore ``` `dev/` / `prod/` / `old/` is a workflow convention: new changes land in `dev/`, the validated build is copied into `prod/`, the previous `prod/` is archived under `old/`. ## Run from source ``` python -m pip install rich paramiko PYTHONPATH=dev/src python -m vrcx ``` ## Editable install ``` cd dev python -m pip install -e . vrcx ``` ## Build the portable .exe ``` python -m pip install pyinstaller rich paramiko python -m PyInstaller --onefile --console --name vrcx \ --icon dev/assets/icon.ico \ --paths dev/src dev/vrcx-launcher.py ``` ## Cut a release 1. Bump `dev/src/vrcx/__init__.py` → `__version__ = "X.Y.Z"`. 2. Update `CHANGELOG.md` — move items from `[Unreleased]` into a new `[X.Y.Z]` section with today's date. 3. Commit: `git commit -am "vX.Y.Z: …"`. 4. Tag: `git tag vX.Y.Z`. 5. Push: `git push && git push --tags`. CI builds the exe and creates the GitHub Release with the zip attached. ## Where features go | Adding... | Touch this module | |---|---| | New BMC artefact | `commands.py` → one new `CommandSpec` row | | New SDS-host artefact | `os_commands.py` → one new `OsCommandSpec` row | | Support for a new BMC API (e.g. IPMI) | `bmc.py` → add a method on `BmcSession`; reference it from `commands.py` with a new `kind` | | Different discovery strategy | `discover.py` | | New per-host UI column / progress detail | `ui.py` → `Ui._render_table` + `set_progress` | | Different output naming or layout | `tarball.py` | | New configuration knob | `config.py` (add field + parser line) and use it from `app.py` | | New translated string | `i18n.py` — add the key to both `en` and `ru` | | Tweaking the startup banner / prompts | `app.py` → `main` / `_prompt_inputs` |