fix: Change Docker publishing to trigger only on GitHub Releases#10
Merged
Conversation
Update the docker-publish workflow to only build and publish images when a GitHub Release is published, rather than on every push to main. Changes: - Replace push (branches/tags) trigger with release (published) trigger - Remove branch-based tag generation - Update latest tag to only apply on release events - Keep PR builds for validation (without publishing) Benefits: - More controlled release process - Images only published for official releases - Cleaner image registry without intermediate builds - Maintains PR validation builds 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
|
Claude finished @Yeraze's task —— View job PR Review in Progress
|
Yeraze
added a commit
that referenced
this pull request
Oct 12, 2025
10 tasks
TheWISPRer
pushed a commit
to TheWISPRer/meshmonitor
that referenced
this pull request
Jun 20, 2026
- Mark messages played from the delivery-success callback, not at enqueue:
handleCommand returns { responses, playOnDelivery }; a dropped body DM now
leaves the message pending instead of losing it. (Yeraze#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
reclaimed daily (purgeExpired returns a count). (Yeraze#2)
- Count the per-recipient cap across the recipient's identity forms via an
injected node resolver, so it can't be bypassed by addressing one node by
several name forms. (Yeraze#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (Yeraze#4)
- inbox play <sender> filter matches !hex/node-num forms too. (Yeraze#5)
- Non-DM commands return [] (no unsolicited DM). (Yeraze#6)
- inbox delete returns the same response for not-yours vs non-existent ids
(no id enumeration). (Yeraze#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (Yeraze#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (Yeraze#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (Yeraze#10)
Docs + tests updated to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yeraze
added a commit
that referenced
this pull request
Jun 20, 2026
…gaps (#3578) Addresses Claude Code Review findings on PR #3578: - Sanitize device-controlled message before logging/forwarding: strip control chars (log-injection defense) and bound length to 500 (#9, #10). - Widen protected-cap regex to {1,8} hex digits so a short node id still reconciles (#4). - Exclude clientNotification from the unknown-FromRadio debug JSON.stringify dump (#3). - Drop the redundant `&& this.sourceId` guard (always set) and comment why the toast still fires when the DB revert fails (#2, #5). - Frontend: name the level magic numbers and note they mirror the backend NOTIFICATION_LEVEL (#1). - Tests: sanitizer (control chars/whitespace/truncation/empty), short-hex-id parse, and the DB-revert-failure path (#6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4
Yeraze
added a commit
that referenced
this pull request
Jun 20, 2026
…8 favorite/ignore cap (#3548) (#3578) * feat(notifications): surface device ClientNotifications + handle firmware 2.8 favorite/ignore cap (#3548) MeshMonitor decoded FromRadio.ClientNotification (mesh.proto field 16) and dropped it. Surface these device-originated warnings/errors as toasts, and handle the firmware 2.8 protected-node-cap refusal for Set Favorite / Ignore. Backend: - clientNotificationPolicy.ts (pure/testable): suppression patterns (recurring power-save "sleeping for N interval" INFO + key-verification variants + empty messages), the 2.8 protected-node-cap refusal parser, level->severity mapping, and a per-source ToastThrottle that dedupes identical messages within a window. - meshtasticProtobufService.ts: add the clientNotification dispatch branch (was falling through to the generic catch-all). - dataEventEmitter.ts: client-notification event type + emitClientNotification(). - meshtasticManager.ts: handleClientNotification() reverts the optimistic favorite/ignore flag and re-broadcasts the node when the device refuses at the protected-node cap, then applies the suppression/throttle policy and emits the toast event. Source-scoped throughout. Frontend: - DeviceNotificationToaster.tsx: listens for client-notification inside ToastProvider, maps level->severity, shows the toast. Wired into App.tsx. - WS forwarding + per-source room filtering needed no changes. Scope: the 2.8 NodeDB warm-tier restructure and the on-disk snr_q4 field do NOT affect the over-the-air wire MeshMonitor reads. OTA NodeInfo.snr stays a float in dB; no protobuf/decode change. A regression test guards this. The cap-refusal warning is only emitted by firmware for the locally-connected node (from == 0). Tests (20 new, full suite green): policy unit tests, manager handler tests (reconciliation/suppression/throttle, per-source), and protobuf dispatch + SNR float guard. Docs: FAQ (node count + blocked-node 2.8 behavior; device-notification toasts), IgnoredNodesSection inline help, CHANGELOG, and the support plan dev-note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4 * address review: sanitize device notification text, robustness + test gaps (#3578) Addresses Claude Code Review findings on PR #3578: - Sanitize device-controlled message before logging/forwarding: strip control chars (log-injection defense) and bound length to 500 (#9, #10). - Widen protected-cap regex to {1,8} hex digits so a short node id still reconciles (#4). - Exclude clientNotification from the unknown-FromRadio debug JSON.stringify dump (#3). - Drop the redundant `&& this.sourceId` guard (always set) and comment why the toast still fires when the DB revert fails (#2, #5). - Frontend: name the level magic numbers and note they mirror the backend NOTIFICATION_LEVEL (#1). - Tests: sanitizer (control chars/whitespace/truncation/empty), short-hex-id parse, and the DB-revert-failure path (#6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TheWISPRer
pushed a commit
to TheWISPRer/meshmonitor
that referenced
this pull request
Jun 21, 2026
- Mark messages played from the delivery-success callback, not at enqueue:
handleCommand returns { responses, playOnDelivery }; a dropped body DM now
leaves the message pending instead of losing it. (Yeraze#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
reclaimed daily (purgeExpired returns a count). (Yeraze#2)
- Count the per-recipient cap across the recipient's identity forms via an
injected node resolver, so it can't be bypassed by addressing one node by
several name forms. (Yeraze#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (Yeraze#4)
- inbox play <sender> filter matches !hex/node-num forms too. (Yeraze#5)
- Non-DM commands return [] (no unsolicited DM). (Yeraze#6)
- inbox delete returns the same response for not-yours vs non-existent ids
(no id enumeration). (Yeraze#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (Yeraze#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (Yeraze#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (Yeraze#10)
Docs + tests updated to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yeraze
added a commit
that referenced
this pull request
Jun 21, 2026
…ore) (#3538) * feat: add Dead Drop / Mailbox auto-responder (async message store) A per-source 'mesh voicemail': a node DMs the radio `msg <name> <text>` and the message is held until the named recipient retrieves it via `inbox` / `inbox play`. Implemented as a new auto-responder responseType ('mailbox'), reusing the existing DM-gating, per-node cooldown, param extraction, and per-source scoping. - DB: dead_drop_messages table (SQLite/PostgreSQL/MySQL) + migration 092 - Repository (Drizzle-only) + DatabaseService.deadDrop accessor - DeadDropService: command brain (store/inbox/play[/sender]/delete/clear, 180-byte cap, per-recipient & per-sender caps, 7-day expiry, batch play) - meshtasticManager: 'mailbox' responseType dispatch branch - UI: 'Mailbox' response type option + guidance in the auto-responder editor - Tests: 34 (migration registry, repository perSource, service) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(dead-drop): add Mailbox option to the Add-Trigger form select The Mailbox response type was only added to the per-trigger edit view (TriggerItem); the separate Add-Trigger form in AutoResponderSection had its own type <select> (Text/HTTP/Script) that was missed, so new mailbox triggers couldn't be created from the UI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(dead-drop): don't require response text to add a Mailbox trigger The Add button's disabled gate required a non-empty response field for all types; Mailbox has no response, so the button stayed greyed out. Exempt mailbox from the response-required check (matches validateResponse). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(dead-drop): accept mailbox responseType in settings save validation The settings-save validator required a non-empty response for every trigger and only allowed text/http/script responseTypes, so saving a Mailbox trigger failed with a generic 400. Exempt mailbox from the response-required check and add it to the responseType allowlist. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(dead-drop): settings-save accepts mailbox triggers without response text Regression coverage for the mailbox responseType in the autoResponderTriggers validator: a mailbox trigger with empty response now saves (200), while non-mailbox empty responses and unknown responseTypes still 400. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dead-drop): tolerate optional command keyword prefix The mailbox service parsed hardcoded msg/inbox, but a trigger configured with prefixed keywords (e.g. betamsg/betainbox, to coexist with another responder already using msg/inbox) would fire the handler yet fall through to help. Strip an optional non-space prefix from the leading verb so prefixed keywords parse correctly; no-op for plain msg/inbox. Caught by live over-the-air testing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(dead-drop): add Mailbox feature docs + live testing brief - automation.md: Mailbox response type + 'Mailbox (Dead Drop)' section (commands, recipient matching, delivery format, limits, command-prefix coexistence, configuration). - dev-notes/DEAD_DROP_TESTING.md: architecture, automated coverage, and the over-the-air validation results (ALTO MF / ALTO LF / ZN Office). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(dead-drop): register dead_drop_messages in migrate-db table lists The cross-database migrate-db CLI tracks every schema table in TABLE_ORDER / SKIP_TABLES; migrationTables.test.ts fails if a new schema table isn't listed. Add dead_drop_messages to TABLE_ORDER and SOURCE_SCOPED_TABLES (it carries a sourceId, like auto_favorite_targets). Caught by the full Vitest suite. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(dead-drop): address PR review feedback - Mark messages played from the delivery-success callback, not at enqueue: handleCommand returns { responses, playOnDelivery }; a dropped body DM now leaves the message pending instead of losing it. (#1) - Wire purgeExpired into databaseMaintenanceService so expired rows are reclaimed daily (purgeExpired returns a count). (#2) - Count the per-recipient cap across the recipient's identity forms via an injected node resolver, so it can't be bypassed by addressing one node by several name forms. (#3) - Mailbox bypasses the per-node cooldown (interactive flow). (#4) - inbox play <sender> filter matches !hex/node-num forms too. (#5) - Non-DM commands return [] (no unsolicited DM). (#6) - inbox delete returns the same response for not-yours vs non-existent ids (no id enumeration). (#7) - Wrap the mailbox dispatch in try/catch like the script branch. (#8) - Remove the command-prefix tolerance: canonical msg/inbox only. (#9) - Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (#10) Docs + tests updated to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(dead-drop): recommend enabling Verify response on the mailbox trigger Played-state is committed from the delivery-success callback; with Verify response off (maxAttempts=1) a single unacked send could mark a voicemail played on transmit. Document enabling Verify response so undelivered bodies resurface. (PR #3538 review follow-up) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: chrisn <chrisn@DebDev1.corp.tlclocal.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Randall Hand <randall.hand@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Update the Docker publish workflow to only build and publish images when a GitHub Release is published, rather than on every push to main.
Problem
The current workflow triggers Docker builds on:
This creates intermediate Docker images that aren't tied to official releases, cluttering the container registry.
Solution
Change the workflow trigger to:
release: types: [published]- Only publish images for official GitHub ReleasesChanges
✅ Workflow Trigger Update
pushto main branchpushto tags (v*)releasewith typepublishedpull_requestfor validation builds✅ Tag Generation Update
type=ref,event=branch(no longer needed)latesttag now only applies whenevent_name == 'release'Behavior After Merge
What Will Trigger Builds:
✅ Creating a GitHub Release (e.g., v1.2.0)
1.2.0,1.2,1,latest✅ Opening/updating a PR
What Will NOT Trigger Builds:
❌ Pushing commits to main
❌ Pushing tags manually with
git push --tagsBenefits
Test Plan
Notes
This aligns with best practices where Docker images are only published for official releases, not on every commit to main. The workflow will automatically trigger when you create releases through the GitHub UI or
gh release create.🤖 Generated with Claude Code