@griffin-app/griffin-cli 1.0.29 → 1.0.31
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/README.md +12 -12
- package/dist/cli.js +28 -21
- package/dist/commands/hub/destroy.js +9 -2
- package/dist/commands/hub/integrations.js +15 -4
- package/dist/commands/hub/metrics.js +1 -1
- package/dist/commands/hub/run.js +2 -1
- package/dist/commands/hub/secrets.js +2 -10
- package/dist/core/secrets.d.ts +8 -32
- package/dist/core/secrets.js +16 -88
- package/dist/monitor-runner.js +21 -8
- package/dist/utils/output.js +6 -1
- package/dist/utils/sdk-error.js +11 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -92,18 +92,18 @@ griffin metrics --env production --period 7d --json
|
|
|
92
92
|
|
|
93
93
|
Commands are **top-level** or under a **group**. The default environment is `default` unless overridden with `--env <name>` where supported.
|
|
94
94
|
|
|
95
|
-
| Area
|
|
96
|
-
|
|
97
|
-
| **Project**
|
|
98
|
-
| **Local run**
|
|
99
|
-
| **Hub sync**
|
|
100
|
-
| **Hub runs**
|
|
101
|
-
| **Auth**
|
|
102
|
-
| **Environments**
|
|
103
|
-
| **Variables**
|
|
104
|
-
| **Secrets**
|
|
105
|
-
| **Integrations**
|
|
106
|
-
| **Notifications** | `notifications list`, `notifications test`
|
|
95
|
+
| Area | Commands | Purpose |
|
|
96
|
+
| ----------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
|
|
97
|
+
| **Project** | `init`, `validate`, `status` | Bootstrap, validate monitors, show status |
|
|
98
|
+
| **Local run** | `test` | Run monitors locally |
|
|
99
|
+
| **Hub sync** | `plan`, `apply`, `destroy` | Preview changes, push to hub, remove from hub |
|
|
100
|
+
| **Hub runs** | `runs`, `run`, `metrics` | List runs, trigger run, view metrics |
|
|
101
|
+
| **Auth** | `auth login`, `auth logout`, `auth connect`, `auth generate-key` | Cloud or self-hosted auth |
|
|
102
|
+
| **Environments** | `env list`, `env add`, `env remove` | Manage environments |
|
|
103
|
+
| **Variables** | `variables list`, `variables add`, `variables remove` | Per-environment variables (in state) |
|
|
104
|
+
| **Secrets** | `secrets list`, `secrets set`, `secrets get`, `secrets delete` | Per-environment secrets (stored on hub) |
|
|
105
|
+
| **Integrations** | `integrations list`, `integrations show`, `integrations connect`, `integrations update`, `integrations remove` | Slack, email, webhooks, etc. |
|
|
106
|
+
| **Notifications** | `notifications list`, `notifications test` | Notification rules and test sends |
|
|
107
107
|
|
|
108
108
|
### Top-level commands
|
|
109
109
|
|
package/dist/cli.js
CHANGED
|
@@ -18,9 +18,9 @@ import { executeLogin } from "./commands/hub/login.js";
|
|
|
18
18
|
import { executeLogout } from "./commands/hub/logout.js";
|
|
19
19
|
import { executeIntegrationsConnect } from "./commands/hub/integrations.js";
|
|
20
20
|
import { executeNotificationsList, executeNotificationsTest, } from "./commands/hub/notifications.js";
|
|
21
|
-
import { executeSecretsList, executeSecretsSet,
|
|
21
|
+
import { executeSecretsList, executeSecretsSet, executeSecretsDelete, } from "./commands/hub/secrets.js";
|
|
22
22
|
import { executeIntegrationsList, executeIntegrationsShow, executeIntegrationsUpdate, executeIntegrationsRemove, } from "./commands/hub/integrations.js";
|
|
23
|
-
import packageInfo from
|
|
23
|
+
import packageInfo from "../package.json" with { type: "json" };
|
|
24
24
|
const program = new Command();
|
|
25
25
|
program
|
|
26
26
|
.name("griffin")
|
|
@@ -60,7 +60,11 @@ program
|
|
|
60
60
|
.option("--env <name>", "Environment name", "default")
|
|
61
61
|
.option("--json", "Output in JSON format")
|
|
62
62
|
.action(async (options) => {
|
|
63
|
-
await executePlan({
|
|
63
|
+
await executePlan({
|
|
64
|
+
...options,
|
|
65
|
+
env: options.env,
|
|
66
|
+
json: program.opts().json ?? options.json,
|
|
67
|
+
});
|
|
64
68
|
});
|
|
65
69
|
program
|
|
66
70
|
.command("apply")
|
|
@@ -70,7 +74,11 @@ program
|
|
|
70
74
|
.option("--dry-run", "Show what would be done without making changes")
|
|
71
75
|
.option("--prune", "Delete monitors on hub that don't exist locally")
|
|
72
76
|
.action(async (options) => {
|
|
73
|
-
await executeApply({
|
|
77
|
+
await executeApply({
|
|
78
|
+
...options,
|
|
79
|
+
env: options.env,
|
|
80
|
+
json: program.opts().json,
|
|
81
|
+
});
|
|
74
82
|
});
|
|
75
83
|
program
|
|
76
84
|
.command("runs")
|
|
@@ -94,7 +102,11 @@ program
|
|
|
94
102
|
.option("--wait", "Wait for run to complete")
|
|
95
103
|
.option("--force", "Run even if local monitor differs from hub")
|
|
96
104
|
.action(async (options) => {
|
|
97
|
-
await executeRun({
|
|
105
|
+
await executeRun({
|
|
106
|
+
...options,
|
|
107
|
+
env: options.env,
|
|
108
|
+
json: program.opts().json,
|
|
109
|
+
});
|
|
98
110
|
});
|
|
99
111
|
program
|
|
100
112
|
.command("metrics")
|
|
@@ -116,8 +128,8 @@ program
|
|
|
116
128
|
.option("--monitor <nameOrId>", "Specific monitor name or ID to destroy")
|
|
117
129
|
.option("--auto-approve", "Skip confirmation prompt")
|
|
118
130
|
.option("--dry-run", "Show what would be destroyed without making changes")
|
|
119
|
-
.action(async (
|
|
120
|
-
await executeDestroy({ ...options,
|
|
131
|
+
.action(async (options) => {
|
|
132
|
+
await executeDestroy({ ...options, json: program.opts().json });
|
|
121
133
|
});
|
|
122
134
|
// Auth command group
|
|
123
135
|
const auth = program.command("auth").description("Manage authentication");
|
|
@@ -234,18 +246,6 @@ secrets
|
|
|
234
246
|
json: program.opts().json,
|
|
235
247
|
});
|
|
236
248
|
});
|
|
237
|
-
secrets
|
|
238
|
-
.command("get <name>")
|
|
239
|
-
.description("Show secret metadata")
|
|
240
|
-
.option("--env <name>", "Environment name", "default")
|
|
241
|
-
.option("--json", "Output as JSON")
|
|
242
|
-
.action(async (name, options) => {
|
|
243
|
-
await executeSecretsGet({
|
|
244
|
-
name,
|
|
245
|
-
environment: options.env,
|
|
246
|
-
json: program.opts().json ?? options.json,
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
249
|
secrets
|
|
250
250
|
.command("delete <name>")
|
|
251
251
|
.description("Delete a secret")
|
|
@@ -285,7 +285,10 @@ integrations
|
|
|
285
285
|
.description("Show integration details")
|
|
286
286
|
.option("--json", "Output as JSON")
|
|
287
287
|
.action(async (id, options) => {
|
|
288
|
-
await executeIntegrationsShow({
|
|
288
|
+
await executeIntegrationsShow({
|
|
289
|
+
id,
|
|
290
|
+
json: program.opts().json ?? options.json,
|
|
291
|
+
});
|
|
289
292
|
});
|
|
290
293
|
integrations
|
|
291
294
|
.command("connect [type] [provider]")
|
|
@@ -323,7 +326,11 @@ integrations
|
|
|
323
326
|
.description("Remove an integration")
|
|
324
327
|
.option("--force", "Skip confirmation")
|
|
325
328
|
.action(async (id, options) => {
|
|
326
|
-
await executeIntegrationsRemove({
|
|
329
|
+
await executeIntegrationsRemove({
|
|
330
|
+
id,
|
|
331
|
+
force: options.force,
|
|
332
|
+
json: program.opts().json,
|
|
333
|
+
});
|
|
327
334
|
});
|
|
328
335
|
// Notifications command group
|
|
329
336
|
const notifications = program
|
|
@@ -35,7 +35,11 @@ export const executeDestroy = createCommandHandler("destroy", async (options, ou
|
|
|
35
35
|
const remoteMonitors = response.data?.data;
|
|
36
36
|
fetchSpinner.succeed(`Found ${remoteMonitors.length} remote monitor(s)`);
|
|
37
37
|
if (remoteMonitors.length === 0) {
|
|
38
|
-
output.setData({
|
|
38
|
+
output.setData({
|
|
39
|
+
destroyed: [],
|
|
40
|
+
total: 0,
|
|
41
|
+
dryRun: options.dryRun ?? false,
|
|
42
|
+
});
|
|
39
43
|
output.success("No monitors to destroy.");
|
|
40
44
|
return;
|
|
41
45
|
}
|
|
@@ -67,7 +71,10 @@ export const executeDestroy = createCommandHandler("destroy", async (options, ou
|
|
|
67
71
|
if (options.dryRun) {
|
|
68
72
|
output.setData({
|
|
69
73
|
dryRun: true,
|
|
70
|
-
wouldDestroy: monitorsToDestroy.map((m) => ({
|
|
74
|
+
wouldDestroy: monitorsToDestroy.map((m) => ({
|
|
75
|
+
id: m.id,
|
|
76
|
+
name: m.name,
|
|
77
|
+
})),
|
|
71
78
|
total: monitorsToDestroy.length,
|
|
72
79
|
});
|
|
73
80
|
output.info("[DRY RUN] No changes will be made");
|
|
@@ -56,7 +56,10 @@ export const executeIntegrationsShow = createCommandHandler("integrations show",
|
|
|
56
56
|
}
|
|
57
57
|
const raw = response.data?.data;
|
|
58
58
|
if (!raw) {
|
|
59
|
-
output.setData({
|
|
59
|
+
output.setData({
|
|
60
|
+
error: "NOT_FOUND",
|
|
61
|
+
message: "Integration not found.",
|
|
62
|
+
});
|
|
60
63
|
output.error("Integration not found.");
|
|
61
64
|
output.exit(1);
|
|
62
65
|
}
|
|
@@ -120,7 +123,10 @@ export const executeIntegrationsUpdate = createCommandHandler("integrations upda
|
|
|
120
123
|
}
|
|
121
124
|
const raw = response.data?.data;
|
|
122
125
|
if (!raw) {
|
|
123
|
-
output.setData({
|
|
126
|
+
output.setData({
|
|
127
|
+
error: "NOT_FOUND",
|
|
128
|
+
message: "Integration not found.",
|
|
129
|
+
});
|
|
124
130
|
output.error("Integration not found.");
|
|
125
131
|
output.exit(1);
|
|
126
132
|
}
|
|
@@ -141,7 +147,10 @@ export const executeIntegrationsRemove = createCommandHandler("integrations remo
|
|
|
141
147
|
}
|
|
142
148
|
const raw = response.data?.data;
|
|
143
149
|
if (!raw) {
|
|
144
|
-
output.setData({
|
|
150
|
+
output.setData({
|
|
151
|
+
error: "NOT_FOUND",
|
|
152
|
+
message: "Integration not found.",
|
|
153
|
+
});
|
|
145
154
|
output.error("Integration not found.");
|
|
146
155
|
output.exit(1);
|
|
147
156
|
}
|
|
@@ -342,7 +351,9 @@ export const executeIntegrationsConnect = createCommandHandler("integrations con
|
|
|
342
351
|
}
|
|
343
352
|
}
|
|
344
353
|
else {
|
|
345
|
-
const categories = [
|
|
354
|
+
const categories = [
|
|
355
|
+
...new Set(providers.map((p) => p.category)),
|
|
356
|
+
].sort();
|
|
346
357
|
output.info("Available categories: " + categories.join(", "));
|
|
347
358
|
}
|
|
348
359
|
output.exit(1);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveEnvironment } from "../../core/state.js";
|
|
2
2
|
import { createSdkFromState } from "../../core/sdk.js";
|
|
3
3
|
import { handleSDKErrorWithOutput } from "../../utils/sdk-error.js";
|
|
4
|
-
import { createCommandHandler
|
|
4
|
+
import { createCommandHandler } from "../../utils/command-wrapper.js";
|
|
5
5
|
const METRICS_PERIODS = ["1h", "6h", "24h", "7d", "30d"];
|
|
6
6
|
/**
|
|
7
7
|
* Show metrics summary from the hub
|
package/dist/commands/hub/run.js
CHANGED
|
@@ -119,7 +119,8 @@ export const executeRun = createCommandHandler("run", async (options, output) =>
|
|
|
119
119
|
handleSDKErrorWithOutput(err, output, "Failed to fetch run status");
|
|
120
120
|
}
|
|
121
121
|
const currentRun = runStatusResponse.data?.data;
|
|
122
|
-
if (currentRun.status === "completed" ||
|
|
122
|
+
if (currentRun.status === "completed" ||
|
|
123
|
+
currentRun.status === "failed") {
|
|
123
124
|
if (currentRun.success) {
|
|
124
125
|
waitSpinner.succeed(`Run ${currentRun.status}`);
|
|
125
126
|
}
|
|
@@ -28,13 +28,9 @@ export const executeSecretsList = createCommandHandler("secrets list", async (op
|
|
|
28
28
|
}
|
|
29
29
|
output.info(`Secrets (environment: ${env})`);
|
|
30
30
|
output.blank();
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
for (const s of secrets) {
|
|
35
|
-
table.push([s.name, s.createdAt ?? "-", s.updatedAt ?? "-"]);
|
|
31
|
+
for (const { name } of secrets) {
|
|
32
|
+
output.log(name);
|
|
36
33
|
}
|
|
37
|
-
output.log(table.toString());
|
|
38
34
|
});
|
|
39
35
|
function promptSecret(promptText) {
|
|
40
36
|
return new Promise((resolve) => {
|
|
@@ -80,8 +76,6 @@ export const executeSecretsSet = createCommandHandler("secrets set", async (opti
|
|
|
80
76
|
const result = response.data;
|
|
81
77
|
output.setData({
|
|
82
78
|
name: result.data?.name ?? options.name,
|
|
83
|
-
createdAt: result.data?.createdAt,
|
|
84
|
-
updatedAt: result.data?.updatedAt,
|
|
85
79
|
});
|
|
86
80
|
output.success(`Secret "${result.data?.name ?? options.name}" saved.`);
|
|
87
81
|
});
|
|
@@ -104,8 +98,6 @@ export const executeSecretsGet = createCommandHandler("secrets get", async (opti
|
|
|
104
98
|
const secret = response.data?.data;
|
|
105
99
|
output.setData(secret);
|
|
106
100
|
output.info(`Secret: ${secret.name}`);
|
|
107
|
-
output.dim(`Created: ${secret.createdAt ?? "-"}`);
|
|
108
|
-
output.dim(`Updated: ${secret.updatedAt ?? "-"}`);
|
|
109
101
|
});
|
|
110
102
|
/**
|
|
111
103
|
* Delete a secret (with confirmation unless --force; in JSON mode --force is required to avoid prompt).
|
package/dist/core/secrets.d.ts
CHANGED
|
@@ -1,37 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Secrets configuration for CLI
|
|
3
|
-
* Reads configuration from environment variables to construct a secret provider.
|
|
4
|
-
*/
|
|
5
|
-
import { type SecretProvider, type SecretProviderConfig } from "@griffin-app/griffin-executor";
|
|
6
|
-
/**
|
|
7
|
-
* Read secrets provider configuration from environment variables.
|
|
8
|
-
*
|
|
9
|
-
* Supported configurations:
|
|
10
|
-
*
|
|
11
|
-
* 1. Environment provider (default if no config):
|
|
12
|
-
* GRIFFIN_SECRETS_PROVIDER=env
|
|
13
|
-
* GRIFFIN_SECRETS_ENV_PREFIX=APP_
|
|
14
|
-
*
|
|
15
|
-
* 2. AWS Secrets Manager:
|
|
16
|
-
* GRIFFIN_SECRETS_PROVIDER=aws
|
|
17
|
-
* GRIFFIN_SECRETS_AWS_REGION=us-east-1
|
|
18
|
-
* GRIFFIN_SECRETS_AWS_PREFIX=myapp/
|
|
19
|
-
* GRIFFIN_SECRETS_AWS_ROLE_ARN=arn:aws:iam::123:role/griffin
|
|
20
|
-
* GRIFFIN_SECRETS_AWS_EXTERNAL_ID=xyz
|
|
21
|
-
* GRIFFIN_SECRETS_AWS_ACCESS_KEY_ID=...
|
|
22
|
-
* GRIFFIN_SECRETS_AWS_SECRET_ACCESS_KEY=...
|
|
2
|
+
* Secrets configuration for CLI runs.
|
|
23
3
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* GRIFFIN_SECRETS_VAULT_TOKEN=...
|
|
28
|
-
* GRIFFIN_SECRETS_VAULT_NAMESPACE=myapp
|
|
29
|
-
* GRIFFIN_SECRETS_VAULT_KV_VERSION=2
|
|
30
|
-
* GRIFFIN_SECRETS_VAULT_PREFIX=myapp/
|
|
4
|
+
* Two providers:
|
|
5
|
+
* - `env`: reads secrets from environment variables (local dev, no hub needed)
|
|
6
|
+
* - `hub`: resolves secrets via POST /secrets/resolve on the hub API
|
|
31
7
|
*/
|
|
32
|
-
|
|
8
|
+
import { HubSecretProvider, type SecretProvider } from "@griffin-app/griffin-executor";
|
|
9
|
+
export { HubSecretProvider };
|
|
33
10
|
/**
|
|
34
|
-
* Create
|
|
35
|
-
* Reads configuration from environment variables.
|
|
11
|
+
* Create an env-based secret provider for fully-local CLI runs (no hub).
|
|
36
12
|
*/
|
|
37
|
-
export declare function
|
|
13
|
+
export declare function createEnvSecretsProvider(): SecretProvider;
|
package/dist/core/secrets.js
CHANGED
|
@@ -1,96 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Secrets configuration for CLI
|
|
3
|
-
*
|
|
2
|
+
* Secrets configuration for CLI runs.
|
|
3
|
+
*
|
|
4
|
+
* Two providers:
|
|
5
|
+
* - `env`: reads secrets from environment variables (local dev, no hub needed)
|
|
6
|
+
* - `hub`: resolves secrets via POST /secrets/resolve on the hub API
|
|
4
7
|
*/
|
|
5
|
-
import {
|
|
8
|
+
import { EnvSecretProvider, HubSecretProvider, } from "@griffin-app/griffin-executor";
|
|
9
|
+
// Re-export so existing imports from this module continue to work
|
|
10
|
+
export { HubSecretProvider };
|
|
6
11
|
/**
|
|
7
|
-
* Environment variable
|
|
12
|
+
* Environment variable name for selecting the local secrets provider.
|
|
13
|
+
* Only "env" is supported for fully-local runs without a hub.
|
|
8
14
|
*/
|
|
9
15
|
const ENV_PREFIX = "GRIFFIN_SECRETS_";
|
|
10
16
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Supported configurations:
|
|
14
|
-
*
|
|
15
|
-
* 1. Environment provider (default if no config):
|
|
16
|
-
* GRIFFIN_SECRETS_PROVIDER=env
|
|
17
|
-
* GRIFFIN_SECRETS_ENV_PREFIX=APP_
|
|
18
|
-
*
|
|
19
|
-
* 2. AWS Secrets Manager:
|
|
20
|
-
* GRIFFIN_SECRETS_PROVIDER=aws
|
|
21
|
-
* GRIFFIN_SECRETS_AWS_REGION=us-east-1
|
|
22
|
-
* GRIFFIN_SECRETS_AWS_PREFIX=myapp/
|
|
23
|
-
* GRIFFIN_SECRETS_AWS_ROLE_ARN=arn:aws:iam::123:role/griffin
|
|
24
|
-
* GRIFFIN_SECRETS_AWS_EXTERNAL_ID=xyz
|
|
25
|
-
* GRIFFIN_SECRETS_AWS_ACCESS_KEY_ID=...
|
|
26
|
-
* GRIFFIN_SECRETS_AWS_SECRET_ACCESS_KEY=...
|
|
27
|
-
*
|
|
28
|
-
* 3. HashiCorp Vault:
|
|
29
|
-
* GRIFFIN_SECRETS_PROVIDER=vault
|
|
30
|
-
* GRIFFIN_SECRETS_VAULT_ADDRESS=https://vault.example.com
|
|
31
|
-
* GRIFFIN_SECRETS_VAULT_TOKEN=...
|
|
32
|
-
* GRIFFIN_SECRETS_VAULT_NAMESPACE=myapp
|
|
33
|
-
* GRIFFIN_SECRETS_VAULT_KV_VERSION=2
|
|
34
|
-
* GRIFFIN_SECRETS_VAULT_PREFIX=myapp/
|
|
35
|
-
*/
|
|
36
|
-
export function getSecretsConfigFromEnv() {
|
|
37
|
-
const provider = process.env[`${ENV_PREFIX}PROVIDER`] || "env";
|
|
38
|
-
switch (provider) {
|
|
39
|
-
case "env":
|
|
40
|
-
return {
|
|
41
|
-
provider: "env",
|
|
42
|
-
prefix: process.env[`${ENV_PREFIX}ENV_PREFIX`] || "",
|
|
43
|
-
env: process.env,
|
|
44
|
-
};
|
|
45
|
-
case "aws": {
|
|
46
|
-
const region = process.env[`${ENV_PREFIX}AWS_REGION`];
|
|
47
|
-
if (!region) {
|
|
48
|
-
throw new Error(`${ENV_PREFIX}AWS_REGION is required when GRIFFIN_SECRETS_PROVIDER=aws`);
|
|
49
|
-
}
|
|
50
|
-
const accessKeyId = process.env[`${ENV_PREFIX}AWS_ACCESS_KEY_ID`];
|
|
51
|
-
const secretAccessKey = process.env[`${ENV_PREFIX}AWS_SECRET_ACCESS_KEY`];
|
|
52
|
-
return {
|
|
53
|
-
provider: "aws",
|
|
54
|
-
region,
|
|
55
|
-
prefix: process.env[`${ENV_PREFIX}AWS_PREFIX`],
|
|
56
|
-
roleArn: process.env[`${ENV_PREFIX}AWS_ROLE_ARN`],
|
|
57
|
-
externalId: process.env[`${ENV_PREFIX}AWS_EXTERNAL_ID`],
|
|
58
|
-
credentials: accessKeyId && secretAccessKey
|
|
59
|
-
? { accessKeyId, secretAccessKey }
|
|
60
|
-
: undefined,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
case "vault": {
|
|
64
|
-
const address = process.env[`${ENV_PREFIX}VAULT_ADDRESS`];
|
|
65
|
-
const token = process.env[`${ENV_PREFIX}VAULT_TOKEN`];
|
|
66
|
-
if (!address) {
|
|
67
|
-
throw new Error(`${ENV_PREFIX}VAULT_ADDRESS is required when GRIFFIN_SECRETS_PROVIDER=vault`);
|
|
68
|
-
}
|
|
69
|
-
if (!token) {
|
|
70
|
-
throw new Error(`${ENV_PREFIX}VAULT_TOKEN is required when GRIFFIN_SECRETS_PROVIDER=vault`);
|
|
71
|
-
}
|
|
72
|
-
const kvVersionStr = process.env[`${ENV_PREFIX}VAULT_KV_VERSION`];
|
|
73
|
-
const kvVersion = kvVersionStr === "1" || kvVersionStr === "2"
|
|
74
|
-
? parseInt(kvVersionStr)
|
|
75
|
-
: 2;
|
|
76
|
-
return {
|
|
77
|
-
provider: "vault",
|
|
78
|
-
address,
|
|
79
|
-
token,
|
|
80
|
-
namespace: process.env[`${ENV_PREFIX}VAULT_NAMESPACE`],
|
|
81
|
-
kvVersion,
|
|
82
|
-
prefix: process.env[`${ENV_PREFIX}VAULT_PREFIX`],
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
default:
|
|
86
|
-
throw new Error(`Unknown secrets provider: ${provider}. Supported: env, aws, vault`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Create a secret provider for CLI local runs.
|
|
91
|
-
* Reads configuration from environment variables.
|
|
17
|
+
* Create an env-based secret provider for fully-local CLI runs (no hub).
|
|
92
18
|
*/
|
|
93
|
-
export
|
|
94
|
-
|
|
95
|
-
|
|
19
|
+
export function createEnvSecretsProvider() {
|
|
20
|
+
return new EnvSecretProvider({
|
|
21
|
+
prefix: process.env[`${ENV_PREFIX}ENV_PREFIX`] || "",
|
|
22
|
+
env: process.env,
|
|
23
|
+
});
|
|
96
24
|
}
|
package/dist/monitor-runner.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import "tsx";
|
|
2
2
|
import { Value } from "typebox/value";
|
|
3
|
-
import { executeMonitorV1, AxiosAdapter, } from "@griffin-app/griffin-executor";
|
|
3
|
+
import { executeMonitorV1, AxiosAdapter, planHasSecrets, } from "@griffin-app/griffin-executor";
|
|
4
4
|
import { MonitorDSLSchema } from "@griffin-app/griffin-core/schema";
|
|
5
5
|
import { randomUUID } from "crypto";
|
|
6
6
|
import { loadVariables } from "./core/variables.js";
|
|
7
7
|
import { getProjectId } from "./core/state.js";
|
|
8
8
|
import { resolveMonitor } from "./resolve.js";
|
|
9
9
|
import { terminal } from "./utils/terminal.js";
|
|
10
|
-
import {
|
|
10
|
+
import { createEnvSecretsProvider, HubSecretProvider } from "./core/secrets.js";
|
|
11
|
+
import { createSdkFromState } from "./core/sdk.js";
|
|
11
12
|
function validateDsl(monitor) {
|
|
12
13
|
const errors = Value.Errors(MonitorDSLSchema, monitor);
|
|
13
14
|
if (errors.length > 0) {
|
|
@@ -25,13 +26,25 @@ export async function runTestFile(filePath, envName) {
|
|
|
25
26
|
const rawMonitor = validateDsl(defaultExport.default);
|
|
26
27
|
terminal.dim(`Project ID: ${projectId}`);
|
|
27
28
|
const resolvedMonitor = resolveMonitor(rawMonitor, projectId, envName, variables);
|
|
28
|
-
// Create secret provider
|
|
29
|
-
|
|
29
|
+
// Create secret provider: prefer hub (authenticated) for cloud secrets,
|
|
30
|
+
// fall back to env provider for fully-local runs.
|
|
31
|
+
let secretProvider;
|
|
32
|
+
const monitorV1 = { ...resolvedMonitor, id: randomUUID() };
|
|
33
|
+
if (planHasSecrets(monitorV1)) {
|
|
34
|
+
try {
|
|
35
|
+
const sdk = await createSdkFromState();
|
|
36
|
+
secretProvider = new HubSecretProvider(sdk, envName);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Hub not available — fall back to env provider
|
|
40
|
+
secretProvider = createEnvSecretsProvider();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
secretProvider = createEnvSecretsProvider();
|
|
45
|
+
}
|
|
30
46
|
try {
|
|
31
|
-
const result = await executeMonitorV1({
|
|
32
|
-
...resolvedMonitor,
|
|
33
|
-
id: randomUUID(),
|
|
34
|
-
}, "default-org", {
|
|
47
|
+
const result = await executeMonitorV1(monitorV1, "default-org", {
|
|
35
48
|
mode: "local",
|
|
36
49
|
httpClient: new AxiosAdapter(),
|
|
37
50
|
secretProvider,
|
package/dist/utils/output.js
CHANGED
|
@@ -178,7 +178,12 @@ export class OutputContext {
|
|
|
178
178
|
const envelope = {
|
|
179
179
|
ok: false,
|
|
180
180
|
command: this.commandName,
|
|
181
|
-
error: {
|
|
181
|
+
error: {
|
|
182
|
+
code,
|
|
183
|
+
message,
|
|
184
|
+
...(details !== undefined && { details }),
|
|
185
|
+
...(hint && { hint }),
|
|
186
|
+
},
|
|
182
187
|
};
|
|
183
188
|
process.stderr.write(JSON.stringify(envelope) + "\n");
|
|
184
189
|
}
|
package/dist/utils/sdk-error.js
CHANGED
|
@@ -47,7 +47,9 @@ function getSDKErrorCodeAndMessage(sdkError, context) {
|
|
|
47
47
|
return {
|
|
48
48
|
code: "CONFLICT",
|
|
49
49
|
message: `${contextMsg}Conflict`,
|
|
50
|
-
details: sdkError.body?.message
|
|
50
|
+
details: sdkError.body?.message
|
|
51
|
+
? { message: sdkError.body.message }
|
|
52
|
+
: undefined,
|
|
51
53
|
hint: "The operation conflicts with the current state.",
|
|
52
54
|
};
|
|
53
55
|
case 422:
|
|
@@ -77,7 +79,9 @@ function getSDKErrorCodeAndMessage(sdkError, context) {
|
|
|
77
79
|
details: {
|
|
78
80
|
status: sdkError.status,
|
|
79
81
|
statusText: sdkError.statusText,
|
|
80
|
-
...(sdkError.body?.message && {
|
|
82
|
+
...(sdkError.body?.message && {
|
|
83
|
+
bodyMessage: sdkError.body.message,
|
|
84
|
+
}),
|
|
81
85
|
},
|
|
82
86
|
hint: "The hub encountered an internal error.",
|
|
83
87
|
};
|
|
@@ -88,7 +92,9 @@ function getSDKErrorCodeAndMessage(sdkError, context) {
|
|
|
88
92
|
details: {
|
|
89
93
|
status: sdkError.status,
|
|
90
94
|
statusText: sdkError.statusText,
|
|
91
|
-
...(sdkError.body?.message && {
|
|
95
|
+
...(sdkError.body?.message && {
|
|
96
|
+
bodyMessage: sdkError.body.message,
|
|
97
|
+
}),
|
|
92
98
|
...(sdkError.message && { message: sdkError.message }),
|
|
93
99
|
},
|
|
94
100
|
};
|
|
@@ -116,7 +122,8 @@ export function handleSDKError(error, context) {
|
|
|
116
122
|
}
|
|
117
123
|
else if (typeof details === "object" && "errors" in details) {
|
|
118
124
|
terminal.dim("Validation failed:");
|
|
119
|
-
for (const err of details
|
|
125
|
+
for (const err of details
|
|
126
|
+
.errors) {
|
|
120
127
|
terminal.dim(` - ${err.message || err}`);
|
|
121
128
|
}
|
|
122
129
|
}
|
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.31",
|
|
4
4
|
"description": "CLI tool for running and managing griffin API tests",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"author": "",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@griffin-app/griffin-hub-sdk": "1.0.
|
|
28
|
-
"@griffin-app/griffin-executor": "0.1.
|
|
27
|
+
"@griffin-app/griffin-hub-sdk": "1.0.27",
|
|
28
|
+
"@griffin-app/griffin-executor": "0.1.4",
|
|
29
29
|
"@griffin-app/griffin-core": "0.2.2",
|
|
30
30
|
"better-auth": "^1.4.17",
|
|
31
31
|
"cli-table3": "^0.6.5",
|