@prism-d1/cli 1.5.0 → 1.6.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/src/aws/check.js +1 -1
- package/dist/src/aws/team.d.ts +39 -0
- package/dist/src/aws/team.d.ts.map +1 -0
- package/dist/src/aws/team.js +172 -0
- package/dist/src/aws/team.js.map +1 -0
- package/dist/src/commands/enable/codeburn.d.ts +6 -2
- package/dist/src/commands/enable/codeburn.d.ts.map +1 -1
- package/dist/src/commands/enable/codeburn.js +126 -21
- package/dist/src/commands/enable/codeburn.js.map +1 -1
- package/dist/src/commands/team/add-developer.d.ts +17 -0
- package/dist/src/commands/team/add-developer.d.ts.map +1 -0
- package/dist/src/commands/team/add-developer.js +22 -0
- package/dist/src/commands/team/add-developer.js.map +1 -0
- package/dist/src/commands/team/info.d.ts +16 -0
- package/dist/src/commands/team/info.d.ts.map +1 -0
- package/dist/src/commands/team/info.js +30 -0
- package/dist/src/commands/team/info.js.map +1 -0
- package/dist/src/dashboard/page.d.ts.map +1 -1
- package/dist/src/dashboard/page.js +13 -2
- package/dist/src/dashboard/page.js.map +1 -1
- package/dist/src/dashboard/payload.d.ts +7 -0
- package/dist/src/dashboard/payload.d.ts.map +1 -1
- package/dist/src/dashboard/payload.js +2 -0
- package/dist/src/dashboard/payload.js.map +1 -1
- package/dist/src/dashboard/setup.d.ts +9 -2
- package/dist/src/dashboard/setup.d.ts.map +1 -1
- package/dist/src/dashboard/setup.js +34 -15
- package/dist/src/dashboard/setup.js.map +1 -1
- package/dist/src/dashboard/summary.d.ts +1 -1
- package/dist/src/dashboard/summary.d.ts.map +1 -1
- package/dist/src/dashboard/summary.js +2 -1
- package/dist/src/dashboard/summary.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/utils/otel-sync-schedule.d.ts +2 -0
- package/dist/src/utils/otel-sync-schedule.d.ts.map +1 -1
- package/dist/src/utils/otel-sync-schedule.js +13 -0
- package/dist/src/utils/otel-sync-schedule.js.map +1 -1
- package/dist/src/utils/sync-mode.d.ts +43 -0
- package/dist/src/utils/sync-mode.d.ts.map +1 -0
- package/dist/src/utils/sync-mode.js +84 -0
- package/dist/src/utils/sync-mode.js.map +1 -0
- package/package.json +1 -1
package/dist/src/aws/check.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { aws } from '../utils/aws.js';
|
|
10
10
|
import { severityRank } from '../utils/audit.js';
|
|
11
11
|
import { auditAccount, ACCOUNT_AUDIT_IDS } from '../utils/audit-account.js';
|
|
12
|
-
import { configuredSyncUrl } from '../
|
|
12
|
+
import { configuredSyncUrl } from '../utils/otel-sync-schedule.js';
|
|
13
13
|
import { collectSecurityStatus, PIPELINE_STACK, } from '../security/setup.js';
|
|
14
14
|
/** `<section>.<id>`: one id space across sections (a check appears in one section only). */
|
|
15
15
|
export const checkId = (section, id) => `${section}.${id}`;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type SecurityOptions } from '../security/setup.js';
|
|
2
|
+
export declare const TEAM_INFO_NOTICE = "Read-only (team info): one describe-stacks call and an identity check; nothing in AWS is changed.";
|
|
3
|
+
export declare const ADD_DEVELOPER_NOTICE = "AWS write (team add-developer): creates one Cognito user after you confirm; nothing else in AWS is changed.";
|
|
4
|
+
export declare const INFO_PERMISSIONS = "cloudformation:DescribeStacks";
|
|
5
|
+
export declare const ADD_PERMISSIONS = "cloudformation:DescribeStacks (unless --user-pool-id) and cognito-idp:AdminCreateUser";
|
|
6
|
+
/**
|
|
7
|
+
* shortcut: a practical shape check, not RFC 5322; Cognito does its own validation on create.
|
|
8
|
+
* ',' and '=' are rejected too: they are separators in AWS CLI shorthand (attributes are also passed as JSON).
|
|
9
|
+
* A leading '-' is rejected so the value can never be read as an AWS CLI option.
|
|
10
|
+
*/
|
|
11
|
+
export declare const EMAIL_RE: RegExp;
|
|
12
|
+
export interface TeamOptions extends Pick<SecurityOptions, 'profile' | 'region' | 'profileSource' | 'connection'> {
|
|
13
|
+
json?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface AddDeveloperOptions extends TeamOptions {
|
|
16
|
+
email?: string;
|
|
17
|
+
userPoolId?: string;
|
|
18
|
+
yes?: boolean;
|
|
19
|
+
dryRun?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface TeamDeps {
|
|
22
|
+
env: NodeJS.ProcessEnv;
|
|
23
|
+
configRegion(profile?: string): string | null;
|
|
24
|
+
isTTY: boolean;
|
|
25
|
+
ask(q: string): Promise<string>;
|
|
26
|
+
log(line?: string): void;
|
|
27
|
+
err(line?: string): void;
|
|
28
|
+
}
|
|
29
|
+
export interface StackInfo {
|
|
30
|
+
account: string;
|
|
31
|
+
region: string;
|
|
32
|
+
stack: string;
|
|
33
|
+
otelCollectorUrl: string | null;
|
|
34
|
+
otelUserPoolId: string | null;
|
|
35
|
+
}
|
|
36
|
+
export declare const developerCommand: (url: string) => string;
|
|
37
|
+
export declare function teamInfo(o: TeamOptions, d: TeamDeps): number;
|
|
38
|
+
export declare function addDeveloper(o: AddDeveloperOptions, d: TeamDeps): Promise<number>;
|
|
39
|
+
//# sourceMappingURL=team.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.d.ts","sourceRoot":"","sources":["../../../src/aws/team.ts"],"names":[],"mappings":"AAeA,OAAO,EAAsE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIhI,eAAO,MAAM,gBAAgB,sGAAsG,CAAC;AACpI,eAAO,MAAM,oBAAoB,gHAAgH,CAAC;AAClJ,eAAO,MAAM,gBAAgB,kCAAkC,CAAC;AAChE,eAAO,MAAM,eAAe,0FAA0F,CAAC;AAEvH;;;;GAIG;AACH,eAAO,MAAM,QAAQ,QAAgE,CAAC;AAItF,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,QAAQ,GAAG,eAAe,GAAG,YAAY,CAAC;IAC/G,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AACD,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AAuC7I,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAkD,CAAC;AAElG,wBAAgB,QAAQ,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CA2B5D;AAID,wBAAsB,YAAY,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CA6CvF"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `prism-cli team`: platform-team helpers for the PRISM metrics stack.
|
|
3
|
+
*
|
|
4
|
+
* team info READ-ONLY. describe-stacks on the metrics stack; prints
|
|
5
|
+
* OtelCollectorUrl and OtelUserPoolId.
|
|
6
|
+
* team add-developer AWS WRITE. One Cognito AdminCreateUser (username = the
|
|
7
|
+
* developer's email, as in README step 2), after the plan
|
|
8
|
+
* is shown and confirmed. Cognito emails the invite; the
|
|
9
|
+
* temporary password is never requested, printed, logged
|
|
10
|
+
* or stored here.
|
|
11
|
+
*
|
|
12
|
+
* Same AWS resolution as the other AWS commands (aws connect precedence,
|
|
13
|
+
* --profile / --region), through the AWS CLI with an argv array (no shell).
|
|
14
|
+
*/
|
|
15
|
+
import { aws } from '../utils/aws.js';
|
|
16
|
+
import { NO_REGION_MESSAGE, credentialSource, resolveRegion, PIPELINE_STACK } from '../security/setup.js';
|
|
17
|
+
import { accountChangeWarning } from './connection.js';
|
|
18
|
+
import { SETUP_DOCS } from '../utils/sync-mode.js';
|
|
19
|
+
export const TEAM_INFO_NOTICE = 'Read-only (team info): one describe-stacks call and an identity check; nothing in AWS is changed.';
|
|
20
|
+
export const ADD_DEVELOPER_NOTICE = 'AWS write (team add-developer): creates one Cognito user after you confirm; nothing else in AWS is changed.';
|
|
21
|
+
export const INFO_PERMISSIONS = 'cloudformation:DescribeStacks';
|
|
22
|
+
export const ADD_PERMISSIONS = 'cloudformation:DescribeStacks (unless --user-pool-id) and cognito-idp:AdminCreateUser';
|
|
23
|
+
/**
|
|
24
|
+
* shortcut: a practical shape check, not RFC 5322; Cognito does its own validation on create.
|
|
25
|
+
* ',' and '=' are rejected too: they are separators in AWS CLI shorthand (attributes are also passed as JSON).
|
|
26
|
+
* A leading '-' is rejected so the value can never be read as an AWS CLI option.
|
|
27
|
+
*/
|
|
28
|
+
export const EMAIL_RE = /^(?!-)[^\s@<>"'`;|&$\\,=]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)+$/;
|
|
29
|
+
const POOL_RE = /^[\w-]+_[0-9a-zA-Z]+$/;
|
|
30
|
+
const ACCESS_DENIED = /AccessDenied|UnauthorizedOperation|NotAuthorized/;
|
|
31
|
+
const lastLine = (r) => r.errorCode || r.raw.split('\n').map((l) => l.trim()).filter(Boolean).pop() || 'unknown error';
|
|
32
|
+
/** Region, identity and the header lines. Returns null after printing the error. */
|
|
33
|
+
function resolveTarget(o, d, say) {
|
|
34
|
+
const r = resolveRegion(o, d);
|
|
35
|
+
if (!r) {
|
|
36
|
+
say(`Error: ${NO_REGION_MESSAGE} Or save one with prism-cli aws connect.`);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const target = { profile: o.profile, env: { AWS_PAGER: '', AWS_REGION: r.region, AWS_DEFAULT_REGION: r.region } };
|
|
40
|
+
const who = aws(['sts', 'get-caller-identity'], target);
|
|
41
|
+
const account = who.ok ? String(who.json?.Account || '') : '';
|
|
42
|
+
if (!account) {
|
|
43
|
+
say(`Error: cannot resolve the AWS identity: ${lastLine(who)}. Sign in (e.g. aws sso login), pass --profile, or run prism-cli aws connect.`);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
say(`Account: ${account}`);
|
|
47
|
+
say(`Region: ${r.region} (${r.source})`);
|
|
48
|
+
say(`Credentials: ${credentialSource(o, d.env)}`);
|
|
49
|
+
const w = accountChangeWarning(o.connection, account);
|
|
50
|
+
if (w)
|
|
51
|
+
say(w);
|
|
52
|
+
say('');
|
|
53
|
+
return { target, account, region: r.region };
|
|
54
|
+
}
|
|
55
|
+
/** The metrics stack's OTEL outputs, or an error line. */
|
|
56
|
+
function readStack(t) {
|
|
57
|
+
const r = aws(['cloudformation', 'describe-stacks', '--stack-name', PIPELINE_STACK, '--region', t.region], t.target);
|
|
58
|
+
if (!r.ok) {
|
|
59
|
+
if (/does not exist/.test(r.raw))
|
|
60
|
+
return { error: `${PIPELINE_STACK} is not deployed in account ${t.account}, ${t.region}. Deploy it first (infra/: npx cdk deploy --all); see ${SETUP_DOCS.platformTeamGuide}` };
|
|
61
|
+
if (ACCESS_DENIED.test(r.errorCode || r.raw))
|
|
62
|
+
return { error: `access denied reading ${PIPELINE_STACK} (${lastLine(r)}). team info needs ${INFO_PERMISSIONS}.` };
|
|
63
|
+
return { error: `cannot read ${PIPELINE_STACK}: ${lastLine(r)}. team info needs ${INFO_PERMISSIONS}.` };
|
|
64
|
+
}
|
|
65
|
+
const outputs = r.json?.Stacks?.[0]?.Outputs || [];
|
|
66
|
+
const out = (k) => { const v = outputs.find((o) => o?.OutputKey === k)?.OutputValue; return typeof v === 'string' && v ? v : null; };
|
|
67
|
+
return { account: t.account, region: t.region, stack: PIPELINE_STACK, otelCollectorUrl: out('OtelCollectorUrl'), otelUserPoolId: out('OtelUserPoolId') };
|
|
68
|
+
}
|
|
69
|
+
export const developerCommand = (url) => `prism-cli enable codeburn --url ${url}`;
|
|
70
|
+
export function teamInfo(o, d) {
|
|
71
|
+
const say = o.json ? d.err : d.log;
|
|
72
|
+
say(TEAM_INFO_NOTICE);
|
|
73
|
+
say('');
|
|
74
|
+
const t = resolveTarget(o, d, say);
|
|
75
|
+
if (!t)
|
|
76
|
+
return 1;
|
|
77
|
+
const s = readStack(t);
|
|
78
|
+
if ('error' in s) {
|
|
79
|
+
say(`Error: ${s.error}`);
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
82
|
+
if (!s.otelCollectorUrl && !s.otelUserPoolId) {
|
|
83
|
+
say(`Error: ${PIPELINE_STACK} has no OtelCollectorUrl or OtelUserPoolId output, so the OTEL collector is not deployed. Redeploy without -c skipOtelCollector=true.`);
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
const cmd = s.otelCollectorUrl ? developerCommand(s.otelCollectorUrl) : null;
|
|
87
|
+
if (o.json) {
|
|
88
|
+
d.log(JSON.stringify({ ...s, developer_command: cmd }, null, 2));
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
d.log(`Stack: ${s.stack}`);
|
|
92
|
+
d.log(`OtelCollectorUrl: ${s.otelCollectorUrl ?? '(no output)'}`);
|
|
93
|
+
d.log(`OtelUserPoolId: ${s.otelUserPoolId ?? '(no output; developer accounts cannot be created in this stack)'}`);
|
|
94
|
+
d.log('');
|
|
95
|
+
if (cmd) {
|
|
96
|
+
d.log('Send each developer this line:');
|
|
97
|
+
d.log(` ${cmd}`);
|
|
98
|
+
}
|
|
99
|
+
if (s.otelUserPoolId)
|
|
100
|
+
d.log('Add a developer: prism-cli team add-developer <email>');
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
const yes = (a) => ['y', 'yes'].includes(a.trim().toLowerCase());
|
|
104
|
+
export async function addDeveloper(o, d) {
|
|
105
|
+
const email = (o.email || '').trim();
|
|
106
|
+
if (!email || email.length > 254 || !EMAIL_RE.test(email)) {
|
|
107
|
+
d.err(`Error: "${email}" is not a valid email address. The username is the developer's email (README step 2).`);
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
110
|
+
if (o.userPoolId !== undefined && !POOL_RE.test(o.userPoolId)) {
|
|
111
|
+
d.err(`Error: "${o.userPoolId}" is not a Cognito user pool id (like us-west-2_AbC123).`);
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
d.log(ADD_DEVELOPER_NOTICE);
|
|
115
|
+
d.log(`Needs: ${ADD_PERMISSIONS}.`);
|
|
116
|
+
d.log('');
|
|
117
|
+
const t = resolveTarget(o, d, d.log);
|
|
118
|
+
if (!t)
|
|
119
|
+
return 1;
|
|
120
|
+
let pool = o.userPoolId;
|
|
121
|
+
if (!pool) {
|
|
122
|
+
const s = readStack(t);
|
|
123
|
+
if ('error' in s) {
|
|
124
|
+
d.err(`Error: ${s.error}`);
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
if (!s.otelUserPoolId) {
|
|
128
|
+
d.err(`Error: ${PIPELINE_STACK} has no OtelUserPoolId output. Pass --user-pool-id, or redeploy with the OTEL collector.`);
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
pool = s.otelUserPoolId;
|
|
132
|
+
}
|
|
133
|
+
d.log('Plan: create one Cognito user');
|
|
134
|
+
d.log(` Account: ${t.account}`);
|
|
135
|
+
d.log(` Region: ${t.region}`);
|
|
136
|
+
d.log(` User pool: ${pool}`);
|
|
137
|
+
d.log(` Username: ${email} (email attribute too; Cognito emails the invite)`);
|
|
138
|
+
d.log('');
|
|
139
|
+
if (o.dryRun) {
|
|
140
|
+
d.log('Dry run: nothing was changed.');
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
if (!o.yes) {
|
|
144
|
+
if (!d.isTTY) {
|
|
145
|
+
d.err('Error: no terminal to confirm. Re-run with --yes to create the user, or --dry-run to see the plan.');
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
if (!yes(await d.ask('Create this user? [y/N] '))) {
|
|
149
|
+
d.err('Not created. Nothing was changed.');
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// No --temporary-password: Cognito generates one and emails it; it never passes through here.
|
|
154
|
+
const r = aws(['cognito-idp', 'admin-create-user', '--user-pool-id', pool, '--username', email,
|
|
155
|
+
'--user-attributes', JSON.stringify([{ Name: 'email', Value: email }]), '--desired-delivery-mediums', 'EMAIL', '--region', t.region], t.target);
|
|
156
|
+
if (r.ok) {
|
|
157
|
+
d.log(`✓ Created ${email} in ${pool}. Cognito emailed the invite with a temporary password.`);
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
// Only the error code is shown: AWS error text can echo request values.
|
|
161
|
+
if (r.errorCode === 'UsernameExistsException') {
|
|
162
|
+
d.log(`✓ ${email} already exists in ${pool}; nothing changed.`);
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
if (ACCESS_DENIED.test(r.errorCode || '')) {
|
|
166
|
+
d.err(`Error: access denied (${r.errorCode}). team add-developer needs ${ADD_PERMISSIONS}.`);
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
d.err(`Error: AdminCreateUser failed (${r.errorCode || 'unknown error'}). Nothing was created.`);
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=team.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.js","sourceRoot":"","sources":["../../../src/aws/team.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { run, type RunResult } from '../../utils/exec.js';
|
|
2
|
+
import { configuredSyncUrl } from '../../utils/otel-sync-schedule.js';
|
|
2
3
|
/** Exact install command, printed before it runs and in every hint. */
|
|
3
4
|
export declare const INSTALL_CMD: string;
|
|
4
5
|
export declare function getCodeburnPath(): string | null;
|
|
@@ -35,8 +36,7 @@ export interface CodeburnDeps {
|
|
|
35
36
|
export declare function defaultDeps(): CodeburnDeps;
|
|
36
37
|
export declare const SCHEDULE_KINDS: readonly ["systemd", "cron"];
|
|
37
38
|
export declare const SYSTEMD_CMD = "prism-cli enable codeburn --schedule systemd";
|
|
38
|
-
|
|
39
|
-
export declare function configuredSyncUrl(home: string): string | null;
|
|
39
|
+
export { configuredSyncUrl };
|
|
40
40
|
/** True when `version` (e.g. "0.9.24") is at least MIN_CODEBURN. */
|
|
41
41
|
export declare function codeburnVersionOk(version: string): boolean;
|
|
42
42
|
export interface CodeburnOptions {
|
|
@@ -48,6 +48,10 @@ export interface CodeburnOptions {
|
|
|
48
48
|
dryRun?: boolean;
|
|
49
49
|
/** Linux: systemd or cron. */
|
|
50
50
|
schedule?: string;
|
|
51
|
+
/** Sync mode local: usage stays on this machine. */
|
|
52
|
+
local?: boolean;
|
|
53
|
+
/** Sync mode admin: print the platform-team steps; no AWS calls. */
|
|
54
|
+
admin?: boolean;
|
|
51
55
|
}
|
|
52
56
|
/**
|
|
53
57
|
* The setup flow. Returns the exit code; every change is skipped on --dry-run,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codeburn.d.ts","sourceRoot":"","sources":["../../../../src/commands/enable/codeburn.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,GAAG,EAAkB,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"codeburn.d.ts","sourceRoot":"","sources":["../../../../src/commands/enable/codeburn.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,8 +13,9 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync } from '
|
|
|
13
13
|
import { join } from 'node:path';
|
|
14
14
|
import { run, runInteractive } from '../../utils/exec.js';
|
|
15
15
|
import { withPrivateTemp } from '../../utils/tempfile.js';
|
|
16
|
-
import { CRON_MARKER, PLIST_LABEL, SCHTASK_NAME, otelLogDir, otelLogFile, codeburnSyncConfigPath, linuxCrontabAvailable, crontabLines, darwinPlistPath, scheduleExists, schedulerName, CODEBURN_INSTALL_ARGS, ENABLE_CODEBURN_CMD, SYNC_SINCE, syncArgs, linuxCronScheduleExists, SYSTEMD_SCHEDULER_NAME, SYSTEMD_UNIT, systemdServicePath, systemdTimerExists, systemdTimerPath, systemdUserAvailable, systemdUserDir, } from '../../utils/otel-sync-schedule.js';
|
|
16
|
+
import { CRON_MARKER, PLIST_LABEL, SCHTASK_NAME, otelLogDir, otelLogFile, codeburnSyncConfigPath, linuxCrontabAvailable, crontabLines, darwinPlistPath, scheduleExists, schedulerName, CODEBURN_INSTALL_ARGS, ENABLE_CODEBURN_CMD, SYNC_SINCE, syncArgs, linuxCronScheduleExists, SYSTEMD_SCHEDULER_NAME, SYSTEMD_UNIT, systemdServicePath, systemdTimerExists, systemdTimerPath, systemdUserAvailable, systemdUserDir, configuredSyncUrl, } from '../../utils/otel-sync-schedule.js';
|
|
17
17
|
import { runGuarded } from './security.js';
|
|
18
|
+
import { effectiveMode, LOCAL_MODE_HELP, MODE_SOURCE_TEXT, PLATFORM_TEAM_HELP, SETUP_DOCS, SYNC_MODE_PATH, TEAM_URL_CMD, writeSyncMode, } from '../../utils/sync-mode.js';
|
|
18
19
|
// ---- Constants ----
|
|
19
20
|
// Marker, label and task name are shared with the dashboard's setup check.
|
|
20
21
|
const LOG_DIR = otelLogDir();
|
|
@@ -382,19 +383,8 @@ function removeSchedules(opts, d) {
|
|
|
382
383
|
d.log('');
|
|
383
384
|
return 0;
|
|
384
385
|
}
|
|
385
|
-
|
|
386
|
-
export
|
|
387
|
-
const configPath = codeburnSyncConfigPath(home);
|
|
388
|
-
if (!existsSync(configPath))
|
|
389
|
-
return null;
|
|
390
|
-
try {
|
|
391
|
-
const cfg = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
392
|
-
return String(cfg.baseUrl || cfg.endpoint || cfg.url || '');
|
|
393
|
-
}
|
|
394
|
-
catch {
|
|
395
|
-
return '';
|
|
396
|
-
}
|
|
397
|
-
}
|
|
386
|
+
// Lives in utils/otel-sync-schedule.ts (shared with the dashboard and aws check); re-exported for existing importers.
|
|
387
|
+
export { configuredSyncUrl };
|
|
398
388
|
/** True when `version` (e.g. "0.9.24") is at least MIN_CODEBURN. */
|
|
399
389
|
export function codeburnVersionOk(version) {
|
|
400
390
|
const parts = version.split('.').map((n) => parseInt(n, 10) || 0);
|
|
@@ -446,8 +436,10 @@ function showStatus(d) {
|
|
|
446
436
|
d.log(` ✗ codeburn not found in PATH (run ${ENABLE_CODEBURN_CMD})`);
|
|
447
437
|
}
|
|
448
438
|
const url = configuredSyncUrl(d.home);
|
|
439
|
+
const m = effectiveMode(d.home, url);
|
|
440
|
+
d.log(` Sync mode: ${m.mode} (${MODE_SOURCE_TEXT[m.source]})`);
|
|
449
441
|
if (url === null)
|
|
450
|
-
d.log(` ✗ sync not configured (run ${
|
|
442
|
+
d.log(m.mode === 'team' ? ` ✗ sync not configured (run ${TEAM_URL_CMD})` : ' - no sync endpoint (usage stays on this machine)');
|
|
451
443
|
else if (url)
|
|
452
444
|
d.log(` ✓ sync configured: ${url}`);
|
|
453
445
|
else
|
|
@@ -484,6 +476,100 @@ function showStatus(d) {
|
|
|
484
476
|
reportSyncStatus(codeburnPath, d);
|
|
485
477
|
d.log('');
|
|
486
478
|
}
|
|
479
|
+
const MODE_CHOICES = [
|
|
480
|
+
['1', 'local', 'just me, keep it on this machine'],
|
|
481
|
+
['2', 'team', "my team's PRISM (I have the collector URL from my platform team)"],
|
|
482
|
+
['3', 'admin', "I'm the platform team setting up PRISM"],
|
|
483
|
+
];
|
|
484
|
+
/**
|
|
485
|
+
* The sync mode for this run: a flag, else the mode already in effect (saved,
|
|
486
|
+
* or team for a machine with a sync endpoint), else the question on a TTY,
|
|
487
|
+
* else local. Returns an exit code on a bad answer.
|
|
488
|
+
*/
|
|
489
|
+
async function chooseMode(opts, d, dry) {
|
|
490
|
+
if (opts.local)
|
|
491
|
+
return 'local';
|
|
492
|
+
if (opts.admin)
|
|
493
|
+
return 'admin';
|
|
494
|
+
if (opts.url)
|
|
495
|
+
return 'team';
|
|
496
|
+
const cur = effectiveMode(d.home);
|
|
497
|
+
if (cur.source !== 'default') {
|
|
498
|
+
d.log(` Sync mode: ${cur.mode} (${MODE_SOURCE_TEXT[cur.source]}; --local, --url or --admin changes it)`);
|
|
499
|
+
return cur.mode;
|
|
500
|
+
}
|
|
501
|
+
if (!d.isTTY) {
|
|
502
|
+
d.log(' No terminal and no --local, --url or --admin: local only.');
|
|
503
|
+
return 'local';
|
|
504
|
+
}
|
|
505
|
+
if (dry) {
|
|
506
|
+
d.log(' → would ask where your usage should go; this plan is for local only (--url or --admin plans the others)');
|
|
507
|
+
return 'local';
|
|
508
|
+
}
|
|
509
|
+
d.log(' Where should your usage go?');
|
|
510
|
+
for (const [n, , text] of MODE_CHOICES)
|
|
511
|
+
d.log(` ${n}) ${text}`);
|
|
512
|
+
const answer = (await d.ask(' Choose 1, 2 or 3 [1]: ')).trim() || '1';
|
|
513
|
+
const picked = MODE_CHOICES.find(([n]) => n === answer);
|
|
514
|
+
if (!picked) {
|
|
515
|
+
d.error(`Error: "${answer}" is not 1, 2 or 3. Or pass --local, --url <collector URL> or --admin.`);
|
|
516
|
+
return 1;
|
|
517
|
+
}
|
|
518
|
+
return picked[1];
|
|
519
|
+
}
|
|
520
|
+
function saveMode(mode, d, dry) {
|
|
521
|
+
if (dry) {
|
|
522
|
+
d.log(` → would save sync mode ${mode} in ${SYNC_MODE_PATH}`);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
writeSyncMode(d.home, mode);
|
|
526
|
+
d.log(` ✓ Sync mode ${mode} saved in ${SYNC_MODE_PATH}`);
|
|
527
|
+
}
|
|
528
|
+
/** Every installed sync schedule's name; an unreadable crontab is skipped (it cannot be told). */
|
|
529
|
+
function installedSchedules(d) {
|
|
530
|
+
const all = d.linux ? [nativeSchedule(d), systemdSchedule(d)] : [nativeSchedule(d)];
|
|
531
|
+
return all.filter((s) => probeSchedule(s) === true).map((s) => s.name);
|
|
532
|
+
}
|
|
533
|
+
/** Local only: codeburn keeps working here; no endpoint is set up and no schedule installed. */
|
|
534
|
+
async function localOnly(opts, d, dry) {
|
|
535
|
+
// Removal first: taking the schedule off never needs codeburn installed.
|
|
536
|
+
if (opts.remove) {
|
|
537
|
+
const code = removeSchedules(opts, d);
|
|
538
|
+
if (code)
|
|
539
|
+
return code;
|
|
540
|
+
}
|
|
541
|
+
const ensured = await ensureCodeburn(opts, d);
|
|
542
|
+
if (typeof ensured === 'number')
|
|
543
|
+
return ensured;
|
|
544
|
+
saveMode('local', d, dry);
|
|
545
|
+
const url = configuredSyncUrl(d.home);
|
|
546
|
+
const left = dry && opts.remove ? [] : installedSchedules(d);
|
|
547
|
+
d.log('');
|
|
548
|
+
if (left.length) {
|
|
549
|
+
d.log(` ⚠ Sync mode is local, but the ${left.join(' and ')} schedule is still installed and still pushes usage.`);
|
|
550
|
+
d.log(` Remove it: ${ENABLE_CODEBURN_CMD} --local --remove`);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
d.log(' ✅ Local only: codeburn usage stays on this machine. No sync endpoint is set up and no schedule is installed.');
|
|
554
|
+
}
|
|
555
|
+
if (url !== null)
|
|
556
|
+
d.log(` Left in place: codeburn's sync config${url ? ` for ${url}` : ''} (${codeburnSyncConfigPath(d.home)}). Nothing pushes to it without a schedule.`);
|
|
557
|
+
d.log(`\n ${LOCAL_MODE_HELP.text}`);
|
|
558
|
+
d.log(` Setup instructions: ${SETUP_DOCS.telemetryAccount}\n`);
|
|
559
|
+
return 0;
|
|
560
|
+
}
|
|
561
|
+
/** Admin: the platform-team steps and helper commands. No AWS call is made. */
|
|
562
|
+
function platformTeam(d, dry) {
|
|
563
|
+
d.log(' Platform team setup (this prints steps only; no AWS calls are made):\n');
|
|
564
|
+
PLATFORM_TEAM_HELP.steps.forEach((step, i) => d.log(` ${i + 1}. ${step}`));
|
|
565
|
+
d.log('\n Helper commands:');
|
|
566
|
+
d.log(' prism-cli team info read-only: prints OtelCollectorUrl and OtelUserPoolId');
|
|
567
|
+
d.log(' prism-cli team add-developer <email> creates the developer\'s telemetry account (asks first; --dry-run shows the plan)');
|
|
568
|
+
d.log(`\n Platform team guide: ${SETUP_DOCS.platformTeamGuide}\n`);
|
|
569
|
+
saveMode('admin', d, dry);
|
|
570
|
+
d.log(` To sync your own usage as well, run ${TEAM_URL_CMD}.\n`);
|
|
571
|
+
return 0;
|
|
572
|
+
}
|
|
487
573
|
/**
|
|
488
574
|
* Step 1: codeburn on PATH, installing it after a confirmation when missing.
|
|
489
575
|
* Returns its path, `null` on a dry run without it, or an exit code on refusal.
|
|
@@ -540,7 +626,12 @@ export async function enableCodeburn(opts, d) {
|
|
|
540
626
|
showStatus(d);
|
|
541
627
|
return 0;
|
|
542
628
|
}
|
|
543
|
-
|
|
629
|
+
const modes = [opts.local && '--local', opts.url && '--url', opts.admin && '--admin'].filter(Boolean);
|
|
630
|
+
if (modes.length > 1) {
|
|
631
|
+
d.error(`Error: ${modes.join(' and ')} choose different sync modes; pass one of them.`);
|
|
632
|
+
return 1;
|
|
633
|
+
}
|
|
634
|
+
if (opts.remove && !opts.local)
|
|
544
635
|
return removeSchedules(opts, d);
|
|
545
636
|
const dry = !!opts.dryRun;
|
|
546
637
|
const intervalHours = opts.interval ? parseInt(opts.interval, 10) : 12;
|
|
@@ -549,6 +640,13 @@ export async function enableCodeburn(opts, d) {
|
|
|
549
640
|
return 1;
|
|
550
641
|
}
|
|
551
642
|
d.log(dry ? '\n🔄 enable codeburn — dry run, nothing is changed\n' : '\n🔄 enable codeburn\n');
|
|
643
|
+
const mode = await chooseMode(opts, d, dry);
|
|
644
|
+
if (typeof mode === 'number')
|
|
645
|
+
return mode;
|
|
646
|
+
if (mode === 'admin')
|
|
647
|
+
return platformTeam(d, dry);
|
|
648
|
+
if (mode === 'local')
|
|
649
|
+
return localOnly(opts, d, dry);
|
|
552
650
|
// 1. codeburn installed, and new enough for --attribution
|
|
553
651
|
const ensured = await ensureCodeburn(opts, d);
|
|
554
652
|
if (typeof ensured === 'number')
|
|
@@ -574,9 +672,13 @@ export async function enableCodeburn(opts, d) {
|
|
|
574
672
|
d.log(' → would ask for the OTEL collector URL (pass --url <OtelCollectorUrl> to skip)');
|
|
575
673
|
}
|
|
576
674
|
else {
|
|
577
|
-
|
|
675
|
+
if (!d.isTTY) {
|
|
676
|
+
d.error(`Error: the collector URL is required. Ask your platform team for it, then run ${TEAM_URL_CMD}.`);
|
|
677
|
+
return 1;
|
|
678
|
+
}
|
|
679
|
+
otelUrl = await d.ask(' Collector URL (from your platform team; the OtelCollectorUrl stack output): ');
|
|
578
680
|
if (!otelUrl) {
|
|
579
|
-
d.error(
|
|
681
|
+
d.error(`Error: the collector URL is required. Ask your platform team for it, then run ${TEAM_URL_CMD}.`);
|
|
580
682
|
return 1;
|
|
581
683
|
}
|
|
582
684
|
}
|
|
@@ -682,6 +784,7 @@ export async function enableCodeburn(opts, d) {
|
|
|
682
784
|
}
|
|
683
785
|
}
|
|
684
786
|
// 6. What codeburn itself reports.
|
|
787
|
+
saveMode('team', d, dry);
|
|
685
788
|
if (dry) {
|
|
686
789
|
d.log(' → would run: codeburn sync status');
|
|
687
790
|
d.log('\n Dry run complete. Re-run without --dry-run to apply.\n');
|
|
@@ -703,12 +806,14 @@ export async function enableCodeburn(opts, d) {
|
|
|
703
806
|
return 0;
|
|
704
807
|
}
|
|
705
808
|
export const CODEBURN_OPTIONS = [
|
|
706
|
-
{ flags: '--
|
|
809
|
+
{ flags: '--local', description: 'Sync mode local (the default): codeburn usage stays on this machine; no endpoint, no schedule. Leaves an existing endpoint and schedule in place unless --remove' },
|
|
810
|
+
{ flags: '--url <url>', description: "Sync mode team: your team's collector URL (the OtelCollectorUrl stack output, from your platform team; default: the URL codeburn already syncs to)" },
|
|
811
|
+
{ flags: '--admin', description: 'Sync mode admin: print the platform-team setup steps and the prism-cli team helper commands (no AWS calls)' },
|
|
707
812
|
{ flags: '--interval <hours>', description: 'Sync interval in hours (default: 12)' },
|
|
708
813
|
{ flags: '--yes', description: `Install codeburn (${INSTALL_CMD}), reconfigure a different endpoint, and accept an offered systemd user timer without a prompt` },
|
|
709
814
|
{ flags: '--dry-run', description: 'Print the plan with the exact commands; change nothing' },
|
|
710
815
|
{ flags: '--status', description: 'Show codeburn, sync and schedule status' },
|
|
711
|
-
{ flags: '--remove', description: 'Remove the sync schedule (both kinds on Linux, unless --schedule picks one)' },
|
|
816
|
+
{ flags: '--remove', description: 'Remove the sync schedule (both kinds on Linux, unless --schedule picks one); with --local, switch to local and remove it' },
|
|
712
817
|
{ flags: '--schedule <kind>', description: 'Linux: systemd (a systemd user timer) or cron (your crontab). Default: cron; when the crontab cannot be read, a systemd user timer is offered' },
|
|
713
818
|
];
|
|
714
819
|
/** The one entry point for `enable codeburn` and its `bootstrapper setup-otel-sync` alias. */
|
|
@@ -716,7 +821,7 @@ export async function runEnableCodeburn(opts, hooks = {}) {
|
|
|
716
821
|
await runGuarded(() => enableCodeburn(opts, (hooks.deps ?? defaultDeps)()), hooks);
|
|
717
822
|
}
|
|
718
823
|
export default {
|
|
719
|
-
description:
|
|
824
|
+
description: "Set up codeburn: local only (default), sync to your team's PRISM every 12h (--url), or the platform-team steps (--admin)",
|
|
720
825
|
options: CODEBURN_OPTIONS,
|
|
721
826
|
action: runEnableCodeburn,
|
|
722
827
|
};
|