Releases: pedrofuentes/stream-deck-github-utilities
v2.3.0 — Branch Network Overhaul
Branch Network overhaul — now powered by the git-network-graph library for accurate commit topology rendering.
Branch Network Improvements:
- Real graph topology — replaced the previous renderer with the git-network-graph library for accurate branch lanes, merge points, and fork connections
- Reverse orientation fixed — newest→oldest mode now renders correctly using 180° grid pre-rotation
- Branch model selector — choose Git Flow, Simple, or None to control how branches are prioritized and colored
- Increased commit depth — now supports 100, 200, or 300 commits (up from 10–50)
Under the Hood:
- Grid-based SVG renderer with CW/CCW rotation support
- Zod runtime validation for GitHub API responses
- Comprehensive test coverage (1,617 tests)
v2.2.4 — Code Review Fixes + Architectural Refactors
What's Changed
Security & Resilience (P0)
- Fix URL injection — encode user inputs (branch names, workflow files) in \openUrl()\ calls
- Add 30s fetch timeouts — \etchWithTimeout()\ with AbortSignal on all 22 API calls
- Network error context — try-catch wrappers convert network failures to typed errors
- Switch exhaustiveness — \default: never\ checks on coordinator fragment dispatch
- Fix setTimeout leaks — track and clean timer IDs in \onWillDisappear()\
- STAT_LABELS type safety — compile-time exhaustiveness via \�s const satisfies\
Error Handling (P1)
- Debug logging — silent catch blocks now log fragment/repo context
- Error type preservation — \GraphQLQueryError\ propagates with structured info
- Interval bounds — max 3600s + NaN/Infinity guards on polling intervals
UX Fix
- Double-click debounce — first click schedules URL after 400ms; second click cancels and force-refreshes. Shared \DebouncedUrlOpener\ utility.
Architecture (P2)
- Structured error types — \GitHubErrorCode\ enum + \classifyErrorLabel()\ replacing string matching
- Split github-api.ts — 1,600-line monolith → 7 domain modules
- Retry logic — \etchWithRetry()\ with exponential backoff for 429/502/503/504
- BaseGitHubAction — abstract base class eliminating ~460 lines of action duplication
- FragmentStrategy pattern — 12 strategy classes replacing 3 switch statements
- Integration test suite — 130 cross-layer tests in \ ests/integration/\
Long-Term Quality (P3)
- Zod validation — 16 schemas replacing 88 unsafe \�s\ type assertions
- Settings composition — \RepoActionSettings\ hierarchy reducing interface duplication
- Singleton removal — coordinator moved to static class property
- RenderDebouncer — shared timer management for dial rotation
- Snapshot tests — 107 golden master tests for all SVG render functions
Test Growth
- 1,045 → 1,562 tests (+517 new tests across 44 test files)
- All passing, build clean, validation successful
Full Changelog: v2.2.3...v2.2.4
v2.2.3 — Multi-quarter positioning fixes
Bug Fixes
- Remove dead quarterPosition setting — the manual position selector in Contribution Heatmap and Branch Network PIs was never used by the code (automatic detection via hardware coordinates already worked)
- Fix sibling offset recalculation — when adding or removing multi-quarter instances, remaining siblings now properly recalculate their rendering offsets
- Fix settings change propagation — changing data source or repo now re-renders all affected sibling groups (tracks old→new scroll key)
- Fix stale cache on data source switch — switching from 'All contributions' to 'Repository commits' no longer shows cached data from the previous mode
- Fix repo dropdown visibility — switching data source in the PI now immediately shows/hides the repository dropdown
- Add quick retry on GitHub 202 — when GitHub's Stats API returns 202 (computing), the heatmap retries after 5 seconds instead of waiting for the full polling interval
Internal
- Added debug logging to heatmap refresh flow for easier troubleshooting
- Added tests for sibling re-render on appear/disappear
v2.2.2 — Security Health Dial Readability
Fixed
- Security health dial text too small — increased grade letter (28→36px), Security label (10→14px), severity counts (12→16px), severity labels (10→13px), and dot size (r=3→4)
- Gauge not vertically centered — recentered arc gauge assembly at strip midpoint (cy=56, r=42)
- Background arc invisible — changed track color from #111 to #2a2d33 so partial score fills show a visible gauge track
v2.2.1 — Fix touch/dial force-refresh + sibling sync
Bug Fixes
-
Touch tap and dial rotate now force-refresh data — 6 actions (Discussions Monitor, PR Counter, Issue Counter, Fleet Monitor, Projects Board, Repo Stats) were returning cached data on touch/dial interactions instead of fetching fresh from GitHub. All actions now consistently use cache invalidation on user-initiated refreshes.
-
Sibling instance synchronization — When multiple instances of the same action watch the same repository, force-refreshing one now automatically updates all others. Previously, only the tapped instance would refresh while siblings showed stale data until their next polling interval.
Technical Details
- Consolidated all 14 actions to use the \orce\ parameter pattern for \invalidateAndFetch\ vs \etchData\
- Removed redundant \orceRefresh()\ methods from 5 actions (eliminated double-fetch overhead)
- Added \onSiblingRefresh\ callback mechanism to \GraphQLQueryCoordinator.subscribe()\
- 22 files changed, 1024 tests passing
v2.2.0 — GraphQL Coordinator + Discussions Monitor + Projects V2 Board
What's New
GraphQL Batch Query Coordinator (v2.1.0)
- Actions sharing the same repository now batch their data needs into a single GraphQL query
- Significantly reduces API calls and improves rate limit efficiency
- All 14 actions route through the coordinator with automatic REST fallback
- Per-repo cache with field-level staleness tracking
New Actions (v2.2.0)
- 💬 Discussions Monitor — track open discussion count and answered status for any repository
- 📊 Projects V2 Board — monitor GitHub Projects V2 boards with item counts and progress
New Token Permissions
- \Discussions: Read\ — required for Discussions Monitor
- \Projects: Read\ — required for Projects V2 Board
Under the Hood
- 4 new infrastructure modules: query builder, coordinator, cache, data fragment extractors
- Generic GraphQL executor with structured errors
- 14 deprecated REST functions preserved as fallback layer
- 1,004 tests across 30 test files (up from 882/27)
v2.0.0 — Stream Deck+ Encoder Support & 5 New Actions
What's New in v2.0.0
Stream Deck+ Encoder/Touch Strip Support
All 12 actions now work on Stream Deck+ dials with rich touch strip visualizations:
- Hero numbers with Tufte-inspired sparklines
- Atmospheric status glow for workflow monitoring
- Run history dots as Tufte small-multiples
- Arc gauges for security health
- Metro-map branch diagrams with horizontal/vertical scrolling
- Contribution heatmaps with contiguous multi-quarter rendering
- Synced scrolling across multi-quarter layouts
5 New Actions
- PR Review Queue — Shows PRs awaiting your review with urgency gradient (blue→amber→red)
- Branch Network — Encoder-only metro-map branch diagram
- Security Health — Arc gauge combining Dependabot alerts with A-F grading
- Contribution Heatmap — GitHub contribution grid on the touch strip (52 weeks)
- Fleet Monitor — Compact per-repo dashboard for multi-repo monitoring
New Features
- Workflow Dispatch — Long-touch on Workflow Status encoder triggers a workflow run
- Double-click refresh — Double-press any key action to force immediate data refresh
- GraphQL API — Profile-level contribution calendar (all repos, all contribution types)
- Run duration — Workflow status buttons now show run duration (e.g., 'Success · 3m 42s')
- Timeframe badges — Commit activity, PR/issue counters show current filter on touch strip
Performance
- O(1) action context lookup (was O(n) spread+find)
- Throttled touch strip rendering (~60fps cap during dial scrolling)
- Array.join() SVG generation (was O(n²) string concatenation)
- Shared API data between multi-quarter siblings (avoids duplicate calls)
Stats
- 735 tests across 24 test files
- 12 actions (7 enhanced + 5 new)
- All actions support both Keypad and Encoder (2 encoder-only)
v1.5.0 — Reliability & Performance
Reliability and performance improvements under the hood.
Architecture:
- Centralized PollingCoordinator replaces per-action timer management (all 7 actions)
- Exponential error backoff — on consecutive API failures, polling intervals increase (up to 32x) to reduce unnecessary requests; pressing the button resets backoff for immediate retry
- Generation counter prevents stale async callbacks from overwriting fresher data
API Improvements:
- HTTP 429 rate-limit-exceeded handling with Retry-After header parsing (seconds + HTTP-date)
- Improved 403 rate limit error messages with reset time information
Visual:
- Native SVG spinner using <animateTransform>\ — single setImage call, no frame-based timer overhead
v1.4.0 — Phase 2 Actions & Visual Polish
New Actions
- PR Counter — Open pull request count via GitHub Search API
- Issue Counter — Open issue count (excludes PRs) via GitHub Search API
- Release Monitor — Latest release version and publish date
- Commit Activity — Recent commit count (today/week/month)
- Branch Comparison — Ahead/behind commit count between branches
Visual Polish
- Animated loading spinner during data fetches (all 7 actions)
- Consistent color palette across all button states
Improvements
- Search API migration for accurate PR and issue counting
- Updated setup guide with all required token scopes
v1.3.4 — PI Settings & UX Fixes
What's Changed
Bug Fixes
- PI settings echo suppression — Fixed stat dropdown changes not persisting on first selection after choosing a repo. Root cause: sdpi-components' \setSettings\ echo was overwriting user changes via \didReceiveSettings\ round-trip. Added WebSocket Proxy with 500ms echo window to detect and skip stale echoes.
- PI-side default injection — Moved default setting injection (statType, refreshInterval) from plugin-side \setSettings()\ to the PI's WebSocket send interceptor. Eliminates the extra echo that raced with sdpi-components' 250ms debounce.
- Disabled user title field — Added \UserTitleEnabled: false\ to both actions in manifest to prevent users from enabling the title overlay that conflicts with full-SVG button rendering.
Improvements
- Updated key images — Replaced outdated PNG key images with proper SVG versions showing 'Setup / Open Settings' placeholder text on dark background.
Technical
- Removed plugin-side
eedsPersist\ / \setSettings()\ logic for defaults (no longer needed with PI-side injection) - Both PI files (repo-stats, workflow-status) now use identical WebSocket Proxy + echo suppression pattern