Skip to content

Branch, PR, and Merge Workflow

This page covers the full lifecycle of a change in projectMM: from creating a branch to merging, including CI requirements, CodeRabbit review, and how release branches differ from feature branches.


Branch naming

Purpose Pattern Example
Feature or bug fix short descriptive name artnet-loopback-fix
Sprint work release<N> or release<N>-sprint<M> Release02, release4-sprint8
Hotfix hotfix/<description> hotfix/wifi-crash

Always branch from main. Never commit directly to main.

Release branches (any branch with release in the name) get extended CI: both ESP32 targets are built, firmware .bin files and the PC executable are uploaded as artifacts, and the docs are deployed to GitHub Pages. See CI behaviour by branch.


Opening a PR

  1. Create a branch from main.
  2. Make a first commit (even a skeleton is enough to open the PR early).
  3. Push and open a PR against main with a short description of the goal.
  4. CodeRabbit analyses the commits and generates a review automatically within a few minutes.

For non-trivial work, include a brief implementation plan in the PR description or as a top comment: what modules are touched, what the test strategy is, and what the footprint impact is expected to be.

PR title format: match the commit style used in this repo: a one-line summary that starts with the scope:

BrightnessModifier: fix brightness=0 not producing black output
Sprint 9: defVal sourcing confirmed + regression tests

Working on an open PR

Push additional commits as you work; GitHub keeps the PR up to date automatically. Do not force-push: it causes CodeRabbit review comments to disappear and makes the history harder to follow.

Addressing CodeRabbit feedback:

When a CodeRabbit comment leads to a change, use an emoji prefix in the commit title to signal the source:

Emoji Source
🐰 CodeRabbit suggestion
✴️ Claude Code generation
🐱 Mistral / other AI

Example commit title: 🐰 remove redundant null check in WifiSta::startConnect

Addressing human review feedback: plain commit title is fine; reference the review comment if helpful.


Definition of done before merge

A PR is not ready to merge until every item below is checked. These match the standards checklist:

  • [ ] All unit tests pass (python3 deploy/unittest.py, 254/254 or higher).
  • [ ] PC build clean (python3 deploy/build.py -target pc).
  • [ ] ESP32 build clean: at minimum esp32dev; both targets for release work.
  • [ ] Every changed or added Module has a test in tests/.
  • [ ] New tests are behavioral or integration (not just smoke or format).
  • [ ] Doc page added or updated for any user-facing change.
  • [ ] No new #ifdef ARDUINO inside src/modules/ (platform guards belong in src/pal/).
  • [ ] Footprint delta reported by CI and within budget (see Footprint Budgeting).
  • [ ] Co-Authored-By trailer present if the commit was AI-generated.

For a new Module, also check the Module definition of done.


CI behaviour by branch

CI runs on every push and every PR targeting main.

Job main PR to main branch with release other branches
PC build + tests yes yes yes no
ESP32 esp32dev build yes yes yes no
ESP32 esp32s3_n16r8 build no no yes no
PC executable artifact no no yes no
ESP32 firmware artifacts no no yes no
Docs build yes yes yes no
Docs deploy (GitHub Pages) yes no yes no
Footprint report yes yes yes no

CI is required to pass before merge. If a step fails, fix the root cause: do not skip hooks or disable checks.

Downloading firmware from a release branch:

After CI completes on a release branch, go to the GitHub Actions run, open the summary, and download the artifacts:

  • projectMM-pc-<branch>: the PC server executable (macOS)
  • projectMM-esp32-<branch>: both firmware.bin files (esp32dev + esp32s3_n16r8)

Merging

Who merges: any maintainer with write access, after at least one human approval and a green CodeRabbit summary.

How: squash-merge by default to keep main linear. The squash commit message should include the full Co-Authored-By trailers from the branch commits.

After merging:

  • Delete the feature branch (GitHub offers this automatically after merge).
  • For release branches, do not delete until the release doc (docs/development/release-NN.md) is finalised.

Target lead time: aim for a week or less from opening to merge. Stale PRs accumulate conflicts and slow everyone down.


Hotfixes

For urgent fixes to main:

  1. Branch hotfix/<description> from main.
  2. Fix, test, open PR, get a fast review.
  3. Merge and tag if the fix affects a released version.

Do not hotfix directly on main.


Release branches

Release branches (Release02, release4-sprint8, etc.) are longer-lived branches used during active sprint work. They follow the same rules as feature branches plus:

  • Docs are deployed to GitHub Pages on every push, so reviewers can see the current state of the documentation without checking out the branch locally.
  • Both ESP32 targets are built and both .bin artifacts are uploaded, ready for flashing to test hardware.
  • Sprint results, retrospectives, and the release-NN.md doc are updated on the branch before the final squash-merge to main.

The CI branch filter includes both '*release*' and '*Release*' patterns because GitHub Actions glob matching is case-sensitive on Linux runners. The step conditionals use contains(github.ref_name, 'release') || contains(github.ref_name, 'Release') for the same reason. Branches named Release02 satisfy the '*Release*' pattern and the uppercase contains check.