Skip to content

ci(sync-device-svgs): refresh the Resources/images catalog the app actually loads#2114

Open
bruschill wants to merge 2 commits into
meshtastic:mainfrom
bruschill:ci/sync-device-images-resources-path
Open

ci(sync-device-svgs): refresh the Resources/images catalog the app actually loads#2114
bruschill wants to merge 2 commits into
meshtastic:mainfrom
bruschill:ci/sync-device-images-resources-path

Conversation

@bruschill

@bruschill bruschill commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What changed?

Retargets the nightly Sync Device SVGs workflow (.github/workflows/sync_device_svgs.yml) so it refreshes the device catalog the app actually loads.

  • Replaces the old "clone meshtastic/web-flasher → svgo → write imagesets into Meshtastic/Assets.xcassets" steps with a single call to the repo's own scripts/download_images.py --force, writing to Meshtastic/Resources/images/ + Meshtastic/Resources/DeviceHardware.json — the same script and output location the Xcode "Download Node SVG Images" build phase uses.
  • Adds explicit permissions: contents: write so the scheduled job can actually commit/push the refresh.
  • Stages new/updated/pruned device SVGs via git add -A, and detects changes (including brand-new untracked SVGs) with a path-scoped git status --porcelain.

Net: +37 / −127 (removes the now-unnecessary web-flasher clone, svgo install, and xcassets generation).

Why did it change?

The app loads device images at runtime from the bundled images subdirectory and DeviceHardware.json (MeshtasticAPI.swiftBundle.main.url(forResource:withExtension:subdirectory:"images") and the bundled hardware catalog), maintained by scripts/download_images.py. The device imagesets under Assets.xcassets are no longer the runtime source (the remaining imagesets there are AppIcons). So the nightly job was updating a legacy location and not keeping the real catalog current — it drifted until someone happened to run a clean build (which force-refreshes the catalog) and committed the result.

Concretely, this catalog is currently behind upstream: a new RAK6421 device is present in the API but missing from the committed snapshot. Pointing the automation at the correct script + path means the bundled catalog stays in sync with https://api.meshtastic.org/resource/deviceHardware automatically, and contributors stop seeing spurious DeviceHardware.json / image_manifest.json diffs after clean builds.

How is this tested?

  • python3 -c "import yaml; yaml.safe_load(...)" — workflow YAML validates.
  • scripts/download_images.py is the exact script already run by the Xcode build phase (unchanged), so the workflow reproduces the same output the app bundle expects; running it locally with these args produces the expected catalog refresh (e.g. adds rak6421.svg + its manifest/JSON entries).
  • The job is schedule + workflow_dispatch only (no untrusted/fork input), and contents: write is the minimum permission required for the auto-commit. It can be dry-run via workflow_dispatch after merge to confirm the commit/push path.

Screenshots/Videos (when applicable)

N/A — CI workflow change only.

Checklist

  • My code adheres to the project's coding and style guidelines.
  • I have conducted a self-review of my code.
  • I have commented my code, particularly in complex areas.
  • I have verified whether these changes require updates to the in-app documentation under docs/user/ or docs/developer/. This is a CI-only change with no Meshtastic/Views/** or @Model changes, so no doc update is required — adding the skip-docs-check label.
  • I have tested the change to ensure that it works as intended.

Summary by CodeRabbit

  • Chores
    • Reworked the automated device resource synchronization process.
    • Device images and the hardware catalog are now updated and pushed directly when changes are detected.
    • Improved workflow logging to clearly report whether device resources were updated.

…tually loads

The nightly Sync Device SVGs job cloned meshtastic/web-flasher and wrote
device imagesets into Meshtastic/Assets.xcassets. But the app loads device
images at runtime from the bundled 'images' subdirectory and DeviceHardware.json
(see MeshtasticAPI.swift), maintained by scripts/download_images.py and the
Xcode 'Download Node SVG Images' build phase. The xcassets device imagesets are
no longer the runtime source, so the job wasn't keeping the real catalog current
— it drifted until someone ran a clean build (which force-refreshes it) and
committed the result.

Retarget the workflow to run the repo's own download_images.py with --force
against Meshtastic/Resources/images + DeviceHardware.json, so the committed
snapshot always matches the upstream device hardware API. Also add explicit
'contents: write' permission so the scheduled auto-commit can push, and stage
new/updated/pruned device SVGs via 'git add -A'.
@bruschill bruschill added the skip-docs-check Use this label to skip the automatic docs audit label Jul 18, 2026
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d01e196a-8182-4c7f-af6e-9b1f692b15ee

📥 Commits

Reviewing files that changed from the base of the PR and between 3153b67 and 8fe7844.

📒 Files selected for processing (1)
  • .github/workflows/sync_device_svgs.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/sync_device_svgs.yml

📝 Walkthrough

Walkthrough

The device resource sync workflow now uses Python to refresh device images and DeviceHardware.json, detects changes only in those resources, commits them directly with write permissions, and reports whether updates occurred.

Changes

Device resource synchronization

Layer / File(s) Summary
Python resource generation
.github/workflows/sync_device_svgs.yml
The workflow replaces Node.js and SVGO processing with Python 3.11 and scripts/download_images.py to refresh device images and the hardware catalog.
Resource commit and reporting
.github/workflows/sync_device_svgs.yml
Change detection, staging, and pushing are limited to the refreshed resource paths, and the final summary reflects whether updates were made.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit watched the images grow,
And saw the catalog sync just so.
Python hopped across the run,
Committing changes one by one.
“No stale sprites remain today!” 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly names the workflow and the main change: refreshing the Resources/images catalog.
Description check ✅ Passed The description matches the template and includes what changed, why, testing, screenshots, and checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/sync_device_svgs.yml (1)

65-71: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prevent code injection via template expansion.

Avoid using expression expansion (${{ ... }}) directly inside inline bash scripts. While has_changes is strictly controlled in this context and not exploitable, mapping it to an environment variable is a safer practice and resolves warnings from static analysis tools.

♻️ Proposed fix
     - name: Summary
+      env:
+        HAS_CHANGES: ${{ steps.check_changes.outputs.has_changes }}
       run: |
-        if [ "${{ steps.check_changes.outputs.has_changes }}" == "true" ]; then
+        if [ "$HAS_CHANGES" == "true" ]; then
           echo "✅ Device images and hardware catalog updated"
         else
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sync_device_svgs.yml around lines 65 - 71, Update the
Summary step’s shell condition to read has_changes through a step-level
environment variable populated from steps.check_changes.outputs.has_changes,
rather than expanding the GitHub expression directly inside the bash script.
Preserve the existing true and no-changes messages.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/sync_device_svgs.yml:
- Around line 51-64: Update the commit-and-push step in the sync workflow to
push HEAD explicitly to the intended branch instead of using an implicit git
push from detached HEAD. Use the workflow’s branch context to construct the
destination, and retain the existing commit behavior; if branch protection
rejects the push, configure checkout authentication with a token authorized to
bypass those rules.

---

Nitpick comments:
In @.github/workflows/sync_device_svgs.yml:
- Around line 65-71: Update the Summary step’s shell condition to read
has_changes through a step-level environment variable populated from
steps.check_changes.outputs.has_changes, rather than expanding the GitHub
expression directly inside the bash script. Preserve the existing true and
no-changes messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f06ffe9-1ec2-4a91-b202-3e60d7012aeb

📥 Commits

Reviewing files that changed from the base of the PR and between e531f15 and 3153b67.

📒 Files selected for processing (1)
  • .github/workflows/sync_device_svgs.yml

Comment thread .github/workflows/sync_device_svgs.yml
Address review feedback:
- actions/checkout leaves a detached HEAD, so a bare 'git push' fails. Push
  HEAD explicitly to the branch (git push origin HEAD:<ref_name>).
- Route github.ref_name and the has_changes output through step-level env vars
  instead of expanding ${{ }} inside inline bash (avoids the shell-injection
  pattern flagged by static analysis).
@bruschill

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — addressed both findings in 8fe7844:

1. Detached HEAD push (major). actions/checkout leaves a detached HEAD, so the bare git push would fail. Now pushes HEAD explicitly to the branch:

git push origin "HEAD:${TARGET_BRANCH}"

2. Expression expansion inside bash (nitpick). Both github.ref_name (for the push) and the has_changes output (Summary step) are now read through step-level env: vars instead of inline ${{ }}, so no GitHub expression is expanded inside a shell script.

Operational note (branch protection): if main is protected, the scheduled job's direct push via secrets.GITHUB_TOKEN may still be rejected regardless of the detached-HEAD fix — this pre-dates the PR (the previous workflow also pushed directly to main). If maintainers prefer, I can switch the commit step to open a PR via peter-evans/create-pull-request (the original file already had this as a disabled alternative), which sidesteps branch protection and keeps the refresh reviewable. Happy to do that if that's the preferred model — otherwise this needs a PAT/GitHub App token with bypass configured on the repo side.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@bruschill Thanks — both fixes look correct. Explicitly pushing HEAD to ${TARGET_BRANCH} handles the detached checkout, and using step-level environment variables avoids GitHub expression interpolation within the shell scripts.

The branch-protection note is a useful operational caveat; a PR-based sync would be an appropriate future alternative if direct scheduled pushes are not permitted.

🐇 ✅


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-docs-check Use this label to skip the automatic docs audit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant