Skip to content

Commit 340b989

Browse files
committed
feat: Add :patch-triggers? source toggle (default true)
1 parent 87881e9 commit 340b989

7 files changed

Lines changed: 101 additions & 11 deletions

File tree

config.edn.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@
168168
;; a list that tightened from :loose to :strict), declare :periods on
169169
;; the source — each period can override :command-syntax.
170170

171+
;; ---- Patches as triggers (per-source, default true) ---------------------
172+
;;
173+
;; A patch in reply to a bug/request auto-Acks/auto-Owns the parent and
174+
;; propagates :resolved closure. Set false to opt out (the :resolves
175+
;; cross-link is still recorded). Overridable per :periods entry.
176+
;; :patch-triggers? false
177+
171178
;; ---- Exports -------------------------------------------------------------
172179

173180
;; Export formats (optional) — per-type feed files generated.

resources/emails.edn

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,4 +1724,29 @@
17241724
:email/in-reply-to "<125@test.org>"
17251725
:email/references "<125@test.org>"
17261726
:email/body-text "Patch 2.\n\ndiff --git a/style.css b/style.css\n--- a/style.css\n+++ b/style.css\n@@ -1,3 +1,3 @@\n-old\n+new\n"}
1727+
1728+
;; =========================================================================
1729+
;; 128-129 — :patch-triggers? false on the source.
1730+
;; A bug, then a patch in reply. The bug must NOT be auto-acked/auto-owned
1731+
;; on patch creation; only the structural :resolves cross-link is recorded.
1732+
;; =========================================================================
1733+
{:email/id "128"
1734+
:email/source "no-triggers"
1735+
:email/message-id "<128@test.org>"
1736+
:email/subject "[BUG] segfault on startup"
1737+
:email/from-address "user@test.org"
1738+
:email/date-sent #inst "2026-03-05T09:00:00"
1739+
:email/ingested-at #inst "2026-03-05T09:00:00"
1740+
:email/body-text "Crashes on startup with empty config.\n"}
1741+
1742+
{:email/id "129"
1743+
:email/source "no-triggers"
1744+
:email/message-id "<129@test.org>"
1745+
:email/subject "Re: [BUG] segfault on startup"
1746+
:email/from-address "dev@test.org"
1747+
:email/date-sent #inst "2026-03-05T10:00:00"
1748+
:email/ingested-at #inst "2026-03-05T10:00:00"
1749+
:email/in-reply-to "<128@test.org>"
1750+
:email/references "<128@test.org>"
1751+
:email/body-text "Patch attached.\n\ndiff --git a/init.clj b/init.clj\n--- a/init.clj\n+++ b/init.clj\n@@ -1,3 +1,3 @@\n-old\n+new\n"}
17271752
]

scripts/validate-config.clj

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@
101101
:source/maintainers :source/notifications
102102
:source/expiry :source/awaiting-delay
103103
:source/export-formats :source/topics-filter
104-
:source/command-syntax :source/periods])
104+
:source/command-syntax :source/patch-triggers?
105+
:source/periods])
105106
exactly-one-source-type?))
106107

107108
(s/def :bark/sources
@@ -266,6 +267,14 @@
266267
(s/def :bark/command-syntax #{:loose :strict})
267268
(s/def :source/command-syntax :bark/command-syntax)
268269

270+
;; Whether patches on this source act as triggers on the bugs/requests
271+
;; they resolve. When false, a patch in reply to a bug/request does not
272+
;; auto-set Acked/Owned, and closing the patch as :resolved does not
273+
;; close the parent. Default true.
274+
(s/def :bark/patch-triggers? boolean?)
275+
(s/def :source/patch-triggers? :bark/patch-triggers?)
276+
(s/def :period/patch-triggers? :bark/patch-triggers?)
277+
269278
;; Per-source periods (optional) -- time-windowed overrides for
270279
;; :maintainers / :commands / :command-syntax / :labels.
271280
;; Each period is a map with optional :start, :end (ISO yyyy-MM-dd) and
@@ -282,7 +291,8 @@
282291
(s/def ::period-entry
283292
(s/keys :opt-un [:period/start :period/end
284293
:period/maintainers :period/commands
285-
:period/command-syntax :period/labels]))
294+
:period/command-syntax :period/patch-triggers?
295+
:period/labels]))
286296
(s/def :source/periods (s/coll-of ::period-entry :kind vector? :min-count 1))
287297

288298
;; Top-level config
@@ -408,6 +418,8 @@
408418
(:report-types src) (conj (str "report-types: " (pr-str (:report-types src))))
409419
(:command-syntax src) (conj (str "command-syntax: "
410420
(name (:command-syntax src))))
421+
(false? (:patch-triggers? src))
422+
(conj "patch-triggers: off")
411423
(seq (:maintainers src))
412424
(conj (str "maintainers: "
413425
(str/join ", " (:maintainers src))))

src/bark/commands.clj

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@
368368
(conj [:db/add report-eid :report/close-reason close-reason]))]
369369
(when (seq all-tx) [(vec all-tx) new-sets close-reason])))
370370

371-
(defn apply-triggers! [conn report-eid trig-result email-eid email-mid from-addr]
371+
(defn apply-triggers! [conn report-eid trig-result email-eid email-mid from-addr source-cfg]
372372
(when trig-result
373373
(let [db (d/db conn)
374374
current (d/pull db proxy-state-attrs report-eid)
@@ -382,7 +382,12 @@
382382
(str "(by " email-mid ")"))
383383
;; Propagate trigger-driven closure of a patch to the
384384
;; bugs/requests it resolves (no successor in the trigger path).
385-
(when (and (= :patch rtype) close-reason (:report/closed new-sets))
385+
;; Sources with `:patch-triggers? false` opt out of the :resolved
386+
;; propagation; :canceled retraction still runs (no-op when no
387+
;; auto-credit was posed in the first place).
388+
(when (and (= :patch rtype) close-reason (:report/closed new-sets)
389+
(or (not= :resolved close-reason)
390+
(common/patch-triggers? source-cfg)))
386391
(rel/propagate-patch-closure! conn report-eid rtype email-eid
387392
close-reason nil))))))
388393

@@ -996,7 +1001,8 @@
9961001
(let [voted? (when (and (= :request report-type) from-addr)
9971002
(apply-vote! conn report-eid from-addr body-text email delivery source-cfg)
9981003
(some? (detect-vote body-text)))]
999-
(apply-triggers! conn report-eid trig-result eid (:email/message-id email) from-addr)
1004+
(apply-triggers! conn report-eid trig-result eid (:email/message-id email) from-addr
1005+
source-cfg)
10001006
(apply-directives! conn report-eid directives eid from-addr is-maint? fail-ctx)
10011007
(boolean (or (seq trig-result) (seq directives) voted?)))))
10021008
false))

src/bark/common.clj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,15 @@
564564
" (expected :loose or :strict)")
565565
{:value (:command-syntax source-cfg)}))))
566566

567+
(defn patch-triggers?
568+
"True when patches on this source act as triggers on the bugs/requests
569+
they resolve: auto-acked + auto-owned on creation, and closure of the
570+
patch as :resolved propagates to close the parent. Default true; set
571+
`:patch-triggers? false` on a source to opt out."
572+
[source-cfg]
573+
(let [v (:patch-triggers? source-cfg)]
574+
(if (nil? v) true (boolean v))))
575+
567576
;; ---------------------------------------------------------------------------
568577
;; Maintainer tenures (pure -- operate on a seq of tenure maps, no DB access)
569578
;; ---------------------------------------------------------------------------

src/bark/digest.clj

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,14 @@
540540

541541
(defn- run-post-creation-hooks!
542542
"Execute post-creation side effects driven by the plan."
543-
[conn report-eid eid email from-addr report-info
543+
[conn report-eid eid email from-addr report-info source-cfg
544544
parent-eids nearest-eids patches plan]
545545
(when (:link-related plan)
546546
(link-rel! conn report-eid (:type report-info) email parent-eids))
547-
;; Auto-credit must run AFTER :link-related so :resolves relations exist
548-
(when (:auto-credit-resolves plan)
547+
;; Auto-credit must run AFTER :link-related so :resolves relations exist.
548+
;; Skipped on sources with `:patch-triggers? false`.
549+
(when (and (:auto-credit-resolves plan)
550+
(common/patch-triggers? source-cfg))
549551
(auto-credit-resolved-reports! conn report-eid email))
550552
(when (:close-changes plan)
551553
(close-changes-for-release! conn (:version report-info) email report-eid))
@@ -654,7 +656,7 @@
654656
(let [patches (detect/build-patch-entities email)
655657
plan (post-creation-plan report-info nearest-eids parent-eids patches)]
656658
(run-post-creation-hooks! conn report-eid eid email from-addr report-info
657-
parent-eids nearest-eids patches plan)))
659+
source-cfg parent-eids nearest-eids patches plan)))
658660

659661
;; Mark email as fully digested so future re-fetches can skip it.
660662
(d/transact! conn [{:db/id eid :email/digested-at (Date.)}])

test/bark/digest_test.clj

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,19 @@
136136
:to "direct@test.org"}
137137
"public-list" {:admin "admin@test.org"
138138
:source-type :mailing-list
139-
:list "list.test.org"}})
139+
:list "list.test.org"}
140+
"no-triggers" {:admin "admin@test.org"
141+
:source-type :mailbox
142+
:to "no-triggers@test.org"
143+
:patch-triggers? false}})
140144

141145
(def sources [{:name "public-list"
142146
:list "list.test.org"}
143147
{:name "direct"
144-
:to "direct@test.org"}])
148+
:to "direct@test.org"}
149+
{:name "no-triggers"
150+
:to "no-triggers@test.org"
151+
:patch-triggers? false}])
145152

146153
;; ---------------------------------------------------------------------------
147154
;; DB setup / teardown
@@ -156,6 +163,9 @@
156163
:maint-tenure/email "admin@test.org"
157164
:maint-tenure/order 0}
158165
{:maint-tenure/source "public-list"
166+
:maint-tenure/email "admin@test.org"
167+
:maint-tenure/order 0}
168+
{:maint-tenure/source "no-triggers"
159169
:maint-tenure/email "admin@test.org"
160170
:maint-tenure/order 0}])
161171
;; Insert test emails. Fixtures only set :email/from-address /
@@ -471,6 +481,25 @@
471481
(is (= "orgweb|kana@test.org|2"
472482
(:series/id (:report/series r127))))))
473483

484+
;; --- :patch-triggers? false on source (emails 128-129) ---
485+
(testing "Source with :patch-triggers? false skips auto-credit"
486+
(let [bug (get-report db "<128@test.org>")
487+
patch (get-report db "<129@test.org>")]
488+
(is (= :bug (:report/type bug)))
489+
(is (= :patch (:report/type patch)))
490+
;; The :resolves cross-link is still recorded -- only the
491+
;; side effects on the bug are gated.
492+
(is (some #(= "<128@test.org>" (:report/message-id %))
493+
(all-related patch))
494+
":resolves cross-link is still recorded")
495+
;; No auto-credit fired on the bug.
496+
(is (nil? (:report/acked bug))
497+
"auto-acked must NOT fire when :patch-triggers? is false")
498+
(is (nil? (:report/owned bug))
499+
"auto-owned must NOT fire when :patch-triggers? is false")
500+
(is (nil? (:report/closed bug))
501+
"the bug must remain open after the patch arrives")))
502+
474503
;; --- Email 40 patch related to bug ---
475504
(testing "Email 40 patch related to bug"
476505
(let [patch (get-report db "<40@test.org>")

0 commit comments

Comments
 (0)