@mikitasazan/notify 1.6.2 → 1.8.0
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-flags.js +1 -1
- package/dist/cli.js +4 -1
- package/dist/events.d.ts +15 -1
- package/dist/render.d.ts +18 -0
- package/dist/render.js +38 -32
- package/package.json +1 -1
package/dist/cli-flags.js
CHANGED
|
@@ -14,7 +14,7 @@ export const KNOWN_FLAGS = new Set([
|
|
|
14
14
|
'command', 'command-note', 'commit-body', 'commit-title', 'commit-url', 'detail',
|
|
15
15
|
'expected', 'filename', 'item',
|
|
16
16
|
'item-group', 'job', 'key', 'last-seen', 'line', 'logs', 'note',
|
|
17
|
-
'number', 'path', 'period', 'project', 'reviewer', 'stat', 'status',
|
|
17
|
+
'aside', 'number', 'path', 'period', 'project', 'reviewer', 'stat', 'status',
|
|
18
18
|
'target', 'title', 'url', 'via', 'workflow-name', 'workflow-url',
|
|
19
19
|
// Флаги без значения. Живут здесь же, чтобы разбор и список не разошлись.
|
|
20
20
|
'json', 'recovered', 'dry-run'
|
package/dist/cli.js
CHANGED
|
@@ -236,6 +236,7 @@ else {
|
|
|
236
236
|
project: project(),
|
|
237
237
|
job: one('job') ?? '(no name)',
|
|
238
238
|
status: jobStatus(),
|
|
239
|
+
aside: one('aside'),
|
|
239
240
|
expected: one('expected'),
|
|
240
241
|
lastSeen: one('last-seen'),
|
|
241
242
|
stats: pairs('stat'),
|
|
@@ -254,7 +255,9 @@ else {
|
|
|
254
255
|
type: 'report',
|
|
255
256
|
project: project(),
|
|
256
257
|
title: one('title') ?? '(no title)',
|
|
257
|
-
period
|
|
258
|
+
// `--period` is the old spelling of `--aside`; both fill the same
|
|
259
|
+
// slot, and two senders still use the old one.
|
|
260
|
+
aside: one('aside') ?? one('period'),
|
|
258
261
|
lines: pairs('line'),
|
|
259
262
|
items: items(),
|
|
260
263
|
url: one('url')
|
package/dist/events.d.ts
CHANGED
|
@@ -111,6 +111,14 @@ export type NotifyEvent = Keyed & (
|
|
|
111
111
|
* ПОЛНОМУ тегу. Один поток на задачу это чинит.
|
|
112
112
|
*/
|
|
113
113
|
status: 'ok' | 'fail' | 'disabled' | 'silent';
|
|
114
|
+
/**
|
|
115
|
+
* The one qualifier the name needs to be readable on its own, printed in
|
|
116
|
+
* brackets right after it: `Yandex game import (reporting again)`. It is
|
|
117
|
+
* the same slot a report uses for the day it covers. Anything that is a
|
|
118
|
+
* FACT about the job goes in a row of its own; this is for the word that
|
|
119
|
+
* finishes the name.
|
|
120
|
+
*/
|
|
121
|
+
aside?: string;
|
|
114
122
|
/** Как часто задача обязана отмечаться — для `silent` и для возврата из него. */
|
|
115
123
|
expected?: string;
|
|
116
124
|
/** Когда её видели в последний раз. */
|
|
@@ -162,7 +170,13 @@ export type NotifyEvent = Keyed & (
|
|
|
162
170
|
type: 'report';
|
|
163
171
|
project: Project;
|
|
164
172
|
title: string;
|
|
165
|
-
|
|
173
|
+
/**
|
|
174
|
+
* Printed in brackets after the title — which day the report covers, or
|
|
175
|
+
* which day its arrows are measured against. Same slot, same name, as a
|
|
176
|
+
* job's. `period` is the old spelling of this field and the CLI still
|
|
177
|
+
* accepts `--period` for it.
|
|
178
|
+
*/
|
|
179
|
+
aside?: string;
|
|
166
180
|
/** Пусто/не передано, когда используются `groups` — два вида отчёта не смешиваются в одном событии. */
|
|
167
181
|
lines?: Array<[label: string, value: string | number, group?: string]>;
|
|
168
182
|
/**
|
package/dist/render.d.ts
CHANGED
|
@@ -46,6 +46,24 @@ export declare const slug: (raw: string) => string;
|
|
|
46
46
|
* заголовок и есть единственное стабильное поле).
|
|
47
47
|
*/
|
|
48
48
|
export declare const eventKey: (e: NotifyEvent) => string;
|
|
49
|
+
/**
|
|
50
|
+
* Третий тег — ИСХОД, и он есть всегда. Владелец: «не хватает тега fail или
|
|
51
|
+
* похожего, чтобы фейлы можно было группировать и ок можно было группировать».
|
|
52
|
+
* Одно нажатие в Telegram собирает все падения проекта разом, каким бы типом
|
|
53
|
+
* они ни пришли — выкатка, проверка, задача по расписанию, авария.
|
|
54
|
+
*
|
|
55
|
+
* The value comes from the ICON, never from the status word. The icon is
|
|
56
|
+
* already the single source of truth for the sound, and a second list of "what
|
|
57
|
+
* counts as broken" would drift from the first — it already did once, when a
|
|
58
|
+
* red card arrived silent.
|
|
59
|
+
*
|
|
60
|
+
* One icon meaning, one tag. A watchdog that SWITCHED SOMETHING OFF is not a
|
|
61
|
+
* failure and must not be filed under the same word as one: the owner read
|
|
62
|
+
* `#fail` under a 🚫 and said so. Nor is a task that has simply gone quiet —
|
|
63
|
+
* nobody knows yet whether it broke, and `#unknown` is the honest word for it.
|
|
64
|
+
*/
|
|
65
|
+
export declare const OUTCOME_TAG: Readonly<Record<string, string>>;
|
|
66
|
+
export declare const outcomeTag: (e: NotifyEvent) => string;
|
|
49
67
|
/**
|
|
50
68
|
* Строка тегов для свободного HTML (`sendReport`). Тег — это ФИЛЬТР владельца,
|
|
51
69
|
* и к формату тела он отношения не имеет: дневной отчёт остаётся свободным
|
package/dist/render.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* строка разделяет БЛОКИ ПО СМЫСЛУ (шапка / суть / действия), не механически
|
|
20
20
|
* после каждой строки.
|
|
21
21
|
*/
|
|
22
|
-
import { ICON,
|
|
22
|
+
import { ICON, iconFor } from "./events.js";
|
|
23
23
|
/** Первая буква — заглавная, остальное как есть (ga4/GitHub остаются собой). */
|
|
24
24
|
/**
|
|
25
25
|
* Ярлык с большой буквы — но НЕ у имени, которое пишется со строчной нарочно:
|
|
@@ -414,6 +414,10 @@ const renderDeploy = (e) => {
|
|
|
414
414
|
...twoBlocks([field('Target', e.target), field('Reason', e.note)], [fieldLink('Commit', e.commitUrl, e.commit), titleField(e.commitTitle), bodyQuote(e.commitBody)])
|
|
415
415
|
]);
|
|
416
416
|
};
|
|
417
|
+
const schedule = (expected, lastSeen, lastLabel) => {
|
|
418
|
+
const rows = [field('Expected', expected), field(lastLabel, lastSeen)].filter((r) => r !== null);
|
|
419
|
+
return rows.length > 0 ? ['', group('Schedule'), ...rows] : [];
|
|
420
|
+
};
|
|
417
421
|
const renderJob = (e) => {
|
|
418
422
|
const icon = iconFor(e);
|
|
419
423
|
const hasItems = (e.items ?? []).length > 0;
|
|
@@ -424,22 +428,18 @@ const renderJob = (e) => {
|
|
|
424
428
|
// were two words for one thing, and the outcome that took the first line is
|
|
425
429
|
// already the icon, and now the third tag too.
|
|
426
430
|
//
|
|
427
|
-
//
|
|
428
|
-
// "it
|
|
429
|
-
// and the
|
|
430
|
-
|
|
431
|
-
? 'switched off, not broken'
|
|
432
|
-
: e.status === 'silent'
|
|
433
|
-
? 'no word from it at all'
|
|
434
|
-
: undefined;
|
|
431
|
+
// There is no `State:` row. It said "switched off, not broken" under a 🚫
|
|
432
|
+
// and "no word from it at all" under a ❓ — the third way of saying what the
|
|
433
|
+
// icon says and what the third tag now says too. The icon table on the
|
|
434
|
+
// catalogue page defines both marks.
|
|
435
435
|
return join([
|
|
436
|
-
typeLine(icon, 'Job', e.job, e.workflowUrl ?? e.url),
|
|
437
|
-
field('State', state),
|
|
436
|
+
typeLine(icon, 'Job', e.job, e.workflowUrl ?? e.url, e.aside),
|
|
438
437
|
field('Reason', e.note),
|
|
439
|
-
|
|
440
|
-
//
|
|
441
|
-
//
|
|
442
|
-
|
|
438
|
+
// The timetable is a different subject from this event: how often the task
|
|
439
|
+
// owes a sign of life and when it last gave one. It stood in a bare run
|
|
440
|
+
// under `Reason:` and read as more of the same. `Last run` when the task
|
|
441
|
+
// is alive, `Last seen` when it is not — one timestamp, two questions.
|
|
442
|
+
...schedule(e.expected, e.lastSeen, e.status === 'silent' ? 'Last seen' : 'Last run'),
|
|
443
443
|
...labelled(e.stats),
|
|
444
444
|
hasItems ? '' : null,
|
|
445
445
|
// Heading ONLY for `disabled`. It used to print for any job carrying a
|
|
@@ -464,7 +464,7 @@ const renderReport = (e) => {
|
|
|
464
464
|
// without a word.
|
|
465
465
|
const numbers = labelled(e.lines);
|
|
466
466
|
return join([
|
|
467
|
-
typeLine(iconFor(e), 'Report', e.title, e.url, e.
|
|
467
|
+
typeLine(iconFor(e), 'Report', e.title, e.url, e.aside),
|
|
468
468
|
// Rows with no group of their own sit flush against the header instead of
|
|
469
469
|
// forming a separate slab under a blank line. `labelled` puts the blank
|
|
470
470
|
// line before the first group itself, so there is none here.
|
|
@@ -477,7 +477,7 @@ const renderReport = (e) => {
|
|
|
477
477
|
return join([
|
|
478
478
|
// Both analytics jobs send a link to the day's snapshot in docs/. It used to
|
|
479
479
|
// hang off a trailing `Details: open` row; now it is the report's own name.
|
|
480
|
-
typeLine(iconFor(e), 'Report', e.title, e.url, e.
|
|
480
|
+
typeLine(iconFor(e), 'Report', e.title, e.url, e.aside),
|
|
481
481
|
// Flush against the header — see the branch above.
|
|
482
482
|
...labelled(e.lines),
|
|
483
483
|
items.length > 0 ? '' : null,
|
|
@@ -560,8 +560,7 @@ const renderHeartbeatMiss = (e) => {
|
|
|
560
560
|
// copy of that watchdog can, and the card it gets must obey the template.
|
|
561
561
|
typeLine(icon, 'Heartbeat', e.job, undefined, action),
|
|
562
562
|
field('Reason', e.note),
|
|
563
|
-
|
|
564
|
-
field(e.recovered ? 'Last run' : 'Last seen', e.lastSeen)
|
|
563
|
+
...schedule(e.expected, e.lastSeen, e.recovered ? 'Last run' : 'Last seen')
|
|
565
564
|
]);
|
|
566
565
|
};
|
|
567
566
|
const RENDERERS = {
|
|
@@ -640,21 +639,28 @@ export const eventKey = (e) => {
|
|
|
640
639
|
* Одно нажатие в Telegram собирает все падения проекта разом, каким бы типом
|
|
641
640
|
* они ни пришли — выкатка, проверка, задача по расписанию, авария.
|
|
642
641
|
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
642
|
+
* The value comes from the ICON, never from the status word. The icon is
|
|
643
|
+
* already the single source of truth for the sound, and a second list of "what
|
|
644
|
+
* counts as broken" would drift from the first — it already did once, when a
|
|
645
|
+
* red card arrived silent.
|
|
646
|
+
*
|
|
647
|
+
* One icon meaning, one tag. A watchdog that SWITCHED SOMETHING OFF is not a
|
|
648
|
+
* failure and must not be filed under the same word as one: the owner read
|
|
649
|
+
* `#fail` under a 🚫 and said so. Nor is a task that has simply gone quiet —
|
|
650
|
+
* nobody knows yet whether it broke, and `#unknown` is the honest word for it.
|
|
649
651
|
*/
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
652
|
+
export const OUTCOME_TAG = {
|
|
653
|
+
[ICON.red]: 'fail',
|
|
654
|
+
[ICON.alarm]: 'fail',
|
|
655
|
+
[ICON.off]: 'off',
|
|
656
|
+
[ICON.unknown]: 'unknown',
|
|
657
|
+
[ICON.ok]: 'ok',
|
|
658
|
+
[ICON.landed]: 'ok',
|
|
659
|
+
[ICON.approved]: 'ok'
|
|
657
660
|
};
|
|
661
|
+
// Everything left over — a task was opened, a PR opened, edits asked for, a
|
|
662
|
+
// digest — is news: something happened, no verdict was passed.
|
|
663
|
+
export const outcomeTag = (e) => OUTCOME_TAG[iconFor(e)] ?? 'news';
|
|
658
664
|
const tagsLine = (e) => `#${TYPE_TAG[e.type]} #${esc(eventKey(e))} #${outcomeTag(e)}`;
|
|
659
665
|
/**
|
|
660
666
|
* Строка тегов для свободного HTML (`sendReport`). Тег — это ФИЛЬТР владельца,
|
package/package.json
CHANGED