@griffin-app/griffin-cli 1.0.12 → 1.0.13
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 +6 -4
- package/dist/commands/hub/integrations.d.ts +1 -1
- package/dist/commands/hub/integrations.js +1 -1
- package/dist/commands/hub/notifications.d.ts +4 -2
- package/dist/commands/hub/notifications.js +98 -3
- package/dist/commands/init.js +1 -1
- package/dist/core/apply.test.js +1 -0
- package/dist/core/diff.test.js +2 -0
- package/dist/core/monitor-diff.js +15 -0
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command } from "commander";
|
|
|
3
3
|
import { executeInit } from "./commands/init.js";
|
|
4
4
|
import { executeValidate } from "./commands/validate.js";
|
|
5
5
|
import { executeGenerateKey } from "./commands/generate-key.js";
|
|
6
|
-
import { executeEnvList, executeEnvAdd, executeEnvRemove } from "./commands/env.js";
|
|
6
|
+
import { executeEnvList, executeEnvAdd, executeEnvRemove, } from "./commands/env.js";
|
|
7
7
|
import { executeVariablesList, executeVariablesAdd, executeVariablesRemove, } from "./commands/variables.js";
|
|
8
8
|
// Local commands
|
|
9
9
|
import { executeRunLocal } from "./commands/local/run.js";
|
|
@@ -67,7 +67,9 @@ env
|
|
|
67
67
|
await executeEnvRemove(name);
|
|
68
68
|
});
|
|
69
69
|
// Variables command group
|
|
70
|
-
const variables = program
|
|
70
|
+
const variables = program
|
|
71
|
+
.command("variables")
|
|
72
|
+
.description("Manage environment variables");
|
|
71
73
|
variables
|
|
72
74
|
.command("list")
|
|
73
75
|
.description("List all variables for an environment")
|
|
@@ -192,8 +194,8 @@ notifications
|
|
|
192
194
|
});
|
|
193
195
|
notifications
|
|
194
196
|
.command("test")
|
|
195
|
-
.description("Send a test notification
|
|
196
|
-
.
|
|
197
|
+
.description("Send a test notification (interactive wizard, or use flags for scripts)")
|
|
198
|
+
.option("--integration <id|name>", "Integration id or name; omit to choose from a list")
|
|
197
199
|
.option("--channel <channel>", "Slack channel (e.g. #alerts); use with Slack integration")
|
|
198
200
|
.option("--to-addresses <emails>", "Email recipients, comma-separated; use with email integration")
|
|
199
201
|
.action(async (options) => {
|
|
@@ -39,7 +39,7 @@ export declare function executeIntegrationsRemove(options: IntegrationsRemoveOpt
|
|
|
39
39
|
export interface IntegrationsConnectOptions {
|
|
40
40
|
category: IntegrationCategory;
|
|
41
41
|
provider: Provider;
|
|
42
|
-
name
|
|
42
|
+
name?: string;
|
|
43
43
|
environment?: string;
|
|
44
44
|
json?: boolean;
|
|
45
45
|
}
|
|
@@ -166,7 +166,7 @@ async function connectOAuth(options, _provider) {
|
|
|
166
166
|
const body = {
|
|
167
167
|
category: options.category,
|
|
168
168
|
provider: options.provider,
|
|
169
|
-
name: options.name,
|
|
169
|
+
name: options.name ?? options.provider,
|
|
170
170
|
environment: options.environment ?? undefined,
|
|
171
171
|
};
|
|
172
172
|
const state = await loadState();
|
|
@@ -4,7 +4,8 @@ export interface NotificationsListOptions {
|
|
|
4
4
|
json?: boolean;
|
|
5
5
|
}
|
|
6
6
|
export interface NotificationsTestOptions {
|
|
7
|
-
integration
|
|
7
|
+
/** Integration id or name. If omitted, wizard runs (select integration + provider options). */
|
|
8
|
+
integration?: string;
|
|
8
9
|
/** Slack channel (e.g. #alerts). Use with Slack integration. */
|
|
9
10
|
channel?: string;
|
|
10
11
|
/** Email recipients, comma-separated. Use with email integration. */
|
|
@@ -16,6 +17,7 @@ export interface NotificationsTestOptions {
|
|
|
16
17
|
*/
|
|
17
18
|
export declare function executeNotificationsList(options: NotificationsListOptions): Promise<void>;
|
|
18
19
|
/**
|
|
19
|
-
* Test a notification integration
|
|
20
|
+
* Test a notification integration. Without options, runs a wizard (select integration, then provider-specific prompts).
|
|
21
|
+
* With --integration and routing flags, runs non-interactively.
|
|
20
22
|
*/
|
|
21
23
|
export declare function executeNotificationsTest(options: NotificationsTestOptions): Promise<void>;
|
|
@@ -2,6 +2,14 @@ import { loadState } from "../../core/state.js";
|
|
|
2
2
|
import { createSdkWithCredentials } from "../../core/sdk.js";
|
|
3
3
|
import { terminal } from "../../utils/terminal.js";
|
|
4
4
|
import { withSDKErrorHandling } from "../../utils/sdk-error.js";
|
|
5
|
+
function orExit(value, errorMessage) {
|
|
6
|
+
if (value === undefined) {
|
|
7
|
+
terminal.error(errorMessage);
|
|
8
|
+
terminal.exit(1);
|
|
9
|
+
throw new Error(errorMessage);
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
5
13
|
/**
|
|
6
14
|
* List notification rules (read-only).
|
|
7
15
|
* Rules are defined in monitor DSL and synced via `griffin hub apply`.
|
|
@@ -55,6 +63,46 @@ export async function executeNotificationsList(options) {
|
|
|
55
63
|
terminal.exit(1);
|
|
56
64
|
}
|
|
57
65
|
}
|
|
66
|
+
async function fetchNotificationIntegrations(sdk) {
|
|
67
|
+
const result = await withSDKErrorHandling(() => sdk.getIntegrations({
|
|
68
|
+
query: { category: "notifications", enabled: true },
|
|
69
|
+
}), "Failed to fetch integrations");
|
|
70
|
+
const list = result?.data?.data ?? [];
|
|
71
|
+
return list
|
|
72
|
+
.filter((i) => i.category === "notifications")
|
|
73
|
+
.map((i) => ({
|
|
74
|
+
id: i.id,
|
|
75
|
+
name: i.name,
|
|
76
|
+
provider: i.provider,
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
function promptRoutingForProvider(provider) {
|
|
80
|
+
switch (provider) {
|
|
81
|
+
case "slack": {
|
|
82
|
+
return terminal
|
|
83
|
+
.input("Slack channel (e.g. #alerts)", "#alerts")
|
|
84
|
+
.then((value) => ({
|
|
85
|
+
provider: "slack",
|
|
86
|
+
channel: (value ?? "").trim() || "#alerts",
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
case "email": {
|
|
90
|
+
return terminal.input("To addresses (comma-separated)").then((value) => {
|
|
91
|
+
const toAddresses = (value ?? "")
|
|
92
|
+
.split(",")
|
|
93
|
+
.map((s) => s.trim())
|
|
94
|
+
.filter(Boolean);
|
|
95
|
+
if (toAddresses.length === 0) {
|
|
96
|
+
terminal.error("At least one email address is required.");
|
|
97
|
+
terminal.exit(1);
|
|
98
|
+
}
|
|
99
|
+
return { provider: "email", toAddresses };
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
default:
|
|
103
|
+
return Promise.resolve({ provider: "webhook" });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
58
106
|
/**
|
|
59
107
|
* Build routing object from CLI options. Exactly one of channel, toAddresses, or webhook (none) must be used.
|
|
60
108
|
*/
|
|
@@ -74,7 +122,43 @@ function buildRoutingFromOptions(options) {
|
|
|
74
122
|
return { provider: "webhook" };
|
|
75
123
|
}
|
|
76
124
|
/**
|
|
77
|
-
*
|
|
125
|
+
* Run interactive wizard: select integration, then prompt for provider-specific options (channel, to-addresses, or none).
|
|
126
|
+
*/
|
|
127
|
+
async function executeNotificationsTestWizard(sdk, options) {
|
|
128
|
+
const integrations = await fetchNotificationIntegrations(sdk);
|
|
129
|
+
if (integrations.length === 0) {
|
|
130
|
+
terminal.error("No notification integrations found.");
|
|
131
|
+
terminal.dim("Connect one with: griffin hub integrations connect notifications <provider>");
|
|
132
|
+
terminal.exit(1);
|
|
133
|
+
}
|
|
134
|
+
if (options.integration) {
|
|
135
|
+
const match = orExit(integrations.find((i) => i.id === options.integration ||
|
|
136
|
+
i.name.toLowerCase() === (options.integration ?? "").toLowerCase()), `Integration not found: ${options.integration}`);
|
|
137
|
+
const routing = await promptRoutingForProvider(match.provider);
|
|
138
|
+
return { integration: match.id, routing };
|
|
139
|
+
}
|
|
140
|
+
const choiceLabels = integrations.map((i) => `${i.name} (${i.provider})`);
|
|
141
|
+
const choice = await terminal.select("Select integration to test", choiceLabels);
|
|
142
|
+
const found = orExit(integrations.find((i) => `${i.name} (${i.provider})` === choice), "No integration selected.");
|
|
143
|
+
const routing = await promptRoutingForProvider(found.provider);
|
|
144
|
+
return { integration: found.id, routing };
|
|
145
|
+
}
|
|
146
|
+
function canBuildRoutingFromOptions(options) {
|
|
147
|
+
if (options.channel !== undefined && options.channel !== "")
|
|
148
|
+
return true;
|
|
149
|
+
if (options.toAddresses !== undefined && options.toAddresses !== "") {
|
|
150
|
+
const toAddresses = options.toAddresses
|
|
151
|
+
.split(",")
|
|
152
|
+
.map((s) => s.trim())
|
|
153
|
+
.filter(Boolean);
|
|
154
|
+
if (toAddresses.length > 0)
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Test a notification integration. Without options, runs a wizard (select integration, then provider-specific prompts).
|
|
161
|
+
* With --integration and routing flags, runs non-interactively.
|
|
78
162
|
*/
|
|
79
163
|
export async function executeNotificationsTest(options) {
|
|
80
164
|
try {
|
|
@@ -85,11 +169,22 @@ export async function executeNotificationsTest(options) {
|
|
|
85
169
|
terminal.dim(" griffin hub connect --url <url> --token <token>");
|
|
86
170
|
terminal.exit(1);
|
|
87
171
|
}
|
|
88
|
-
const routing = buildRoutingFromOptions(options);
|
|
89
172
|
const sdk = await createSdkWithCredentials(state.hub.baseUrl);
|
|
173
|
+
const useWizard = !options.integration || !canBuildRoutingFromOptions(options);
|
|
174
|
+
let integration;
|
|
175
|
+
let routing;
|
|
176
|
+
if (useWizard) {
|
|
177
|
+
const wizardResult = await executeNotificationsTestWizard(sdk, options);
|
|
178
|
+
integration = wizardResult.integration;
|
|
179
|
+
routing = wizardResult.routing;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
integration = options.integration;
|
|
183
|
+
routing = buildRoutingFromOptions(options);
|
|
184
|
+
}
|
|
90
185
|
const spinner = terminal.spinner("Sending test notification...").start();
|
|
91
186
|
const response = await withSDKErrorHandling(() => sdk.postNotificationsTest({
|
|
92
|
-
body: { integration
|
|
187
|
+
body: { integration, routing },
|
|
93
188
|
}), "Failed to send test notification");
|
|
94
189
|
spinner.stop();
|
|
95
190
|
const result = response?.data?.data;
|
package/dist/commands/init.js
CHANGED
package/dist/core/apply.test.js
CHANGED
package/dist/core/diff.test.js
CHANGED
|
@@ -11,6 +11,7 @@ function createMonitor(name, overrides) {
|
|
|
11
11
|
frequency: { every: 5, unit: "MINUTE" },
|
|
12
12
|
nodes: [],
|
|
13
13
|
edges: [],
|
|
14
|
+
notifications: [],
|
|
14
15
|
...overrides,
|
|
15
16
|
};
|
|
16
17
|
}
|
|
@@ -24,6 +25,7 @@ function createResolvedMonitor(name, overrides) {
|
|
|
24
25
|
frequency: { every: 5, unit: "MINUTE" },
|
|
25
26
|
nodes: [],
|
|
26
27
|
edges: [],
|
|
28
|
+
notifications: [],
|
|
27
29
|
...overrides,
|
|
28
30
|
};
|
|
29
31
|
}
|
|
@@ -247,6 +247,21 @@ function compareTopLevel(local, remote) {
|
|
|
247
247
|
newValue: localLocations,
|
|
248
248
|
});
|
|
249
249
|
}
|
|
250
|
+
// Compare notifications (normalize empty array to undefined)
|
|
251
|
+
const localNotifications = local.notifications && local.notifications.length > 0
|
|
252
|
+
? local.notifications
|
|
253
|
+
: undefined;
|
|
254
|
+
const remoteNotifications = remote.notifications && remote.notifications.length > 0
|
|
255
|
+
? remote.notifications
|
|
256
|
+
: undefined;
|
|
257
|
+
console.log("REMOTE NOTIFICATIONS", remoteNotifications);
|
|
258
|
+
if (!deepEqual(localNotifications, remoteNotifications)) {
|
|
259
|
+
changes.push({
|
|
260
|
+
field: "notifications",
|
|
261
|
+
oldValue: remoteNotifications,
|
|
262
|
+
newValue: localNotifications,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
250
265
|
return changes;
|
|
251
266
|
}
|
|
252
267
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griffin-app/griffin-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "CLI tool for running and managing griffin API tests",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"author": "",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@griffin-app/griffin-hub-sdk": "1.0.
|
|
27
|
+
"@griffin-app/griffin-hub-sdk": "1.0.16",
|
|
28
28
|
"@griffin-app/griffin-plan-executor": "0.1.19",
|
|
29
|
-
"@griffin-app/griffin-ts": "0.1.
|
|
29
|
+
"@griffin-app/griffin-ts": "0.1.18",
|
|
30
30
|
"better-auth": "^1.4.17",
|
|
31
31
|
"cli-table3": "^0.6.5",
|
|
32
32
|
"commander": "^12.1.0",
|