Skip to main content
Version: 3.1.0

Simplified Git Trigger Picker & Dev Mock

Version: 3.1.0 Date: 2026-06-12

Goal: The Git step of the workflow editor exposed too much complexity at once (Push/Tag radio, branch/tag pattern with wildcards, no business explanation), confusing users who just wanted to "protect every release". Replace it with a one-click default, an explicit live preview, and coherent add/remove semantics.

Solution: New TriggerSelector component with two modes — simple (default, "Every tagged release") and advanced (Customize: Tag / Push toggle + wildcard pattern field with three concrete live examples). The ProjectFormatter add/remove semantics were reworked to emit a backend-clean shape and stay backward-compatible with every historical config shape.

Features:

  • Default trigger is "Every tagged release" — one click on Add registers { name: 'tag' } (match all tags)
  • Customize link reveals the advanced picker (Tag / Push toggle + wildcard pattern); Use simple mode returns to default
  • Pattern input supports Enter to submit
  • Reserved-space preview block (no layout shift): 3 concrete examples that change with the wildcard
  • Helper text "Select a repository first." next to the Add button when no repo is picked
  • Repository-events table keeps a one-line layout with tag/branch icon + label, pattern chips, and an info tooltip (480 px) with summary + 3 examples
  • The ALL chip (every-tag mode) exposes a delete button

Implementation Details:

  • ProjectFormatter refactored: addEvents(params, type, pattern?), removeEvent(key, type, index) (drops the event entry when the last pattern is removed), removeEventEntry(key, type), and .clean always emits { name: 'tag' } for ALL or { name: 'tag', pattern: [...] } for specifics
  • Backward-compatible hydrate (ProjectFormatter.for) tolerates { name: 'tag' }, { pattern: [] }, legacy { pattern: [''] }, and mixed { pattern: ['v*', ''] }
  • New helpers: eventSummary.ts (summarize) and triggerExamples.ts (triggerExamples, regex-safe wildcard substitution)
  • ProjectFormatter test coverage grew from 15 to 21 cases

Dev-only mock for "Test connection": a surgical mock for discoverProjects only, active by default in vite dev, persisted per-developer in localStorage, with a "Use mock data (dev only)" switch. Tree-shaken from production builds.

Files Modified:

  • ui/src/utils/format.ts - optional pattern param, strict add/remove semantics, legacy-tolerant hydrate, removeEventEntry
  • ui/src/utils/format.test.ts - expanded coverage (legacy shapes, ALL-overwrite, drop-on-empty)
  • ui/src/utils/eventSummary.ts (new) + eventSummary.test.ts (new)
  • ui/src/utils/triggerExamples.ts (new) + triggerExamples.test.ts (new)
  • ui/src/pages/workflows/stepForms/TriggerSelector.tsx (new)
  • ui/src/pages/workflows/stepForms/StepGitForm.tsx - use TriggerSelector
  • ui/src/pages/workflows/stepForms/StepStorageForm.tsx - drop "Remove empty patterns" workaround
  • ui/src/pages/workflows/display.tsx - tag/branch icons, info tooltip, ALL chip delete
  • ui/src/protocol/dev-mocks/devMocks.ts (new) + discoverMock.ts (new)
  • ui/src/protocol/tower.api.ts - discoverProjects dev-mock short-circuit
  • ui/src/pages/workflows/stepForms/StepInitForm.tsx - dev-mock switch + "(mock data)" suffix
  • ui/e2e/workflow-creation.spec.ts - adapted to advanced-mode entry path