* esp32_platform: update to 55.03.39
## Summary
- Add support for Python 3.14
- Improve ESP32 platform and framework compatibility.
- Update board support and toolchain integrations.
- Fix stability and hardware-specific issues across supported ESP32 targets.
- Release notes:
- [55.03.39](https://github.com/pioarduino/platform-espressif32/releases/tag/55.03.39)
- [55.03.38](https://github.com/pioarduino/platform-espressif32/releases/tag/55.03.38)
- [55.03.37](https://github.com/pioarduino/platform-espressif32/releases/tag/55.03.37)
- [55.03.36](https://github.com/pioarduino/platform-espressif32/releases/tag/55.03.36)
- [55.03.35](https://github.com/pioarduino/platform-espressif32/releases/tag/55.03.35)
- [55.03.34](https://github.com/pioarduino/platform-espressif32/releases/tag/55.03.34)
* update build to use python 3.14 with platformio 6.1.19
* Update esp32-arduino-lib-builder to v1.5
* [CI] Fix call8 link overflow on large Xtensa builds (IDF 5.5.4)
The 55.03.39 / IDF 5.5.4 bump enlarges the precompiled libs enough that
large Xtensa images (esp32 / esp32s3) overflow the call8 reach and fail to
link with "dangerous relocation: call8: call target out of range".
-mlongcalls (which makes calls linker-relaxable) is injected by
esp32-arduino-libs into the framework compile but NOT into lib_deps
(NimBLE-Arduino, ArduinoJson) or project sources.
Add a project pre: extra_script (scripts/add_mlongcalls.py) that applies
-mlongcalls to CCFLAGS/ASFLAGS, gated on the Xtensa MCUs (RISC-V c3 has no
call8 and rejects the flag). Wired into [env]; the four esp32dev-*pilight*
envs that set their own extra_scripts list it explicitly too, since
PlatformIO replaces rather than merges extra_scripts.
Also bump esp32-arduino-libs 0.1.5 -> 0.1.6, which restores the
framework-side -mdisable-hardware-atomics / -fno-builtin-* flags that 0.1.5
dropped under IDF 5.5.4 (separate from the lib_deps call8 issue).
Verified clean (0 call8): esp32dev-all-test, esp32dev-ble, theengs-bridge,
theengs-plug, esp32dev-pilight (+cc1101); esp32c3 unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Florian <florian@theengs.io>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 KiB
GitHub Actions Workflows Documentation
This document provides an overview of all GitHub Actions workflows in the OpenMQTTGateway project.
Architecture Overview
The workflow system is organized in two layers:
Main Workflows (User-facing triggers)
Entry points triggered by user actions, schedules, or events:
build.yml- CI validation on push/PRbuild_and_docs_to_dev.yml- Daily development buildsrelease.yml- Production releasesmanual_docs.yml- Documentation deploymentsecurity-scan.yml- Security vulnerability scanningstale.yml- Issue management
Task Workflows (Reusable components)
Parameterized building blocks called by main workflows:
task-build.yml- Configurable firmware buildtask-docs.yml- Configurable documentation buildtask-lint.yml- Configurable code formatting checktask-security-scan.yml- Configurable security scanning
Workflow Overview Table
| Workflow | Trigger | Purpose | Artifacts |
|---|---|---|---|
build.yml |
Push, Pull Request | CI Build Validation | Firmware binaries (7 days) |
build_and_docs_to_dev.yml |
Daily Cron, Manual | Development Builds + Docs | Firmware + Docs deployment |
release.yml |
Release Published | Production Release | Release assets + Docs |
manual_docs.yml |
Manual, Workflow Call | Documentation Only | GitHub Pages docs |
security-scan.yml |
Weekly Cron, Manual | Security Vulnerability Scanning | SARIF, SBOM reports |
stale.yml |
Daily Cron | Issue Management | None |
task-build.yml |
Workflow Call | Reusable Build Logic | Configurable |
task-docs.yml |
Workflow Call | Reusable Docs Logic | GitHub Pages |
task-lint.yml |
Workflow Call | Reusable Lint Logic | None |
task-security-scan.yml |
Workflow Call | Reusable Security Scan | SARIF, SBOM, Reports |
Workflow Dependencies and Call Chain
flowchart TD
%% Triggers
subgraph triggers ["🎯 Triggers"]
push["Push"]
pr["Pull Request"]
release["Release Published"]
cron1["Cron: Daily 00:00 UTC"]
manual["Manual Trigger"]
cron3["Cron: Weekly Monday 02:00 UTC"]
cron2["Cron: Daily 00:30 UTC"]
end
subgraph github_workflows ["📋 GitHub Workflows"]
%% Main Workflows
subgraph main ["📋 Main Workflows"]
build["build.yml<br/>CI Build"]
release_wf["release.yml<br/>Production Release"]
build_dev["build_and_docs_to_dev.yml<br/>Dev Builds"]
security_scan["security-scan.yml<br/>Security Scan"]
stale["stale.yml<br/>Issue Management"]
manual_docs["manual_docs.yml<br/>Docs Only"]
end
%% Task Workflows
subgraph tasks ["⚙️ Task Workflows"]
task_build["task-build.yml<br/>Build Firmware"]
task_lint["task-lint.yml<br/>Code Format"]
task_security["task-security-scan.yml<br/>Security Scan"]
task_docs["task-docs.yml<br/>Build & Deploy Docs"]
end
end
subgraph ci_scripts ["🔧 CI Scripts"]
%% CI Scripts Layer
subgraph bash ["🔧 Orchestrator"]
ci_main["ci.sh<br/>(main dispatcher)"]
ci_build_script["ci_build.sh<br/>(build orchestrator)"]
ci_site_script["ci_site.sh<br/>(docs orchestrator)"]
ci_qa_script["ci_qa.sh<br/>(lint orchestrator)"]
ci_security_script["ci_security.sh<br/>(security orchestrator)"]
end
%% Sub-Scripts Layer
subgraph sub_scripts ["⚙️ Workers"]
ci_build_fw["ci_build_firmware.sh<br/>(PlatformIO build)"]
ci_prep_art["ci_prepare_artifacts.sh<br/>(artifact packaging)"]
gen_board["generate_board_docs<br/>(npm package)"]
gen_wu["gen_wu<br/>(npm package)"]
clang_fmt["clang-format<br/>(code formatter)"]
trivy["Trivy<br/>(vulnerability scanner)"]
end
end
%% Trigger connections
push -->|"all or subset<br/>(depends on branch)"| build
pr -->|"all<br/>(always full)"| build
release --> release_wf
manual --> manual_docs
cron1 --> build_dev
cron2 --> stale
cron3 --> security_scan
%% Main workflow to task workflow connections
build --> task_build
build_dev --> task_build
build_dev --> task_docs
release_wf --> task_build
release_wf --> task_docs
manual_docs --> task_docs
security_scan --> task_security
%% Task workflow internal dependencies
task_build --> task_lint
task_build --> task_security
%% Task workflows to CI scripts
task_build -->|"ci.sh build ..."| ci_main
task_docs -->|"ci.sh site ..."| ci_main
task_lint -->|"ci.sh qa ..."| ci_main
task_security -->|"ci.sh security ..."| ci_main
%% CI main dispatcher to orchestrators
ci_main -->|"route: build"| ci_build_script
ci_main -->|"route: site"| ci_site_script
ci_main -->|"route: qa"| ci_qa_script
ci_main -->|"route: security"| ci_security_script
%% Orchestrators to workers
ci_build_script --> ci_build_fw
ci_build_script --> ci_prep_art
ci_site_script --> gen_board
ci_site_script --> gen_wu
ci_qa_script --> clang_fmt
ci_security_script --> trivy
%% Styling
classDef triggerStyle fill:#e1f5ff,stroke:#0066cc,stroke-width:2px
classDef mainStyle fill:#fff4e6,stroke:#ff9900,stroke-width:2px
classDef taskStyle fill:#e6f7e6,stroke:#00aa00,stroke-width:2px
classDef ciStyle fill:#ffe6f0,stroke:#cc0066,stroke-width:2px
classDef subStyle fill:#f0e6ff,stroke:#9933ff,stroke-width:2px
class push,pr,release,manual,cron1,cron2,cron3 triggerStyle
class build,release_wf,manual_docs,build_dev,stale,security_scan mainStyle
class task_build,task_docs,task_lint,task_security taskStyle
class ci_main,ci_build_script,ci_site_script,ci_qa_script,ci_security_script ciStyle
class ci_build_fw,ci_prep_art,gen_board,gen_wu,clang_fmt,trivy subStyle
style github_workflows stroke:#6A7BD8,stroke-dasharray:6 4,stroke-width:1.8px,fill:#fbfbfc
style main stroke:#6A7BD8,stroke-dasharray:6 4,stroke-width:0.6px,fill:#fcfdff
style tasks stroke:#6A7BD8,stroke-dasharray:6 4,stroke-width:0.6px,fill:#fcfdff
style ci_scripts stroke:#FF9A3C,stroke-dasharray:6 4,stroke-width:1.8px,fill:#fffaf5
style bash stroke:#FF9A3C,stroke-dasharray:6 4,stroke-width:0.6px,fill:#fffaf5
style sub_scripts stroke:#FF9A3C,stroke-dasharray:6 4,stroke-width:0.6px,fill:#fffaf5
style triggers fill:none,stroke:none
linkStyle 0,1,2,3,4,5,6 stroke:#0066cc,stroke-width:3px;
linkStyle 7,8,9,10,11,12,13,14,15 stroke:orange, stroke-width:2px;
linkStyle 16,17,18,19,20,21,22,23,24,25,26,27,28,29 stroke:red, stroke-width:2px;
Workflow Relationships
Main → Task Mapping:
build.yml→ callstask-build.yml(also contains inline documentation job)build_and_docs_to_dev.yml→ callstask-build.yml+task-docs.ymlrelease.yml→ callstask-build.yml+task-docs.ymlmanual_docs.yml→ callstask-docs.ymlsecurity-scan.yml→ callstask-security-scan.ymlstale.yml→ standalone (no dependencies)
Task → CI Script Mapping:
task-build.yml→ci.sh build --version --mode --deploy-ready- Routes to:
ci_build.sh→ci_build_firmware.sh,ci_prepare_artifacts.sh - Output:
generated/artifacts/firmware_build/
- Routes to:
task-docs.yml→ci.sh site --mode --version --url-prefix- Routes to:
ci_site.sh→generate_board_docs(npm),gen_wu(npm), VuePress - Output:
generated/site/
- Routes to:
task-lint.yml→ci.sh qa --check --source --extensions --clang-format-version- Routes to:
ci_qa.sh→clang-format
- Routes to:
task-security-scan.yml→ci.sh security --scan-type --severity --generate-sbom- Routes to:
ci_security.sh→ Trivy (vulnerability scanner) - Output:
generated/reports/(SARIF, JSON, SBOM)
- Routes to:
Job Dependencies:
build_and_docs_to_dev.yml: prepare → build (task) → deploy & documentation (task)release.yml: prepare → build (task) → deploy → documentation (task)
Script Execution Flow:
GitHub Action (task-*.yml)
↓
./scripts/ci.sh <command> [OPTIONS] ← Main dispatcher
↓
./scripts/ci_<command>.sh ← Command orchestrator
↓
./scripts/ci_*.sh / *.py ← Worker scripts
Detailed Workflow Documentation
1. build.yml - Continuous Integration Build
Purpose: Validates that code changes compile successfully with intelligent environment selection based on branch importance.
Triggers:
- Push: Every commit pushed to any branch
- Pull Request: Every PR creation or update
What it does:
- Determine build scope: Selects environment list based on branch name
- Full build (
allenvironment): All PRs and Push on important branches (development, master, edge, stable, release/, hotfix/) - Quick build (
cisubset environment): All PRs and Push on non-critical branches
- Full build (
- Build job: Calls
task-build.ymlwith appropriate environment set- Builds firmware in parallel
- Documentation job: Inline job that validates docs build (doesn't deploy)
- Downloads common config from theengs.io
- Runs
npm installandnpm run docs:build - Uses Node.js 14.x
Technical Details:
- Calls:
task-build.ymlonly (documentation is inline) - Python version: 3.13 (for build job)
- Build strategy: Parallel matrix via task workflow
- Artifact retention: 7 days
- Development OTA: Enabled (
enable-dev-ota: true) - Environment selection logic:
- Full build (
all): All Pull Requests + branches: development, master, edge, stable, release/, hotfix/ - Quick build (
cisubset): All other feature branches
- Full build (
Outputs:
- Firmware binaries for selected environments
- No documentation deployment (validation only)
Use Case: Ensures no breaking changes before merge. Fast feedback for feature branches (~10 min), comprehensive validation for PRs and critical branches (~40 min).
Execution Context: Runs for ALL contributors on ALL branches with smart scaling based on branch importance.
2. build_and_docs_to_dev.yml - Development Deployment Pipeline
Purpose: Creates nightly development builds and deploys documentation to the /dev subdirectory for testing.
Triggers:
- Schedule: Daily at midnight UTC (
0 0 * * *) - Manual: Via workflow_dispatch button
What it does:
- Prepare job: Generates 6-character short SHA
- Handle-firmwares job: Calls
task-build.ymlwith development parameters- Builds firmware for all environments in parallel
- Enables development OTA updates with SHA commit version
- Artifact retention: 1 day
- Handle-documentation job: Calls
task-docs.ymlwith development parameters- Deploys to
/devsubdirectory on GitHub Pages - Uses short SHA as version identifier
- Runs PageSpeed Insights on dev site
- Deploys to
Technical Details:
- Calls:
task-build.yml+task-docs.yml - Repository restriction: Hardcoded to
1technophileowner only - Version: 6-character short SHA (e.g.,
abc123) - Documentation URL prefix:
/dev/ - GitHub Pages destination:
devsubdirectory - PageSpeed URL:
https://docs.openmqttgateway.com/dev/
Workflow Parameters:
- Build:
enable-dev-ota: true,version-tag: <short-sha>,artifact-retention-days: 1 - Docs:
mode: "dev",version: <short-sha>,url-prefix: "/dev/",destination-dir: "dev",run-pagespeed: true
Outputs:
- Firmware binaries with
-firmware.binsuffix (1 day retention) - Bootloader and partition binaries
- Documentation deployed to
docs.openmqttgateway.com/dev/
Version Labeling:
- Git SHA (6 chars) injected into firmware via
version-tag - Docs display short SHA as version
Use Case: Daily bleeding-edge builds for early adopters and testing. Preview documentation changes before production release.
Execution Context: Only runs on 1technophile repository owner. Forks will skip this workflow automatically.
3. release.yml - Production Release Pipeline
Purpose: Creates official release builds when a new version is published.
Triggers:
- Release: When a GitHub release is published (tagged)
What it does:
- Prepare job: Extracts version tag and release info from GitHub event
- Build job: Calls
task-build.ymlwith production parameters
- Builds firmware for all environments in parallel
- Injects release tag version into firmware
- Artifact retention: 90 days
- Deploy job: Downloads and uploads release assets
- Downloads all firmware artifacts from build job
- Uploads binaries to GitHub Release
- Documentation job: Calls
task-docs.ymlfor production docs
- Deploys to root (
/) of GitHub Pages - Uses release tag as version
Technical Details:
- Calls:
task-build.yml+task-docs.yml - Build flag: Standard (no DEVELOPMENTOTA)
- Artifact retention: 90 days
- Deploy uses
bgpat/release-asset-actionto attach assets to GitHub Release
Workflow Parameters:
- Build:
enable-dev-ota: false,version-tag: <git-tag>,artifact-retention-days: 90 - Docs:
mode: "prod",version: <git-tag>,url-prefix: "/",destination-dir: "."
Outputs:
- Production firmware binaries attached to GitHub Release (all prepared by
task-build.ymlwith--deploy-ready) - Production documentation at
docs.openmqttgateway.com/
Version Labeling:
- Git tag (e.g.,
v1.2.3) injected into firmware
Workflow Chain:
prepare → build (task-build.yml) → deploy → documentation (task-docs.yml)
Use Case: Official releases for end users. Stable, versioned firmware.
Execution Context: Triggered by repository maintainers creating releases.
4. manual_docs.yml - Documentation Deployment
Purpose: Entry point for standalone documentation deployment to GitHub Pages.
Triggers:
- Manual: Via workflow_dispatch button
- Workflow Call: Can be called by other workflows (legacy compatibility)
What it does:
- Calls
task-docs.ymlwith production parameters - Deploys to root directory (
/) of GitHub Pages
Technical Details:
- Calls:
task-docs.yml - Mode:
prod - Version: Uses latest release tag by default (or provided input)
- URL prefix:
/ - Destination: Root of GitHub Pages
- PageSpeed: Optional (disabled by default)
Outputs:
- Production documentation at
docs.openmqttgateway.com/ - Custom domain:
docs.openmqttgateway.com(via CNAME)
Use Case: Standalone documentation updates without full release process.
Execution Context: Manual trigger or legacy workflow calls.
5. security-scan.yml - Security Vulnerability Scanning
Purpose: Scans the project for security vulnerabilities and generates Software Bill of Materials (SBOM) for supply chain security.
Triggers:
- Schedule: Weekly on Monday at 02:00 UTC (
0 2 * * 1) - Manual: Via workflow_dispatch button with input parameters
Manual Trigger Inputs:
severity: Severity levels to scan (choices: UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL; default: HIGH,CRITICAL)- Allows filtering results to specific severity levels
What it does:
- Prepare job: Sets up environment for scanning
- Security scan job: Calls
task-security-scan.ymlwith parameters- Runs Trivy vulnerability scanner on filesystem
- Filters results by severity level
- Generates SARIF format for GitHub Security tab integration
- Creates SBOM in CycloneDX and SPDX formats
- Uploads findings to GitHub Security tab (code scanning dashboard)
- Artifact upload job: Stores generated reports and SBOM
- SARIF results for GitHub integration
- SBOM files for supply chain tracking
- Retention: 90 days
Technical Details:
- Calls:
task-security-scan.yml - Vulnerability scanner: Trivy (vulnerability database updated automatically)
- Report formats: SARIF (GitHub), JSON (detailed), Markdown (summary)
- SBOM formats: CycloneDX and SPDX (standard formats)
- Failure behavior: Does NOT fail the workflow on vulnerabilities (exit-code: 0)
- GitHub Security tab: Auto-uploads SARIF for code scanning dashboard visibility
Workflow Parameters:
scan-type: "fs"(filesystem scan)severity: "HIGH,CRITICAL"(default, or manual input)generate-sbom: true(always enabled)upload-to-security-tab: true(GitHub Security integration)
Outputs:
- SARIF report:
generated/reports/trivy-results.sarif(GitHub Security tab) - JSON report:
generated/reports/trivy-results.json(detailed findings) - Markdown summary:
generated/reports/security-summary.md - SBOM:
generated/reports/sbom/sbom.cyclonedx.json+sbom.spdx.json - Artifacts retained for 90 days
Use Case: Regular security audits, compliance tracking, vulnerability management, supply chain security.
Execution Context: Weekly automated scans + manual on-demand scanning for developers.
6. stale.yml - Issue and PR Management
Purpose: Automatically closes inactive issues and pull requests to reduce maintenance burden.
Triggers:
- Schedule: Daily at 00:30 UTC (
30 0 * * *)
What it does:
- Marks issues/PRs as stale after 90 days of inactivity
- Closes stale issues/PRs after 14 additional days
- Exempts issues labeled "enhancement"
Configuration:
- Stale after: 90 days
- Close after: 14 days (104 days total)
- Stale label:
stale - Exempt labels:
enhancement
Messages:
- Stale: "This issue is stale because it has been open for 90 days with no activity."
- Close: "This issue was closed because it has been inactive for 14 days since being marked as stale."
Use Case: Housekeeping. Reduces backlog of abandoned issues.
Execution Context: Automated maintenance by GitHub bot.
Task Workflows (Reusable Components)
7. task-build.yml - Reusable Build Workflow
Purpose: Parameterized firmware build logic used by multiple workflows.
Trigger: workflow_call only (called by other workflows)
Parameters:
python-version: Python version to use (default: '3.13')pio-version: PlatformIO version to use (default: 'v6.1.19')environment-set: Which set of environments to build: 'all' or 'ci' (default: 'all')enable-dev-ota: Enable development OTA builds (default: false)version-tag: Optional version tag to pass to ci.sh build - omitted if empty (default: '')artifact-retention-days: Number of days to retain build artifacts (default: 7)
What it does:
- Lint code: Runs
task-lint.ymlto check code formatting (main directory, .h and .ino files) - Load environments: Reads environment list from
environments.jsonbased onenvironment-setinput (allorci) - Install PlatformIO: Uses
uvto install thepio-versioninput (custompioarduino/platformio-corefork) - Matrix build: Builds selected environments in parallel, blocking on lint job completion
- Build execution: Calls unified
ci.sh build <environment> [OPTIONS]:<environment>: Target hardware (e.g.,esp32dev-ble)--version <tag>: Version to inject (SHA for dev, tag for prod)--mode <dev|prod>: Build mode (enables/disables OTA)--deploy-ready: Prepare artifacts for deployment--output <dir>: Output directory for artifacts (default:generated/artifacts/)
Command Flow:
./scripts/ci.sh build esp32dev-ble --version v1.8.0 --mode prod --deploy-ready
↓
├─→ ci_build.sh (orchestrator)
│ ├─→ ci_build_firmware.sh esp32dev-ble [--dev-ota]
│ └─→ ci_prepare_artifacts.sh esp32dev-ble [--deploy] → outputs to generated/artifacts/
Technical Details:
- Runs on: Ubuntu latest
- PlatformIO version: Configurable via
pio-versioninput (default: v6.1.19, custom fork:pioarduino/platformio-core) - Python package manager:
uv(astral-sh/setup-uv@v6) - Environment sets:
all(complete set) orci(subset for quick validation) - Strategy: Matrix with fail-fast: false (builds complete even if one environment fails)
- Dependencies: Lint job must pass before build matrix starts
- Main orchestrator:
ci.sh→ci_build.sh→ sub-scripts
Callers:
build.yml(CI validation)build_and_docs_to_dev.yml(development builds)release.yml(production releases)
8. task-docs.yml - Reusable Documentation Workflow
Purpose: Parameterized documentation build and deployment logic.
Trigger: workflow_call only (called by other workflows)
Parameters:
mode: Documentation mode (prodordev, default:prod)version: Version string for docs (default:auto→ tag or short SHA depending on caller)url-prefix: Base URL path (default:/for prod,/dev/for dev callers)destination-dir: Deploy directory on GitHub Pages (default:.)run-pagespeed: Run PageSpeed Insights after deploy (default: false)pagespeed-url: URL to test with PageSpeed (default:https://docs.openmqttgateway.com/)
What it does:
- Build documentation: Calls unified
ci.sh site --mode <mode> --version <ver> --url-prefix <path> - Deploy: Publishes to GitHub Pages using
peaceiris/actions-gh-pages@v3 - PageSpeed test: Optionally runs performance audit on the provided URL
Command Flow:
./scripts/ci.sh site --mode prod --version v1.2.3 --url-prefix /
↓
└─→ ci_site.sh (orchestrator)
└─→ npm run docs:build (VuePress compilation)
Callers:
build_and_docs_to_dev.yml(dev docs to/dev)release.yml(production docs to/)manual_docs.yml(manual production docs)
9. task-lint.yml - Reusable Lint Workflow
Purpose: Parameterized code formatting validation for consistent code style.
Trigger: workflow_call only (called by other workflows)
Parameters:
source: Source directory to lint (default: 'main')extensions: File extensions to check, comma-separated (default: 'h,ino')clang-format-version: clang-format version to use (default: '9')
What it does:
- Checks out code
- Installs clang-format (specified version)
- Runs unified
ci.sh qa [OPTIONS]:--check: Validation mode (exit on violations)--fix: Auto-fix formatting issues--source <dir>: Directory to lint--extensions <list>: File extensions (comma-separated)--clang-format-version <ver>: Formatter version
- Fails if formatting violations found
Command Flow:
./scripts/ci.sh qa --check --source main --extensions h,ino --clang-format-version 9
↓
└─→ ci_qa.sh (formatter)
└─→ clang-format (checks/fixes code style)
Technical Details:
- Runs on: Ubuntu latest
- Script:
ci_qa.sh(custom formatting check script) - Formatter:
clang-format-$versioninstalled via apt-get - Default scope:
maindirectory only (not lib) - Default file types:
.hand.ino(not.cpp) - Strategy: Single sequential job (not parallelized)
Callers:
build.yml(inline lint check before build)- Can be called by other workflows as needed
Default Behavior: If called without parameters, lints main directory for .h and .ino files only.
10. task-security-scan.yml - Reusable Security Scan Workflow
Purpose: Parameterized security vulnerability scanning and SBOM generation logic.
Trigger: workflow_call only (called by other workflows)
Parameters:
scan-type: Type of scan: 'fs' (filesystem), 'config' (configuration), or 'image' (container) (default: 'fs')severity: Severity levels to report (comma-separated: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL) (default: 'HIGH,CRITICAL')scan-path: Path to scan (default: '.')exit-code: Exit code when vulnerabilities found (0=continue, 1=fail) (default: '0')upload-to-security-tab: Upload SARIF to GitHub Security tab (default: true)generate-sbom: Generate SBOM artifacts (default: true)
What it does:
- Install Trivy: Retrieves and installs Trivy vulnerability scanner
- Run security scan: Calls unified
ci.sh securitywith parameters:--scan-type <fs|config|image>: Target type--severity <levels>: Filter by severity--scan-path <path>: Directory to scan--generate-sbom: Generate SBOM in CycloneDX and SPDX formats--exit-code <0|1>: Fail behavior on critical vulnerabilities--upload-to-security-tab: Upload SARIF to GitHub
- Upload artifacts: Stores reports and SBOM for later download
- GitHub Security integration: SARIF automatically appears in Security tab
Command Flow:
./scripts/ci.sh security --scan-type fs --severity HIGH,CRITICAL --generate-sbom --upload-to-security-tab
↓
└─→ ci_security.sh (security orchestrator)
└─→ Trivy (vulnerability scanner)
├─→ Generate SARIF, JSON, summary
├─→ Generate SBOM (CycloneDX, SPDX)
└─→ Upload to GitHub Security tab
Technical Details:
- Runs on: Ubuntu latest
- Scanner: Trivy (latest version auto-installed)
- Report formats: SARIF (GitHub integration), JSON (detailed), Markdown (summary)
- SBOM formats: CycloneDX and SPDX (industry standards)
- GitHub Security tab: Auto-uploads SARIF for code scanning dashboard
- Strategy: Single sequential job (not parallelized)
- Artifact retention: As configured by caller
Output Files:
generated/reports/trivy-results.sarif- SARIF format (GitHub Security tab upload)generated/reports/trivy-results.json- JSON format (detailed results)generated/reports/security-summary.md- Human-readable summarygenerated/reports/sbom/sbom.cyclonedx.json- CycloneDX SBOMgenerated/reports/sbom/sbom.spdx.json- SPDX SBOM
Callers:
security-scan.yml(weekly + manual scanning)- Can be called by other workflows for custom security workflows
Environment Configuration
Centralized Environment Management
All build environments are defined in .github/workflows/environments.json:
{
"environments": {
"all": [ ...all environments ],
"ci": [...a subset of environments]
}
}
}
Environment Sets:
all: Complete production set for releases and comprehensive validationci: Representative subset for fast CI feedback
Environment Categories
ESP32 Family (~50 environments):
- Standard:
esp32dev-*variants - ESP32-S3:
esp32s3-*variants - ESP32-C3:
esp32c3-*variants - Specialized boards: M5Stack, Heltec, LilyGO, Theengs
ESP8266 Family (~20 environments):
- NodeMCU:
nodemcuv2-*variants - Sonoff:
sonoff-*variants - Generic:
esp8266-*variants
Specialized Boards (~13 environments):
- Theengs Plug
- Theengs Bridge
- RF Bridge variants
- Custom board configurations
Configuration Variables
Repository Restrictions
Development Builds (build_and_docs_to_dev.yml):
- Hardcoded restriction:
github.repository_owner == '1technophile' - Only runs for the main repository owner
- Prevents accidental deployments from forks
- No configuration variable needed
Release Builds (release.yml):
- No repository restrictions
- Runs on any fork when a release is published
- Deploy step requires proper GitHub token permissions
Documentation (manual_docs.yml):
- No repository restrictions
- Can be triggered manually from any fork
- Requires GitHub Pages to be configured
Glossary
- Environment: A specific hardware board + gateway combination (e.g.,
esp32dev-ble) - Matrix Build: Parallel execution of builds across multiple environments
- Artifact: Build output stored temporarily for download (firmware binaries)
- workflow_call: GitHub Actions feature for calling one workflow from another
- workflow_dispatch: Manual trigger button for workflows
- Task Workflow: Reusable workflow component with parameterized inputs
- Main Workflow: Entry point workflow triggered by events or schedules
- CNAME: Custom domain configuration for GitHub Pages
- OTA: Over-The-Air firmware update capability
- SHA: Git commit hash used for version identification in dev builds
Maintenance Notes
CI/CD Script Architecture
Main Entry Point: ci.sh (unified interface)
- Commands:
build,site,qa,all - Routes to specialized orchestrators
- Provides consistent CLI across all operations
Build System (ci.sh build):
- PlatformIO 6.1.19 from custom fork:
pioarduino/platformio-core - Python package manager:
uvfor fast dependency installation - Orchestrator:
ci_build.sh- Worker:
ci_build_firmware.sh(PlatformIO compilation) - Worker:
ci_prepare_artifacts.sh(artifact packaging)
- Worker:
Documentation System (ci.sh site):
- Documentation framework: VuePress
- Orchestrator:
ci_site.sh- Worker:
generate_board_docs(npm package - auto-generate board pages) - Worker:
gen_wu(npm package - WebUpdater manifest) - External: Common config from theengs.io
- Worker:
Code Quality (ci.sh qa):
- Orchestrator:
ci_qa.sh- Worker:
clang-formatversion 9 - Worker:
shellcheckfor shell scripts - Default scope:
maindirectory,.hand.inofiles
- Worker:
Security Scanning System (ci.sh security):
- Vulnerability scanner: Trivy (container vulnerability database)
- Orchestrator:
ci_security.sh- Worker: Trivy (filesystem, configuration, and container image scanning)
- Report formats: SARIF (GitHub Security tab), JSON (detailed), Markdown (summary)
- SBOM generation: CycloneDX and SPDX formats
- GitHub Security integration: Auto-uploads SARIF for code scanning dashboard
- Output:
generated/reports/(security findings and artifacts)
Configuration:
- Environment list:
.github/workflows/environments.json - Task workflows:
task-*.yml(reusable GitHub Actions components) - Repository owner restriction: Hardcoded to
1technophilefor dev deployments - All scripts located in:
./scripts/
Local Development:
# Build firmware locally
./scripts/ci.sh build esp32dev-ble --mode dev --version test
# Build documentation locally
./scripts/ci.sh site --mode dev --version test
# Check code format
./scripts/ci.sh qa --check --source main --extensions h,ino --clang-format-version 9
# Security scanning
./scripts/ci.sh security --scan-type fs --severity HIGH,CRITICAL --generate-sbom
# Run complete pipeline
./scripts/ci.sh all --mode dev
Document Version: 2.3
Last Updated: 01/14/2026
Maintainer: OpenMQTTGateway Development Team