Skip to content

Development (Basic)

1. Clone the repository

git clone https://github.com/MarkusThill/BitBully.git
cd BitBully
git submodule update --init --recursive   # Initialize and update submodules

BitBully uses submodules, so make sure to always clone with them initialized. If you already cloned earlier without them, run:

git submodule update --remote --merge
python -m venv .venv
source .venv/bin/activate      # Linux/Mac
# or
.\.venv\Scripts\activate       # Windows

3. Install development dependencies

pip install -e .[dev]

This installs BitBully in editable mode plus all development tooling (ruff, mypy, pytest, coverage, commitizen, pre-commit, etc.).

4. Install Git hooks (pre-commit)

pre-commit install --hook-type pre-commit --hook-type commit-msg --hook-type pre-push

This activates:

  • pre-commit: formatting, linting, static checks before each commit
  • commit-msg: Commitizen / conventional commit message validation
  • pre-push: optional checks before pushing (e.g., running tests)

To run all hooks manually:

pre-commit run --all-files

5. Running tests

pytest tests/ -vv

6. Building wheels locally (optional)

python -m build

Testing and CI

Running Tests

Run unit tests using pytest:

pytest tests/

For more detailed output:

pytest tests/ -v          # verbose: show each test
pytest tests/ -vv         # very verbose: show full node IDs

Run only tests matching a pattern:

# A boolean expression that selects tests:
#   - containing the substring board
#   - but not containing the substring slow
pytest tests/ -k "board and not slow"
pytest tests/test_opening_book_core.py

Run a specific test case:

pytest tests/test_board_core_basic.py::test_can_win_1

Stop after the first failure:

pytest tests/ -x

Run with coverage (requires pytest-cov):

pytest tests/ --cov=bitbully --cov-report=term-missing

GitHub Actions

This project uses GitHub Actions to build and test the library. The CI workflow includes:

  • Building wheels for Linux and Windows using cibuildwheel.
  • Building source distributions (sdist).
  • Optionally uploading artifacts to PyPI.

The workflows are found under .github/workflows/.


Contributing

Contributions are welcome! Follow these steps:

  1. Fork the repository.
  2. Create a new branch for your changes:
    git checkout -b feature-name
    
  3. Install dev dependencies:
    pip install -e .[dev]
    
  4. Install pre-commit hooks:
    pre-commit install --hook-type pre-commit --hook-type commit-msg --hook-type pre-push
    
  5. Commit your changes:
    git commit -m "feat: Add feature or fix description"
    
  6. Push to your branch:
    git push origin feature-name
    
  7. Open a pull request.

Development

Usual Push Procedure

If possible, also try the build on a windows-native machine since there are some subtle differences in the build process:

pytest tests/ # ensure that tests run through
mv dist/ dist.old # if applicable
python -m build # local build should pass
cibuildwheel --output-dir dist # now build for the other specified platforms
twine check dist/* # Check package metadata in dist folder
twine check dist/* --strict # Check package metadata in dist folder (strict)
git add -u # or add whatever you want to commit
pre-commit run # make sure that this passes
git commit -m "fix|feat|docs|...: message" # commit using semantic versioning
cz bump --dry-run
cz bump
git push --atomic origin master vx.x.x # make sure that you set the correct version
# build will now be performed on GitHub Runners

In case you run into an error during cibuildwheel, like

CMake Error: The current CMakeCache.txt directory /project/build/temp.linux-x86_64-cpython-312/CMakeCache.txt is different than the directory /workspaces/BitBully/build/temp.linux-x86_64-cpython-312 where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
CMake Error: The source "/project/CMakeLists.txt" does not match the source "/workspaces/BitBully/CMakeLists.txt" used to generate cache.  Re-run cmake with a different source directory.

it might help to clean up old builds:

rm -rf build/ dist/ src/bitbully/*.so src/bitbully/assets/*.so

You can also build pre-release versions like this.

cz bump --prerelease alpha   # Creates 1.2.3a0 if current is 1.2.3
cz bump --prerelease beta
cz bump --prerelease rc
cz bump --prerelease rc --increment minor # To bump the minor version and start a pre-release

In this case, after pushing to the repository, only a small build for Python3.11 is performed and the results wheels are pushed to Test-PyPI instead of the real PyPi.

Generating Python Type Stubs for Pybind11 Modules

To enable type checking with tools like mypy for Pybind11 compiled modules, you can generate a .pyi stub file using pybind11-stubgen. For example:

pip install pybind11-stubgen
pybind11-stubgen bitbully.bitbully_core -o src/

Notes

The generated .pyi file contains function and class signatures with type hints, which helps mypy and other type checkers.

Compiler

The code was compiled with: gcc 13.1.0

Configure gov-13 to match g++-13/gcc-13

The version of gcov has to match our compiler version, in order to be able to produce coverage reports:

sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-11 50 # for compiler version 11
sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-13 100 # for compiler version 13 (as we have here)
sudo update-alternatives --config gcov

Development (Debian-based Systems)

Install Python 3

sudo apt install python3.11
sudo apt install python3.11-venv

Configure alternatives, if you have other versions of python installed:

sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.11 2
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2

sudo update-alternatives --config python

sudo update-alternatives --config python3

Install & Activate virtualenv

python3 -m venv venv
source venv/bin/activate

Install Dependencies

pip install -e .[dev,ci]
pre-commit install
pre-commit install --hook-type commit-msg --hook-type pre-push

You can run pre-commit before a commit with:

pre-commit run

Commitizen

Bump Version

cz bump --dry-run # first perform a dry run
cz bump
git push origin tag x.x.x

Push commit and tag atomically

git push --atomic origin master v0.0.14

Commit types

Commit Type Title Description Emoji
feat Features A new feature
fix Bug Fixes A bug Fix 🐛
docs Documentation Documentation only changes 📚
style Styles Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) 💎
refactor Code Refactoring A code change that neither fixes a bug nor adds a feature 📦
perf Performance Improvements A code change that improves performance 🚀
test Tests Adding missing tests or correcting existing tests 🚨
build Builds Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) 🛠
ci Continuous Integrations Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) ⚙️
chore Chores Other changes that don't modify src or test files ♻️
revert Reverts Reverts a previous commit 🗑

Publish to PyPI

  1. Create a PyPi Test Account

  2. Log in to Test PyPI or create a new account.

  3. Navigate to "Account Settings" → "API Tokens".
  4. Generate a new API token if needed.

  5. Create a PyPI Account:

  6. Sign up on PyPI.

  7. Set up 2FA (Two-Factor Authentication) for enhanced security.
  8. Install Required Tools: Ensure you have build and twine installed for building and publishing:
pip install build twine
  1. Update your ~/.pypirc File:
[ distutils ]
  index-servers =
  pypi
  testpypi

  [ testpypi ]
  repository = https://test.pypi.org/legacy/
  username = __token__
  password = <your_api_token>

  [ pypi ]
  repository = https://upload.pypi.org/legacy/
  username = __token__
  password = <your_api_token>

Build the Package

Check the Readme

pip install readme_renderer[md]
python -m readme_renderer README.md
python -m build

Build

cd /path/to/project
python -m build

Upload to Test PyPI

Upload to Test pypi first:

twine upload --repository testpypi dist/*

Test installation:

pip install --index-url https://test.pypi.org/simple/ bitbully

Publish to PyPI

twine upload dist/*

Test installation from PyPI:

pip install bitbully

Compile Libs using CMake

Compile and run Google Tests

cmake -B build -S . -DCMAKE_BUILD_TYPE=Release # run in project root
cmake --build build --target gtest_run --config Release
cd build # navigate into build directory
./gtests/gtest_run # run tests

Updates

Update pybind11 Submodule

git -C thirdParty/pybind11 rev-parse --abbrev-ref HEAD && git -C thirdParty/pybind11 describe --tags --always && git -C thirdParty/pybind11 remote -v
git -C thirdParty/pybind11 fetch --tags origin && git -C thirdParty/pybind11 tag --list "v3.*" | tail -n 200 # adapt to v4.* etc., depending on your needs
git -C thirdParty/pybind11 status --porcelain
git -C thirdParty/pybind11 fetch --tags origin
git -C thirdParty/pybind11 tag --list
git -C thirdParty/pybind11 checkout v3.0.1 # adapt to the version that you wish to checkout
git add thirdParty/pybind11
git commit -m "fix: update pybind11 submodule to vx.x.x" # adapt the version in the message

Update GoogleTests Submodule

git -C thirdParty/googletest rev-parse --abbrev-ref HEAD && git -C thirdParty/googletest describe --tags --always && git -C thirdParty/googletest remote -v
git -C thirdParty/googletest fetch --tags origin && git -C thirdParty/googletest tag --list | sort -V | tail -n 20
git -C thirdParty/googletest status --porcelain # check status
git -C thirdParty/googletest fetch --tags origin # fetch remote tags (if not done already)
git -C thirdParty/googletest checkout vx.x.x # select a tag you want to check out
git add thirdParty/googletest
git commit -m "fix: update googletest submodule to vx.x.x" # adapt the tag here

Update doxygen-awesome-css Submodule

git -C thirdParty/doxygen-awesome-css rev-parse --abbrev-ref HEAD && git -C thirdParty/doxygen-awesome-css describe --tags --always && git -C thirdParty/doxygen-awesome-css remote -v
git -C thirdParty/doxygen-awesome-css fetch --tags origin && git -C thirdParty/doxygen-awesome-css tag --list | sort -V | tail -n 20


git -C thirdParty/doxygen-awesome-css status --porcelain # 1. Check status
git -C thirdParty/doxygen-awesome-css fetch --tags origin # 2. Fetch remote tags (if not already done)
git -C thirdParty/doxygen-awesome-css checkout vx.x.x # 3. Checkout a tag (e.g., v2.4.1 for the latest)
git add thirdParty/doxygen-awesome-css # 4. Update superproject reference
git commit -m "fix: update doxygen-awesome-css submodule to vx.x.x"
git push origin HEAD # 5. Push

Cheatsheet: Most Useful Commands

Version Control (Git)

  1. git status – Check repository status.
  2. git add -u – Stage all changes.
  3. git add <files> – Stage specific files.
  4. git commit -m "<message>" – Commit changes with a message.
  5. git commit --amend – Modify the last commit.
  6. git push --atomic origin master v<version> – Atomically pushes master branch and tags
  7. git push – Push changes to the remote repository.
  8. git tag -l, git tag --list – List tags.
  9. git tag -d <tag> – Delete a local tag.
  10. git push origin --delete <tag> – Delete a remote tag.
  11. git diff – Show differences between changes.
  12. git fetch – Fetch changes from the remote repository.
  13. git fetch upstream – Fetches changes from the upstream repository
  14. git rebase <branch> – Rebase the current branch.
  15. git merge <branch> – Merge a branch into the current branch.
  16. git merge upstream/main – Merge changes from upstream/main branch
  17. git checkout <file> – Revert changes in a specific file

Git Submodule Commands

  1. git submodule status – Show the status of submodules.
  2. git submodule add <repo-url> <path> – Add a new submodule.
  3. git submodule update --init --recursive – Initialize and update submodules.
  4. git submodule add -b <branch> <repo-url> <path> – Add a submodule tracking a specific branch.

Formatting and Linting

  1. ruff format <file> – Format Python code using Ruff.
  2. ruff format . – Format all files using Ruff
  3. ruff check --fix – Run Ruff checks and apply automatic fixes
  4. ruff check --unsafe-fixes --fix – Run Ruff checks with unsafe fixes
  5. ruff format notebooks/* – Format Jupyter notebook files
  6. ruff clean – Clean Ruff cache and temporary files
  7. clang-format <file> – Format C++ code using Clang-Format.

CMake Commands

  1. cmake --version – Check the version of CMake.
  2. cmake <options> – Generate build files based on CMakeLists.txt.

Testing and Debugging

  1. gdb --version – Check the version of GDB (GNU Debugger).
  2. gdb <program> – Debug a program.

Python Environment Management

  1. python3 --version – Check Python version.
  2. python3 -m venv <name> – Create a virtual environment.
  3. source <venv>/bin/activate – Activate a virtual environment.
  4. deactivate – Deactivate the virtual environment.

Dependency and Package Management

  1. pip install <package> – Install a Python package.
  2. pip install -e . – Install the package in editable mode.
  3. pip uninstall <package> – Uninstall a Python package.
  4. pip freeze – List installed packages.
  5. gem install <gem> – Install a Ruby gem.
  6. bundle install – Install Ruby gem dependencies.
  7. pip install /path/to/<package.whl> – Install a locally built wheel.
  8. pip uninstall <package> – Uninstall a Python package.

Building and Publishing Python Packages

  1. python -m build – Build a Python package.
  2. twine upload dist/* – Upload the package to PyPI.
  3. twine check dist/* – Check package metadata in dist folder
  4. twine check dist/* --strict – Strictly check package metadata in dist fol
  5. python -m build --wheel – Build only the wheel package.
  6. python -m build --sdist – Build only the source distribution.
  7. python -m build --platform-tag – Add a specific platform tag to the build.

CIBuildWheel

  1. cibuildwheel --output-dir <dir> – Build Python wheels for multiple platforms.
  2. cibuildwheel --output-dir <dir> --verbose – Build wheels with detailed output.
  3. cibuildwheel --output-dir <dir> --platform <platform> – Specify a platform for the build (e.g., linux, macos, or windows). However, usually, defined in the pyproject.toml.

Pre-Commit Commands

  1. pre-commit install --hook-type <type> – Install specific pre-commit hooks (e.g., commit-msg, pre-push).
  2. pre-commit migrate-config – Migrate .pre-commit-config.yaml to the latest format.
  3. pre-commit autoupdate – Update all pre-commit hooks to their latest versions.
  4. pre-commit run --all-files – Run hooks on all files.

Testing and CI/CD

  1. pre-commit install – Install pre-commit hooks.
  2. pre-commit run – Run all pre-commit hooks.
  3. ctest – Run CMake-based tests.
  4. cibuildwheel --output-dir dist – Build Python wheels.

Commitizen (cz)

  1. cz init – Initialize Commitizen configuration.
  2. cz bump – Automate version bump.
  3. cz bump --dry-run – Simulate version bump.

Doxygen

  1. sudo apt install doxygen – Install Doxygen using APT
  2. apt show doxygen – displays detailed information about the doxygen package
  3. doxygen -g Doxyfile – generates a default configuration file named Doxyfile for Doxygen
  4. doxygen Doxyfile – Generate Doxgen Docs based on configuration in Doxyfile
  5. python3 -m http.server 8000 --directory docs/html/ – Serve documentation locally on port 8000
  6. doxygen -w html header.html footer.html style.css – Generate template files for customizing Doxygen's output.
  7. doxygen --version - get version

Installation script (used in doxygen.yml):

export DOXY_VERSION=1.13.1
echo "Installing doxgen v$DOXY_VERSION"
sudo apt-get update && sudo apt-get install -y graphviz
mkdir doxygen-installer
wget "https://www.doxygen.nl/files/doxygen-${DOXY_VERSION}.linux.bin.tar.gz"
mv "doxygen-${DOXY_VERSION}.linux.bin.tar.gz" doxygen-installer
cd doxygen-installer
gunzip "doxygen-${DOXY_VERSION}.linux.bin.tar.gz"
tar xf "doxygen-${DOXY_VERSION}.linux.bin.tar"
cd "doxygen-${DOXY_VERSION}"
ls -laht
sudo make install

Configuration and Logs

  1. nano ~/.bashrc – Edit the bash configuration file.
  2. cat <file> – View file contents.
  3. pip show <package> – Display package details.
  4. sudo apt install <package> – Install a package using APT.

mkdocs

  1. pip install mkdocs-material mkdocstrings[python] pymdown-extensions - mkdocs extensions
  2. mkdocs build
  3. mkdocs serve

Node.js and NPM

  1. nvm install <version> – Install a specific Node.js version.
  2. node -v – Check Node.js version.
  3. npm -v – Check NPM version.
  4. npm install --save-dev <package> – Install a development dependency.
  5. npx prettier . --check – Check code formatting with Prettier.
  6. npx prettier . --write – Format code with Prettier.

Docker

  1. docker compose pull – Pull updated images for the services.
  2. docker compose up – Start Docker Compose services.
  3. docker compose up --help – Display help for Docker Compose.

Ruby and Rbenv

  1. rbenv install <version> – Install a specific Ruby version.
  2. rbenv local <version> – Set a local Ruby version for a project.
  3. gem install bundle – Install the Bundler gem.
  4. bundle install – Install Ruby project dependencies.

Jekyll

  1. bundle exec jekyll serve --incremental – Run a Jekyll server incrementally.
  2. bundle exec jekyll serve --lsi – Run Jekyll with LSI (Latent Semantic Indexing).
  3. bundle install – Install dependencies from the Gemfile.

Miscellaneous

  1. ls – List directory contents.
  2. cd <path> – Change directory.
  3. history | grep <keyword> – Search command history.
  4. htop – Display interactive process viewer.
  5. tmux – Start a new tmux session.

GitHub Snake

https://raw.githubusercontent.com/MarkusThill/snk/refs/heads/manual-run-output/only-svg/github-contribution-grid-snake.svg