281 lines
9.5 KiB
Markdown
281 lines
9.5 KiB
Markdown
|
|
# CI, Build, Release & Code Style
|
||
|
|
|
||
|
|
This document covers the CrossPoint Reader build system, CI pipeline, release process, code formatting rules, static analysis, and contribution guidelines.
|
||
|
|
|
||
|
|
## Build System
|
||
|
|
|
||
|
|
The project uses **PlatformIO** with the Arduino framework targeting the ESP32-C3.
|
||
|
|
|
||
|
|
### Build Environments
|
||
|
|
|
||
|
|
Defined in `platformio.ini`:
|
||
|
|
|
||
|
|
| Environment | Purpose | Version String |
|
||
|
|
|---|---|---|
|
||
|
|
| `default` | Local development builds | `1.0.0-dev` |
|
||
|
|
| `gh_release` | Official tagged releases | `1.0.0` |
|
||
|
|
| `gh_release_rc` | Release candidates | `1.0.0-rc+{7-char SHA}` |
|
||
|
|
|
||
|
|
### Build Command
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Development build
|
||
|
|
pio run
|
||
|
|
|
||
|
|
# Release build
|
||
|
|
pio run -e gh_release
|
||
|
|
|
||
|
|
# Release candidate build (requires CROSSPOINT_RC_HASH env var)
|
||
|
|
CROSSPOINT_RC_HASH=abc1234 pio run -e gh_release_rc
|
||
|
|
```
|
||
|
|
|
||
|
|
### Build Flags
|
||
|
|
|
||
|
|
All environments share a common set of flags (`[base]` section):
|
||
|
|
|
||
|
|
| Flag | Purpose |
|
||
|
|
|---|---|
|
||
|
|
| `-std=c++2a` | C++20 standard |
|
||
|
|
| `-DARDUINO_USB_MODE=1` | USB mode selection |
|
||
|
|
| `-DARDUINO_USB_CDC_ON_BOOT=1` | Enable USB CDC serial on boot |
|
||
|
|
| `-DMINIZ_NO_ZLIB_COMPATIBLE_NAMES=1` | Avoid miniz/zlib symbol conflicts |
|
||
|
|
| `-DEINK_DISPLAY_SINGLE_BUFFER_MODE=1` | Single frame buffer (saves RAM) |
|
||
|
|
| `-DDISABLE_FS_H_WARNING=1` | Suppress Arduino FS.h warning |
|
||
|
|
| `-DXML_GE=0` | Disable expat general entity expansion |
|
||
|
|
| `-DXML_CONTEXT_BYTES=1024` | Expat context buffer size |
|
||
|
|
| `-DUSE_UTF8_LONG_NAMES=1` | Enable UTF-8 long filenames in SdFat |
|
||
|
|
|
||
|
|
### Pre-Build Step
|
||
|
|
|
||
|
|
`scripts/build_html.py` runs before compilation (configured via `extra_scripts = pre:scripts/build_html.py`). It:
|
||
|
|
|
||
|
|
1. Finds all `.html` files under `src/`.
|
||
|
|
2. Minifies them (strips comments, collapses whitespace, preserves `<pre>`, `<code>`, `<textarea>`, `<script>`, `<style>` blocks).
|
||
|
|
3. Generates `.generated.h` files containing `constexpr char ...Html[] PROGMEM = R"rawliteral(...)rawliteral";` strings.
|
||
|
|
|
||
|
|
### Dependencies
|
||
|
|
|
||
|
|
**SDK libraries** (symlinked from `open-x4-sdk` submodule):
|
||
|
|
- `BatteryMonitor`
|
||
|
|
- `InputManager`
|
||
|
|
- `EInkDisplay`
|
||
|
|
- `SDCardManager`
|
||
|
|
|
||
|
|
**External libraries** (managed by PlatformIO):
|
||
|
|
- `bblanchon/ArduinoJson @ 7.4.2` -- JSON parsing
|
||
|
|
- `ricmoo/QRCode @ 0.0.1` -- QR code generation
|
||
|
|
- `links2004/WebSockets @ 2.7.3` -- WebSocket server
|
||
|
|
|
||
|
|
### Tool Versions
|
||
|
|
|
||
|
|
| Tool | Version | Notes |
|
||
|
|
|---|---|---|
|
||
|
|
| PlatformIO | Latest (via pip) | `espressif32 @ 6.12.0` platform |
|
||
|
|
| Python | 3.14 | Used in CI and build scripts |
|
||
|
|
| clang-format | 21 | From LLVM apt repository |
|
||
|
|
| cppcheck | Latest (via PlatformIO) | Static analysis |
|
||
|
|
|
||
|
|
## CI Pipeline
|
||
|
|
|
||
|
|
All CI workflows are in `.github/workflows/`.
|
||
|
|
|
||
|
|
### `ci.yml` -- Main CI
|
||
|
|
|
||
|
|
**Triggers:** Push to `master`, all pull requests.
|
||
|
|
|
||
|
|
Runs **4 jobs in parallel** (the first 3 are independent; the 4th aggregates results):
|
||
|
|
|
||
|
|
#### 1. `clang-format` -- Code Formatting Check
|
||
|
|
|
||
|
|
1. Installs `clang-format-21` from the LLVM apt repository.
|
||
|
|
2. Runs `bin/clang-format-fix` on the full codebase.
|
||
|
|
3. Checks `git diff --exit-code` -- fails if any file was reformatted.
|
||
|
|
|
||
|
|
#### 2. `cppcheck` -- Static Analysis
|
||
|
|
|
||
|
|
1. Installs PlatformIO.
|
||
|
|
2. Runs `pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high`.
|
||
|
|
3. Fails on any low, medium, or high severity defect.
|
||
|
|
|
||
|
|
#### 3. `build` -- Compilation
|
||
|
|
|
||
|
|
1. Installs PlatformIO.
|
||
|
|
2. Runs `pio run` (default environment).
|
||
|
|
3. Extracts RAM and Flash usage stats into the GitHub step summary.
|
||
|
|
4. Uploads `firmware.bin` as a build artifact.
|
||
|
|
|
||
|
|
#### 4. `test-status` -- PR Gate
|
||
|
|
|
||
|
|
- Depends on all three jobs above.
|
||
|
|
- Fails if any dependency failed or was cancelled.
|
||
|
|
- This is the required status check for pull requests, decoupling CI steps from PR merge requirements.
|
||
|
|
|
||
|
|
### `pr-formatting-check.yml` -- PR Title Validation
|
||
|
|
|
||
|
|
**Triggers:** Pull request `opened`, `reopened`, `edited` events.
|
||
|
|
|
||
|
|
Uses `amannn/action-semantic-pull-request@v6` to enforce semantic PR title format (e.g., `feat: add dark mode`, `fix: correct page numbering`).
|
||
|
|
|
||
|
|
### `release.yml` -- Official Release
|
||
|
|
|
||
|
|
**Trigger:** Push of any git tag.
|
||
|
|
|
||
|
|
1. Builds using the `gh_release` environment.
|
||
|
|
2. Uploads release artifacts named `CrossPoint-{tag}`:
|
||
|
|
- `bootloader.bin`
|
||
|
|
- `firmware.bin`
|
||
|
|
- `firmware.elf`
|
||
|
|
- `firmware.map`
|
||
|
|
- `partitions.bin`
|
||
|
|
|
||
|
|
### `release_candidate.yml` -- RC Build
|
||
|
|
|
||
|
|
**Trigger:** Manual `workflow_dispatch`, restricted to branches matching `release/*`.
|
||
|
|
|
||
|
|
1. Extracts the 7-character short SHA and branch suffix (e.g., `v1.0.0` from `release/v1.0.0`).
|
||
|
|
2. Sets `CROSSPOINT_RC_HASH` env var.
|
||
|
|
3. Builds using the `gh_release_rc` environment.
|
||
|
|
4. Uploads artifacts named `CrossPoint-RC-{suffix}`.
|
||
|
|
|
||
|
|
## Release Process
|
||
|
|
|
||
|
|
### Official Release
|
||
|
|
|
||
|
|
1. Create and push a git tag (e.g., `v1.0.0`).
|
||
|
|
2. The `release.yml` workflow triggers automatically.
|
||
|
|
3. Artifacts are uploaded to the GitHub Actions run.
|
||
|
|
|
||
|
|
### Release Candidate
|
||
|
|
|
||
|
|
1. Create a branch named `release/{identifier}` (e.g., `release/v1.0.0`).
|
||
|
|
2. Navigate to Actions in GitHub and manually trigger `Compile Release Candidate` on that branch.
|
||
|
|
3. The RC version string includes the commit SHA for traceability.
|
||
|
|
|
||
|
|
### Version Scheme
|
||
|
|
|
||
|
|
```
|
||
|
|
1.0.0-dev # Local development (default env)
|
||
|
|
1.0.0 # Official release (gh_release env)
|
||
|
|
1.0.0-rc+a1b2c3d # Release candidate (gh_release_rc env)
|
||
|
|
```
|
||
|
|
|
||
|
|
The version base is set in `platformio.ini` under `[crosspoint] version = 1.0.0`.
|
||
|
|
|
||
|
|
## Code Style
|
||
|
|
|
||
|
|
### Formatting: clang-format
|
||
|
|
|
||
|
|
The project uses **clang-format 21** with a `.clang-format` config at the repository root. Key rules:
|
||
|
|
|
||
|
|
| Setting | Value | Meaning |
|
||
|
|
|---|---|---|
|
||
|
|
| `IndentWidth` | `2` | 2-space indentation |
|
||
|
|
| `TabWidth` / `UseTab` | `8` / `Never` | Spaces only (no tabs) |
|
||
|
|
| `ColumnLimit` | `120` | Maximum line width |
|
||
|
|
| `BreakBeforeBraces` | `Attach` | K&R brace style (opening brace on same line) |
|
||
|
|
| `PointerAlignment` | `Left` | `int* ptr` not `int *ptr` |
|
||
|
|
| `ReferenceAlignment` | `Pointer` | References follow pointer style |
|
||
|
|
| `ContinuationIndentWidth` | `4` | 4-space continuation indent |
|
||
|
|
| `AllowShortFunctionsOnASingleLine` | `All` | Short functions may be single-line |
|
||
|
|
| `AllowShortIfStatementsOnASingleLine` | `WithoutElse` | `if (x) return;` allowed |
|
||
|
|
| `AllowShortLoopsOnASingleLine` | `true` | Short loops may be single-line |
|
||
|
|
| `BreakBeforeTernaryOperators` | `true` | `?` and `:` start new lines |
|
||
|
|
| `BreakBeforeBinaryOperators` | `None` | Binary operators stay at end of line |
|
||
|
|
| `SortIncludes` | `Enabled` | Includes sorted lexicographically |
|
||
|
|
| `IncludeBlocks` | `Regroup` | Includes grouped by category |
|
||
|
|
| `ReflowComments` | `Always` | Long comments are rewrapped |
|
||
|
|
| `SpacesBeforeTrailingComments` | `2` | Two spaces before `// comment` |
|
||
|
|
| `LineEnding` | `DeriveLF` | Unix-style line endings |
|
||
|
|
|
||
|
|
### Include Order
|
||
|
|
|
||
|
|
Includes are regrouped into priority categories:
|
||
|
|
|
||
|
|
1. **Priority 1:** System headers with `.h` extension (`<foo.h>`)
|
||
|
|
2. **Priority 2:** Other system headers (`<foo>`) and extension headers (`<ext/foo.h>`)
|
||
|
|
3. **Priority 3:** Project-local headers (`"foo.h"`)
|
||
|
|
|
||
|
|
### Running the Formatter
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Format all tracked source files
|
||
|
|
./bin/clang-format-fix
|
||
|
|
|
||
|
|
# Format only modified (staged or unstaged) files
|
||
|
|
./bin/clang-format-fix -g
|
||
|
|
```
|
||
|
|
|
||
|
|
The script formats `.c`, `.cpp`, `.h`, `.hpp` files tracked by git, **excluding** `lib/EpdFont/builtinFonts/` (script-generated font headers).
|
||
|
|
|
||
|
|
### Static Analysis: cppcheck
|
||
|
|
|
||
|
|
Configuration in `platformio.ini`:
|
||
|
|
|
||
|
|
```
|
||
|
|
check_tool = cppcheck
|
||
|
|
check_flags = --enable=all
|
||
|
|
--suppress=missingIncludeSystem
|
||
|
|
--suppress=unusedFunction
|
||
|
|
--suppress=unmatchedSuppression
|
||
|
|
--suppress=*:*/.pio/*
|
||
|
|
--inline-suppr
|
||
|
|
```
|
||
|
|
|
||
|
|
- `--enable=all` enables all checks.
|
||
|
|
- Suppressed: missing system includes, unused functions (common in library code), PlatformIO build directory.
|
||
|
|
- `--inline-suppr` allows `// cppcheck-suppress` comments in source.
|
||
|
|
- CI fails on **any** defect severity (low, medium, or high).
|
||
|
|
|
||
|
|
Run locally:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
pio check
|
||
|
|
```
|
||
|
|
|
||
|
|
## Contribution Guidelines
|
||
|
|
|
||
|
|
### PR Requirements
|
||
|
|
|
||
|
|
1. **Semantic PR title** -- enforced by CI. Must follow conventional format:
|
||
|
|
- `feat: ...`, `fix: ...`, `refactor: ...`, `docs: ...`, `chore: ...`, etc.
|
||
|
|
|
||
|
|
2. **PR template** (`.github/PULL_REQUEST_TEMPLATE.md`) must be filled out:
|
||
|
|
- **Summary:** Goal and changes included.
|
||
|
|
- **Additional Context:** Performance implications, risks, focus areas.
|
||
|
|
- **AI Usage:** Transparent disclosure -- `YES`, `PARTIALLY`, or `NO`.
|
||
|
|
|
||
|
|
3. **Code formatting** -- run `bin/clang-format-fix` before pushing. CI will reject unformatted code.
|
||
|
|
|
||
|
|
4. **Static analysis** -- ensure `pio check` passes without low/medium/high defects.
|
||
|
|
|
||
|
|
5. **Build** -- confirm `pio run` compiles without errors.
|
||
|
|
|
||
|
|
### Project Scope
|
||
|
|
|
||
|
|
All contributions must align with the project's core mission: **focused reading on the Xteink X4**. See `SCOPE.md` for full details.
|
||
|
|
|
||
|
|
**In scope:** UX improvements, document rendering (EPUB), typography, e-ink driver refinement, library management, local file transfer, language support.
|
||
|
|
|
||
|
|
**Out of scope:** Interactive apps, active connectivity (RSS/news/browsers), media playback, complex reader features (highlighting, notes, dictionary).
|
||
|
|
|
||
|
|
When unsure, open a Discussion before coding.
|
||
|
|
|
||
|
|
### Governance
|
||
|
|
|
||
|
|
From `GOVERNANCE.md`:
|
||
|
|
|
||
|
|
- **Assume good intent** in technical discussions.
|
||
|
|
- **Critique code, not people.**
|
||
|
|
- **Public by default** -- decisions happen in Issues, PRs, and Discussions.
|
||
|
|
- Maintainers guide technical direction for ESP32-C3 hardware constraints.
|
||
|
|
- Report harassment privately to `@daveallie`.
|
||
|
|
|
||
|
|
### Checklist Before Submitting
|
||
|
|
|
||
|
|
- [ ] Code compiles: `pio run`
|
||
|
|
- [ ] Code is formatted: `bin/clang-format-fix`
|
||
|
|
- [ ] Static analysis passes: `pio check`
|
||
|
|
- [ ] PR title follows semantic format
|
||
|
|
- [ ] PR template filled out (summary, context, AI disclosure)
|
||
|
|
- [ ] Changes align with project scope (`SCOPE.md`)
|