Contributing
Running from source
No PyPI dependency is required for the application runtime — NativeDev uses the distro-provided PyGObject/GTK4 bindings.
sudo apt update
sudo apt install python3 python3-gi gir1.2-gtk-4.0 pkexec
./run.shrun.sh explicitly opts into the source-tree privileged helper; this only exists for local development, and installed builds never use a user-writable helper. See Security model.
Running the tests
The core test suite does not import GTK, so it runs anywhere Python 3.10+ is available — no display server required:
python3 -m unittest discover -s tests -vSyntax/compile check:
python3 -m compileall -q srcPushing a version tag such as v0.2.2 triggers the release workflow, which validates the tag against the source version, runs this same test suite, builds the .deb, and publishes the GitHub Release — so a change that breaks the test suite also blocks a release.
Coding conventions this project follows
These are load-bearing conventions, not style preferences — code review and the test suite both assume them:
- No
shell=True, ever. Allsubprocesscalls use argv lists. If a change needs to build a command from user-influenced input, build the argv list directly; do not construct a shell string. - Root only executes fixed, named operations. New privileged functionality is added as a new semantic operation in
privileged_helper.pywith its own input validation on the root side — never as a way to let the GUI send an arbitrary path, package name, or SQL fragment. See Security model andproject-summary.mdin the repository root for the existing operation catalog. - Validate identifiers with fixed patterns, not blocklists. Database usernames/passwords and PHP INI directive names are checked against fixed allow-pattern regular expressions (see
managers/database_access.pyandmanagers/php.py), not by trying to strip or escape dangerous characters after the fact. - Simulate destructive APT operations before running them. Removing a PHP version, a PHP extension, or migrating away from System Node all run
apt-get -s removefirst and cross-reference the result againstapt-mark showmanual, so a manually installed package is never swept away as an unannounced side effect. If you add a new APT removal path, follow the sameremoval_impact-style pattern used inmanagers/php_extensions.py,managers/node.py, andmanagers/php.pyrather than callingapt-get removedirectly. - Managers stay GTK-free. Business logic belongs in
managers/,controller.py, andsystem.py, all of which have no GTK import.gui.pyshould only call into that layer and render its results. - Cross-manager invariants live in the controller. If a change to one manager's state needs another manager to react (for example, a PHP default change needing Nginx regenerated), add that sequencing to
NativeDevControllerrather than having the GUI call both managers directly. - Long-running/mutating operations are serialized. All mutations go through one global lock so two privileged operations can never race; read-only probes may run concurrently. Keep new mutating operations inside that same serialization point.
- Fail closed, not silently. Prefer raising a clear
RuntimeErrorwith an actionable message over catching an exception and continuing as if nothing happened, especially anywhere close to the privilege boundary.
Changelog
User-visible changes are recorded in CHANGELOG.md at the repository root, newest first. Add an entry there alongside any behavioral change.
Submitting a change
- Fork the repository and branch from
main. - Make your change, keeping the conventions above in mind.
- Add or update tests under
tests/—python3 -m unittest discover -s tests -vshould pass with 0 failures. - Update
CHANGELOG.mdand any affected page underdocs/. - Open a pull request against
sayedsahin/nativedevdescribing the change and, for anything touching the privileged helper or an APT/systemd/database code path, explicitly what you tested it against.
Where to look first
- Architecture — the layered model before touching any manager
- Security model — required reading before touching
privileged_helper.pyorsystem.py project-summary.md(repository root) — a condensed architecture handoff document with the full privileged-operation catalog