@griffin-app/griffin-cli 1.0.18 → 1.0.19
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 +183 -196
- package/dist/commands/env.d.ts +3 -3
- package/dist/commands/env.js +28 -45
- package/dist/commands/hub/apply.d.ts +1 -1
- package/dist/commands/hub/apply.js +54 -95
- package/dist/commands/hub/connect.d.ts +1 -1
- package/dist/commands/hub/connect.js +2 -6
- package/dist/commands/hub/destroy.d.ts +10 -0
- package/dist/commands/hub/destroy.js +141 -0
- package/dist/commands/hub/integrations.d.ts +9 -9
- package/dist/commands/hub/integrations.js +104 -115
- package/dist/commands/hub/login.js +3 -0
- package/dist/commands/hub/metrics.d.ts +2 -2
- package/dist/commands/hub/metrics.js +41 -69
- package/dist/commands/hub/monitor.d.ts +1 -1
- package/dist/commands/hub/monitor.js +30 -70
- package/dist/commands/hub/notifications.d.ts +3 -3
- package/dist/commands/hub/notifications.js +61 -89
- package/dist/commands/hub/run.d.ts +1 -1
- package/dist/commands/hub/run.js +118 -144
- package/dist/commands/hub/runs.d.ts +1 -1
- package/dist/commands/hub/runs.js +60 -81
- package/dist/commands/hub/secrets.d.ts +8 -8
- package/dist/commands/hub/secrets.js +88 -148
- package/dist/commands/hub/status.d.ts +1 -1
- package/dist/commands/hub/status.js +13 -26
- package/dist/commands/init.js +3 -3
- package/dist/commands/local/run.d.ts +2 -2
- package/dist/commands/local/run.js +37 -42
- package/dist/commands/validate.d.ts +1 -1
- package/dist/commands/validate.js +19 -39
- package/dist/commands/variables.d.ts +3 -3
- package/dist/commands/variables.js +51 -69
- package/dist/core/discovery.js +0 -2
- package/dist/core/monitor-helpers.d.ts +19 -0
- package/dist/core/monitor-helpers.js +48 -0
- package/dist/core/sdk.d.ts +5 -0
- package/dist/core/sdk.js +11 -0
- package/dist/core/state.d.ts +1 -1
- package/dist/core/state.js +0 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/utils/command-wrapper.d.ts +10 -0
- package/dist/utils/command-wrapper.js +27 -0
- package/dist/utils/sdk-error.js +1 -1
- package/dist/utils/terminal.d.ts +4 -0
- package/dist/utils/terminal.js +17 -0
- package/package.json +1 -1
|
@@ -1,107 +1,66 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { discoverMonitors, formatDiscoveryErrors, } from "../../core/discovery.js";
|
|
1
|
+
import { resolveEnvironment } from "../../core/state.js";
|
|
3
2
|
import { computeDiff, formatDiff } from "../../core/diff.js";
|
|
4
3
|
import { applyDiff, formatApplyResult } from "../../core/apply.js";
|
|
5
|
-
import {
|
|
4
|
+
import { createSdkAndState } from "../../core/sdk.js";
|
|
6
5
|
import { terminal } from "../../utils/terminal.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { resolveMonitor } from "../../resolve.js";
|
|
6
|
+
import { withCommandErrorHandler } from "../../utils/command-wrapper.js";
|
|
7
|
+
import { discoverLocalMonitors, fetchRemoteMonitors, resolveLocalMonitors, } from "../../core/monitor-helpers.js";
|
|
10
8
|
/**
|
|
11
9
|
* Apply changes to the hub
|
|
12
10
|
*/
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
spinner.succeed(`Found ${monitors.length} local monitor(s)`);
|
|
44
|
-
// Fetch remote monitors for this project + environment
|
|
45
|
-
const fetchSpinner = terminal
|
|
46
|
-
.spinner("Fetching remote monitors...")
|
|
47
|
-
.start();
|
|
48
|
-
const response = await withSDKErrorHandling(() => sdk.getMonitor({
|
|
49
|
-
query: {
|
|
50
|
-
projectId: state.projectId,
|
|
51
|
-
environment: envName,
|
|
52
|
-
},
|
|
53
|
-
}), "Failed to fetch remote monitors");
|
|
54
|
-
const remoteMonitors = response?.data?.data;
|
|
55
|
-
fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
|
|
56
|
-
// Load variables and resolve local monitors before computing diff
|
|
57
|
-
const variables = await loadVariables(envName);
|
|
58
|
-
const resolvedMonitors = monitors.map((p) => resolveMonitor(p.monitor, state.projectId, envName, variables));
|
|
59
|
-
// Compute diff (include deletions if --prune)
|
|
60
|
-
const diff = computeDiff(resolvedMonitors, remoteMonitors, {
|
|
61
|
-
includeDeletions: options.prune || false,
|
|
62
|
-
});
|
|
63
|
-
// Show monitor
|
|
64
|
-
terminal.blank();
|
|
65
|
-
terminal.log(formatDiff(diff));
|
|
11
|
+
export const executeApply = withCommandErrorHandler(async (options) => {
|
|
12
|
+
const { sdk, state } = await createSdkAndState();
|
|
13
|
+
// Resolve environment
|
|
14
|
+
const envName = await resolveEnvironment(options.env);
|
|
15
|
+
terminal.info(`Applying to ${terminal.colors.cyan(envName)} environment`);
|
|
16
|
+
terminal.blank();
|
|
17
|
+
// Discover local monitors
|
|
18
|
+
const { monitors } = await discoverLocalMonitors(state);
|
|
19
|
+
// Fetch remote monitors for this project + environment
|
|
20
|
+
const remoteMonitors = await fetchRemoteMonitors(sdk, state.projectId, envName);
|
|
21
|
+
// Load variables and resolve local monitors before computing diff
|
|
22
|
+
const resolvedMonitors = await resolveLocalMonitors(monitors, state.projectId, envName);
|
|
23
|
+
// Compute diff (include deletions if --prune)
|
|
24
|
+
const diff = computeDiff(resolvedMonitors, remoteMonitors, {
|
|
25
|
+
includeDeletions: options.prune || false,
|
|
26
|
+
});
|
|
27
|
+
// Show monitor
|
|
28
|
+
terminal.blank();
|
|
29
|
+
terminal.log(formatDiff(diff));
|
|
30
|
+
terminal.blank();
|
|
31
|
+
// Check if there are changes
|
|
32
|
+
if (diff.summary.creates + diff.summary.updates + diff.summary.deletes ===
|
|
33
|
+
0) {
|
|
34
|
+
terminal.success("No changes to apply.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Show deletions warning if --prune
|
|
38
|
+
if (options.prune && diff.summary.deletes > 0) {
|
|
39
|
+
terminal.warn(`--prune will DELETE ${diff.summary.deletes} monitor(s) from the hub`);
|
|
66
40
|
terminal.blank();
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
41
|
+
}
|
|
42
|
+
// Ask for confirmation unless auto-approved
|
|
43
|
+
if (!options.autoApprove && !options.dryRun) {
|
|
44
|
+
const confirmed = await terminal.confirm("Do you want to perform these actions?");
|
|
45
|
+
if (!confirmed) {
|
|
46
|
+
terminal.warn("Apply cancelled.");
|
|
71
47
|
return;
|
|
72
48
|
}
|
|
73
|
-
// Show deletions warning if --prune
|
|
74
|
-
if (options.prune && diff.summary.deletes > 0) {
|
|
75
|
-
terminal.warn(`--prune will DELETE ${diff.summary.deletes} monitor(s) from the hub`);
|
|
76
|
-
terminal.blank();
|
|
77
|
-
}
|
|
78
|
-
// Ask for confirmation unless auto-approved
|
|
79
|
-
if (!options.autoApprove && !options.dryRun) {
|
|
80
|
-
const confirmed = await terminal.confirm("Do you want to perform these actions?");
|
|
81
|
-
if (!confirmed) {
|
|
82
|
-
terminal.warn("Apply cancelled.");
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// Apply changes with environment injection
|
|
87
|
-
const applySpinner = terminal.spinner("Applying changes...").start();
|
|
88
|
-
const result = await applyDiff(diff, sdk, {
|
|
89
|
-
dryRun: options.dryRun,
|
|
90
|
-
});
|
|
91
|
-
if (result.success) {
|
|
92
|
-
applySpinner.succeed("Changes applied successfully");
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
applySpinner.fail("Apply failed");
|
|
96
|
-
}
|
|
97
|
-
terminal.blank();
|
|
98
|
-
terminal.log(formatApplyResult(result));
|
|
99
|
-
if (!result.success) {
|
|
100
|
-
terminal.exit(1);
|
|
101
|
-
}
|
|
102
49
|
}
|
|
103
|
-
|
|
104
|
-
|
|
50
|
+
// Apply changes with environment injection
|
|
51
|
+
const applySpinner = terminal.spinner("Applying changes...").start();
|
|
52
|
+
const result = await applyDiff(diff, sdk, {
|
|
53
|
+
dryRun: options.dryRun,
|
|
54
|
+
});
|
|
55
|
+
if (result.success) {
|
|
56
|
+
applySpinner.succeed("Changes applied successfully");
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
applySpinner.fail("Apply failed");
|
|
60
|
+
}
|
|
61
|
+
terminal.blank();
|
|
62
|
+
terminal.log(formatApplyResult(result));
|
|
63
|
+
if (!result.success) {
|
|
105
64
|
terminal.exit(1);
|
|
106
65
|
}
|
|
107
|
-
}
|
|
66
|
+
});
|
|
@@ -9,9 +9,7 @@ export async function executeConnect(options) {
|
|
|
9
9
|
try {
|
|
10
10
|
const state = await loadState();
|
|
11
11
|
// Save token to user-level credentials file if provided
|
|
12
|
-
|
|
13
|
-
await saveHubCredentials(options.token);
|
|
14
|
-
}
|
|
12
|
+
await saveHubCredentials(options.token);
|
|
15
13
|
// Update hub config in project state (without token)
|
|
16
14
|
state.hub = {
|
|
17
15
|
baseUrl: options.url,
|
|
@@ -20,9 +18,7 @@ export async function executeConnect(options) {
|
|
|
20
18
|
await saveState(state);
|
|
21
19
|
terminal.success("Hub connection configured");
|
|
22
20
|
terminal.log(` URL: ${terminal.colors.cyan(options.url)}`);
|
|
23
|
-
|
|
24
|
-
terminal.log(` API Token: ${terminal.colors.dim("***")} (saved to user credentials)`);
|
|
25
|
-
}
|
|
21
|
+
terminal.log(` API Token: ${terminal.colors.dim("***")} (saved to user credentials)`);
|
|
26
22
|
terminal.blank();
|
|
27
23
|
}
|
|
28
24
|
catch (error) {
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { loadState, resolveEnvironment } from "../../core/state.js";
|
|
2
|
+
import { createSdkWithCredentials } from "../../core/sdk.js";
|
|
3
|
+
import { terminal } from "../../utils/terminal.js";
|
|
4
|
+
import { withSDKErrorHandling } from "../../utils/sdk-error.js";
|
|
5
|
+
/**
|
|
6
|
+
* Destroy monitors on the hub
|
|
7
|
+
*/
|
|
8
|
+
export async function executeDestroy(options) {
|
|
9
|
+
try {
|
|
10
|
+
// Load state
|
|
11
|
+
const state = await loadState();
|
|
12
|
+
// Resolve environment
|
|
13
|
+
const envName = await resolveEnvironment(options.env);
|
|
14
|
+
// Check if hub is configured
|
|
15
|
+
if (!state.hub?.baseUrl) {
|
|
16
|
+
terminal.error("Hub connection not configured.");
|
|
17
|
+
terminal.dim("Connect with:");
|
|
18
|
+
terminal.dim(" griffin hub connect --url <url> --token <token>");
|
|
19
|
+
terminal.exit(1);
|
|
20
|
+
}
|
|
21
|
+
terminal.info(`Destroying monitors in ${terminal.colors.cyan(envName)} environment`);
|
|
22
|
+
terminal.blank();
|
|
23
|
+
// Create SDK client with credentials
|
|
24
|
+
const sdk = await createSdkWithCredentials(state.hub.baseUrl);
|
|
25
|
+
// Fetch remote monitors for this project + environment
|
|
26
|
+
const fetchSpinner = terminal
|
|
27
|
+
.spinner("Fetching remote monitors...")
|
|
28
|
+
.start();
|
|
29
|
+
const response = await withSDKErrorHandling(() => sdk.getMonitor({
|
|
30
|
+
query: {
|
|
31
|
+
projectId: state.projectId,
|
|
32
|
+
environment: envName,
|
|
33
|
+
},
|
|
34
|
+
}), "Failed to fetch remote monitors");
|
|
35
|
+
const remoteMonitors = response?.data?.data;
|
|
36
|
+
fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
|
|
37
|
+
if (remoteMonitors.length === 0) {
|
|
38
|
+
terminal.success("No monitors to destroy.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Filter monitors if --monitor option is provided
|
|
42
|
+
let monitorsToDestroy = remoteMonitors;
|
|
43
|
+
if (options.monitor) {
|
|
44
|
+
const targetMonitor = remoteMonitors.find((m) => m.name === options.monitor || m.id === options.monitor);
|
|
45
|
+
if (!targetMonitor) {
|
|
46
|
+
terminal.error(`Monitor "${options.monitor}" not found in ${envName} environment`);
|
|
47
|
+
terminal.blank();
|
|
48
|
+
terminal.dim("Available monitors:");
|
|
49
|
+
remoteMonitors.forEach((m) => {
|
|
50
|
+
terminal.dim(` - ${m.name} (${m.id})`);
|
|
51
|
+
});
|
|
52
|
+
terminal.exit(1);
|
|
53
|
+
return; // TypeScript doesn't know exit(1) terminates
|
|
54
|
+
}
|
|
55
|
+
monitorsToDestroy = [targetMonitor];
|
|
56
|
+
}
|
|
57
|
+
// Show what will be destroyed
|
|
58
|
+
terminal.blank();
|
|
59
|
+
terminal.warn(`The following ${monitorsToDestroy.length} monitor(s) will be DESTROYED:`);
|
|
60
|
+
terminal.blank();
|
|
61
|
+
monitorsToDestroy.forEach((monitor) => {
|
|
62
|
+
terminal.log(` ${terminal.colors.red("-")} ${monitor.name} (${monitor.id})`);
|
|
63
|
+
});
|
|
64
|
+
terminal.blank();
|
|
65
|
+
// Show dry run message if applicable
|
|
66
|
+
if (options.dryRun) {
|
|
67
|
+
terminal.info("[DRY RUN] No changes will be made");
|
|
68
|
+
terminal.blank();
|
|
69
|
+
terminal.log("Summary:");
|
|
70
|
+
terminal.log(` Would destroy: ${monitorsToDestroy.length} monitor(s)`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Ask for confirmation unless auto-approved
|
|
74
|
+
if (!options.autoApprove) {
|
|
75
|
+
terminal.blank();
|
|
76
|
+
terminal.warn(terminal.colors.bold("This action is DESTRUCTIVE and cannot be undone!"));
|
|
77
|
+
terminal.blank();
|
|
78
|
+
const confirmed = await terminal.confirm("Do you really want to destroy these monitors?");
|
|
79
|
+
if (!confirmed) {
|
|
80
|
+
terminal.warn("Destroy cancelled.");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// Double confirmation for destroying all monitors
|
|
84
|
+
if (!options.monitor && monitorsToDestroy.length > 1) {
|
|
85
|
+
terminal.blank();
|
|
86
|
+
const doubleConfirmed = await terminal.confirm(`Type 'yes' to confirm destroying ALL ${monitorsToDestroy.length} monitors`);
|
|
87
|
+
if (!doubleConfirmed) {
|
|
88
|
+
terminal.warn("Destroy cancelled.");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Destroy monitors
|
|
94
|
+
terminal.blank();
|
|
95
|
+
const destroySpinner = terminal.spinner("Destroying monitors...").start();
|
|
96
|
+
let successCount = 0;
|
|
97
|
+
let failureCount = 0;
|
|
98
|
+
const errors = [];
|
|
99
|
+
for (const monitor of monitorsToDestroy) {
|
|
100
|
+
try {
|
|
101
|
+
await withSDKErrorHandling(() => sdk.deleteMonitorById({
|
|
102
|
+
path: {
|
|
103
|
+
id: monitor.id,
|
|
104
|
+
},
|
|
105
|
+
}), `Failed to delete monitor "${monitor.name}"`);
|
|
106
|
+
successCount++;
|
|
107
|
+
terminal.success(`Destroyed: ${terminal.colors.cyan(monitor.name)}`);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
failureCount++;
|
|
111
|
+
const errorMessage = error.message;
|
|
112
|
+
errors.push({ monitor, error: errorMessage });
|
|
113
|
+
terminal.error(`Failed to destroy: ${monitor.name} - ${errorMessage}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (failureCount === 0) {
|
|
117
|
+
destroySpinner.succeed("All monitors destroyed successfully");
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
destroySpinner.fail("Some monitors failed to destroy");
|
|
121
|
+
}
|
|
122
|
+
// Show summary
|
|
123
|
+
terminal.blank();
|
|
124
|
+
terminal.log("Destroy complete:");
|
|
125
|
+
terminal.blank();
|
|
126
|
+
terminal.log(` ${terminal.colors.green("✓")} Destroyed: ${successCount}`);
|
|
127
|
+
if (failureCount > 0) {
|
|
128
|
+
terminal.log(` ${terminal.colors.red("✗")} Failed: ${failureCount}`);
|
|
129
|
+
terminal.blank();
|
|
130
|
+
terminal.error("Errors:");
|
|
131
|
+
errors.forEach(({ monitor, error }) => {
|
|
132
|
+
terminal.error(` - ${monitor.name}: ${error}`);
|
|
133
|
+
});
|
|
134
|
+
terminal.exit(1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
terminal.error(error.message);
|
|
139
|
+
terminal.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -2,45 +2,45 @@ import type { IntegrationCategory, Provider } from "@griffin-app/griffin-ts/type
|
|
|
2
2
|
export interface IntegrationsListOptions {
|
|
3
3
|
category?: IntegrationCategory;
|
|
4
4
|
provider?: Provider;
|
|
5
|
-
environment
|
|
5
|
+
environment: string;
|
|
6
6
|
enabled?: boolean;
|
|
7
7
|
json?: boolean;
|
|
8
8
|
}
|
|
9
|
-
export declare
|
|
9
|
+
export declare const executeIntegrationsList: (options: IntegrationsListOptions) => Promise<void>;
|
|
10
10
|
export interface IntegrationsShowOptions {
|
|
11
11
|
id: string;
|
|
12
12
|
json?: boolean;
|
|
13
13
|
}
|
|
14
|
-
export declare
|
|
14
|
+
export declare const executeIntegrationsShow: (options: IntegrationsShowOptions) => Promise<void>;
|
|
15
15
|
export interface IntegrationsAddOptions {
|
|
16
16
|
category: IntegrationCategory;
|
|
17
17
|
provider: Provider;
|
|
18
18
|
name: string;
|
|
19
19
|
config?: Record<string, string>;
|
|
20
|
-
environment
|
|
20
|
+
environment: string;
|
|
21
21
|
enabled?: boolean;
|
|
22
22
|
json?: boolean;
|
|
23
23
|
}
|
|
24
|
-
export declare
|
|
24
|
+
export declare const executeIntegrationsAdd: (options: IntegrationsAddOptions) => Promise<void>;
|
|
25
25
|
export interface IntegrationsUpdateOptions {
|
|
26
26
|
id: string;
|
|
27
27
|
name?: string;
|
|
28
28
|
config?: Record<string, string>;
|
|
29
|
-
environment
|
|
29
|
+
environment: string;
|
|
30
30
|
enabled?: boolean;
|
|
31
31
|
json?: boolean;
|
|
32
32
|
}
|
|
33
|
-
export declare
|
|
33
|
+
export declare const executeIntegrationsUpdate: (options: IntegrationsUpdateOptions) => Promise<void>;
|
|
34
34
|
export interface IntegrationsRemoveOptions {
|
|
35
35
|
id: string;
|
|
36
36
|
force?: boolean;
|
|
37
37
|
}
|
|
38
|
-
export declare
|
|
38
|
+
export declare const executeIntegrationsRemove: (options: IntegrationsRemoveOptions) => Promise<void>;
|
|
39
39
|
export interface IntegrationsConnectOptions {
|
|
40
40
|
category: IntegrationCategory;
|
|
41
41
|
provider: Provider;
|
|
42
42
|
name?: string;
|
|
43
|
-
environment
|
|
43
|
+
environment: string;
|
|
44
44
|
json?: boolean;
|
|
45
45
|
}
|
|
46
46
|
export declare function printConnectHelp(): void;
|