@mikitasazan/notify 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +69 -60
- package/dist/events.d.ts +127 -117
- package/dist/events.js +23 -21
- package/dist/render.d.ts +48 -45
- package/dist/render.js +220 -189
- package/dist/routes.d.ts +31 -27
- package/dist/routes.js +25 -20
- package/package.json +1 -1
package/dist/events.d.ts
CHANGED
|
@@ -1,57 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* `send.ts`)
|
|
4
|
-
*
|
|
2
|
+
* The event catalogue — the single entry point for sending. `notify()` (see
|
|
3
|
+
* `send.ts`) accepts ONLY values of this type: there is no free text in the
|
|
4
|
+
* API, so a "custom" message cannot technically be written.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
6
|
+
* The schema evolution rule (there is no version and never will be — a
|
|
7
|
+
* message lives one second and is read by eyes, there is nothing to
|
|
8
|
+
* version):
|
|
9
|
+
* - a new field on an EXISTING type is added ONLY as optional;
|
|
10
|
+
* - required fields are never added — only a new event type.
|
|
11
|
+
* That keeps old caller code and a new package compatible both ways.
|
|
11
12
|
*/
|
|
12
13
|
export type Project = 'playhub' | 'one-q' | 'arvent' | 'game-publisher' | 'vault' | 'mac-config' | 'alitools';
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
15
|
+
* A stable machine key for the task — the last line of every card, shaped
|
|
16
|
+
* as `#key` (with no project name: the card already sits in its own
|
|
17
|
+
* project's forum — `targets()` never sends it to someone else's). The
|
|
18
|
+
* daily parser uses it to check "is this 🔴 already closed by a later card
|
|
19
|
+
* with the same key?" without comparing human wording, which changes. It
|
|
20
|
+
* is optional: without it, the key is derived from the type and the title
|
|
21
|
+
* (see `render.ts`), but a derived one inherits the fragility of wording —
|
|
22
|
+
* our regular senders pass it explicitly. The key never reaches CLI output
|
|
23
|
+
* (stderr, which the VPS watchdog also reads as one combined stream by the
|
|
24
|
+
* words `sent|failed|skipped`) — a new word there would blind the
|
|
25
|
+
* watchdog.
|
|
24
26
|
*/
|
|
25
27
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* The common part of any event. `path` is a local file that travels WITH the
|
|
29
|
+
* card: the card becomes a caption on the attachment. There has been no
|
|
30
|
+
* separate `file` type since 25.08.2026 — an Arvent run used to send the
|
|
31
|
+
* verdict and the log as two cards about one piece of news.
|
|
30
32
|
*/
|
|
31
33
|
type Keyed = {
|
|
32
34
|
key?: string;
|
|
33
|
-
/**
|
|
35
|
+
/** A local file; the card goes out as its caption (caption limit 1024). */
|
|
34
36
|
path?: string;
|
|
35
|
-
/**
|
|
37
|
+
/** The file's name in the chat; defaults to the name from `path`. */
|
|
36
38
|
filename?: string;
|
|
37
39
|
};
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
+
* A list item inside a message: a task from a digest, a failed check, a
|
|
42
|
+
* remark. `url` is optional — then it renders as a plain row.
|
|
41
43
|
*/
|
|
42
44
|
/**
|
|
43
|
-
* `label` —
|
|
44
|
-
* `#287`)
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* `label` — an optional bold prefix before `text` (`#243 (overdue)`,
|
|
46
|
+
* `#287`) for items inside a report's named groups. Without `label` an
|
|
47
|
+
* item renders as an ordinary numbered/bulleted row — that is already how
|
|
48
|
+
* digest tasks and the list of disabled workflows work.
|
|
47
49
|
*/
|
|
48
50
|
/**
|
|
49
|
-
* `group` —
|
|
50
|
-
* `lines`
|
|
51
|
+
* `group` — the name of the block the item will sit under. The same law
|
|
52
|
+
* `lines` and `stats` follow: without a name the item goes into the
|
|
53
|
+
* general list, as before.
|
|
51
54
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* 🔁
|
|
55
|
+
* Introduced because the import list was mixing three DIFFERENT things in
|
|
56
|
+
* one listing and telling them apart by an icon at the start of the row:
|
|
57
|
+
* 🆕 came out today, 🔁 came out of the queue, ⚠ did not come out at all.
|
|
58
|
+
* The icon was doing a heading's job.
|
|
55
59
|
*/
|
|
56
60
|
export type Item = {
|
|
57
61
|
text: string;
|
|
@@ -60,55 +64,57 @@ export type Item = {
|
|
|
60
64
|
group?: string;
|
|
61
65
|
};
|
|
62
66
|
export type NotifyEvent = Keyed & (
|
|
63
|
-
/**
|
|
67
|
+
/** Shipping code to the server. */
|
|
64
68
|
{
|
|
65
69
|
type: 'deploy';
|
|
66
70
|
project: Project;
|
|
67
71
|
status: 'ok' | 'fail';
|
|
68
72
|
commit?: string;
|
|
69
|
-
/**
|
|
73
|
+
/** A link to the commit — the "commit" row becomes clickable. */
|
|
70
74
|
commitUrl?: string;
|
|
71
|
-
/**
|
|
75
|
+
/** The commit's title — renders as the `Title:` field, the body follows as a quote. */
|
|
72
76
|
commitTitle?: string;
|
|
73
|
-
/**
|
|
77
|
+
/** The commit's body, if there is one — the same quote shape as the title. */
|
|
74
78
|
commitBody?: string;
|
|
75
79
|
workflowUrl?: string;
|
|
76
|
-
/**
|
|
80
|
+
/** The run's name, for the link's visible text (defaults to `open`). */
|
|
77
81
|
workflowName?: string;
|
|
78
82
|
url?: string;
|
|
79
83
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
84
|
+
* Where it shipped to. Fill it in ONLY when there is more than one
|
|
85
|
+
* environment: on sites with a single prod, "where: prod" is a row
|
|
86
|
+
* the eye reads and learns nothing from.
|
|
83
87
|
*/
|
|
84
88
|
target?: string;
|
|
85
89
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
+
* Where it was run from: "manually from the Mac," "GitHub Actions."
|
|
91
|
+
* This is exactly the news — there are two deploy paths, they carry
|
|
92
|
+
* different consequences (a manual one runs from the laptop and takes
|
|
93
|
+
* its variables from the local .env), and the card shows which one
|
|
94
|
+
* fired.
|
|
90
95
|
*/
|
|
91
96
|
via?: string;
|
|
92
|
-
/**
|
|
97
|
+
/** An explanation: why a post-deploy run was cancelled/skipped. */
|
|
93
98
|
note?: string;
|
|
94
99
|
}
|
|
95
|
-
/**
|
|
100
|
+
/** A recurring scheduled task: a game import, a DB backup, a validator. */
|
|
96
101
|
| {
|
|
97
102
|
type: 'job';
|
|
98
103
|
project: Project;
|
|
99
104
|
job: string;
|
|
100
105
|
/**
|
|
101
|
-
* `disabled` —
|
|
102
|
-
*
|
|
106
|
+
* `disabled` — the task was switched off from outside (GitHub Actions
|
|
107
|
+
* ran out of free minutes, for example), it did not fail on its own.
|
|
103
108
|
*
|
|
104
|
-
* `silent` —
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
109
|
+
* `silent` — the task did not report in on time: it did not fail, it
|
|
110
|
+
* gave no sign of life at all. This is a state of the TASK, not a
|
|
111
|
+
* separate event type — it used to live under the type
|
|
112
|
+
* `heartbeat_miss`, and the owner rightly asked why one scheduled task
|
|
113
|
+
* of his carried two different tags. Worse: the silence watchdog sends
|
|
114
|
+
* the same machine key as the task itself, so a red card
|
|
115
|
+
* `#heartbeat #daily_import` did not get closed by a green
|
|
116
|
+
* `#job #daily_import` — the parser looks for a pair by the FULL tag.
|
|
117
|
+
* One stream per task fixes that.
|
|
112
118
|
*/
|
|
113
119
|
status: 'ok' | 'fail' | 'disabled' | 'silent';
|
|
114
120
|
/**
|
|
@@ -119,22 +125,23 @@ export type NotifyEvent = Keyed & (
|
|
|
119
125
|
* finishes the name.
|
|
120
126
|
*/
|
|
121
127
|
aside?: string;
|
|
122
|
-
/**
|
|
128
|
+
/** How often the task owes a check-in — for `silent` and for recovering from it. */
|
|
123
129
|
expected?: string;
|
|
124
|
-
/**
|
|
130
|
+
/** When it was last seen. */
|
|
125
131
|
lastSeen?: string;
|
|
126
132
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* (
|
|
131
|
-
*
|
|
133
|
+
* Numbers from the sender. The third element is the GROUP NAME the
|
|
134
|
+
* row will sit under. The owner asked for groups six times, and every
|
|
135
|
+
* time the sender was already trying to fake them with whatever was
|
|
136
|
+
* at hand: parentheses in the label ("GA4 users (sum of days)"), an
|
|
137
|
+
* icon at the start of the row (🆕 versus ⚠), an extra row at the
|
|
138
|
+
* bottom. There was nothing to group with — now there is.
|
|
132
139
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
140
|
+
* Without the third element the row goes with no heading, as before:
|
|
141
|
+
* every existing sender keeps working unchanged.
|
|
135
142
|
*/
|
|
136
143
|
stats?: Array<[label: string, value: string | number, group?: string]>;
|
|
137
|
-
/**
|
|
144
|
+
/** Details: exactly what failed, notes from the run; for `disabled` — the list of switched-off processes (each with its own link). */
|
|
138
145
|
items?: Item[];
|
|
139
146
|
note?: string;
|
|
140
147
|
/**
|
|
@@ -144,9 +151,10 @@ export type NotifyEvent = Keyed & (
|
|
|
144
151
|
*/
|
|
145
152
|
command?: string;
|
|
146
153
|
/**
|
|
147
|
-
* WHAT that command does. The owner, on a bare `rm` in a card: "
|
|
148
|
-
*
|
|
149
|
-
* cannot read is one he cannot run, so it never
|
|
154
|
+
* WHAT that command does. The owner, on a bare `rm` in a card: "I'm
|
|
155
|
+
* about to type it and do god knows what, I don't even know what I'm
|
|
156
|
+
* doing." A command he cannot read is one he cannot run, so it never
|
|
157
|
+
* travels alone.
|
|
150
158
|
*/
|
|
151
159
|
commandNote?: string;
|
|
152
160
|
/**
|
|
@@ -156,16 +164,16 @@ export type NotifyEvent = Keyed & (
|
|
|
156
164
|
*/
|
|
157
165
|
logs?: string;
|
|
158
166
|
workflowUrl?: string;
|
|
159
|
-
/**
|
|
167
|
+
/** The run's name, for the link's visible text (defaults to `open`). */
|
|
160
168
|
workflowName?: string;
|
|
161
169
|
/**
|
|
162
|
-
*
|
|
163
|
-
* `--url`.
|
|
164
|
-
*
|
|
170
|
+
* A fallback name for the run link: half the senders send it as
|
|
171
|
+
* `--url`. The renderer takes `workflowUrl ?? url`, so both names
|
|
172
|
+
* work. In new calls prefer `workflowUrl` — it says where it leads.
|
|
165
173
|
*/
|
|
166
174
|
url?: string;
|
|
167
175
|
}
|
|
168
|
-
/**
|
|
176
|
+
/** A summary with numbers: a daily report, an analytics digest. */
|
|
169
177
|
| {
|
|
170
178
|
type: 'report';
|
|
171
179
|
project: Project;
|
|
@@ -177,19 +185,19 @@ export type NotifyEvent = Keyed & (
|
|
|
177
185
|
* accepts `--period` for it.
|
|
178
186
|
*/
|
|
179
187
|
aside?: string;
|
|
180
|
-
/**
|
|
188
|
+
/** Empty/not passed when `groups` is used — the two kinds of report are not mixed in one event. */
|
|
181
189
|
lines?: Array<[label: string, value: string | number, group?: string]>;
|
|
182
190
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* `lines`.
|
|
191
|
+
* A list of items with links — for task digests, where the value is
|
|
192
|
+
* in the names themselves, not in a number. Renders as a separate
|
|
193
|
+
* block after `lines`.
|
|
186
194
|
*/
|
|
187
195
|
items?: Item[];
|
|
188
196
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
197
|
+
* Named groups (a task board: Ready/In Progress/Not on the board;
|
|
198
|
+
* analytics: Metrics/Links) — each with its own heading and list of
|
|
199
|
+
* items. Replaces `lines`/`items` when set: different reports use
|
|
200
|
+
* either the flat form or groups, never both at once.
|
|
193
201
|
*/
|
|
194
202
|
groups?: Array<{
|
|
195
203
|
name: string;
|
|
@@ -197,18 +205,18 @@ export type NotifyEvent = Keyed & (
|
|
|
197
205
|
}>;
|
|
198
206
|
url?: string;
|
|
199
207
|
}
|
|
200
|
-
/**
|
|
208
|
+
/** The CI outcome on the main branch. */
|
|
201
209
|
| {
|
|
202
210
|
type: 'ci';
|
|
203
211
|
project: Project;
|
|
204
212
|
status: 'ok' | 'fail';
|
|
205
213
|
branch?: string;
|
|
206
214
|
commit?: string;
|
|
207
|
-
/**
|
|
215
|
+
/** A link to the commit — the hash becomes clickable. */
|
|
208
216
|
commitUrl?: string;
|
|
209
|
-
/**
|
|
217
|
+
/** The commit's title (subject) — a separate `Title:` field, not a quote. */
|
|
210
218
|
commitTitle?: string;
|
|
211
|
-
/**
|
|
219
|
+
/** The commit's body (after the subject) — the same quote shape as the title. */
|
|
212
220
|
commitBody?: string;
|
|
213
221
|
actor?: string;
|
|
214
222
|
/**
|
|
@@ -216,16 +224,17 @@ export type NotifyEvent = Keyed & (
|
|
|
216
224
|
* schedule, a manual press. Renders as `Reason:`, same as on deploy.
|
|
217
225
|
*/
|
|
218
226
|
note?: string;
|
|
219
|
-
/**
|
|
227
|
+
/** A link to the run (workflow run) — separate from `url`, a fallback for `workflowUrl`. */
|
|
220
228
|
workflowUrl?: string;
|
|
221
|
-
/**
|
|
229
|
+
/** The run's name, for the link's visible text (defaults to `open`). */
|
|
222
230
|
workflowName?: string;
|
|
223
231
|
url?: string;
|
|
224
232
|
}
|
|
225
233
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
234
|
+
* A pull request event. The kinds cover the whole life of a PR, because
|
|
235
|
+
* the owner follows the team's work through the Ops tab, not through
|
|
236
|
+
* mail: mail only arrives when you were personally pinged, and half of
|
|
237
|
+
* the events never reach it.
|
|
229
238
|
*/
|
|
230
239
|
| {
|
|
231
240
|
type: 'pr';
|
|
@@ -239,26 +248,26 @@ export type NotifyEvent = Keyed & (
|
|
|
239
248
|
reviewer?: string;
|
|
240
249
|
url?: string;
|
|
241
250
|
}
|
|
242
|
-
/**
|
|
251
|
+
/** An issue event: filed, taken up, closed. */
|
|
243
252
|
| {
|
|
244
253
|
type: 'issue';
|
|
245
254
|
project: Project;
|
|
246
255
|
action: 'opened' | 'assigned' | 'closed';
|
|
247
256
|
number: number;
|
|
248
257
|
title: string;
|
|
249
|
-
/**
|
|
258
|
+
/** The issue's body — a quote under the `Title:` field, separate from the title. */
|
|
250
259
|
body?: string;
|
|
251
260
|
author?: string;
|
|
252
261
|
assignee?: string;
|
|
253
262
|
url?: string;
|
|
254
263
|
}
|
|
255
|
-
/**
|
|
264
|
+
/** The app is broken right now (a runtime alert). */
|
|
256
265
|
| {
|
|
257
266
|
type: 'incident';
|
|
258
267
|
project: Project;
|
|
259
268
|
title: string;
|
|
260
269
|
detail?: string;
|
|
261
|
-
/**
|
|
270
|
+
/** A local path to the logs (not a URL — renders monospaced, to copy, not to click). */
|
|
262
271
|
logs?: string;
|
|
263
272
|
url?: string;
|
|
264
273
|
}
|
|
@@ -298,10 +307,10 @@ export type NotifyEvent = Keyed & (
|
|
|
298
307
|
status?: 'fail' | 'ok';
|
|
299
308
|
}
|
|
300
309
|
/**
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
310
|
+
* DEPRECATED since 1.4.2: use `job` with status `silent`. The type stays,
|
|
311
|
+
* because the silence watchdog lives on the server and sends exactly this
|
|
312
|
+
* one until it is redeployed — removing it means losing the silence card
|
|
313
|
+
* exactly when it is needed. Do not add new calls.
|
|
305
314
|
*/
|
|
306
315
|
| {
|
|
307
316
|
type: 'heartbeat_miss';
|
|
@@ -309,27 +318,28 @@ export type NotifyEvent = Keyed & (
|
|
|
309
318
|
job: string;
|
|
310
319
|
lastSeen?: string;
|
|
311
320
|
expected?: string;
|
|
312
|
-
/**
|
|
321
|
+
/** The task reported in again — same type, a green card instead of a red one, the key (for matching) does not change. */
|
|
313
322
|
recovered?: boolean;
|
|
314
|
-
/**
|
|
323
|
+
/** A ready-made reason sentence; without it, one is built from lastSeen/expected. */
|
|
315
324
|
note?: string;
|
|
316
325
|
});
|
|
317
326
|
export type EventType = NotifyEvent['type'];
|
|
318
|
-
/**
|
|
327
|
+
/** Red = with sound. Everything else is silent. (There is no separate "incidents" topic any more — an incident is visible in the project's feed.) */
|
|
319
328
|
/**
|
|
320
|
-
*
|
|
329
|
+
* The icon dictionary. Two laws, both set by the owner on 25.08.2026:
|
|
321
330
|
*
|
|
322
|
-
* 1.
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* silent —
|
|
326
|
-
* 2.
|
|
327
|
-
*
|
|
328
|
-
*
|
|
331
|
+
* 1. WITHIN one tag every word gets its own icon. There used to be exactly
|
|
332
|
+
* four icons for the whole package, and `Issue: opened` looked the same
|
|
333
|
+
* as `Issue: assigned`, while a task's three different kinds of trouble —
|
|
334
|
+
* fail, disabled, silent — were the same red circle.
|
|
335
|
+
* 2. BETWEEN tags the same meaning looks the same. `fail` is 🔴 whether on a
|
|
336
|
+
* deploy, on CI, or on a task; "something new appeared" is 🆕 on a board
|
|
337
|
+
* task, on a PR, and on a file alike.
|
|
329
338
|
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
339
|
+
* And a third law that keeps the first two honest: the sound is a fixed
|
|
340
|
+
* property of the icon. Not of the event, not of the status — of the icon.
|
|
341
|
+
* While the sound was a separate rule, `🔴 PR: changes_requested` arrived
|
|
342
|
+
* silent.
|
|
333
343
|
*/
|
|
334
344
|
export declare const ICON: {
|
|
335
345
|
readonly ok: "✅";
|
|
@@ -353,7 +363,7 @@ export declare const PR_ICON: Record<Extract<NotifyEvent, {
|
|
|
353
363
|
export declare const ISSUE_ICON: Record<Extract<NotifyEvent, {
|
|
354
364
|
type: 'issue';
|
|
355
365
|
}>['action'], string>;
|
|
356
|
-
/**
|
|
366
|
+
/** One place decides the card's icon — both the render and the sound take it from here. */
|
|
357
367
|
export declare const iconFor: (e: NotifyEvent) => string;
|
|
358
368
|
export declare const severity: (e: NotifyEvent) => "info" | "error";
|
|
359
369
|
export {};
|
package/dist/events.js
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* `send.ts`)
|
|
4
|
-
*
|
|
2
|
+
* The event catalogue — the single entry point for sending. `notify()` (see
|
|
3
|
+
* `send.ts`) accepts ONLY values of this type: there is no free text in the
|
|
4
|
+
* API, so a "custom" message cannot technically be written.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
6
|
+
* The schema evolution rule (there is no version and never will be — a
|
|
7
|
+
* message lives one second and is read by eyes, there is nothing to
|
|
8
|
+
* version):
|
|
9
|
+
* - a new field on an EXISTING type is added ONLY as optional;
|
|
10
|
+
* - required fields are never added — only a new event type.
|
|
11
|
+
* That keeps old caller code and a new package compatible both ways.
|
|
11
12
|
*/
|
|
12
|
-
/**
|
|
13
|
+
/** Red = with sound. Everything else is silent. (There is no separate "incidents" topic any more — an incident is visible in the project's feed.) */
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
+
* The icon dictionary. Two laws, both set by the owner on 25.08.2026:
|
|
15
16
|
*
|
|
16
|
-
* 1.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* silent —
|
|
20
|
-
* 2.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
17
|
+
* 1. WITHIN one tag every word gets its own icon. There used to be exactly
|
|
18
|
+
* four icons for the whole package, and `Issue: opened` looked the same
|
|
19
|
+
* as `Issue: assigned`, while a task's three different kinds of trouble —
|
|
20
|
+
* fail, disabled, silent — were the same red circle.
|
|
21
|
+
* 2. BETWEEN tags the same meaning looks the same. `fail` is 🔴 whether on a
|
|
22
|
+
* deploy, on CI, or on a task; "something new appeared" is 🆕 on a board
|
|
23
|
+
* task, on a PR, and on a file alike.
|
|
23
24
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* And a third law that keeps the first two honest: the sound is a fixed
|
|
26
|
+
* property of the icon. Not of the event, not of the status — of the icon.
|
|
27
|
+
* While the sound was a separate rule, `🔴 PR: changes_requested` arrived
|
|
28
|
+
* silent.
|
|
27
29
|
*/
|
|
28
30
|
export const ICON = {
|
|
29
31
|
ok: '✅', // passed, closed, done
|
|
@@ -59,7 +61,7 @@ const JOB_ICON = {
|
|
|
59
61
|
disabled: ICON.off,
|
|
60
62
|
silent: ICON.unknown
|
|
61
63
|
};
|
|
62
|
-
/**
|
|
64
|
+
/** One place decides the card's icon — both the render and the sound take it from here. */
|
|
63
65
|
export const iconFor = (e) => {
|
|
64
66
|
switch (e.type) {
|
|
65
67
|
case 'deploy':
|