koppler 0.0.0-stage → 0.0.2
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/LICENSE +21 -0
- package/README.md +101 -2
- package/bin/run-logged +16 -0
- package/bin/secret-list +7 -0
- package/bin/secret-psql +41 -0
- package/bin/secret-set +17 -0
- package/bin/secret-store +82 -0
- package/bin/secret-test +10 -0
- package/bin/with-secrets +25 -0
- package/dist/.built +1 -0
- package/dist/cli/agent.js +144 -0
- package/dist/cli/agent.js.map +1 -0
- package/dist/cli/doctor.js +173 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/mcp.js +204 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/output.js +37 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/records.js +121 -0
- package/dist/cli/records.js.map +1 -0
- package/dist/cli/running.js +270 -0
- package/dist/cli/running.js.map +1 -0
- package/dist/cli/shell.js +43 -0
- package/dist/cli/shell.js.map +1 -0
- package/dist/cli/wait.js +59 -0
- package/dist/cli/wait.js.map +1 -0
- package/dist/core/addresses.js +55 -0
- package/dist/core/addresses.js.map +1 -0
- package/dist/core/arrange.js +329 -0
- package/dist/core/arrange.js.map +1 -0
- package/dist/core/cables.js +158 -0
- package/dist/core/cables.js.map +1 -0
- package/dist/core/expressions.js +72 -0
- package/dist/core/expressions.js.map +1 -0
- package/dist/core/frameworks.js +13 -0
- package/dist/core/frameworks.js.map +1 -0
- package/dist/core/kinds.js +244 -0
- package/dist/core/kinds.js.map +1 -0
- package/dist/core/launch.js +181 -0
- package/dist/core/launch.js.map +1 -0
- package/dist/core/logfmt.js +144 -0
- package/dist/core/logfmt.js.map +1 -0
- package/dist/core/mock.js +27 -0
- package/dist/core/mock.js.map +1 -0
- package/dist/core/plan.js +147 -0
- package/dist/core/plan.js.map +1 -0
- package/dist/core/ports.js +155 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/presets.js +186 -0
- package/dist/core/presets.js.map +1 -0
- package/dist/core/secret-types.js +3 -0
- package/dist/core/secret-types.js.map +1 -0
- package/dist/core/sign-in.js +30 -0
- package/dist/core/sign-in.js.map +1 -0
- package/dist/core/stack-path.js +64 -0
- package/dist/core/stack-path.js.map +1 -0
- package/dist/core/stack.js +509 -0
- package/dist/core/stack.js.map +1 -0
- package/dist/core/terraform.js +393 -0
- package/dist/core/terraform.js.map +1 -0
- package/dist/data.js +37 -0
- package/dist/data.js.map +1 -0
- package/dist/engine/actions.js +99 -0
- package/dist/engine/actions.js.map +1 -0
- package/dist/engine/app-commands.js +106 -0
- package/dist/engine/app-commands.js.map +1 -0
- package/dist/engine/app-start.js +167 -0
- package/dist/engine/app-start.js.map +1 -0
- package/dist/engine/app-state.js +43 -0
- package/dist/engine/app-state.js.map +1 -0
- package/dist/engine/boards.js +219 -0
- package/dist/engine/boards.js.map +1 -0
- package/dist/engine/branch.js +194 -0
- package/dist/engine/branch.js.map +1 -0
- package/dist/engine/browser-console.js +45 -0
- package/dist/engine/browser-console.js.map +1 -0
- package/dist/engine/calls.js +97 -0
- package/dist/engine/calls.js.map +1 -0
- package/dist/engine/checks.js +270 -0
- package/dist/engine/checks.js.map +1 -0
- package/dist/engine/clones.js +67 -0
- package/dist/engine/clones.js.map +1 -0
- package/dist/engine/config.js +26 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/deployed.js +488 -0
- package/dist/engine/deployed.js.map +1 -0
- package/dist/engine/devices.js +81 -0
- package/dist/engine/devices.js.map +1 -0
- package/dist/engine/discover.js +236 -0
- package/dist/engine/discover.js.map +1 -0
- package/dist/engine/down.js +253 -0
- package/dist/engine/down.js.map +1 -0
- package/dist/engine/history.js +215 -0
- package/dist/engine/history.js.map +1 -0
- package/dist/engine/investigate.js +278 -0
- package/dist/engine/investigate.js.map +1 -0
- package/dist/engine/libraries.js +129 -0
- package/dist/engine/libraries.js.map +1 -0
- package/dist/engine/linked.js +146 -0
- package/dist/engine/linked.js.map +1 -0
- package/dist/engine/listen.js +223 -0
- package/dist/engine/listen.js.map +1 -0
- package/dist/engine/locks.js +38 -0
- package/dist/engine/locks.js.map +1 -0
- package/dist/engine/messages.js +177 -0
- package/dist/engine/messages.js.map +1 -0
- package/dist/engine/needs.js +363 -0
- package/dist/engine/needs.js.map +1 -0
- package/dist/engine/processes.js +350 -0
- package/dist/engine/processes.js.map +1 -0
- package/dist/engine/query.js +241 -0
- package/dist/engine/query.js.map +1 -0
- package/dist/engine/queues.js +100 -0
- package/dist/engine/queues.js.map +1 -0
- package/dist/engine/recipes.js +248 -0
- package/dist/engine/recipes.js.map +1 -0
- package/dist/engine/reload.js +32 -0
- package/dist/engine/reload.js.map +1 -0
- package/dist/engine/repos.js +214 -0
- package/dist/engine/repos.js.map +1 -0
- package/dist/engine/research.js +134 -0
- package/dist/engine/research.js.map +1 -0
- package/dist/engine/run-logs.js +79 -0
- package/dist/engine/run-logs.js.map +1 -0
- package/dist/engine/run.js +54 -0
- package/dist/engine/run.js.map +1 -0
- package/dist/engine/runs.js +223 -0
- package/dist/engine/runs.js.map +1 -0
- package/dist/engine/session.js +130 -0
- package/dist/engine/session.js.map +1 -0
- package/dist/engine/share.js +124 -0
- package/dist/engine/share.js.map +1 -0
- package/dist/engine/stack-file.js +206 -0
- package/dist/engine/stack-file.js.map +1 -0
- package/dist/engine/stack-share.js +86 -0
- package/dist/engine/stack-share.js.map +1 -0
- package/dist/engine/stacks.js +143 -0
- package/dist/engine/stacks.js.map +1 -0
- package/dist/engine/sync.js +214 -0
- package/dist/engine/sync.js.map +1 -0
- package/dist/engine/traces.js +65 -0
- package/dist/engine/traces.js.map +1 -0
- package/dist/engine/up.js +621 -0
- package/dist/engine/up.js.map +1 -0
- package/dist/engine/watch.js +71 -0
- package/dist/engine/watch.js.map +1 -0
- package/dist/engine/wire.js +120 -0
- package/dist/engine/wire.js.map +1 -0
- package/dist/failure.js +16 -0
- package/dist/failure.js.map +1 -0
- package/dist/github.js +95 -0
- package/dist/github.js.map +1 -0
- package/dist/ids.js +6 -0
- package/dist/ids.js.map +1 -0
- package/dist/json-files.js +36 -0
- package/dist/json-files.js.map +1 -0
- package/dist/koppler.mjs +840 -0
- package/dist/koppler.mjs.map +1 -0
- package/dist/lambda-local.mjs +250 -0
- package/dist/lambda-local.mjs.map +1 -0
- package/dist/lambda-secrets-proxy.go +31 -0
- package/dist/mock-server.mjs +23 -0
- package/dist/mock-server.mjs.map +1 -0
- package/dist/page/assets/JetBrainsMono-cyrillic-D2jMJ_bk.woff2 +0 -0
- package/dist/page/assets/JetBrainsMono-greek-D2nYnAec.woff2 +0 -0
- package/dist/page/assets/JetBrainsMono-latin-Db4Uuiha.woff2 +0 -0
- package/dist/page/assets/JetBrainsMono-latin-ext-Bnd2h4Br.woff2 +0 -0
- package/dist/page/assets/JetBrainsMono-vietnamese-CNlsqbWb.woff2 +0 -0
- package/dist/page/assets/SchibstedGrotesk-latin-DxefFeRw.woff2 +0 -0
- package/dist/page/assets/SchibstedGrotesk-latin-ext-CnpJE18X.woff2 +0 -0
- package/dist/page/assets/index-Bkj_pX35.js +42 -0
- package/dist/page/assets/index-Dq45jswH.css +1 -0
- package/dist/page/index.html +14 -0
- package/dist/page/theme.js +8 -0
- package/dist/paths.js +19 -0
- package/dist/paths.js.map +1 -0
- package/dist/safe-env.js +73 -0
- package/dist/safe-env.js.map +1 -0
- package/dist/sam-local.mjs +135 -0
- package/dist/sam-local.mjs.map +1 -0
- package/dist/scrub.js +87 -0
- package/dist/scrub.js.map +1 -0
- package/dist/secret-check.mjs +262 -0
- package/dist/secret-check.mjs.map +1 -0
- package/dist/server/browser-console.js +117 -0
- package/dist/server/browser-console.js.map +1 -0
- package/dist/server/cable-test.js +365 -0
- package/dist/server/cable-test.js.map +1 -0
- package/dist/server/choices.js +51 -0
- package/dist/server/choices.js.map +1 -0
- package/dist/server/files.js +107 -0
- package/dist/server/files.js.map +1 -0
- package/dist/server/gate.js +128 -0
- package/dist/server/gate.js.map +1 -0
- package/dist/server/logs.js +76 -0
- package/dist/server/logs.js.map +1 -0
- package/dist/server/mobile.js +113 -0
- package/dist/server/mobile.js.map +1 -0
- package/dist/server/routes.js +326 -0
- package/dist/server/routes.js.map +1 -0
- package/dist/server/runs.js +111 -0
- package/dist/server/runs.js.map +1 -0
- package/dist/server/sanitize.js +242 -0
- package/dist/server/sanitize.js.map +1 -0
- package/dist/server/secrets.js +111 -0
- package/dist/server/secrets.js.map +1 -0
- package/dist/server/status.js +321 -0
- package/dist/server/status.js.map +1 -0
- package/dist/server/token.js +38 -0
- package/dist/server/token.js.map +1 -0
- package/dist/server/waiting.js +79 -0
- package/dist/server/waiting.js.map +1 -0
- package/dist/status-watch.mjs +63 -0
- package/dist/status-watch.mjs.map +1 -0
- package/package.json +74 -4
- package/skills/koppler-run/SKILL.md +169 -0
- package/skills/koppler-run/VERSION +1 -0
- package/skills/koppler-run/references/action-log.md +50 -0
- package/skills/koppler-run/references/permissions.md +25 -0
- package/skills/koppler-run/references/preparing-nodes.md +62 -0
- package/skills/koppler-run/references/reporting-bugs.md +76 -0
- package/skills/koppler-run/references/research.md +40 -0
- package/skills/koppler-run/references/secrets.md +56 -0
- package/skills/koppler-run/references/stack.md +197 -0
- package/skills/koppler-run/references/status.md +92 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
// What the user has to do before a set of apps can start, in plain words with one command each, checked live.
|
|
2
|
+
// Usage: koppler doctor [app...] [--env <env>] [--no-tunnels <app,app>] [--json] (default: the apps on the canvas)
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fail as exit } from "../failure.js";
|
|
7
|
+
import { isProtected } from "../core/plan.js";
|
|
8
|
+
import { planSteps, planTunnels, tunnelKind } from "../core/ports.js";
|
|
9
|
+
import { isSignIn, signInOf } from "../core/sign-in.js";
|
|
10
|
+
import { readClones, readData, readStack } from "../data.js";
|
|
11
|
+
import { APPROVE, approved, checksFor, envGaps, stackCommands, startsFromStack } from "./checks.js";
|
|
12
|
+
import { storeOf } from "../core/stack.js";
|
|
13
|
+
const words = (value) => (typeof value === 'string' ? value : undefined);
|
|
14
|
+
/** "Cache (Valkey)" -> "Valkey cache", "Database" -> "database": what an address leads to, in plain words. */
|
|
15
|
+
const friendly = (host) => {
|
|
16
|
+
const kind = tunnelKind({ tunnel: host });
|
|
17
|
+
const [, what, engine] = /^(\w+) \((.+)\)$/.exec(kind) ?? [];
|
|
18
|
+
if (what && engine)
|
|
19
|
+
return `${engine} ${what.toLowerCase()}`;
|
|
20
|
+
return kind === 'Tunnel' ? 'private' : kind.toLowerCase();
|
|
21
|
+
};
|
|
22
|
+
/** A secret's condition: "always" or none means it is needed; anything else is only needed in that case. */
|
|
23
|
+
const always = (when) => !when || /^always\b/i.test(when.trim());
|
|
24
|
+
const run = (command, args, timeout = 8000) => {
|
|
25
|
+
try {
|
|
26
|
+
return {
|
|
27
|
+
ok: true,
|
|
28
|
+
out: execFileSync(command, args, { encoding: 'utf8', timeout, stdio: ['ignore', 'pipe', 'ignore'] }),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { ok: false, out: '' };
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
/** One step per prerequisite: plain title, why the app needs it, the command, where to run it, and how to tell it is done. */
|
|
36
|
+
export function stepsFor(appName, prereqs, context = {}) {
|
|
37
|
+
const steps = [];
|
|
38
|
+
for (const need of prereqs) {
|
|
39
|
+
const signIn = signInOf({ signIns: context.signIns }, need);
|
|
40
|
+
if (signIn)
|
|
41
|
+
steps.push({
|
|
42
|
+
id: signIn.id,
|
|
43
|
+
title: `Sign in to ${signIn.what}`,
|
|
44
|
+
why: need.sso
|
|
45
|
+
? `${appName} reads its settings from AWS when it starts.`
|
|
46
|
+
: `${appName} needs it when it starts.`,
|
|
47
|
+
command: signIn.login,
|
|
48
|
+
where: 'anywhere',
|
|
49
|
+
check: 'shell' in signIn.check
|
|
50
|
+
? { shell: signIn.check.shell }
|
|
51
|
+
: { sso: need.sso ?? '', ...(signIn.account && { account: signIn.account }) },
|
|
52
|
+
browser: true,
|
|
53
|
+
});
|
|
54
|
+
if (need.hosts)
|
|
55
|
+
steps.push({
|
|
56
|
+
id: `hosts:${need.hosts}`,
|
|
57
|
+
title: `Point the ${friendly(need.hosts)} address at your Mac`,
|
|
58
|
+
why: `${appName} connects to ${need.hosts}; on your Mac that name has to lead to the local tunnel.`,
|
|
59
|
+
command: `echo "127.0.0.1 ${need.hosts}" | sudo tee -a /etc/hosts`,
|
|
60
|
+
where: 'your terminal (asks for your Mac password)',
|
|
61
|
+
check: { hosts: need.hosts },
|
|
62
|
+
});
|
|
63
|
+
if (need.devCerts)
|
|
64
|
+
steps.push({
|
|
65
|
+
id: 'devcerts',
|
|
66
|
+
title: 'Trust the local HTTPS certificate',
|
|
67
|
+
why: `${appName} serves https on your Mac; your browser and other apps must trust it.`,
|
|
68
|
+
command: 'dotnet dev-certs https --trust',
|
|
69
|
+
where: 'anywhere',
|
|
70
|
+
check: { devCerts: true },
|
|
71
|
+
});
|
|
72
|
+
if (need.nuget)
|
|
73
|
+
steps.push({
|
|
74
|
+
id: 'nuget',
|
|
75
|
+
title: 'Connect to the private package feed',
|
|
76
|
+
why: `${appName} downloads company packages while it builds.`,
|
|
77
|
+
command: null,
|
|
78
|
+
where: null,
|
|
79
|
+
how: words(need.note),
|
|
80
|
+
check: { stackCheck: /nuget/i },
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const skillPath = (text) => words(text)?.replaceAll('<skill>', context.skill ?? '');
|
|
84
|
+
for (const secret of context.secrets ?? []) {
|
|
85
|
+
const fetch = (secret.fetch ?? {});
|
|
86
|
+
const when = words(secret.when);
|
|
87
|
+
const onlyIf = always(when) ? undefined : when;
|
|
88
|
+
const store = context.store ?? context.appId ?? '';
|
|
89
|
+
const file = words(secret.file);
|
|
90
|
+
if (secret.env)
|
|
91
|
+
steps.push({
|
|
92
|
+
id: `secret:${store}:${secret.env}`,
|
|
93
|
+
title: `Store ${secret.env} for ${appName}`,
|
|
94
|
+
why: `${appName} needs it to start.`,
|
|
95
|
+
onlyIf,
|
|
96
|
+
command: skillPath(fetch.cli) ?? `koppler secret set ${store} ${secret.env}`,
|
|
97
|
+
where: 'your own terminal, not the agent (the value must not land in the conversation)',
|
|
98
|
+
alt: skillPath(fetch.ui),
|
|
99
|
+
check: { secret: [store, secret.env] },
|
|
100
|
+
});
|
|
101
|
+
if (file)
|
|
102
|
+
steps.push({
|
|
103
|
+
id: `file:${context.appId ?? ''}:${file}`,
|
|
104
|
+
title: `Put ${path.basename(file)} in place for ${appName}`,
|
|
105
|
+
why: `${appName} reads it when it starts.`,
|
|
106
|
+
onlyIf,
|
|
107
|
+
command: skillPath(fetch.cli) ?? null,
|
|
108
|
+
where: 'your own terminal',
|
|
109
|
+
alt: skillPath(fetch.ui),
|
|
110
|
+
how: words(secret.note),
|
|
111
|
+
check: { file: path.join(context.repo ?? '', file) },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return steps;
|
|
115
|
+
}
|
|
116
|
+
const inHosts = (file, host) => {
|
|
117
|
+
const mapped = (line) => !line.trim().startsWith('#') && line.split(/\s+/).slice(1).includes(host);
|
|
118
|
+
try {
|
|
119
|
+
return fs.readFileSync(file, 'utf8').split('\n').some(mapped);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
/** Live checks: true when done, false when not, null when it cannot be told. */
|
|
126
|
+
export function isDone(check, world = {}) {
|
|
127
|
+
if (check.sso) {
|
|
128
|
+
const account = ['--query', 'Account', '--output', 'text'];
|
|
129
|
+
const who = run('aws', ['sts', 'get-caller-identity', '--profile', check.sso, ...account]);
|
|
130
|
+
// Signed in to another account is not signed in: its settings and secrets would be the wrong ones.
|
|
131
|
+
return who.ok && (!check.account || who.out.trim() === check.account);
|
|
132
|
+
}
|
|
133
|
+
// The stack wrote it: it runs only once the user approved the stack's commands.
|
|
134
|
+
if (check.shell)
|
|
135
|
+
return world.approved ? run('sh', ['-c', check.shell], 20000).ok : null;
|
|
136
|
+
if (check.hosts)
|
|
137
|
+
return inHosts(world.hostsFile ?? '/etc/hosts', check.hosts);
|
|
138
|
+
if (check.devCerts)
|
|
139
|
+
return run('dotnet', ['dev-certs', 'https', '--check', '--trust']).ok;
|
|
140
|
+
if (check.secret) {
|
|
141
|
+
const [store, name] = check.secret;
|
|
142
|
+
return run(path.join(world.skill ?? '', 'bin', 'secret-list'), [store])
|
|
143
|
+
.out.split(/\s+/)
|
|
144
|
+
.includes(name);
|
|
145
|
+
}
|
|
146
|
+
if (check.file)
|
|
147
|
+
return fs.existsSync(check.file);
|
|
148
|
+
if (check.approved)
|
|
149
|
+
return false;
|
|
150
|
+
if (check.stackCheck) {
|
|
151
|
+
const own = (world.checks ?? []).find(one => check.stackCheck?.test(one.name));
|
|
152
|
+
return own ? run('sh', ['-c', own.run], 20000).ok : null;
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const GAP_WHY = {
|
|
157
|
+
tunnel: (app, what, env) => `Without it ${app} cannot reach its ${what} on ${env}; another environment's would be the wrong database.`,
|
|
158
|
+
'sign-in': (app) => `Another environment's sign-in would give ${app} the wrong account.`,
|
|
159
|
+
hosts: (app) => `Another environment's address would send ${app} to the wrong place.`,
|
|
160
|
+
secret: () => 'The stack only says how to get it for another environment.',
|
|
161
|
+
};
|
|
162
|
+
const literal = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
163
|
+
const runIn = (step) => (step.where && step.where !== 'anywhere' ? `Run in ${step.where}` : 'Run');
|
|
164
|
+
function print(found, names, onProtected, notSetUp) {
|
|
165
|
+
const { steps } = found;
|
|
166
|
+
const ENV = found.env.toUpperCase();
|
|
167
|
+
const todo = steps.filter(step => step.done !== true && !step.onlyIf);
|
|
168
|
+
const maybe = steps.filter(step => step.done !== true && step.onlyIf);
|
|
169
|
+
console.log(`Before ${names.join(', ')} can run on ${ENV}:`);
|
|
170
|
+
// On a protected environment, say up front what stays with the user and what Koppler does.
|
|
171
|
+
if (onProtected)
|
|
172
|
+
console.log(`\n On ${ENV} only you can: sign in to AWS in your browser, store secrets in your own terminal, run sudo steps, and query data (koppler query, in your terminal). Koppler opens the production tunnels and starts the apps when you press Send to ${ENV}.`);
|
|
173
|
+
// An app not set up yet has no prerequisites recorded, so an empty list would wrongly read as "ready".
|
|
174
|
+
if (notSetUp.length) {
|
|
175
|
+
const one = notSetUp.length === 1;
|
|
176
|
+
console.log(`\n Not known yet: ${notSetUp.join(', ')} ${one ? 'is' : 'are'} not set up, so what ${one ? 'it needs' : 'they need'} (sign-ins, tunnels, secrets) is not known. The agent reads ${one ? 'its repo' : 'their repos'} first, then lists it here.`);
|
|
177
|
+
}
|
|
178
|
+
if (!todo.length && !notSetUp.length)
|
|
179
|
+
console.log(' Nothing for you to do.');
|
|
180
|
+
todo.forEach((step, at) => {
|
|
181
|
+
const unsure = step.done === null ? ' (cannot check this one; skip it if you already did)' : '';
|
|
182
|
+
console.log(`\n ${String(at + 1)}. ${step.title}${unsure}`);
|
|
183
|
+
const others = step.apps.length > 1 ? ` (also for ${step.apps.slice(1).join(', ')})` : '';
|
|
184
|
+
console.log(` Why: ${String(step.why)}${others}`);
|
|
185
|
+
if (step.command)
|
|
186
|
+
console.log(` ${runIn(step)}:\n ${step.command}`);
|
|
187
|
+
if (step.browser)
|
|
188
|
+
console.log(' It opens your browser to approve the sign-in.');
|
|
189
|
+
if (step.alt)
|
|
190
|
+
console.log(` Or by hand: ${step.alt}`);
|
|
191
|
+
if (step.how && !step.command)
|
|
192
|
+
console.log(` How: ${step.how}`);
|
|
193
|
+
if (step.undo)
|
|
194
|
+
console.log(` To undo later: ${step.undo}`);
|
|
195
|
+
});
|
|
196
|
+
if (maybe.length) {
|
|
197
|
+
console.log('\n Only in some setups:');
|
|
198
|
+
for (const step of maybe) {
|
|
199
|
+
const when = (step.onlyIf ?? '').replace(/^only\s+(if\s+|with\s+)?/i, '');
|
|
200
|
+
const what = step.command ? `${runIn(step)}: ${step.command}` : (step.how ?? '');
|
|
201
|
+
console.log(` - ${step.title}: only if ${when}\n ${what}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const done = steps.filter(step => step.done === true);
|
|
205
|
+
if (done.length)
|
|
206
|
+
console.log(`\n Already done: ${done.map(step => step.title).join('; ')}.`);
|
|
207
|
+
console.log(`\n Koppler does the rest: ${found.koppler.join(', ')}.`);
|
|
208
|
+
}
|
|
209
|
+
/** The steps for a set of apps on an environment: returned with `collect`, else printed (as JSON with `--json`). */
|
|
210
|
+
export function needs(args, { skill, fail = exit, collect = false }) {
|
|
211
|
+
const stack = readStack() ?? fail('no stack loaded (koppler init)');
|
|
212
|
+
const clones = readClones();
|
|
213
|
+
const envAt = args.indexOf('--env');
|
|
214
|
+
const offAt = args.indexOf('--no-tunnels');
|
|
215
|
+
// Apps run without their tunnels: no tunnel, and no hosts entry pointing at one.
|
|
216
|
+
const noTunnels = new Set(offAt >= 0 ? (args[offAt + 1] ?? '').split(',').filter(Boolean) : []);
|
|
217
|
+
const first = stack.envs[0];
|
|
218
|
+
const env = (envAt >= 0 ? args[envAt + 1] : first) ?? '';
|
|
219
|
+
if (!stack.envs.includes(env))
|
|
220
|
+
fail(`unknown env ${env}; the stack has ${stack.envs.join(', ')}`);
|
|
221
|
+
const given = args.filter((arg, at) => !arg.startsWith('--') && (envAt < 0 || at !== envAt + 1) && (offAt < 0 || at !== offAt + 1));
|
|
222
|
+
const ids = given.length ? given : Object.keys(readData('state')?.['nodes'] ?? {});
|
|
223
|
+
for (const id of ids)
|
|
224
|
+
if (!stack.apps[id])
|
|
225
|
+
fail(`${id} is not an app in the stack`);
|
|
226
|
+
const nameOf = (id) => stack.apps[id]?.name ?? id;
|
|
227
|
+
const ENV = env.toUpperCase();
|
|
228
|
+
// What the stack does not say for this environment: never filled in from the first one.
|
|
229
|
+
const gaps = envGaps(stack, env === first ? '-' : env).filter(gap => ids.includes(gap.app) && !(noTunnels.has(gap.app) && (gap.kind === 'tunnel' || gap.kind === 'hosts')));
|
|
230
|
+
const borrowed = new Set(gaps.filter(gap => gap.kind !== 'secret').map(gap => gap.app));
|
|
231
|
+
const noFetch = new Set(gaps.filter(gap => gap.kind === 'secret').map(gap => `${gap.app}:${String(gap.name)}`));
|
|
232
|
+
// An app without its own prerequisites here keeps only those that hold anywhere (a certificate, a file); never
|
|
233
|
+
// another environment's tunnels, sign-ins, hosts or secret fetch steps.
|
|
234
|
+
const appFor = (id) => {
|
|
235
|
+
const app = stack.apps[id];
|
|
236
|
+
const own = env === first ? undefined : app?.envs?.[env];
|
|
237
|
+
const merged = { ...app, ...own };
|
|
238
|
+
const secrets = merged.secrets?.map(secret => noFetch.has(`${id}:${String(secret.env)}`) ? { ...secret, fetch: undefined } : secret);
|
|
239
|
+
const all = merged.prereqs ?? [];
|
|
240
|
+
// Only the first environment's list is borrowed; an environment's own list is its own, even when it misses a kind.
|
|
241
|
+
const prereqs = borrowed.has(id) && !app?.envs?.[env]?.prereqs
|
|
242
|
+
? all.filter(need => !need.tunnel && !isSignIn(need) && !need.hosts)
|
|
243
|
+
: all;
|
|
244
|
+
return {
|
|
245
|
+
name: nameOf(id),
|
|
246
|
+
secrets,
|
|
247
|
+
prereqs: noTunnels.has(id) ? prereqs.filter(need => !need.tunnel && !need.hosts) : prereqs,
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
// Steps from every app, one per thing to do even when several apps need it.
|
|
251
|
+
const byId = new Map();
|
|
252
|
+
for (const id of ids) {
|
|
253
|
+
const app = appFor(id);
|
|
254
|
+
const context = {
|
|
255
|
+
appId: id,
|
|
256
|
+
store: storeOf(stack, id, env),
|
|
257
|
+
secrets: app.secrets,
|
|
258
|
+
skill,
|
|
259
|
+
repo: clones[id]?.path,
|
|
260
|
+
signIns: stack.signIns,
|
|
261
|
+
};
|
|
262
|
+
for (const step of stepsFor(app.name, app.prereqs, context)) {
|
|
263
|
+
const seen = byId.get(step.id);
|
|
264
|
+
if (seen)
|
|
265
|
+
seen.apps.push(app.name);
|
|
266
|
+
else
|
|
267
|
+
byId.set(step.id, { ...step, apps: [app.name] });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
for (const gap of gaps) {
|
|
271
|
+
const id = `gap:${gap.app}:${gap.kind}:${String(gap.name)}`;
|
|
272
|
+
const app = nameOf(gap.app);
|
|
273
|
+
byId.set(id, {
|
|
274
|
+
id,
|
|
275
|
+
title: gap.detail,
|
|
276
|
+
why: GAP_WHY[gap.kind](app, String(gap.name), ENV),
|
|
277
|
+
command: null,
|
|
278
|
+
where: null,
|
|
279
|
+
how: `Ask the agent: find the ${ENV} facts for ${app}. It reads the repo and your local tunnel aliases and proposes the stack.json change.`,
|
|
280
|
+
check: {},
|
|
281
|
+
gap: true,
|
|
282
|
+
apps: [app],
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
// The tunnel plan can add sudo steps (a loopback alias); tunnels themselves are Koppler's job.
|
|
286
|
+
const tunnels = planTunnels(ids.flatMap(id => appFor(id).prereqs.flatMap(({ tunnel, port, env: setting, connectsAs }) => tunnel && port ? [{ app: id, tunnel, port, env: setting, connectsAs }] : [])));
|
|
287
|
+
const hostOf = (host) => host.split('.')[0] ?? host;
|
|
288
|
+
for (const tunnel of tunnels) {
|
|
289
|
+
if (!tunnel.needsAlias)
|
|
290
|
+
continue;
|
|
291
|
+
const { sudo, undo } = planSteps(tunnel);
|
|
292
|
+
const id = `alias:${tunnel.bind}`;
|
|
293
|
+
byId.set(id, {
|
|
294
|
+
id,
|
|
295
|
+
title: `Give ${hostOf(tunnel.host)} its own local address`,
|
|
296
|
+
why: `Another tunnel needs port ${String(tunnel.port)}; this one keeps it on ${tunnel.bind}.`,
|
|
297
|
+
command: sudo.join(' && '),
|
|
298
|
+
where: 'your terminal (asks for your Mac password)',
|
|
299
|
+
undo: undo.join(' && '),
|
|
300
|
+
apps: tunnel.apps.map(nameOf),
|
|
301
|
+
check: { manual: true },
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
const kindsInRun = new Set(ids.map(id => stack.apps[id]?.kind));
|
|
305
|
+
const own = checksFor(stack).flatMap(check => (check.safe ? [] : [check]));
|
|
306
|
+
for (const check of own) {
|
|
307
|
+
if (check.kinds && !check.kinds.some(kind => kindsInRun.has(kind)))
|
|
308
|
+
continue;
|
|
309
|
+
if ([...byId.values()].some(step => step.check.stackCheck?.test(check.name)))
|
|
310
|
+
continue;
|
|
311
|
+
const id = `check:${check.name}`;
|
|
312
|
+
byId.set(id, {
|
|
313
|
+
id,
|
|
314
|
+
title: check.fix,
|
|
315
|
+
doneTitle: check.ok,
|
|
316
|
+
why: `The stack checks this before a run (${check.name}).`,
|
|
317
|
+
command: null,
|
|
318
|
+
apps: [],
|
|
319
|
+
check: { stackCheck: new RegExp(`^${literal(check.name)}$`) },
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// The stack's own checks are shell commands: they run only once the user approved them (koppler doctor --approve).
|
|
323
|
+
const mayRun = approved(stack.source ?? '', stack);
|
|
324
|
+
// What the stack runs or writes for these apps needs the user's yes first: its checks, a start command it gives, a
|
|
325
|
+
// code change.
|
|
326
|
+
const writes = (id) => startsFromStack(stack, id, env) || !!stack.apps[id]?.localChanges?.length;
|
|
327
|
+
if (!mayRun && (stackCommands(stack).some(command => command.what === 'check') || ids.some(writes)))
|
|
328
|
+
byId.set('approve-stack', {
|
|
329
|
+
id: 'approve-stack',
|
|
330
|
+
title: 'Review and allow what this stack runs on your Mac',
|
|
331
|
+
why: 'The stack carries its own commands or code changes, written by whoever edits it. Koppler runs none of them until you have seen them.',
|
|
332
|
+
command: APPROVE,
|
|
333
|
+
where: 'your own terminal',
|
|
334
|
+
apps: [],
|
|
335
|
+
check: { approved: true },
|
|
336
|
+
});
|
|
337
|
+
// In the order they can be done: what the stack is missing, then sign-ins (a secret's fetch needs them), then the
|
|
338
|
+
// rest, secrets last.
|
|
339
|
+
const rank = (step) => step.gap ? 0 : step.check.sso || step.check.shell ? 1 : step.id.startsWith('secret:') ? 3 : 2;
|
|
340
|
+
const world = { skill, checks: mayRun ? own : [], approved: mayRun };
|
|
341
|
+
const steps = [...byId.values()]
|
|
342
|
+
.sort((a, b) => rank(a) - rank(b))
|
|
343
|
+
.map((step) => {
|
|
344
|
+
const done = step.gap ? false : isDone(step.check, world);
|
|
345
|
+
return { ...step, done, title: done && step.doneTitle ? step.doneTitle : step.title };
|
|
346
|
+
});
|
|
347
|
+
// A tunnel whose port already answers is not opened again.
|
|
348
|
+
const open = (port) => /\bLISTEN\b/.test(run('lsof', ['-nP', `-iTCP:${String(port)}`, '-sTCP:LISTEN']).out);
|
|
349
|
+
const koppler = [
|
|
350
|
+
...tunnels.map(tunnel => `tunnel to ${hostOf(tunnel.host)} on ${tunnel.bind}:${String(tunnel.port)}${open(tunnel.port) ? ' (already open)' : ''}`),
|
|
351
|
+
...ids.map(id => `start ${nameOf(id)}`),
|
|
352
|
+
];
|
|
353
|
+
const notSetUp = ids.filter(id => stack.apps[id]?.['pending']);
|
|
354
|
+
const found = { env, apps: ids, steps, koppler, notSetUp };
|
|
355
|
+
if (collect)
|
|
356
|
+
return found;
|
|
357
|
+
if (args.includes('--json'))
|
|
358
|
+
console.log(JSON.stringify(found, null, 2));
|
|
359
|
+
else
|
|
360
|
+
print(found, ids.map(nameOf), isProtected(stack, env), notSetUp.map(nameOf));
|
|
361
|
+
return undefined;
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=needs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"needs.js","sourceRoot":"","sources":["../../src/engine/needs.ts"],"names":[],"mappings":"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"}
|