Contribution Guidelines
=======================
Thank you for your interest in contributing to the Petal Stack! This guide will help you
understand the dependency architecture and version management across all repositories.
Dependency Architecture
-----------------------
Understanding the Petal Stack Dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Petal Stack consists of multiple repositories with specific dependency relationships:
.. graphviz::
:caption: Petal Stack Dependency Architecture
digraph dependency_structure {
rankdir=TB;
node [shape=box, style=filled];
// Core components
pam [label="Petal App Manager\n(pyproject.toml)\nDefault: main", fillcolor=lightblue];
pymavlink [label="pymavlink\n(mavlink/pymavlink/__init__.py)\nDefault: dev-sitl", fillcolor=orange];
leafsdk [label="LeafSDK\n(pyproject.toml)\nDefault: main", fillcolor=lightgreen];
// Petals
flight_log [label="petal-flight-log\n(pyproject.toml)\nDefault: master", fillcolor=palegreen];
warehouse [label="petal-warehouse\n(pyproject.toml)\nDefault: main", fillcolor=palegreen];
leafsdk_petal [label="petal-leafsdk\n(pyproject.toml)\nDefault: main\n⚠️ Depends on LeafSDK", fillcolor=palegreen];
journey [label="petal-user-journey-coordinator\n(pyproject.toml)\nDefault: main", fillcolor=palegreen];
qgc [label="petal-qgc-mission-server\n(pyproject.toml)\nDefault: main", fillcolor=palegreen];
// Dependencies
pam -> pymavlink [label="PROD: PyPI\nSITL: file://", color=blue, style=bold];
pam -> flight_log [label="PROD: git tag\nSITL: editable", color=blue, style=bold];
pam -> warehouse [label="PROD: git tag\nSITL: editable", color=blue, style=bold];
pam -> leafsdk_petal [label="PROD: git tag\nSITL: editable", color=blue, style=bold];
pam -> journey [label="PROD: git tag\nSITL: editable", color=blue, style=bold];
pam -> qgc [label="PROD: git tag\nSITL: editable", color=blue, style=bold];
leafsdk_petal -> leafsdk [label="PROD: PyPI\nSITL: editable", color=green, style=bold];
// Legend
subgraph cluster_legend {
label="Legend";
style=filled;
color=lightgray;
rankdir=TB;
leg_note [label="Version stored in pyproject.toml (except pymavlink: __init__.py)\nPROD = Production deployment | SITL = Development environment", shape=plaintext];
}
}
**Key Points:**
- **PAM (Petal App Manager)**: Only depends on ``pymavlink`` and the petals
- **petal-leafsdk**: Special case - depends on ``LeafSDK``
- **Production (PROD)**: Uses PyPI packages or git tags for stable releases
- **SITL (Development)**: Uses editable installs for live development
- **CI/CD**: Does not install petals (framework testing only)
Version Management by Repository
---------------------------------
Petal App Manager
~~~~~~~~~~~~~~~~~
**Repository**: ``petal-app-manager``
**Default Branch**: ``main``
**Version Location**: ``pyproject.toml``
**Deployment Modes**:
- **Production**: Installs petals directly from git tags (versions specified in ``pyproject.toml``)
- **CI/CD**: Does not install petals (framework testing only)
- **SITL**: Installs petals in editable mode + ``LeafSDK`` (editable)
**Release Process**:
1. Update version in ``pyproject.toml``
2. Update petal versions in ``pyproject.toml`` under ``[project.optional-dependencies]``
3. Commit changes
4. Create and push git tag: ``git tag v0.1.x && git push origin v0.1.x``
Individual Petals
~~~~~~~~~~~~~~~~~
All petals follow the same versioning pattern:
petal-flight-log
^^^^^^^^^^^^^^^^
**Default Branch**: ``master``
**Version Location**: ``pyproject.toml``
**Release Process**:
1. Bump version in ``pyproject.toml``
2. Commit changes
3. Create and push git tag: ``git tag v0.1.x && git push origin v0.1.x``
4. PAM will install in production directly from this git tag
petal-warehouse
^^^^^^^^^^^^^^^
**Default Branch**: ``main``
**Version Location**: ``pyproject.toml``
**Release Process**: Same as ``petal-flight-log``
petal-user-journey-coordinator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Default Branch**: ``main``
**Version Location**: ``pyproject.toml``
**Release Process**: Same as ``petal-flight-log``
petal-qgc-mission-server
^^^^^^^^^^^^^^^^^^^^^^^^^
**Default Branch**: ``main``
**Version Location**: ``pyproject.toml``
**Release Process**: Same as ``petal-flight-log``
petal-leafsdk (Special Case)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Default Branch**: ``main``
**Version Location**: ``pyproject.toml``
**⚠️ Important**: This petal depends on ``LeafSDK``
**Release Process**:
1. **First**, ensure ``LeafSDK`` is updated and published to PyPI (see below)
2. Bump ``LeafSDK`` version in ``petal-leafsdk``'s ``pyproject.toml`` dependencies
3. Bump ``petal-leafsdk`` version in ``pyproject.toml``
4. Commit changes
5. Create and push git tag: ``git tag v0.1.x && git push origin v0.1.x``
Non-Petal Packages
------------------
LeafSDK
~~~~~~~
**Repository**: ``LeafSDK``
**Default Branch**: ``main``
**Version Location**: ``pyproject.toml``
**Deployment**:
- **Production**: Installed from PyPI (due to dependency from ``petal-leafsdk``)
- **SITL**: Installed in editable mode
**Release Process**:
1. Commit all changes
2. Bump version in ``pyproject.toml``
3. Create and push git tag: ``git tag v0.2.x && git push origin v0.2.x``
4. This triggers a CI/CD workflow to publish to PyPI
mavlink/pymavlink (Very Special Case)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Repository**: ``leaf-mavlink``
**Default Branch**: ``dev-sitl``
**Version Location**: ``mavlink/pymavlink/__init__.py``
**Deployment**:
- **Production**: Installed from PyPI
- **CI/CD**: Installed from PyPI
- **SITL**: Installed via ``file://`` (not editable, requires rebuild)
**⚠️ Critical Notes**:
- Message definitions and pymavlink must be maintained together
- Always commit both message changes and submodule updates together
- Ensure the ``mavlink`` repository is checked out to ``dev-sitl`` branch
**Release Process**:
1. **Add/Modify MAVLink Messages**:
.. code-block:: bash
# Edit message definitions
cd ~/petal-app-manager-dev/mavlink
# Ensure on dev-sitl branch
git checkout dev-sitl
# Edit: message_definitions/v1.0/droneleaf_mav_msgs.xml
# Add your new message definitions
2. **Format XML Files** (if CI/CD "Formatting Checks" job fails):
.. code-block:: bash
cd ~/petal-app-manager-dev/mavlink
./scripts/format_xml.sh /v1.0/common.xml
./scripts/format_xml.sh /v1.0/droneleaf_mav_msgs.xml
3. **Bump pymavlink Version**:
.. code-block:: bash
# Edit: mavlink/pymavlink/__init__.py
# Update __version__ = '0.1.x'
4. **Commit All Changes** (including submodule updates):
.. code-block:: bash
cd ~/petal-app-manager-dev/mavlink/pymavlink
git add .
git commit -m "chore: bump version to 0.1.x"
# IMPORTANT: Also commit the submodule update in parent if needed
cd ~/petal-app-manager-dev/mavlink
git add .
git commit -m "feat: add new MAVLink message definitions"
5. **Tag and Push**:
.. code-block:: bash
# Tag the latest commit on mavlink/pymavlink
cd ~/petal-app-manager-dev/mavlink/pymavlink
git tag v0.1.x
git push origin dev-sitl
git push origin v0.1.x
# This triggers a release to PyPI via workflow
**MAVLink Message Definition Location**:
.. code-block:: text
~/petal-app-manager-dev/mavlink/message_definitions/v1.0/droneleaf_mav_msgs.xml
Example message definition structure:
.. code-block:: xml
The system mode, as defined by enum LEAF_MODE
The new leaf mode.
Adding New DroneLeaf MAVLink Messages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When adding a new custom DroneLeaf message, follow this complete workflow:
**Step 1: Define the Message in XML**
Edit ``message_definitions/v1.0/droneleaf_mav_msgs.xml``:
.. code-block:: xml
Description of what this message does
Status field description
Value field description
First value description
Second value description
**Step 2: Use the Message in Python Code**
After the message is built into pymavlink, use it in your petal code:
.. code-block:: python
from pymavlink.dialects.v20 import droneleaf_mav_msgs as leafMAV
# Register a handler for receiving the message
proxy.register_handler(
str(leafMAV.MAVLINK_MSG_ID_LEAF_YOUR_NEW_MESSAGE),
my_handler_function
)
# Create and send the message
msg = leafMAV.MAVLink_leaf_your_new_message(
status=1,
value=3.14
)
proxy.send("mav", msg)
# Use enum values
if current_status == leafMAV.LEAF_YOUR_NEW_ENUM_VALUE1:
# Handle this state
pass
**Step 3: Register in Message Verification Config**
Edit ``mavlink/pymavlink/.github/workflows/required_pymavlink_messages.json`` to register
your new symbols. This ensures CI verifies they exist after building pymavlink.
.. code-block:: json
{
"dialects": {
"pymavlink.dialects.v20.droneleaf_mav_msgs": {
"message_ids": {
"items": [
"MAVLINK_MSG_ID_LEAF_STATUS",
"MAVLINK_MSG_ID_LEAF_YOUR_NEW_MESSAGE"
]
},
"message_classes": {
"items": [
"MAVLink_leaf_status_message",
"MAVLink_leaf_your_new_message"
]
},
"enums": {
"LEAF_YOUR_NEW_ENUM": [
"LEAF_YOUR_NEW_ENUM_VALUE1",
"LEAF_YOUR_NEW_ENUM_VALUE2"
]
}
}
}
}
**What to Register:**
.. list-table:: Message Verification Categories
:header-rows: 1
:widths: 25 35 40
* - Category
- Example
- When to Add
* - ``message_ids``
- ``MAVLINK_MSG_ID_LEAF_STATUS``
- When you register a handler for the message
* - ``message_classes``
- ``MAVLink_leaf_status_message``
- When you create/send the message
* - ``enums``
- ``LEAF_STATUS_FLYING``
- When you use enum values in code
* - ``constants``
- ``ENABLED_ALWAYS``
- When you use standalone constants
**Step 4: Verify Locally (Optional)**
.. code-block:: bash
# Create and activate a virtual environment with Python 3.11
cd ~/petal-app-manager-dev/mavlink/pymavlink
python3.11 -m venv .venv
source .venv/bin/activate
# Build and install pymavlink with new message definitions
# MDEF must point to the message_definitions directory
MDEF=~/petal-app-manager-dev/mavlink/message_definitions/v1.0 python3 -m pip install . -v
# Run verification script
python .github/workflows/verify_pymavlink_messages.py --verbose
.. note::
The ``MDEF`` environment variable must point to the directory containing the message
definition XML files. Typically, this is the ``message_definitions/v1.0`` folder in the
mavlink repository (e.g., ``/home/droneleaf/petal-app-manager-dev/mavlink/message_definitions/v1.0``).
**Step 5: Commit, Tag, and Push**
Follow the standard release process above. The CI workflow will:
1. Clone ``leaf-mavlink`` with latest message definitions
2. Build pymavlink from source
3. Run the verification script
4. Fail if any registered symbol is missing
**⚠️ Important**: Only messages that are **actually used in source code** should be
registered in the verification config - not all messages from the dialect files.
Version Summary Table
---------------------
.. list-table:: Repository Version Management
:header-rows: 1
:widths: 25 15 20 40
* - Repository
- Default Branch
- Version File
- Installation Method
* - petal-app-manager
- main
- pyproject.toml
- PROD: git tag | SITL: editable
* - petal-flight-log
- master
- pyproject.toml
- PROD: git tag | SITL: editable
* - petal-warehouse
- main
- pyproject.toml
- PROD: git tag | SITL: editable
* - petal-user-journey-coordinator
- main
- pyproject.toml
- PROD: git tag | SITL: editable
* - petal-qgc-mission-server
- main
- pyproject.toml
- PROD: git tag | SITL: editable
* - petal-leafsdk
- main
- pyproject.toml
- PROD: git tag | SITL: editable (⚠️ depends on LeafSDK)
* - LeafSDK
- main
- pyproject.toml
- PROD: PyPI | SITL: editable
* - leaf-mavlink (pymavlink)
- dev-sitl
- pymavlink/__init__.py
- PROD: PyPI | CI/CD: PyPI | SITL: file://
Getting Help
------------
**Communication Channels**
- **GitHub Issues**: For bug reports and feature requests
- **GitHub Discussions**: For questions and general discussion
- **Pull Request Comments**: For code-specific questions
**Resources**
- :doc:`../getting_started/index` - Setup guides
- :doc:`adding_petals` - Petal development guide
- :doc:`../api_reference/index` - API documentation
- :doc:`../known_issues` - Common problems and solutions
Thank you for contributing to the Petal Stack! 🚁✨