@monster-orange/den 0.0.0-stage → 0.1.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/CHANGELOG.md +67 -0
- package/LICENSE +21 -0
- package/README.md +166 -2
- package/bin/den +61 -0
- package/docs/distributions.md +256 -0
- package/make/demo.mk +82 -0
- package/make/den.mk +80 -0
- package/make/journeys.mk +57 -0
- package/make/local_dev.mk +154 -0
- package/make/security.mk +59 -0
- package/make/test.mk +405 -0
- package/package.json +104 -4
- package/scripts/auth-configure.ts +415 -0
- package/scripts/heal-config.ts +92 -0
- package/scripts/jsonl-playwright-reporter.js +70 -0
- package/scripts/manifest-read.cjs +91 -0
- package/scripts/setup-1password.ts +570 -0
- package/scripts/setup-secrets.ts +149 -0
- package/scripts/view-results.js +156 -0
- package/service/install.sh +112 -0
- package/src/pillars/api/fixtures/index.ts +128 -0
- package/src/pillars/api/fixtures/openapi-validator.ts +111 -0
- package/src/pillars/api/global-setup.ts +103 -0
- package/src/pillars/api/playwright.config.ts +105 -0
- package/src/pillars/api/schemas/example-api.json +110 -0
- package/src/pillars/api/tests/health/health.spec.ts +19 -0
- package/src/pillars/api/tests/health/manifest.yml +6 -0
- package/src/pillars/browser/fixtures/index.ts +232 -0
- package/src/pillars/browser/fixtures/package.json +10 -0
- package/src/pillars/browser/global-setup.ts +140 -0
- package/src/pillars/browser/global-teardown.ts +48 -0
- package/src/pillars/browser/playwright.config.ts +212 -0
- package/src/pillars/browser/setup.ts +219 -0
- package/src/pillars/journeys/app-config.ts +237 -0
- package/src/pillars/journeys/discover.ts +160 -0
- package/src/pillars/journeys/hooks/deny-shell.cjs +44 -0
- package/src/pillars/journeys/observability/events.ts +288 -0
- package/src/pillars/journeys/observability/sdk-mapper.ts +306 -0
- package/src/pillars/journeys/report/friction.ts +304 -0
- package/src/pillars/journeys/report/junit.ts +105 -0
- package/src/pillars/journeys/report/render.ts +273 -0
- package/src/pillars/journeys/report/results.ts +323 -0
- package/src/pillars/journeys/run.ts +673 -0
- package/src/pillars/journeys/runner.ts +1025 -0
- package/src/pillars/journeys/sandbox.ts +406 -0
- package/src/pillars/journeys/spec/loader.ts +152 -0
- package/src/pillars/journeys/spec/schema.ts +208 -0
- package/src/pillars/journeys/teardown.ts +98 -0
- package/src/pillars/journeys/tools/browser-session.ts +219 -0
- package/src/pillars/journeys/tools/browser-tool.ts +914 -0
- package/src/pillars/journeys/tools/http-tool.ts +564 -0
- package/src/pillars/journeys/tools/ledger.ts +278 -0
- package/src/pillars/journeys/tools/snapshot-store.ts +117 -0
- package/src/pillars/journeys/verify/assertions.ts +502 -0
- package/src/pillars/journeys/verify/verdict.ts +71 -0
- package/src/pillars/perf/build-report.ts +36 -0
- package/src/pillars/perf/k6.config.js +112 -0
- package/src/pillars/perf/run.ts +345 -0
- package/src/pillars/perf/scenarios/load-profile.js +97 -0
- package/src/pillars/perf/staging.ts +73 -0
- package/src/pillars/security/discover.ts +108 -0
- package/src/pillars/security/findings.ts +151 -0
- package/src/pillars/security/plan.ts +355 -0
- package/src/pillars/security/run.ts +729 -0
- package/src/pillars/smoke/admin-probe.ts +68 -0
- package/src/pillars/smoke/base-url.ts +56 -0
- package/src/pillars/smoke/cleanup.ts +8 -0
- package/src/pillars/smoke/discover.ts +237 -0
- package/src/pillars/smoke/ensure-smoke-teardown.ts +40 -0
- package/src/pillars/smoke/fixture-manager.ts +217 -0
- package/src/pillars/smoke/fixtures.ts +468 -0
- package/src/pillars/smoke/global-setup-all.ts +262 -0
- package/src/pillars/smoke/global-setup-global.ts +262 -0
- package/src/pillars/smoke/global-setup.ts +273 -0
- package/src/pillars/smoke/global-teardown-all.ts +8 -0
- package/src/pillars/smoke/global-teardown-global.ts +8 -0
- package/src/pillars/smoke/global-teardown.ts +139 -0
- package/src/pillars/smoke/playwright-all.config.ts +147 -0
- package/src/pillars/smoke/playwright-global.config.ts +141 -0
- package/src/pillars/smoke/playwright.config.ts +162 -0
- package/src/pillars/smoke/setup-env.ts +132 -0
- package/src/pillars/smoke/setup-global.ts +126 -0
- package/src/pillars/smoke/setup.ts +115 -0
- package/src/pillars/smoke/smoke-repo.ts +16 -0
- package/src/pillars/smoke/staging.ts +49 -0
- package/src/pillars/suites/run.ts +147 -0
- package/src/scripts/configure-aws-profiles.ts +114 -0
- package/src/scripts/register-repos.ts +307 -0
- package/src/scripts/setup-default-workspace.ts +203 -0
- package/src/shared/applications.ts +138 -0
- package/src/shared/auth/api-token.ts +416 -0
- package/src/shared/auth/auth0-helper.ts +284 -0
- package/src/shared/auth/headless-login.ts +265 -0
- package/src/shared/auth/jwt-helper.ts +186 -0
- package/src/shared/auth/sudo-vault.ts +69 -0
- package/src/shared/auth/test-accounts.ts +98 -0
- package/src/shared/auth/token-injection.ts +184 -0
- package/src/shared/auth/token-providers/auth0.ts +80 -0
- package/src/shared/auth/token-providers/index.ts +182 -0
- package/src/shared/auth/token-refresh.ts +273 -0
- package/src/shared/banner.ts +15 -0
- package/src/shared/brand.ts +79 -0
- package/src/shared/cli-tabs.ts +131 -0
- package/src/shared/constants.ts +128 -0
- package/src/shared/den-config.ts +566 -0
- package/src/shared/dev-metrics/emit.ts +354 -0
- package/src/shared/edge/config.ts +229 -0
- package/src/shared/edge/render.ts +221 -0
- package/src/shared/edge/runtime.ts +268 -0
- package/src/shared/edge/types.ts +62 -0
- package/src/shared/engine.ts +67 -0
- package/src/shared/environment/aws-profiles.ts +49 -0
- package/src/shared/environment/env-selector.ts +161 -0
- package/src/shared/environment/playwright-env.ts +82 -0
- package/src/shared/environment-manager/catalog.ts +77 -0
- package/src/shared/environment-manager/clone-guard.ts +163 -0
- package/src/shared/environment-manager/dag.ts +286 -0
- package/src/shared/environment-manager/default-workspace.ts +182 -0
- package/src/shared/environment-manager/derivation/alias.ts +90 -0
- package/src/shared/environment-manager/derivation/cache.ts +97 -0
- package/src/shared/environment-manager/derivation/derive-graph.ts +421 -0
- package/src/shared/environment-manager/derivation/derived-up.ts +354 -0
- package/src/shared/environment-manager/derivation/load-alias.ts +11 -0
- package/src/shared/environment-manager/derivation/rules-compose.ts +42 -0
- package/src/shared/environment-manager/derivation/rules-events.ts +50 -0
- package/src/shared/environment-manager/derivation/rules-http.ts +247 -0
- package/src/shared/environment-manager/derivation/rules-infra.ts +64 -0
- package/src/shared/environment-manager/derivation/rules-readiness.ts +96 -0
- package/src/shared/environment-manager/derivation/scan.ts +160 -0
- package/src/shared/environment-manager/derivation/text.ts +40 -0
- package/src/shared/environment-manager/derivation/types.ts +69 -0
- package/src/shared/environment-manager/health.ts +589 -0
- package/src/shared/environment-manager/index.ts +6 -0
- package/src/shared/environment-manager/load-applications.ts +78 -0
- package/src/shared/environment-manager/log-tail.ts +212 -0
- package/src/shared/environment-manager/make-targets.ts +78 -0
- package/src/shared/environment-manager/opctl.ts +334 -0
- package/src/shared/environment-manager/readiness.ts +93 -0
- package/src/shared/environment-manager/register-local.ts +72 -0
- package/src/shared/environment-manager/secrets-check.ts +260 -0
- package/src/shared/environment-manager/service-env.ts +110 -0
- package/src/shared/environment-manager/service-runner.ts +1588 -0
- package/src/shared/environment-manager/up-plan.ts +302 -0
- package/src/shared/environment-manager/workspace-manager.ts +905 -0
- package/src/shared/environment-manager/workspaces.ts +860 -0
- package/src/shared/manifest/deps.ts +27 -0
- package/src/shared/manifest/migrate-manifest.ts +101 -0
- package/src/shared/manifest/read-manifest.ts +160 -0
- package/src/shared/manifest/schema.ts +299 -0
- package/src/shared/manifest/service-links.ts +93 -0
- package/src/shared/manifest/validate-manifest.ts +140 -0
- package/src/shared/manifest/workspace-manifests.ts +92 -0
- package/src/shared/open-url.ts +122 -0
- package/src/shared/org.ts +44 -0
- package/src/shared/paths.ts +178 -0
- package/src/shared/perf/optional-fields.ts +105 -0
- package/src/shared/perf/report-normalizer.ts +404 -0
- package/src/shared/perf/report-paths.ts +19 -0
- package/src/shared/perf/report-store.ts +110 -0
- package/src/shared/perf/report-types.ts +70 -0
- package/src/shared/perf/test-paths.ts +25 -0
- package/src/shared/process/log-rotation.ts +147 -0
- package/src/shared/process/spawn-streaming.ts +229 -0
- package/src/shared/product.ts +92 -0
- package/src/shared/profile.ts +141 -0
- package/src/shared/repo-kind.ts +32 -0
- package/src/shared/reporting/jsonl-reporter.ts +131 -0
- package/src/shared/reporting/slack-reporter.ts +340 -0
- package/src/shared/results/result-reader.ts +266 -0
- package/src/shared/results/result-writer.ts +168 -0
- package/src/shared/secrets/doppler.ts +126 -0
- package/src/shared/secrets/env.ts +48 -0
- package/src/shared/secrets/index.ts +197 -0
- package/src/shared/secrets/keys.ts +33 -0
- package/src/shared/secrets/onepassword.ts +75 -0
- package/src/shared/secrets/types.ts +52 -0
- package/src/shared/service-url.ts +119 -0
- package/src/shared/smoke/branch-resolver.ts +141 -0
- package/src/shared/smoke/git-remote.ts +70 -0
- package/src/shared/smoke/repo-cloner.ts +151 -0
- package/src/shared/stacks/config.ts +137 -0
- package/src/shared/stacks/manifest-commands.ts +88 -0
- package/src/shared/stacks/render.ts +253 -0
- package/src/shared/stacks/runtime.ts +334 -0
- package/src/shared/stacks/types.ts +53 -0
- package/src/shared/terminal/tabs.ts +212 -0
- package/src/shared/test-discovery/module-scanner.ts +569 -0
- package/src/shared/types/index.ts +678 -0
- package/src/shared/ui-marker.ts +19 -0
- package/src/ui/cli/applications-command.ts +116 -0
- package/src/ui/cli/config-command.ts +68 -0
- package/src/ui/cli/create-main.ts +9 -0
- package/src/ui/cli/create.ts +360 -0
- package/src/ui/cli/edge-command.ts +91 -0
- package/src/ui/cli/flag-parser.ts +246 -0
- package/src/ui/cli/graph-command.ts +524 -0
- package/src/ui/cli/health-display.ts +63 -0
- package/src/ui/cli/index.ts +3656 -0
- package/src/ui/cli/init.ts +855 -0
- package/src/ui/cli/invocation-target.ts +175 -0
- package/src/ui/cli/logs-command.ts +104 -0
- package/src/ui/cli/module-selection.ts +31 -0
- package/src/ui/cli/prompts.ts +767 -0
- package/src/ui/cli/results-viewer.ts +436 -0
- package/src/ui/cli/secrets-preflight.ts +91 -0
- package/src/ui/cli/stack-command.ts +144 -0
- package/src/ui/cli/stalled-setup-recovery.ts +129 -0
- package/src/ui/cli/test-runner.ts +1312 -0
- package/src/ui/cli/web-command.ts +1073 -0
- package/src/ui/server/changelog-parser.ts +94 -0
- package/src/ui/server/daemon-reaper.ts +129 -0
- package/src/ui/server/editor-manager.ts +301 -0
- package/src/ui/server/github-service.ts +223 -0
- package/src/ui/server/http-helpers.ts +98 -0
- package/src/ui/server/index.ts +3236 -0
- package/src/ui/server/log-history.ts +452 -0
- package/src/ui/server/perf-report.ts +42 -0
- package/src/ui/server/public/environments.html +494 -0
- package/src/ui/server/public/favicon.ico +0 -0
- package/src/ui/server/public/header.js +1371 -0
- package/src/ui/server/public/index.html +2595 -0
- package/src/ui/server/public/local-dev.html +7405 -0
- package/src/ui/server/public/logs.html +1489 -0
- package/src/ui/server/public/perf-report.js +359 -0
- package/src/ui/server/public/release.html +2111 -0
- package/src/ui/server/public/services.html +1098 -0
- package/src/ui/server/public/workspace-picker.js +69 -0
- package/src/ui/server/release-deploy-session.ts +246 -0
- package/src/ui/server/release-service.ts +1125 -0
- package/src/ui/server/sudo-store.ts +111 -0
- package/src/ui/server/workspace-routes.ts +2154 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { getInvokeCwd } from "../../shared/paths.js";
|
|
4
|
+
import type {
|
|
5
|
+
ResolvedService,
|
|
6
|
+
ServiceCatalog,
|
|
7
|
+
WorkspaceConfig,
|
|
8
|
+
} from "../../shared/types/index.js";
|
|
9
|
+
import {
|
|
10
|
+
listWorkspaceServices,
|
|
11
|
+
parseAddress,
|
|
12
|
+
} from "../../shared/environment-manager/workspaces.js";
|
|
13
|
+
import { readManifest } from "../../shared/manifest/read-manifest.js";
|
|
14
|
+
import { getGitHubCoords } from "../../shared/smoke/git-remote.js";
|
|
15
|
+
import type { AliasResolver } from "../../shared/environment-manager/derivation/alias.js";
|
|
16
|
+
import { loadAliasResolver } from "../../shared/environment-manager/derivation/load-alias.js";
|
|
17
|
+
|
|
18
|
+
import { product } from "../../shared/product.js";
|
|
19
|
+
export interface InvocationTarget {
|
|
20
|
+
repoRoot: string;
|
|
21
|
+
repoName: string;
|
|
22
|
+
addresses: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function realPathSafe(input: string): string {
|
|
26
|
+
try {
|
|
27
|
+
return fs.realpathSync.native(input);
|
|
28
|
+
} catch {
|
|
29
|
+
return path.resolve(input);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function hasRepoMarker(dir: string): boolean {
|
|
34
|
+
return (
|
|
35
|
+
fs.existsSync(path.join(dir, `${product().manifestYml}`)) ||
|
|
36
|
+
fs.existsSync(path.join(dir, `${product().manifestJson}`)) ||
|
|
37
|
+
fs.existsSync(path.join(dir, ".git"))
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function findInvocationRepoRoot(
|
|
42
|
+
cwd: string = getInvokeCwd(),
|
|
43
|
+
): string | null {
|
|
44
|
+
let dir = path.resolve(cwd);
|
|
45
|
+
while (dir.length > 0) {
|
|
46
|
+
if (hasRepoMarker(dir)) return dir;
|
|
47
|
+
const parent = path.dirname(dir);
|
|
48
|
+
if (parent === dir) return null;
|
|
49
|
+
dir = parent;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The canonical repo-system the cwd belongs to (and its repo root), identified by
|
|
56
|
+
* IDENTITY not exact path — so it resolves whether you're in a sibling checkout
|
|
57
|
+
* or a managed clone. Tries, in order: the repo's `.den.yml` name, the
|
|
58
|
+
* folder name, the parent folder name (managed clones live at `<repo>/<branch>/`).
|
|
59
|
+
* Returns null when the cwd isn't inside a known repo.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveCwdRepo(
|
|
62
|
+
alias: AliasResolver = loadAliasResolver(),
|
|
63
|
+
): { repo: string; root: string } | null {
|
|
64
|
+
const root = findInvocationRepoRoot();
|
|
65
|
+
if (!root) return null;
|
|
66
|
+
const candidates = [
|
|
67
|
+
readManifest(root)?.name,
|
|
68
|
+
path.basename(root),
|
|
69
|
+
path.basename(path.dirname(root)),
|
|
70
|
+
];
|
|
71
|
+
for (const c of candidates) {
|
|
72
|
+
if (!c) continue;
|
|
73
|
+
const resolved = alias.resolve(c);
|
|
74
|
+
const node =
|
|
75
|
+
resolved && alias.knownRepos.has(resolved)
|
|
76
|
+
? resolved
|
|
77
|
+
: alias.knownRepos.has(c)
|
|
78
|
+
? c
|
|
79
|
+
: undefined;
|
|
80
|
+
if (node) return { repo: node, root };
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function uniqueServices(services: ResolvedService[]): ResolvedService[] {
|
|
86
|
+
const seen = new Set<string>();
|
|
87
|
+
const result: ResolvedService[] = [];
|
|
88
|
+
for (const svc of services) {
|
|
89
|
+
if (seen.has(svc.address)) continue;
|
|
90
|
+
seen.add(svc.address);
|
|
91
|
+
result.push(svc);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function servicesForRepoPath(
|
|
97
|
+
repoRoot: string,
|
|
98
|
+
services: ResolvedService[],
|
|
99
|
+
): ResolvedService[] {
|
|
100
|
+
const target = realPathSafe(repoRoot);
|
|
101
|
+
return services.filter((svc) => realPathSafe(svc.repoPath) === target);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function servicesForGitRemote(
|
|
105
|
+
repoRoot: string,
|
|
106
|
+
services: ResolvedService[],
|
|
107
|
+
catalog: ServiceCatalog,
|
|
108
|
+
): ResolvedService[] {
|
|
109
|
+
const coords = getGitHubCoords(repoRoot);
|
|
110
|
+
if (!coords) return [];
|
|
111
|
+
|
|
112
|
+
const slug = `${coords.owner}/${coords.repo}`.toLowerCase();
|
|
113
|
+
return services.filter((svc) => {
|
|
114
|
+
const catalogSlug = catalog[svc.repoName]?.gh?.toLowerCase();
|
|
115
|
+
return catalogSlug === slug || svc.repoName === coords.repo;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function selectAddresses(
|
|
120
|
+
repoRoot: string,
|
|
121
|
+
repoName: string,
|
|
122
|
+
services: ResolvedService[],
|
|
123
|
+
): string[] {
|
|
124
|
+
const unique = uniqueServices(services);
|
|
125
|
+
const manifest = readManifest(repoRoot);
|
|
126
|
+
const serviceKeys = Object.keys(manifest?.services ?? {});
|
|
127
|
+
|
|
128
|
+
if (serviceKeys.length <= 1 || unique.length <= 1) {
|
|
129
|
+
return [unique[0].address];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (manifest?.entrypoint) {
|
|
133
|
+
const entrypointAddress = `${repoName}/${manifest.entrypoint}`;
|
|
134
|
+
const matched = unique.find(
|
|
135
|
+
(svc) =>
|
|
136
|
+
svc.address === entrypointAddress ||
|
|
137
|
+
svc.subsystem === manifest.entrypoint,
|
|
138
|
+
);
|
|
139
|
+
return [matched?.address ?? entrypointAddress];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return unique.map((svc) => svc.address);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function resolveInvocationTarget(
|
|
146
|
+
workspaceName: string,
|
|
147
|
+
workspace: WorkspaceConfig,
|
|
148
|
+
catalog: ServiceCatalog,
|
|
149
|
+
cwd: string = getInvokeCwd(),
|
|
150
|
+
): InvocationTarget | null {
|
|
151
|
+
const repoRoot = findInvocationRepoRoot(cwd);
|
|
152
|
+
if (!repoRoot) return null;
|
|
153
|
+
|
|
154
|
+
const workspaceServices = listWorkspaceServices(
|
|
155
|
+
workspace,
|
|
156
|
+
catalog,
|
|
157
|
+
workspaceName,
|
|
158
|
+
);
|
|
159
|
+
const matched = uniqueServices([
|
|
160
|
+
...servicesForRepoPath(repoRoot, workspaceServices),
|
|
161
|
+
...servicesForGitRemote(repoRoot, workspaceServices, catalog),
|
|
162
|
+
]);
|
|
163
|
+
if (matched.length === 0) return null;
|
|
164
|
+
|
|
165
|
+
const repoName =
|
|
166
|
+
matched[0].repoName ||
|
|
167
|
+
parseAddress(matched[0].address, catalog).repoName ||
|
|
168
|
+
path.basename(repoRoot);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
repoRoot,
|
|
172
|
+
repoName,
|
|
173
|
+
addresses: selectAddresses(repoRoot, repoName, matched),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import type { AliasResolver } from "../../shared/environment-manager/derivation/alias.js";
|
|
3
|
+
import {
|
|
4
|
+
followTailSources,
|
|
5
|
+
resolveTailSources,
|
|
6
|
+
} from "../../shared/environment-manager/log-tail.js";
|
|
7
|
+
import type { ResolvedService } from "../../shared/types/index.js";
|
|
8
|
+
import { resolveCwdRepo } from "./invocation-target.js";
|
|
9
|
+
|
|
10
|
+
import { product } from "../../shared/product.js";
|
|
11
|
+
export type LogsTarget =
|
|
12
|
+
| { kind: "repo"; target: string }
|
|
13
|
+
| { kind: "address"; target: string }
|
|
14
|
+
| { kind: "unknown-repo"; arg: string }
|
|
15
|
+
| { kind: "no-cwd-repo" };
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `den logs [repo]` target resolution: an explicit arg is alias-resolved
|
|
19
|
+
* against the known repo-systems (a `repo/subsystem` address passes through
|
|
20
|
+
* untouched); with no arg, the cwd repo is used.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveLogsTarget(
|
|
23
|
+
args: string[],
|
|
24
|
+
alias: AliasResolver,
|
|
25
|
+
cwdRepo: () => { repo: string; root: string } | null = () =>
|
|
26
|
+
resolveCwdRepo(alias),
|
|
27
|
+
): LogsTarget {
|
|
28
|
+
const arg = args.find((a) => !a.startsWith("-"));
|
|
29
|
+
if (arg) {
|
|
30
|
+
if (arg.includes("/")) return { kind: "address", target: arg };
|
|
31
|
+
const resolved = alias.resolve(arg);
|
|
32
|
+
const repo =
|
|
33
|
+
resolved && alias.knownRepos.has(resolved)
|
|
34
|
+
? resolved
|
|
35
|
+
: alias.knownRepos.has(arg)
|
|
36
|
+
? arg
|
|
37
|
+
: undefined;
|
|
38
|
+
return repo
|
|
39
|
+
? { kind: "repo", target: repo }
|
|
40
|
+
: { kind: "unknown-repo", arg };
|
|
41
|
+
}
|
|
42
|
+
const cwd = cwdRepo();
|
|
43
|
+
return cwd ? { kind: "repo", target: cwd.repo } : { kind: "no-cwd-repo" };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Tail the service's live logs to stdout until the stream ends or the user
|
|
48
|
+
* hits Ctrl-C. Returns the exit code the CLI should finish with.
|
|
49
|
+
* `waitForSourceMs` keeps polling for a log source to appear — used right
|
|
50
|
+
* after starting a service, when its container/daemon log may not exist yet
|
|
51
|
+
* (e.g. tab-runtime ups write no daemon file until the container is up).
|
|
52
|
+
*/
|
|
53
|
+
export async function tailServiceLogs(
|
|
54
|
+
resolved: ResolvedService,
|
|
55
|
+
opts: { waitForSourceMs?: number } = {},
|
|
56
|
+
): Promise<number> {
|
|
57
|
+
let candidates = resolveTailSources(resolved);
|
|
58
|
+
if (candidates.length === 0 && opts.waitForSourceMs) {
|
|
59
|
+
const deadline = Date.now() + opts.waitForSourceMs;
|
|
60
|
+
while (candidates.length === 0 && Date.now() < deadline) {
|
|
61
|
+
await new Promise((resolve) => setTimeout(resolve, 1_000));
|
|
62
|
+
candidates = resolveTailSources(resolved);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (candidates.length === 0) {
|
|
66
|
+
console.log(
|
|
67
|
+
chalk.yellow(`\n No local log source found for ${resolved.address}.`),
|
|
68
|
+
);
|
|
69
|
+
console.log(
|
|
70
|
+
chalk.gray(
|
|
71
|
+
` (no manifest logs.local command, no running container, and no ${product().cli}`,
|
|
72
|
+
),
|
|
73
|
+
);
|
|
74
|
+
console.log(
|
|
75
|
+
chalk.gray(
|
|
76
|
+
` daemon log — services started outside ${product().cli} don't get one; '${product().cli} up ${resolved.repoName}' does.)\n`,
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(
|
|
83
|
+
chalk.gray(`\n Tailing logs for ${resolved.address} — Ctrl-C to stop.`),
|
|
84
|
+
);
|
|
85
|
+
const handle = followTailSources(candidates, {
|
|
86
|
+
onLine: (line) => console.log(line),
|
|
87
|
+
onMeta: (line) => console.log(chalk.gray(` ${line}`)),
|
|
88
|
+
});
|
|
89
|
+
// Ctrl-C stops the tail (the child shares our process group); SIGTERM/SIGHUP
|
|
90
|
+
// land only on this process, so without stop() they'd orphan a live
|
|
91
|
+
// `docker logs -f`/`tail -F` child.
|
|
92
|
+
const onSignal = (): void => handle.stop();
|
|
93
|
+
const signals: NodeJS.Signals[] = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
94
|
+
for (const sig of signals) process.once(sig, onSignal);
|
|
95
|
+
// `den logs x | head` closes stdout mid-stream: without a handler the
|
|
96
|
+
// next console.log crashes node with an unhandled EPIPE and orphans the
|
|
97
|
+
// detached tail child. Standard pipe semantics: stop tailing, exit clean.
|
|
98
|
+
const onStdoutError = (): void => handle.stop();
|
|
99
|
+
process.stdout.on("error", onStdoutError);
|
|
100
|
+
const code = await handle.done;
|
|
101
|
+
for (const sig of signals) process.removeListener(sig, onSignal);
|
|
102
|
+
process.stdout.removeListener("error", onStdoutError);
|
|
103
|
+
return code;
|
|
104
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
interface NamedModule {
|
|
2
|
+
name: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
interface ResolvePerformanceModulesOptions {
|
|
6
|
+
availableModules: NamedModule[];
|
|
7
|
+
selectedModule?: string | null;
|
|
8
|
+
repoName?: string | null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function resolvePerformanceModules({
|
|
12
|
+
availableModules,
|
|
13
|
+
selectedModule,
|
|
14
|
+
repoName,
|
|
15
|
+
}: ResolvePerformanceModulesOptions): string[] {
|
|
16
|
+
if (selectedModule) {
|
|
17
|
+
return [selectedModule];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (repoName) {
|
|
21
|
+
const repoModules = availableModules
|
|
22
|
+
.map((module) => module.name)
|
|
23
|
+
.filter((name) => name.startsWith(`${repoName}/`));
|
|
24
|
+
if (repoModules.length === 0) {
|
|
25
|
+
throw new Error(`No performance modules found for repo "${repoName}"`);
|
|
26
|
+
}
|
|
27
|
+
return repoModules;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return availableModules.map((module) => module.name);
|
|
31
|
+
}
|