Skip to content

Check and apply plugin icon requests with workflows - #1305

Merged
NorthernMan54 merged 9 commits into
latestfrom
icon-request-workflow
Oct 26, 2026
Merged

NorthernMan54 merged 9 commits into
latestfrom
icon-request-workflow

Conversation

@NorthernMan54

@NorthernMan54 NorthernMan54 commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Adds two workflows that check icon requests and apply them once a maintainer approves, so icons no longer need adding by hand.

1. Checking requests: icon-request-check.yml

When it runs: an icon request is opened, edited or reopened; someone comments /check on its own line; or a maintainer runs it by hand with an issue number, which is useful for the current backlog. It applies to issues labelled request-icon or titled "Plugin Icon Request:".

What it does: runs the read-only prepare step of scripts/apply-icon-request.js:

  • reads the plugin name and icon from the issue form
  • checks the package exists on npm
  • checks the requester develops the plugin: the owner of its GitHub repo, an npm maintainer with the same username, or a public member of the org that owns the repo (maintainers of this repo may request any plugin)
  • downloads the icon: GitHub-hosted images only, 30 s timeout, at most 5 MB
  • checks it's a square PNG, JPEG or WebP, at least 64 px and at most 4096×4096 px, and converts it to a 100×100 PNG

Nothing is committed.

Reports back: it keeps one comment on the issue, updated in place.

  • ✅ Ready for review: shows the icon, its size, why the requester counts as the developer, and the current icon if this would replace one.
  • ❌ Needs changes: says what to fix.

It also sets awaiting-final-review or awaiting-changes (and removes pending). Requests opened without the form get the request-icon label.

Plugins that aren't verified: the check reports them as needing changes and asks the author to request verification first. The hidden marker still records the request and image as valid, and the approval workflow doesn't look at verification, so a maintainer can still approve one as a one-off.

2. Approving: icon-approved.yml

A maintainer adds the new icon-approved label. Four jobs then run:

  1. authorize: the approver must have write access. The icon is only applied if the latest check passed and the issue hasn't been edited since. Otherwise it says why on the issue.
  2. prepare (read-only token, no stored git credentials): runs the same step again. It refuses unless the downloaded image matches the SHA-256 the check recorded, so the icon committed is the one the check showed.
  3. apply (can push):
    • gets only the finished PNG, and checks its header is a 100×100 PNG without decoding it
    • writes icons/<name>.png and the plugin-icons.json entry, replacing an existing icon if there is one
    • runs sort-json-files.js to regenerate assets/
    • commits icon: <plugin> straight to latest
  4. report: comments with the icon as committed and closes the request. If anything fails, it comments with the reason instead.

The untrusted image is only ever decoded in read-only jobs. The label is removed after every run, so adding it again retries. Approvals run one at a time.

Run summaries: every job in both workflows writes a summary to the Actions run page. It covers who approved and why it went ahead or was refused, the prepared image (source, original size, SHA-256, converted size), the commit, and what was done on the issue.

icon-approved does nothing on issues without request-icon. Stage 2, noted in the files, will also apply an icon attached to a verification request when verified is added.

sort-json-files.js now keeps every icon entry whose file exists, and includes those plugins in assets/plugins*.json.

Testing

I ran the script against real open issues, and the workflows' GitHub API calls against mocked responses:

  • Icons: 24 applied correctly, including resizing from 110 to 1254 px. Rejected with clear messages: an SVG, a non-square image, a non-GitHub host, a package that doesn't exist, an invalid name and a 5000×5000 image.
  • Requester check: accepted the repo owner for Plugin Icon Request: homebridge-philips-airplus-cloud #1301, Verification Request: homebridge-pax-calima #1302, Plugin Icon Request: homebridge-my-tadiran #1303 and Verification Request: @rygine/homebridge-omnilogic-local #1248, an npm maintainer, and a maintainer requesting someone else's plugin. Rejected Plugin Icon Request: homebridge-eufy #1212 (not homebridge-eufy's developer) and a made-up requester.
  • The fingerprint: approval goes ahead when the image matches what the check recorded, and is refused when it differs.
  • Check comment:
    • creates one comment, then updates it in place
    • sets awaiting-final-review or awaiting-changes, removes pending, and adds request-icon to requests opened without the form
    • ignores ordinary comments, closed issues and non-icon issues
  • Approval gate: refuses when nothing has been checked, when the check failed, or when the issue was edited after the check, and goes ahead otherwise. A fake check marker in a comment by the author is ignored, and a non-writer's label is removed.
  • commit refuses tampered input: random bytes, a 480×480 PNG, and a plugin name containing ../.
  • No change to current output: on a clean tree, sort-json-files.js produces the same output as before. The only difference is one line of existing drift in assets/ (from author: homebridge-simplisafe3 → shamoon #1304).
  • Lint: ESLint passes.

Neither workflow has run on GitHub yet.

Before merging

🤖 Generated with Claude Code

NorthernMan54 and others added 3 commits October 26, 2026 10:55
Adding the `icon-approved` label to an icon request (or to a
verification request that attached an icon) downloads the icon, resizes
it to a 100x100 PNG, adds it to icons/ and plugin-icons.json (replacing
the existing icon if the plugin has one), regenerates assets/ via
sort-json-files, commits `icon: <plugin>` to latest, and reports back on
the issue. Icon requests are closed once applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Icons no longer require verification. sort-json-files.js keeps icon
entries for any plugin whose icon file exists and adds those plugins to
assets/plugins*.json, so the UI (which shows any plugin with an `i`
entry) picks them up. The icon workflow drops its verified check and
instead confirms the package exists on npm. The README and icon request
template no longer say an icon needs a verified plugin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The icon workflow now runs only when `icon-approved` is added to an
issue labelled `request-icon`, and closes the request once the icon is
in. Icons attached to verification requests need their own icon request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NorthernMan54
NorthernMan54 requested a review from bwp91 October 26, 2026 15:04
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread scripts/apply-icon-request.js Fixed
NorthernMan54 and others added 4 commits October 26, 2026 11:07
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes the CodeQL incomplete-escaping alert: replace('/', '%2F') only
replaced the first slash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Decode the untrusted image in a `prepare` job with read-only access
  and no stored git credentials; the `apply` job that pushes only gets
  the finished PNG and checks its header without decoding it.
- Check the requester develops the plugin (repo owner, npm maintainer,
  or public member of the owning org); maintainers may request any.
- Cap image size at 4096x4096 px, time out downloads after 30 s, stop
  reading past 5 MB, and give each job a timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new Icon Request Check workflow runs the read-only prepare step when
an icon request is opened, edited or reopened, on a `/check` comment, or
by hand. It keeps one comment on the issue saying whether the request is
ready (with the icon as it will appear) or what to fix, and sets
awaiting-final-review or awaiting-changes. Requests opened without the
form get the request-icon label.

`icon-approved` now only applies an icon when the latest check passed,
the issue has not been edited since, and the image downloaded matches
the SHA-256 the check recorded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NorthernMan54 NorthernMan54 changed the title Apply approved plugin icons with a workflow Check and apply plugin icon requests with workflows Oct 26, 2026
Each job in both workflows now writes a summary for the Actions run
page: who approved and why it went ahead or was refused, the prepared
image (source, size, SHA-256), the commit, and what was done on the
issue. The approval workflow is renamed icon-approved.yml ("Icon
Approved").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NorthernMan54
NorthernMan54 merged commit 17abab6 into latest Oct 26, 2026
4 checks passed
@NorthernMan54
NorthernMan54 deleted the icon-request-workflow branch October 26, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants