Table of Contents
- Fork the Project.
- Create your Feature Branch (
git checkout -b feature_name). - Commit your Changes (
git commit -a -m "a wonderful new feature"). - Push to the Branch (
git push origin feature_name). - Open a Pull Request.
plugin_src/PyCharmRemoteDebug/
Source/ editor module: menu + Project Settings
Content/Python/pycharmremotedebug/ bridge.py, session.py - all pydevd calls
scripts/package_plugin.py builds the release zip
tests/unit/ pytest suite (CI)
tests/uat/ run by hand in the editor
docs/ user-facing docs site, see Documentation
mkdocs.yml docs site config
settrace() must run inside Unreal's embedded interpreter, hence the split.
Dependencies live in pyproject.toml and are pinned by
uv.lock. The plugin itself ships none - it uses the standard library,
the unreal module and pydevd from your PyCharm install - so the groups are
tooling only: dev (ruff, mypy), test (pytest), docs (mkdocs).
- Install uv.
- Create the environment (reads .python-version and the lock):
uv sync --group dev --group test --group docs - Add or change a dependency in
pyproject.toml, then re-lock:uv lock
Commit uv.lock with the change. Commands below use uv run, which syncs the
environment first, so an explicit uv sync is only needed to prepare an IDE.
Python changes need only an editor restart. C++ changes need a build - the editor rebuilds a plugin only when its binary is missing or engine-incompatible.
Point a test project at this repo:
Build with the editor closed:
# macOS
<Engine>/Build/BatchFiles/Mac/Build.sh <Project>Editor Mac Development \
-Project="<path>/<Project>.uproject" -Progress
# Windows
<Engine>\Build\BatchFiles\Build.bat <Project>Editor Win64 Development ^
-Project="<path>\<Project>.uproject" -Progress- Target is
<Project>Editor, notUnrealEditor. - Adding
-TargetType=Editorto that fails withActionGraphInvalid. UPROPERTYnames reach Python snake-cased:PyCharmPath->py_charm_path.
Continuous integration is set up with GitHub Actions, workflows can be found in the .github/workflows directory.
- ci-main.yml runs tests, performs linting, formatting, and type hinting checks. It runs automatically on every push and pull request to main or can be triggered from the
Run workflowbutton on the actions menu. - docs.yml builds and publishes the docs site, see Documentation. Runs on push to main when
docs/ormkdocs.ymlchange, or manually. - release.yml packages a release, see Releasing. Manual trigger only.
Neither compiles the plugin - hosted runners have no Unreal. Verify C++ locally.
Tests are written with Pytest and should adhere to the "Arrange, Act, Assert" pattern.
To run tests locally:
-
uv run --group test pytest
with coverage:
-
uv run --group test pytest --cov=plugin_src/PyCharmRemoteDebug/Content/Python
tests/unit is what CI runs; unreal is mocked. tests/uat is run by hand from
the editor's Python console against a live session.
Static code analysis and formatting are performed with Ruff, and type hinting with mypy.
To run ruff's linter locally:
-
uv run --group dev ruff check plugin_src/PyCharmRemoteDebug/Content/Python/ scripts/
- Rule selection lives in pyproject.toml's
[tool.ruff.lint]. Append toselectas needed.
- Rule selection lives in pyproject.toml's
Ruff's formatter can be run locally with:
-
uv run --group dev ruff format plugin_src/PyCharmRemoteDebug/Content/Python/ scripts/
Run mypy checks locally with:
-
uv run --group dev mypy plugin_src/PyCharmRemoteDebug/Content/Python/ scripts/
- Overrides live in pyproject.toml's
[[tool.mypy.overrides]]to ignore missing imports forunreal,pydevd, andpydevd_pycharm. Append to this table as needed.
- Overrides live in pyproject.toml's
The user-facing docs site is built with MkDocs and
Material for MkDocs from the
docs/ directory, configured in mkdocs.yml. README.md and
CONTRIBUTING.md stay repo-only; anything a plugin user needs (installation,
usage, remote setup) belongs in docs/ instead.
Preview locally with live reload:
-
uv run --group docs mkdocs serve
docs.yml builds and publishes the site to GitHub
Pages on every push to main that touches docs/ or mkdocs.yml. To check the
build without publishing:
-
uv run --group docs mkdocs build --strict
Run release.yml from the Run workflow button:
| input | example | meaning |
|---|---|---|
version |
1.2.0 |
must be major.minor.patch |
engine_versions |
5.6,5.7 |
one zip per entry |
draft |
true |
create the release as a draft |
Tests and static analysis run first, then PyCharmRemoteDebug-<version>-UE<engine>.zip
is attached to a v<version> release. Each zip is the plugin folder at the archive
root, build output stripped - the layout Fab expects, since Fab distributes source
and Epic compiles it. Only the staged .uplugin is stamped, never the repo's.
Same artifacts locally:
uv run scripts/package_plugin.py --plugin-dir plugin_src/PyCharmRemoteDebug \
--output-dir dist --version 1.2.0 --engine-versions "5.7"Nothing verifies the plugin compiles on the engine versions you list. Build against them locally first.