Development Guide

July 14, 2026 ยท View on GitHub

For project overview, prerequisites, and build instructions, see the README. This guide covers architecture, testing, contributing guidelines, and CI/CD details.

Architecture

For a detailed description of the firmware architecture, source code structure, modules, build system, and linker scripts, see the Architecture document.

Testing

See unittests/README.md for details on running and adding tests.

Contributing

Code Style

C code is formatted with Artistic Style (astyle) version 3.4.7, configured in .astyle-rules.yml. Python code follows ruff formatting and linting rules defined in pyproject.toml.

Pre-commit Hooks

Install and activate the pre-commit hooks:

source venv/bin/activate
pip install pre-commit
pre-commit install -t pre-commit -t commit-msg

Run all checks manually:

pre-commit run --all-files

The hooks enforce:

  • C code formatting (astyle)
  • Python linting and formatting (ruff, mypy)
  • Copyright header validation (Apache-2.0 OR MIT)
  • Trailing whitespace, line endings, and YAML formatting
  • Conventional Commits message format

All source files must include an SPDX copyright header. The copyright year range is automatically managed by the check-copyright tool.

C files:

/*
 * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0 OR MIT
 */

Python files:

# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 OR MIT

Commit Messages

This project uses Conventional Commits. Releases are managed with commitizen.

Pull Request Checklist

Before submitting a pull request:

  1. Run host tests:

    cd unittests/host && ./run-tests.sh && cd ../..
    
  2. Build firmware for at least one chip:

    source venv/bin/activate
    source ./tools/export_toolchains.sh
    cmake . -B build -G Ninja -DTARGET_CHIP=esp32s2 --fresh
    ninja -C build
    
  3. Run pre-commit hooks:

    pre-commit run --all-files
    
  4. Verify the JSON output was generated:

    ls -la build/*.json
    

CI/CD

GitHub Actions Workflows

WorkflowTriggerPurpose
Build and ReleasePush, PR, tagBuild firmware for all chips; generate the stub size report on PRs; create a draft GitHub release on tags
Publish npm packageGitHub release publishedPackage stub JSON files and publish to npm (triggered when a draft release is manually published)
Post stub size reportworkflow_run after Build and ReleasePost/update the size report comment on the PR (runs with a write token so it also works for fork PRs)
Host TestsPushRun native unit tests
DangerJSPRValidate PR style and conventions
JiraPRSync with Jira issue tracker

Pre-commit.ci also runs automatically on pull requests to verify code style.

Releasing (Maintainers Only)

python -m venv venv
source venv/bin/activate
pip install commitizen czespressif
git fetch
git checkout -b update/release_v<version>
git reset --hard origin/master
cz bump
git push -u
git push --tags

Create a pull request and edit the automatically created draft release on the releases page.

Publishing the release automatically triggers the Publish npm package workflow, which downloads the stub JSON files attached to the release and publishes the esp-flasher-stub npm package.

Utilities

ScriptDescription
tools/build_all_chips.shBuild firmware for all supported chips
tools/setup_toolchains.shDownload and extract cross-compilation toolchains
tools/export_toolchains.shAdd toolchain directories to PATH (must be sourced)
tools/elf2json.pyConvert ELF binary to JSON format for esptool; embeds plugin data when --plugin is specified
tools/compare_sizes.pyCompare stub segment sizes between two builds; used by CI to post size reports on PRs
tools/compute_plugin_addrs.pyEmit a linker fragment with plugin load addresses computed from the base stub ELF
tools/install_all_chips.shCopy built JSON files into an esptool installation
tools/generate_npm_package.mjsAssemble the esp-flasher-stub npm package from stub JSON files; used by the Publish npm package workflow