@intentius/chant-lexicon-prometheus 0.97.0 → 0.99.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.
Files changed (69) hide show
  1. package/README.md +6 -1
  2. package/dist/alertmanager.d.ts +4 -2
  3. package/dist/alertmanager.d.ts.map +1 -1
  4. package/dist/build.d.ts.map +1 -1
  5. package/dist/codegen/docs.d.ts.map +1 -1
  6. package/dist/import/embedded.d.ts +14 -0
  7. package/dist/import/embedded.d.ts.map +1 -0
  8. package/dist/import/generator.d.ts +50 -0
  9. package/dist/import/generator.d.ts.map +1 -0
  10. package/dist/import/parser.d.ts +52 -0
  11. package/dist/import/parser.d.ts.map +1 -0
  12. package/dist/import/slo.d.ts +15 -0
  13. package/dist/import/slo.d.ts.map +1 -0
  14. package/dist/integrations.d.ts +531 -0
  15. package/dist/integrations.d.ts.map +1 -0
  16. package/dist/integrity.json +7 -7
  17. package/dist/lint/rules/literal-credential.d.ts.map +1 -1
  18. package/dist/lint/rules/prom-ast.d.ts +8 -0
  19. package/dist/lint/rules/prom-ast.d.ts.map +1 -1
  20. package/dist/lint/rules/promql-literal.d.ts.map +1 -1
  21. package/dist/manifest.json +1 -1
  22. package/dist/model.d.ts +77 -121
  23. package/dist/model.d.ts.map +1 -1
  24. package/dist/plugin.d.ts.map +1 -1
  25. package/dist/rules/literal-credential.ts +52 -15
  26. package/dist/rules/prom-ast.ts +36 -0
  27. package/dist/rules/promql-literal.ts +15 -1
  28. package/dist/skills/chant-prometheus-alertmanager.md +4 -0
  29. package/dist/skills/chant-prometheus.md +11 -0
  30. package/package.json +2 -2
  31. package/src/alertmanager.ts +4 -1
  32. package/src/build.ts +2 -0
  33. package/src/codegen/docs.ts +5 -1
  34. package/src/import/cli.test.ts +98 -0
  35. package/src/import/embedded.test.ts +56 -0
  36. package/src/import/embedded.ts +44 -0
  37. package/src/import/generated-types.e2e.test.ts +77 -0
  38. package/src/import/generator.test.ts +138 -0
  39. package/src/import/generator.ts +578 -0
  40. package/src/import/parser.test.ts +133 -0
  41. package/src/import/parser.ts +365 -0
  42. package/src/import/roundtrip.test.ts +358 -0
  43. package/src/import/slo.ts +175 -0
  44. package/src/import/testdata/alertmanager-full.yml +89 -0
  45. package/src/import/testdata/alertmanager-integrations.yml +215 -0
  46. package/src/import/testdata/fixtures.ts +122 -0
  47. package/src/import/testdata/rules-full.yml +42 -0
  48. package/src/import/testdata/upstream/alertmanager-conf-good.yml +120 -0
  49. package/src/import/testdata/upstream/alertmanager-mattermost-default-webhook-url-file.yml +16 -0
  50. package/src/import/testdata/upstream/alertmanager-opsgenie-default-apikey-file.yml +27 -0
  51. package/src/import/testdata/upstream/alertmanager-rocketchat-default-token-file.yml +25 -0
  52. package/src/import/testdata/upstream/alertmanager-route-labels.yml +65 -0
  53. package/src/import/testdata/upstream/alertmanager-simple.yml +130 -0
  54. package/src/import/testdata/upstream/alertmanager-sns-topic-arn.yml +17 -0
  55. package/src/import/testdata/upstream/alertmanager-telegram-default-bot-token-file.yml +16 -0
  56. package/src/import/testdata/upstream/alertmanager-victorops-default-apikey-file.yml +23 -0
  57. package/src/import/testdata/upstream/alertmanager-wechat-default-api-secret-file.yml +18 -0
  58. package/src/import/testdata/upstream/prometheus-alerting-rules.yml +15 -0
  59. package/src/import/testdata/upstream/prometheus-alerting-templates.yml +23 -0
  60. package/src/import/testdata/upstream/prometheus-recording-rules.yml +7 -0
  61. package/src/integrations.ts +538 -0
  62. package/src/lint/rules/literal-credential.ts +52 -15
  63. package/src/lint/rules/prom-ast.ts +36 -0
  64. package/src/lint/rules/promql-literal.ts +15 -1
  65. package/src/lint/rules/rules.test.ts +58 -0
  66. package/src/model.ts +157 -109
  67. package/src/plugin.ts +15 -0
  68. package/src/skills/chant-prometheus-alertmanager.md +4 -0
  69. package/src/skills/chant-prometheus.md +11 -0
package/dist/model.d.ts CHANGED
@@ -12,6 +12,7 @@
12
12
  * so a declaration reads the same as the file it produces and the upstream
13
13
  * docs apply word for word.
14
14
  */
15
+ import { type DiscordConfig, type EmailConfig, type HttpClientConfig, type IncidentioConfig, type JiraConfig, type MattermostConfig, type MSTeamsConfig, type MSTeamsV2Config, type OpsGenieConfig, type PagerDutyConfig, type PushoverConfig, type ReceiverIntegration, type RocketchatConfig, type SlackConfig, type SNSConfig, type TelegramConfig, type TlsConfig, type VictorOpsConfig, type WebexConfig, type WebhookConfig, type WechatConfig } from "./integrations.js";
15
16
  /** Labels or annotations: string keys to string values. */
16
17
  export type LabelSet = Record<string, string>;
17
18
  /** A recording rule: evaluates `expr` and stores the result as the series `record`. */
@@ -60,126 +61,30 @@ export declare function isRecordingRuleConfig(rule: unknown): rule is RecordingR
60
61
  export declare function isAlertingRuleConfig(rule: unknown): rule is AlertingRuleConfig;
61
62
  /** The rule's name: `record` for a recording rule, `alert` for an alerting rule. */
62
63
  export declare function ruleName(rule: RuleConfig): string;
63
- /** HTTP client settings shared by the receivers that make HTTP calls. */
64
- export interface HttpClientConfig {
65
- basic_auth?: {
66
- username?: string;
67
- username_file?: string;
68
- password?: string;
69
- password_file?: string;
70
- };
71
- authorization?: {
72
- type?: string;
73
- credentials?: string;
74
- credentials_file?: string;
75
- };
76
- bearer_token?: string;
77
- bearer_token_file?: string;
78
- oauth2?: Record<string, unknown>;
79
- proxy_url?: string;
80
- follow_redirects?: boolean;
81
- enable_http2?: boolean;
82
- tls_config?: {
83
- ca_file?: string;
84
- cert_file?: string;
85
- key_file?: string;
86
- server_name?: string;
87
- insecure_skip_verify?: boolean;
88
- min_version?: string;
89
- };
90
- }
91
- interface NotifierBase {
92
- /** Whether to notify about resolved alerts too. */
93
- send_resolved?: boolean;
94
- }
95
- export interface WebhookConfig extends NotifierBase {
96
- /** Where alerts are POSTed. Set this or `url_file`. */
97
- url?: string;
98
- url_file?: string;
99
- http_config?: HttpClientConfig;
100
- /** Most alerts per message; 0 sends them all. */
101
- max_alerts?: number;
102
- timeout?: string;
103
- }
104
- export interface EmailConfig extends NotifierBase {
105
- to: string;
106
- from?: string;
107
- /** `host:port` of the SMTP server. Falls back to `global.smtp_smarthost`. */
108
- smarthost?: string;
109
- hello?: string;
110
- auth_username?: string;
111
- auth_password?: string;
112
- auth_password_file?: string;
113
- auth_secret?: string;
114
- auth_secret_file?: string;
115
- auth_identity?: string;
116
- require_tls?: boolean;
117
- tls_config?: HttpClientConfig["tls_config"];
118
- html?: string;
119
- text?: string;
120
- headers?: Record<string, string>;
121
- }
122
- export interface SlackConfig extends NotifierBase {
123
- /** The incoming-webhook URL. It is a credential: prefer `api_url_file`. */
124
- api_url?: string;
125
- api_url_file?: string;
126
- channel?: string;
127
- username?: string;
128
- color?: string;
129
- title?: string;
130
- title_link?: string;
131
- pretext?: string;
132
- text?: string;
133
- footer?: string;
134
- fallback?: string;
135
- icon_emoji?: string;
136
- icon_url?: string;
137
- link_names?: boolean;
138
- short_fields?: boolean;
139
- mrkdwn_in?: string[];
140
- fields?: Array<{
141
- title: string;
142
- value: string;
143
- short?: boolean;
144
- }>;
145
- actions?: Array<Record<string, unknown>>;
146
- http_config?: HttpClientConfig;
147
- }
148
- export interface PagerDutyConfig extends NotifierBase {
149
- /** Events API v2 integration key. A credential: prefer `routing_key_file`. */
150
- routing_key?: string;
151
- routing_key_file?: string;
152
- /** Events API v1 integration key. A credential: prefer `service_key_file`. */
153
- service_key?: string;
154
- service_key_file?: string;
155
- url?: string;
156
- client?: string;
157
- client_url?: string;
158
- description?: string;
159
- severity?: string;
160
- class?: string;
161
- component?: string;
162
- group?: string;
163
- source?: string;
164
- details?: Record<string, string>;
165
- links?: Array<{
166
- href: string;
167
- text?: string;
168
- }>;
169
- images?: Array<{
170
- src: string;
171
- alt?: string;
172
- href?: string;
173
- }>;
174
- http_config?: HttpClientConfig;
175
- }
64
+ export * from "./integrations.js";
176
65
  /** One entry under `receivers:`. */
177
66
  export interface ReceiverConfig {
178
67
  name: string;
179
- webhook_configs?: WebhookConfig[];
68
+ /** Labels on the receiver, exposed to notification templates. */
69
+ labels?: LabelSet;
70
+ discord_configs?: DiscordConfig[];
180
71
  email_configs?: EmailConfig[];
181
- slack_configs?: SlackConfig[];
72
+ incidentio_configs?: IncidentioConfig[];
182
73
  pagerduty_configs?: PagerDutyConfig[];
74
+ slack_configs?: SlackConfig[];
75
+ webhook_configs?: WebhookConfig[];
76
+ opsgenie_configs?: OpsGenieConfig[];
77
+ wechat_configs?: WechatConfig[];
78
+ pushover_configs?: PushoverConfig[];
79
+ victorops_configs?: VictorOpsConfig[];
80
+ sns_configs?: SNSConfig[];
81
+ telegram_configs?: TelegramConfig[];
82
+ webex_configs?: WebexConfig[];
83
+ msteams_configs?: MSTeamsConfig[];
84
+ msteamsv2_configs?: MSTeamsV2Config[];
85
+ jira_configs?: JiraConfig[];
86
+ rocketchat_configs?: RocketchatConfig[];
87
+ mattermost_configs?: MattermostConfig[];
183
88
  }
184
89
  /** A route in the routing tree. The top-level `route:` is the root. */
185
90
  export interface RouteConfig {
@@ -193,10 +98,17 @@ export interface RouteConfig {
193
98
  repeat_interval?: string;
194
99
  mute_time_intervals?: string[];
195
100
  active_time_intervals?: string[];
101
+ /**
102
+ * Labels on the route, inherited by child routes and exposed to
103
+ * notification templates as `routeLabels`. Values may be Go templates.
104
+ */
105
+ labels?: LabelSet;
196
106
  routes?: RouteConfig[];
197
107
  }
198
108
  /** One entry under `inhibit_rules:`. */
199
109
  export interface InhibitRuleConfig {
110
+ /** A name for the rule, shown in Alertmanager's logs and metrics. */
111
+ name?: string;
200
112
  source_matchers?: string[];
201
113
  target_matchers?: string[];
202
114
  /** Labels that must be equal on source and target for the inhibition to apply. */
@@ -225,12 +137,18 @@ export interface TimeIntervalConfig {
225
137
  name: string;
226
138
  time_intervals: TimePeriodConfig[];
227
139
  }
228
- /** `global:` settings. */
140
+ /**
141
+ * `global:` settings: defaults the receivers fall back to. Credentials with
142
+ * a `*_file` sibling are best set through it; PROM001 flags a literal.
143
+ */
229
144
  export interface AlertmanagerGlobalConfig {
145
+ /** How long an alert that stops being updated stays firing. */
230
146
  resolve_timeout?: string;
147
+ http_config?: HttpClientConfig;
148
+ jira_api_url?: string;
231
149
  smtp_from?: string;
232
- smtp_smarthost?: string;
233
150
  smtp_hello?: string;
151
+ smtp_smarthost?: string;
234
152
  smtp_auth_username?: string;
235
153
  smtp_auth_password?: string;
236
154
  smtp_auth_password_file?: string;
@@ -238,10 +156,48 @@ export interface AlertmanagerGlobalConfig {
238
156
  smtp_auth_secret_file?: string;
239
157
  smtp_auth_identity?: string;
240
158
  smtp_require_tls?: boolean;
159
+ smtp_tls_config?: TlsConfig;
160
+ smtp_force_implicit_tls?: boolean;
241
161
  slack_api_url?: string;
242
162
  slack_api_url_file?: string;
163
+ slack_app_token?: string;
164
+ slack_app_token_file?: string;
165
+ slack_app_url?: string;
243
166
  pagerduty_url?: string;
244
- http_config?: HttpClientConfig;
167
+ opsgenie_api_url?: string;
168
+ opsgenie_api_key?: string;
169
+ opsgenie_api_key_file?: string;
170
+ wechat_api_url?: string;
171
+ wechat_api_secret?: string;
172
+ wechat_api_secret_file?: string;
173
+ wechat_api_corp_id?: string;
174
+ victorops_api_url?: string;
175
+ victorops_api_key?: string;
176
+ victorops_api_key_file?: string;
177
+ telegram_api_url?: string;
178
+ telegram_bot_token?: string;
179
+ telegram_bot_token_file?: string;
180
+ webex_api_url?: string;
181
+ rocketchat_api_url?: string;
182
+ rocketchat_token?: string;
183
+ rocketchat_token_file?: string;
184
+ rocketchat_token_id?: string;
185
+ rocketchat_token_id_file?: string;
186
+ mattermost_webhook_url?: string;
187
+ mattermost_webhook_url_file?: string;
188
+ }
189
+ /** Every `global:` field, as a list, for code that reads a parsed file. */
190
+ export declare const ALERTMANAGER_GLOBAL_FIELDS: readonly (keyof AlertmanagerGlobalConfig)[];
191
+ /** `tracing:` settings: where Alertmanager sends its own traces. */
192
+ export interface AlertmanagerTracingConfig {
193
+ client_type?: "grpc" | "http";
194
+ endpoint?: string;
195
+ sampling_fraction?: number;
196
+ insecure?: boolean;
197
+ headers?: Record<string, string>;
198
+ compression?: string;
199
+ timeout?: string;
200
+ tls_config?: TlsConfig;
245
201
  }
246
202
  /** A whole `alertmanager.yml`, the file `amtool check-config` reads. */
247
203
  export interface AlertmanagerConfig {
@@ -251,12 +207,12 @@ export interface AlertmanagerConfig {
251
207
  inhibit_rules?: InhibitRuleConfig[];
252
208
  receivers?: ReceiverConfig[];
253
209
  time_intervals?: TimeIntervalConfig[];
210
+ tracing?: AlertmanagerTracingConfig;
254
211
  }
255
- /** The four receiver integrations this lexicon types. */
256
- export declare const RECEIVER_INTEGRATIONS: readonly ["webhook_configs", "email_configs", "slack_configs", "pagerduty_configs"];
212
+ /** The receiver integrations, every one Alertmanager defines. */
213
+ export declare const RECEIVER_INTEGRATIONS: readonly ReceiverIntegration[];
257
214
  /** True when a parsed document has the shape of a Prometheus rule file. */
258
215
  export declare function looksLikeRuleFile(value: unknown): value is RuleFileConfig;
259
216
  /** True when a parsed document has the shape of an `alertmanager.yml`. */
260
217
  export declare function looksLikeAlertmanagerConfig(value: unknown): value is AlertmanagerConfig;
261
- export {};
262
218
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA4B9D;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,aA6F9B,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA+B9D;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,aAyG9B,CAAC"}
@@ -1,26 +1,53 @@
1
1
  import * as ts from "typescript";
2
2
  import type { LintRule, LintDiagnostic, LintContext } from "@intentius/chant/lint/rule";
3
- import { calleeName, CREDENTIAL_CLASS, literalText, position, propertyName } from "./prom-ast";
3
+ import { calleeName, constInitializers, CREDENTIAL_CLASS, literalText, position, propertyName, resolveConst } from "./prom-ast";
4
4
 
5
5
  /**
6
6
  * Alertmanager fields that hold a secret, each with a `*_file` sibling that
7
7
  * reads it from a mounted file instead.
8
8
  */
9
9
  export const SECRET_FIELDS = new Set([
10
- "api_url", // slack_configs: the incoming-webhook URL is the credential
11
- "slack_api_url",
12
- "routing_key",
10
+ "api_url", // slack_configs only: the incoming-webhook URL is the credential (see SECRET_ONLY_IN)
11
+ "webhook_url", // discord, msteams, msteamsv2 and mattermost
12
+ "app_token",
13
+ "routing_key", // pagerduty (victorops' routing_key names a route, see SECRET_ONLY_IN)
13
14
  "service_key",
15
+ "api_key",
16
+ "api_secret",
17
+ "bot_token",
18
+ "token",
19
+ "token_id",
20
+ "user_key",
21
+ "alert_source_token",
14
22
  "auth_password",
15
23
  "auth_secret",
16
24
  "smtp_auth_password",
17
25
  "smtp_auth_secret",
26
+ "slack_api_url",
27
+ "slack_app_token",
28
+ "opsgenie_api_key",
29
+ "wechat_api_secret",
30
+ "victorops_api_key",
31
+ "telegram_bot_token",
32
+ "rocketchat_token",
33
+ "rocketchat_token_id",
34
+ "mattermost_webhook_url",
18
35
  "password",
19
36
  "credentials",
20
37
  "bearer_token",
21
38
  "client_secret",
22
39
  ]);
23
40
 
41
+ /**
42
+ * Fields that are a secret in one integration and plain elsewhere: `api_url`
43
+ * is Slack's webhook credential but only an endpoint for the others, and a
44
+ * VictorOps `routing_key` names a route.
45
+ */
46
+ const SECRET_ONLY_IN: Record<string, string> = {
47
+ api_url: "slack_configs",
48
+ routing_key: "pagerduty_configs",
49
+ };
50
+
24
51
  /**
25
52
  * PROM001: a credential written as a literal in a `Receiver` or
26
53
  * `AlertmanagerSettings`.
@@ -41,16 +68,25 @@ export const literalCredentialRule: LintRule = {
41
68
  const diagnostics: LintDiagnostic[] = [];
42
69
  const source = context.sourceFile;
43
70
 
44
- const scanValue = (key: string | undefined, init: ts.Expression) => {
45
- if (ts.isObjectLiteralExpression(init)) {
46
- scan(init);
47
- return;
48
- }
49
- if (ts.isArrayLiteralExpression(init)) {
50
- for (const el of init.elements) if (ts.isObjectLiteralExpression(el)) scan(el);
71
+ const consts = constInitializers(source);
72
+ const scanned = new Set<ts.Node>();
73
+
74
+ // A value is followed to the const it names, so a list lifted out of the
75
+ // constructor (`email_configs: heartbeatEmail`) is scanned where it is used.
76
+ // `integration` is the `*_configs` list a value sits in, when that is known.
77
+ const scanValue = (key: string | undefined, value: ts.Expression, integration?: string) => {
78
+ const init = resolveConst(value, consts);
79
+ const within = key?.endsWith("_configs") ? key : integration;
80
+ if (ts.isObjectLiteralExpression(init) || ts.isArrayLiteralExpression(init)) {
81
+ if (scanned.has(init)) return;
82
+ scanned.add(init);
83
+ if (ts.isObjectLiteralExpression(init)) scan(init, within);
84
+ else for (const el of init.elements) scanValue(undefined, el, within);
51
85
  return;
52
86
  }
53
87
  if (!key || !SECRET_FIELDS.has(key)) return;
88
+ const only = SECRET_ONLY_IN[key];
89
+ if (only && integration !== undefined && integration !== only) return;
54
90
  const text = literalText(init);
55
91
  if (text === undefined || text === "") return;
56
92
  diagnostics.push({
@@ -62,10 +98,11 @@ export const literalCredentialRule: LintRule = {
62
98
  });
63
99
  };
64
100
 
65
- const scan = (obj: ts.ObjectLiteralExpression) => {
101
+ const scan = (obj: ts.ObjectLiteralExpression, integration?: string) => {
66
102
  for (const prop of obj.properties) {
67
- if (!ts.isPropertyAssignment(prop)) continue;
68
- scanValue(propertyName(prop), prop.initializer);
103
+ if (ts.isPropertyAssignment(prop)) scanValue(propertyName(prop), prop.initializer, integration);
104
+ else if (ts.isShorthandPropertyAssignment(prop)) scanValue(prop.name.text, prop.name, integration);
105
+ else if (ts.isSpreadAssignment(prop)) scanValue(undefined, prop.expression, integration);
69
106
  }
70
107
  };
71
108
 
@@ -73,7 +110,7 @@ export const literalCredentialRule: LintRule = {
73
110
  if (ts.isNewExpression(node) || ts.isCallExpression(node)) {
74
111
  const name = calleeName(node);
75
112
  const arg = node.arguments?.[0];
76
- if (name && CREDENTIAL_CLASS.test(name) && arg && ts.isObjectLiteralExpression(arg)) scan(arg);
113
+ if (name && CREDENTIAL_CLASS.test(name) && arg) scanValue(undefined, arg);
77
114
  }
78
115
  ts.forEachChild(node, visit);
79
116
  };
@@ -28,3 +28,39 @@ export function position(source: ts.SourceFile, node: ts.Node): { line: number;
28
28
  const { line, character } = source.getLineAndCharacterOfPosition(node.getStart(source));
29
29
  return { line: line + 1, column: character + 1 };
30
30
  }
31
+
32
+ /**
33
+ * Every `const name = <initializer>` in the file, so a rule can follow a
34
+ * value lifted out of a constructor into a named const (the way COR001 asks
35
+ * for it, and the way `chant import` writes it) back to its literal.
36
+ */
37
+ export function constInitializers(source: ts.SourceFile): Map<string, ts.Expression> {
38
+ const consts = new Map<string, ts.Expression>();
39
+ const collect = (node: ts.Node) => {
40
+ if (ts.isVariableDeclarationList(node) && node.flags & ts.NodeFlags.Const) {
41
+ for (const d of node.declarations) {
42
+ if (ts.isIdentifier(d.name) && d.initializer) consts.set(d.name.text, d.initializer);
43
+ }
44
+ }
45
+ ts.forEachChild(node, collect);
46
+ };
47
+ collect(source);
48
+ return consts;
49
+ }
50
+
51
+ /** `expr` itself, or the initializer of the const it names (followed through `as` and `satisfies`). */
52
+ export function resolveConst(expr: ts.Expression, consts: Map<string, ts.Expression>): ts.Expression {
53
+ let cur = expr;
54
+ for (let hops = 0; hops < 8; hops++) {
55
+ if (ts.isAsExpression(cur) || ts.isSatisfiesExpression(cur) || ts.isParenthesizedExpression(cur)) {
56
+ cur = cur.expression;
57
+ continue;
58
+ }
59
+ if (ts.isIdentifier(cur) && consts.has(cur.text)) {
60
+ cur = consts.get(cur.text)!;
61
+ continue;
62
+ }
63
+ break;
64
+ }
65
+ return cur;
66
+ }
@@ -1,6 +1,6 @@
1
1
  import * as ts from "typescript";
2
2
  import type { LintRule, LintDiagnostic, LintContext } from "@intentius/chant/lint/rule";
3
- import { calleeName, literalText, position, propertyName } from "./prom-ast";
3
+ import { calleeName, constInitializers, literalText, position, propertyName, resolveConst } from "./prom-ast";
4
4
  import { checkPromql } from "../../promql";
5
5
 
6
6
  /**
@@ -21,7 +21,21 @@ export const promqlLiteralRule: LintRule = {
21
21
  const diagnostics: LintDiagnostic[] = [];
22
22
  const source = context.sourceFile;
23
23
 
24
+ const consts = constInitializers(source);
25
+ const scanned = new Set<ts.Node>();
26
+
27
+ // Rules lifted into a const (`rules: apiRules`) are followed to it and
28
+ // checked where the group uses them.
29
+ const follow = (value: ts.Expression) => {
30
+ const init = resolveConst(value, consts);
31
+ if (init !== value && !scanned.has(init)) {
32
+ scanned.add(init);
33
+ scan(init);
34
+ }
35
+ };
24
36
  const scan = (node: ts.Node) => {
37
+ if (ts.isShorthandPropertyAssignment(node)) follow(node.name);
38
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.initializer)) follow(node.initializer);
25
39
  if (ts.isPropertyAssignment(node) && propertyName(node) === "expr") {
26
40
  const text = literalText(node.initializer);
27
41
  if (text !== undefined) {
@@ -47,6 +47,10 @@ export const pageMutesTicket = new InhibitRule({
47
47
  });
48
48
  ```
49
49
 
50
+ ## Starting from an existing alertmanager.yml
51
+
52
+ Import it rather than retyping it: `chant import alertmanager.yml --output src` (with `--lexicon prometheus` outside a chant project). The importer writes `receivers.ts`, `time-intervals.ts`, `routes.ts` (the root `Route`, children as `RouteProps` that reference receivers and time intervals by variable), `inhibit-rules.ts` and `settings.ts`. `*_file` paths and Go templates are kept as written; a literal credential is imported as found and PROM001 reports it, so offer to move it to the `*_file` field. Every integration comes back typed (`OpsGenieConfig[]`, `MSTeamsV2Config[]`, ...); a receiver or `global` key Alertmanager doesn't define is spread in from an untyped const, with a warning. `match`/`match_re` and the top-level `mute_time_intervals` come back in their current spelling (`matchers`, `time_intervals`), and `chant import` prints a warning for each.
53
+
50
54
  ## What the checks hold you to
51
55
 
52
56
  - One root route (the `Route` no other route nests), with a receiver and no matchers (PROM205).
@@ -15,6 +15,17 @@ The prometheus lexicon (`@intentius/chant-lexicon-prometheus`) types Prometheus
15
15
  export default { lexicons: ["prometheus"] };
16
16
  ```
17
17
 
18
+ ## Starting from an existing rule file
19
+
20
+ When the user already has a rule file, import it rather than retyping it:
21
+
22
+ ```bash
23
+ chant import rules.yml --output src # add --lexicon prometheus outside a chant project
24
+ chant build src --lexicon prometheus -o rules.yml # the same groups back
25
+ ```
26
+
27
+ The importer writes `rules.ts` (per group, a `Rule[]` const of plain objects and a `RuleGroup`) and `slos.ts` for any group an `Slo()` built, as the `Slo` call. Multi-line expressions become template literals and Go templates in annotations stay as written. Read the warnings `chant import` prints: they name any field Prometheus doesn't define, which is not carried.
28
+
18
29
  ## Declaring a group
19
30
 
20
31
  A group takes the rule file's own keys (`name`, `interval`, `query_offset`, `limit`, `labels`, `rules`). Rules are plain objects: `record` + `expr` for a recording rule, `alert` + `expr` (+ `for`, `keep_firing_for`, `labels`, `annotations`) for an alerting rule.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-prometheus",
3
- "version": "0.97.0",
3
+ "version": "0.99.0",
4
4
  "description": "Prometheus lexicon for chant — typed recording and alerting rule groups and Alertmanager routing, serialized to a rule file and alertmanager.yml",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -71,7 +71,7 @@
71
71
  "typescript": "^5.9.3"
72
72
  },
73
73
  "peerDependencies": {
74
- "@intentius/chant": "^0.97.0",
74
+ "@intentius/chant": "^0.99.0",
75
75
  "typescript": "^5.9.3"
76
76
  }
77
77
  }
@@ -16,6 +16,7 @@ import { createResource } from "@intentius/chant/runtime";
16
16
  import type { Declarable } from "@intentius/chant/declarable";
17
17
  import type {
18
18
  AlertmanagerGlobalConfig,
19
+ AlertmanagerTracingConfig,
19
20
  InhibitRuleConfig,
20
21
  ReceiverConfig,
21
22
  RouteConfig,
@@ -112,13 +113,15 @@ export interface AlertmanagerSettingsProps {
112
113
  global?: AlertmanagerGlobalConfig;
113
114
  /** Paths of notification template files. */
114
115
  templates?: string[];
116
+ /** Where Alertmanager sends its own traces. */
117
+ tracing?: AlertmanagerTracingConfig;
115
118
  }
116
119
 
117
120
  export interface AlertmanagerSettingsEntity extends Declarable {
118
121
  readonly props: AlertmanagerSettingsProps;
119
122
  }
120
123
 
121
- /** The `global:` block and `templates:` list. Optional; declare at most one. */
124
+ /** The `global:` block, `templates:` list and `tracing:` block. Optional; declare at most one. */
122
125
  export const AlertmanagerSettings = entityClass<AlertmanagerSettingsProps, AlertmanagerSettingsEntity>(
123
126
  SETTINGS_TYPE,
124
127
  "AlertmanagerSettings",
package/src/build.ts CHANGED
@@ -109,6 +109,7 @@ function routeConfig(route: RouteEntity | RouteProps): RouteConfig {
109
109
  if (p.repeat_interval !== undefined) out.repeat_interval = p.repeat_interval;
110
110
  if (p.mute_time_intervals !== undefined) out.mute_time_intervals = p.mute_time_intervals.map(intervalName);
111
111
  if (p.active_time_intervals !== undefined) out.active_time_intervals = p.active_time_intervals.map(intervalName);
112
+ if (p.labels !== undefined) out.labels = { ...p.labels };
112
113
  if (p.routes !== undefined) out.routes = p.routes.map(routeConfig);
113
114
  return out;
114
115
  }
@@ -177,6 +178,7 @@ export function buildAlertmanagerConfig(entities: Iterable<Declarable> | Map<str
177
178
  intervals.sort((a, b) => byName(a.props.name, b.props.name));
178
179
  if (receivers.length > 0) config.receivers = receivers.map((r) => plain(r.props) as ReceiverConfig);
179
180
  if (intervals.length > 0) config.time_intervals = intervals.map((t) => plain(t.props) as TimeIntervalConfig);
181
+ if (settings?.props.tracing) config.tracing = plain(settings.props.tracing) as AlertmanagerConfig["tracing"];
180
182
 
181
183
  return { config, warnings, count };
182
184
  }
@@ -47,6 +47,10 @@ group names (PROM101), valid durations (PROM103), routes that name
47
47
  declared receivers (PROM201), and every alert severity routed by some route
48
48
  (PROM202). \`promtool check rules\` and \`amtool check-config\` are wrapped as
49
49
  helpers for tests and CI, and run when installed.
50
+
51
+ \`chant import\` turns an existing rule file or \`alertmanager.yml\` into this
52
+ TypeScript, and \`chant build\` on the result gives the file back (see
53
+ Importing Rule Files and alertmanager.yml).
50
54
  `;
51
55
 
52
56
  const outputFormat = `The prometheus lexicon serializes two files:
@@ -58,7 +62,7 @@ const outputFormat = `The prometheus lexicon serializes two files:
58
62
  - **\`alertmanager.yml\`**, from the \`AlertmanagerSettings\`, \`Route\`,
59
63
  \`InhibitRule\`, \`Receiver\` and \`TimeInterval\` entities, in that section
60
64
  order: \`global\`, \`templates\`, \`route\`, \`inhibit_rules\`, \`receivers\`,
61
- \`time_intervals\`.
65
+ \`time_intervals\`, \`tracing\`.
62
66
 
63
67
  The rule file is the primary output when the build declares any rule
64
68
  groups, and \`alertmanager.yml\` is written beside it (\`-o dist/rules.yml\`