-
Existing issues — Before opening a new issue, check if a similar issue or feature request already exists.
-
Expected behavior — If you are unsure whether the behavior you are encountering is expected, check the documentation at https://docs.hashtopolis.org. You can also check the FAQ to see if your problem is already addressed there.
-
Coding style — Follow the existing coding style and conventions used throughout the project.
-
Test coverage — Include tests for your changes. Depending on the case this means PHPUnit tests, pytest tests for the API, or both if necessary.
-
Documentation — Document your code using PHPDoc for PHP code or inline comments where necessary.
-
PR titles should be phrased as an imperative sentence describing what was added, fixed, or changed (e.g., "Add user authentication", "Fix memory leak in worker pool", "Update dependency versions").
-
Issues — Every pull request that resolves an issue must reference it in the description using a closing keyword (e.g.,
closes #123,fixes #456). -
Branch cleanup — The person merging the pull request is responsible for deleting the branch after the merge.
When submitting a pull request that includes database migration scripts, adhere to the following:
-
Never alter an existing migration script that has been released or lived on
masterfor any amount of time. Changing a released migration will leave setups that already applied the unaltered script in an inconsistent state that cannot be recovered without manual intervention or deletion. -
One migration per atomic change — Create a new migration script for each distinct feature or change. The database must be in a healthy, consistent state between every migration.
-
Dual database support — New migration scripts must be provided for both MySQL and PostgreSQL in their respective directories (
src/migrations/mysql/andsrc/migrations/postgres/). -
Timestamp ordering — Right before a PR with new migration scripts is merged, the script file names must be updated to reflect the actual merge date prefix. This ensures correct ordering across concurrent PRs. Commit this rename into the PR branch before merging.
The dev Docker image (hashtopolis-server-dev) installs xdebug via PIE (PHP Installer for Extensions), which is the official replacement for the now-deprecated PECL.
- PIE is downloaded as a pinned PHAR (
1.4.8) from the GitHub releases, verified with a SHA-256 checksum, and placed at/usr/local/bin/pie. - xdebug is installed with
pie install --skip-enable-extension xdebug/xdebug:3.5.3(version-pinned). The--skip-enable-extensionflag prevents PIE from writing its own ini; a customxdebug.iniis written instead with the project's debug settings (xdebug.mode = debug,xdebug.client_port = 9003,xdebug.idekey = PHPSTORM). - Build deps
libtoolandunzipare installed via apt in the sameRUNblock (PIE needs them; pecl didn't).
To bump xdebug or PIE, edit the Dockerfile and update both the version pin (xdebug/xdebug:<version>) and — if bumping PIE — the PHAR URL + SHA-256. The SHA-256 of a release PHAR can be obtained with curl -fL https://github.com/php/pie/releases/download/<version>/pie.phar | sha256sum.
The pytest suite in ci/apiv2/ uses pinned dependencies installed into a virtualenv at /opt/venv inside the dev container (see Dockerfile). The venv's bin/ is prepended to PATH, so pytest and python3 resolve to the venv automatically — no manual activation needed.
ci/apiv2/requirements.in— the human-edited list of direct dependencies (with constraints, e.g.pytest>=8,<10). Edit this file to add, remove, or constrain a dependency.ci/apiv2/requirements.txt— the fully resolved, transitively pinned lock file (with hashes), generated bypip-compile. Never hand-edit this file; regenerate it instead.
To update a dependency (run inside the dev container or anywhere with pip-tools):
pip install pip-tools
cd ci/apiv2
pip-compile --generate-hashes --output-file requirements.txt requirements.in
Then commit both requirements.in and the regenerated requirements.txt.
The python-hashtopolis git dependency is intentionally not pinned (it always installs the newest commit from main).
Because a floating git URL cannot be hashed, it is installed separately into the venv in the Dockerfile rather than from requirements.txt.
To pin it to a specific commit instead, add git+https://github.com/hashtopolis/python-hashtopolis.git@<sha> to requirements.in and remove the separate pip install line from the Dockerfile.
The docs build workflows (.github/workflows/docs.yml and .github/workflows/docs-build.yml) use pinned MkDocs dependencies:
doc/requirements.in- the human-edited list of direct dependencies (mkdocs and the plugins enabled inmkdocs.yml). Edit this file to add, remove, or constrain a dependency. When adding a new plugin tomkdocs.yml, also add it here.doc/requirements.txt- the fully resolved, transitively pinned lock file (with hashes), generated bypip-compile. Never hand-edit this file; regenerate it instead.
To update a dependency:
pip install pip-tools
cd doc
pip-compile --generate-hashes --output-file requirements.txt requirements.in
Then commit both requirements.in and the regenerated requirements.txt.
Note: doc/requirements.txt must be compiled with Python 3.10 to match the setup-python version in the workflows. Use a matching environment when regenerating.