-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
ci: discover and build custom PlatformIO envs from usermods platformi… #5649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
71767b7
badfcfc
2daf17a
af4b39e
d459e6c
e68bd2a
50cd900
fb0c1df
9b4eafa
3007564
83e32ea
818c3cb
76a505f
76b1e0a
a2a2596
1391e46
23c6903
f08daf9
a96bd64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,9 @@ on: | |
| pull_request: | ||
| paths: | ||
| - usermods/** | ||
| push: | ||
| paths: | ||
| - usermods/** | ||
|
|
||
| env: | ||
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | ||
|
|
@@ -12,28 +15,40 @@ jobs: | |
|
|
||
| get_usermod_envs: | ||
| # Only run for pull requests from forks (not from branches within wled/WLED) | ||
| if: github.event.pull_request.head.repo.full_name != github.repository | ||
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository | ||
| name: Gather Usermods | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.12' | ||
| cache: 'pip' | ||
| - name: Install PlatformIO | ||
| run: pip install -r requirements.txt | ||
| - name: Get default environments | ||
| fetch-depth: 0 | ||
| - name: Get changed usermod environments | ||
| id: envs | ||
| run: | | ||
| echo "usermods=$(find usermods/ -name library.json | xargs dirname | xargs -n 1 basename | jq -R | grep -v PWM_fan | grep -v BME68X_v2| grep -v pixels_dice_tray | jq --slurp -c)" >> $GITHUB_OUTPUT | ||
| # Usermods whose directories changed in this PR | ||
| changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \ | ||
| | grep '^usermods/' | cut -d/ -f2 | sort -u || true) | ||
|
Comment on lines
27
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pass Both scripts inject Suggested change - name: Get changed usermod environments
id: envs
+ env:
+ PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
# Usermods whose directories changed in this PR
- changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \
+ changed=$(git diff --name-only "$PR_BASE_SHA" HEAD \
| grep '^usermods/' | cut -d/ -f2 | sort -u || true) - name: Find usermods with custom build environments
id: custom_envs
+ env:
+ PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
# On PRs: only scan usermods whose directories changed.
# On push: scan all usermods (validates the full set on merge).
if [ "${{ github.event_name }}" = "pull_request" ]; then
- changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \
+ changed=$(git diff --name-only "$PR_BASE_SHA" HEAD \
| grep '^usermods/' | cut -d/ -f2 | sort -u || true)As per coding guidelines, "Never interpolate github.event.* values directly into run: steps — pass them through an env: variable to prevent script injection." Also applies to: 107-109 🤖 Prompt for AI Agents |
||
|
|
||
| # All usermods with a library.json (excluding known-incompatible ones) | ||
| all=$(find usermods/ -name library.json \ | ||
| | xargs dirname | xargs -n 1 basename \ | ||
| | grep -v PWM_fan | grep -v BME68X_v2 | grep -v pixels_dice_tray \ | ||
| | sort || true) | ||
|
|
||
| if [ -z "$changed" ] || [ -z "$all" ]; then | ||
| echo "usermods=[]" >> $GITHUB_OUTPUT | ||
| else | ||
| usermods=$(comm -12 <(echo "$all") <(echo "$changed") | jq -R | jq --slurp -c) | ||
| echo "usermods=$usermods" >> $GITHUB_OUTPUT | ||
| fi | ||
| outputs: | ||
| usermods: ${{ steps.envs.outputs.usermods }} | ||
|
|
||
|
|
||
| build: | ||
| # Only run for pull requests from forks (not from branches within wled/WLED) | ||
| if: github.event.pull_request.head.repo.full_name != github.repository | ||
| # Skip when no changed usermods were found (e.g. only non-library changes) | ||
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && needs.get_usermod_envs.outputs.usermods != '[]' | ||
| name: Build Enviornments | ||
| runs-on: ubuntu-latest | ||
| needs: get_usermod_envs | ||
|
|
@@ -74,4 +89,85 @@ jobs: | |
| cat platformio_override.ini | ||
|
|
||
| - name: Build firmware | ||
| run: pio run -e ${{ matrix.environment }} | ||
| run: pio run -e ${{ matrix.environment }} | ||
|
|
||
|
|
||
| get_custom_build_envs: | ||
| name: Gather Custom Build Environments | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Find usermods with custom build environments | ||
| id: custom_envs | ||
| run: | | ||
| # On PRs: only scan usermods whose directories changed. | ||
| # On push: scan all usermods (validates the full set on merge). | ||
| if [ "${{ github.event_name }}" = "pull_request" ]; then | ||
| changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \ | ||
| | grep '^usermods/' | cut -d/ -f2 | sort -u || true) | ||
| if [ -z "$changed" ]; then | ||
| echo "matrix=[]" >> $GITHUB_OUTPUT | ||
| exit 0 | ||
| fi | ||
| samples=$(for mod in $changed; do | ||
| f="usermods/$mod/platformio_override.ini.sample" | ||
| [ -f "$f" ] && echo "$f" | ||
| done | sort) | ||
| else | ||
| samples=$(find usermods/ -name "platformio_override.ini.sample" | sort) | ||
| fi | ||
|
|
||
| result='[]' | ||
| for sample in $samples; do | ||
| usermod=$(dirname "$sample" | xargs basename) | ||
| # Skip usermods known to be incompatible (same list as get_usermod_envs) | ||
| case "$usermod" in PWM_fan|BME68X_v2|pixels_dice_tray) continue ;; esac | ||
| envs=$(grep -E '^\[env:[^]]+\]' "$sample" | sed 's/^\[env:\(.*\)\]$/\1/') | ||
| for env in $envs; do | ||
| result=$(echo "$result" | jq --arg u "$usermod" --arg e "$env" '. + [{usermod: $u, env: $e}]') | ||
| done | ||
| done | ||
| echo "matrix=$(echo "$result" | jq -c '.')" >> $GITHUB_OUTPUT | ||
| outputs: | ||
| matrix: ${{ steps.custom_envs.outputs.matrix }} | ||
|
|
||
|
|
||
| build_custom: | ||
| name: Build Custom Env (${{ matrix.usermod }} / ${{ matrix.env }}) | ||
| runs-on: ubuntu-latest | ||
| needs: get_custom_build_envs | ||
| if: needs.get_custom_build_envs.outputs.matrix != '[]' | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: ${{ fromJSON(needs.get_custom_build_envs.outputs.matrix) }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Set up Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version-file: '.nvmrc' | ||
| cache: 'npm' | ||
| - run: npm ci | ||
| - name: Cache PlatformIO | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/.platformio/.cache | ||
| ~/.buildcache | ||
| build_output | ||
| key: pio-${{ runner.os }}-${{ matrix.env }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-${{ hashFiles('wled00/**', 'usermods/**') }} | ||
| restore-keys: pio-${{ runner.os }}-${{ matrix.env }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}- | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.12' | ||
| cache: 'pip' | ||
| - name: Install PlatformIO | ||
| run: pip install -r requirements.txt | ||
| - name: Apply custom build environment | ||
| run: cp -v "usermods/${{ matrix.usermod }}/platformio_override.ini.sample" platformio_override.ini | ||
| - name: Build firmware | ||
| run: pio run -e ${{ matrix.env }} | ||
|
Comment on lines
+95
to
+173
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add an explicit These new jobs currently inherit the default Suggested change+permissions:
+ contents: read
+
jobs:As per coding guidelines, "Declare explicit permissions: blocks scoped to least privilege." 🧰 Tools🪛 zizmor (1.25.2)[warning] 99-101: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [warning] 147-147: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [warning] 95-134: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block (excessive-permissions) [error] 99-99: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 147-147: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 149-149: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 155-155: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 164-164: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI Agents |
||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,16 @@ | ||
| ; Options | ||
| ; ------- | ||
| ; USERMOD_SN_PHOTORESISTOR - define this to have this user mod included wled00\usermods_list.cpp | ||
| ; USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds | ||
| ; USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - the number of milliseconds after boot to take first measurement, defaults to 20 seconds | ||
| ; USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE - the voltage supplied to the sensor, defaults to 5v | ||
| ; USERMOD_SN_PHOTORESISTOR_ADC_PRECISION - the ADC precision is the number of distinguishable ADC inputs, defaults to 1024.0 (10 bits) | ||
| ; USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE - the resistor size, defaults to 10000.0 (10K hms) | ||
| ; USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE - the offset value to report on, defaults to 25 | ||
| ; | ||
| [env:usermod_sn_photoresistor_d1_mini] | ||
| extends = env:d1_mini | ||
| [env:usermod_sn_photoresistor_esp8266_2m] | ||
| extends = env:esp8266_2m | ||
| custom_usermods = ${env:esp8266_2m.custom_usermods} SN_Photoresistor | ||
| build_flags = | ||
| ${common.build_flags_esp8266} | ||
| -D USERMOD_SN_PHOTORESISTOR | ||
| lib_deps = ${env.lib_deps} | ||
| ${env:esp8266_2m.build_flags} | ||
| -D USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL=60 | ||
| lib_deps = ${env:esp8266_2m.lib_deps} |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -143,7 +143,13 @@ void ShtUsermod::appendDeviceToMqttDiscoveryMessage(JsonDocument& root) { | |
| device[F("ids")] = escapedMac.c_str(); | ||
| device[F("name")] = serverDescription; | ||
| device[F("sw")] = versionString; | ||
| // AI: below section was generated by an AI | ||
| #ifdef ARDUINO_ARCH_ESP32 | ||
| device[F("mdl")] = ESP.getChipModel(); | ||
| #else | ||
| device[F("mdl")] = F("ESP8266"); | ||
| #endif | ||
| // AI: end | ||
|
Comment on lines
+146
to
+152
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win Add a descriptive comment explaining the conditional. The AI-generated block lacks a comment describing what it does and why the conditional is needed. As per coding guidelines, AI-generated code must have a brief comment explaining intent and assumptions. 📝 Suggested documentation // AI: below section was generated by an AI
+// Set device model: ESP.getChipModel() is ESP32-only; ESP8266 uses hardcoded string
`#ifdef` ARDUINO_ARCH_ESP32
device[F("mdl")] = ESP.getChipModel();As per coding guidelines: AI-generated code must be well documented with meaningful comments explaining intent, assumptions, and non-obvious logic. 🤖 Prompt for AI Agents
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please double-check if
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for ESP.getChipModel usages in the codebase
rg -n "getChipModel" --type cpp -C3Length of output: 4271 🌐 Web query:
Length of output: 11721
As for the intent: since the ESP8266 framework provides no equivalent API, hardcoding This pattern is actually already established in the WLED codebase — `#if` defined(ARDUINO_ARCH_ESP32)
ESP.getChipModel()
`#else`
"ESP8266"
`#endif`So the AI-generated code in ✏️ Learnings added
🧠 Learnings used |
||
| device[F("mf")] = F("espressif"); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broaden the path filter to cover the files that define this CI behavior.
Right now this workflow only fires for
usermods/**, so changes to.github/workflows/usermods.ymlorplatformio_override.sample.inican skip the very checks they affect.Suggested change
on: pull_request: paths: - usermods/** + - .github/workflows/usermods.yml + - platformio_override.sample.ini push: paths: - usermods/** + - .github/workflows/usermods.yml + - platformio_override.sample.iniAs per coding guidelines, "Follow the CI/CD conventions documented in docs/cicd.instructions.md."
📝 Committable suggestion
🤖 Prompt for AI Agents