Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Build

on:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
- 'img/**'
- 'tools/companion/**'
- 'tools/*.exe'
pull_request:
paths-ignore:
- '**.md'
- 'docs/**'
- 'img/**'
- 'tools/companion/**'
- 'tools/*.exe'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
PIO_VERSION: '6.1.19'

jobs:
checks:
name: Checks
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
envs: ${{ steps.envs.outputs.envs }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Portal script syntax
run: node --check web/app.js

- name: Error tables match the portal mirror
run: python -c "import sys; sys.path.insert(0, 'tools'); import release; release.check_error_tables()"

- name: List environments
id: envs
run: |
python - <<'EOF' >> "$GITHUB_OUTPUT"
import glob, json, re
envs = []
for f in ["platformio.ini"] + sorted(glob.glob("boards/*.ini")):
envs += re.findall(r"^\[env:([^\]]+)\]", open(f, encoding="utf-8").read(), re.M)
print("envs=" + json.dumps(envs))
EOF

build:
name: ${{ matrix.env }}
needs: checks
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
env: ${{ fromJson(needs.checks.outputs.envs) }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Cache PlatformIO packages
uses: actions/cache@v4
with:
path: |
~/.platformio/packages
~/.platformio/platforms
~/.platformio/.cache
key: pio-${{ runner.os }}-${{ env.PIO_VERSION }}-${{ hashFiles('platformio.ini', 'boards/*.ini') }}
restore-keys: |
pio-${{ runner.os }}-${{ env.PIO_VERSION }}-

- name: Install PlatformIO
run: pip install "platformio==${PIO_VERSION}"

- name: Build
run: pio run -e "${{ matrix.env }}"

- name: Image fits its app partition
run: python tools/ci_slot_check.py "${{ matrix.env }}"

- name: Upload firmware
uses: actions/upload-artifact@v4
with:
name: firmware-${{ matrix.env }}
path: .pio/build/${{ matrix.env }}/firmware.bin
retention-days: 14
if-no-files-found: error
4 changes: 2 additions & 2 deletions boards/sensecap_indicator.ini
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ platform_packages =
platformio/framework-arduinoespressif32 @ https://github.com/mverch67/arduino-esp32/archive/aef7fef6de3329ed6f75512d46d63bba12b09bb5.zip
lib_deps =
https://github.com/mverch67/LovyanGFX/archive/4c76238c1344162a234ae917b27651af146d6fb2.zip
knolleary/PubSubClient@^2.8
bblanchon/ArduinoJson@^7.0
knolleary/PubSubClient@2.8.0
bblanchon/ArduinoJson@7.4.3
; Improv comes from the vendored lib/ImprovWiFi copy - the registry package's
; depends=WiFi pulls the Arduino WiFi-shield library, which shadows the ESP32
; core WiFi and breaks the build.
Expand Down
2 changes: 1 addition & 1 deletion boards/tzt_2432.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ upload_speed = 230400
board_build.partitions = min_spiffs.csv
lib_deps =
${common.lib_deps}
https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
https://github.com/PaulStoffregen/XPT2046_Touchscreen.git#f956c5d8ce3bf39169c7378416b89e7cfe70a034
build_flags =
; --- Touch (XPT2046 - same pins as CYD) ---
-D USE_XPT2046=1
Expand Down
12 changes: 7 additions & 5 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ extra_scripts = pre:tools/gen_web_assets.py
; Improv WiFi Library is vendored in lib/ImprovWiFi (see its library.json) -
; the registry package pulls in arduino-libraries/WiFi via `depends=WiFi`,
; which shadows the ESP32 core WiFi library and breaks the build.
; Exact versions on purpose: a range resolves differently on every fresh
; install, so two builds of one commit would not ship the same firmware.
lib_deps =
lovyan03/LovyanGFX@^1.2.19
knolleary/PubSubClient@^2.8
bblanchon/ArduinoJson@^7.0
lovyan03/LovyanGFX@1.2.36
knolleary/PubSubClient@2.8.0
bblanchon/ArduinoJson@7.4.3

; --- No C++ exceptions: the 4 MB-flash envs (1.75 MB app slots) ---
; ESP-IDF's own default; the Arduino core turns exceptions on. Dropping them from
Expand Down Expand Up @@ -120,7 +122,7 @@ upload_speed = 230400
board_build.partitions = min_spiffs.csv
lib_deps =
${common.lib_deps}
https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
https://github.com/PaulStoffregen/XPT2046_Touchscreen.git#f956c5d8ce3bf39169c7378416b89e7cfe70a034
build_flags =
; --- CYD touch (XPT2046 on separate SPI bus) ---
-D USE_XPT2046=1
Expand Down Expand Up @@ -282,7 +284,7 @@ board_build.f_flash = 80000000L
board_build.flash_mode = qio
lib_deps =
${common.lib_deps}
moononournation/GFX Library for Arduino@~1.5.0
moononournation/GFX Library for Arduino@1.5.9
build_flags =
-D BOARD_VARIANT=\"jc3248w535\"
-D BOARD_NAME=\"Guition_JC3248W535\"
Expand Down
57 changes: 57 additions & 0 deletions tools/ci_slot_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
"""CI helper: check one env's firmware.bin against its app partition.

Reuses the partition lookup from tools/release.py. A release-set board that does
not fit fails the job; any other env only gets a warning (some DIY envs are
over their slot and are not shipped).

Usage: python tools/ci_slot_check.py <env>
"""

import os
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
import release # noqa: E402


def main():
if len(sys.argv) != 2:
sys.exit("usage: ci_slot_check.py <env>")
env = sys.argv[1]
image = release.REPO_ROOT / ".pio" / "build" / env / "firmware.bin"
if not image.is_file():
sys.exit(f"::error::{image} not found")

shipped = env in release.WEB_FLASHER_BOARDS
size = image.stat().st_size
csv_name = release._partition_csv_for(env)
slot = release._app_slot_bytes(csv_name) if csv_name else None

if slot is None:
line = f"{env}: {size:,} B, partition table {csv_name!r} not found - not checked"
print(f"::warning::{line}")
status = 0
else:
free = slot - size
line = f"{env}: {size:,} / {slot:,} B ({free:+,} B)"
if free >= 0:
print(line)
status = 0
elif shipped:
print(f"::error::{line} - over its app slot, would brick on first OTA")
status = 1
else:
print(f"::warning::{line} - over its app slot (not in the release set)")
status = 0

summary = os.environ.get("GITHUB_STEP_SUMMARY")
if summary:
with open(summary, "a", encoding="utf-8") as fh:
fh.write(f"- `{line}`{' (release set)' if shipped else ''}\n")
sys.exit(status)


if __name__ == "__main__":
main()
Loading