@kici-dev/orchestrator 0.1.20 → 0.1.22
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/agent/dispatcher.d.ts +44 -0
- package/dist/agent/host-roster-reaper.d.ts +2 -1
- package/dist/agent/host-roster.d.ts +54 -1
- package/dist/agent/registry.d.ts +22 -0
- package/dist/app.d.ts +5 -0
- package/dist/approvals/step-approval-bridge.d.ts +5 -0
- package/dist/cli/commands/source-manifest.d.ts +42 -0
- package/dist/cli/loopback-callback.d.ts +24 -0
- package/dist/cli/open-browser.d.ts +12 -0
- package/dist/cli/service/compose.d.ts +13 -0
- package/dist/cli/service/deploy-env.d.ts +31 -0
- package/dist/cli.js +1204 -256
- package/dist/cluster/coordinator.d.ts +5 -3
- package/dist/cluster/index.d.ts +2 -0
- package/dist/cluster/join-token.d.ts +27 -5
- package/dist/cluster/peer-auth-coordinator.d.ts +36 -0
- package/dist/cluster/peer-client.d.ts +34 -14
- package/dist/cluster/peer-credentials.d.ts +14 -2
- package/dist/cluster/peer-handler.d.ts +2 -2
- package/dist/cluster/rerouted-job-guard.d.ts +39 -0
- package/dist/config.d.ts +6 -0
- package/dist/dashboard/needs-edges.d.ts +4 -3
- package/dist/db/migrations/043_rerouted_to_peer.d.ts +4 -0
- package/dist/db/migrations/044_check_mode.d.ts +4 -0
- package/dist/db/migrations/045_host_properties.d.ts +16 -0
- package/dist/db/migrations/046_join_token_consumed_by_instance.d.ts +17 -0
- package/dist/db/migrations/047_needs_run_on.d.ts +4 -0
- package/dist/db/migrations/048_host_reboot_pending.d.ts +19 -0
- package/dist/db/migrations/049_held_runs_payload.d.ts +14 -0
- package/dist/db/migrations/050_sources_slug.d.ts +17 -0
- package/dist/db/types.d.ts +60 -5
- package/dist/deployment/deployment-identity.d.ts +9 -0
- package/dist/entry-helpers.d.ts +7 -0
- package/dist/environments/held-runs.d.ts +7 -1
- package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +77 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +1187 -33
- package/dist/lockfile-validate.d.ts +24 -0
- package/dist/orchestrator-core.d.ts +13 -1
- package/dist/pipeline/decorating-secret-resolver.d.ts +32 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +127 -3
- package/dist/pipeline/install-secrets-resolver.d.ts +2 -2
- package/dist/pipeline/needs-scheduler.d.ts +22 -13
- package/dist/pipeline/processor.d.ts +2 -2
- package/dist/pipeline/test-pipeline.d.ts +37 -58
- package/dist/providers/github/manifest-form.d.ts +15 -0
- package/dist/providers/github/manifest.d.ts +103 -0
- package/dist/reporting/execution-tracker.d.ts +10 -1
- package/dist/routes/admin-sources.d.ts +18 -0
- package/dist/routes/admin.d.ts +8 -0
- package/dist/secrets/pg-secret-store.d.ts +9 -0
- package/dist/secrets/secret-resolver.d.ts +16 -1
- package/dist/server.js +4373 -2322
- package/dist/sources/source-store.d.ts +4 -0
- package/dist/sources/source-validator.d.ts +2 -0
- package/dist/stale-detector/reboot-deadline-sweep.d.ts +29 -0
- package/dist/stale-detector/stale-run-detector.d.ts +8 -0
- package/dist/standalone.js +3582 -1932
- package/dist/worker/in-memory-job-queue.d.ts +17 -0
- package/dist/worker/peer-outbox.d.ts +36 -0
- package/dist/worker/worker-outbox-relay.d.ts +13 -0
- package/dist/ws/agent-handler.d.ts +11 -6
- package/dist/ws/dashboard-fleet-handler.d.ts +33 -0
- package/dist/ws/dashboard-fleet-write-handler.d.ts +60 -0
- package/dist/ws/fleet-runs-on-all.d.ts +16 -0
- package/dist/ws/inventory-api.d.ts +17 -0
- package/dist/ws/platform-client.d.ts +13 -1
- package/dist/ws/test-relay-handlers.d.ts +4 -2
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +77 -128
|
@@ -13,6 +13,18 @@ export interface DispatchMetrics {
|
|
|
13
13
|
/** Set the queue depth gauge. */
|
|
14
14
|
setQueueDepth(depth: number): void;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Narrow slice of `HostRosterStore` the dispatcher needs for the host-restart
|
|
18
|
+
* flow. Kept as an interface so the dispatcher doesn't import the full store
|
|
19
|
+
* (which pulls in engine label matchers) and to make the reboot logic testable
|
|
20
|
+
* with a tiny in-memory stub.
|
|
21
|
+
*/
|
|
22
|
+
export interface HostRosterRebootStore {
|
|
23
|
+
/** True when the host's reboot-pending deadline is still in the future. */
|
|
24
|
+
isRebootPending(agentId: string, nowMs: number): Promise<boolean>;
|
|
25
|
+
/** Clear the reboot-pending flag (down-then-up release on reconnect). */
|
|
26
|
+
clearRebootPending(agentId: string): Promise<void>;
|
|
27
|
+
}
|
|
16
28
|
/**
|
|
17
29
|
* Result of a dispatch attempt.
|
|
18
30
|
*/
|
|
@@ -120,6 +132,8 @@ export declare class Dispatcher {
|
|
|
120
132
|
private readonly recoveringJobs;
|
|
121
133
|
/** Grace period = 2x max reconnection delay. */
|
|
122
134
|
private get gracePeriodMs();
|
|
135
|
+
/** Host roster store for the reboot-pending gate; undefined ⇒ flow inert. */
|
|
136
|
+
private readonly rosterStore?;
|
|
123
137
|
constructor(deps: {
|
|
124
138
|
registry: AgentRegistry;
|
|
125
139
|
queue: JobQueue;
|
|
@@ -139,6 +153,14 @@ export declare class Dispatcher {
|
|
|
139
153
|
getAckTimeoutMs?: (job: QueuedJob) => Promise<number>;
|
|
140
154
|
/** Cancel + disconnect an agent whose dispatch ack deadline expired. */
|
|
141
155
|
onAckTimeout?: (agentId: string, jobId: string, runId: string) => void;
|
|
156
|
+
/**
|
|
157
|
+
* Host roster store, used for the workflow-level host-restart flow: gate the
|
|
158
|
+
* pinned-drain off for a reboot-pending agent, and treat a reboot-pending
|
|
159
|
+
* agent's disconnect as the expected reboot (complete its in-flight job
|
|
160
|
+
* success rather than starting the recovery-fail timer). Omitted ⇒ the
|
|
161
|
+
* reboot-pending behavior is inert (every host reads not-pending).
|
|
162
|
+
*/
|
|
163
|
+
rosterStore?: HostRosterRebootStore;
|
|
142
164
|
});
|
|
143
165
|
/**
|
|
144
166
|
* Dispatch a job to a matching agent, or queue it if none available.
|
|
@@ -181,6 +203,20 @@ export declare class Dispatcher {
|
|
|
181
203
|
* Dequeues matching jobs from the queue while the agent has capacity,
|
|
182
204
|
* calling onDispatch for each.
|
|
183
205
|
*/
|
|
206
|
+
/**
|
|
207
|
+
* Drop agents whose reboot-pending flag is set from a candidate list. Used by
|
|
208
|
+
* the label-routed dispatch path so a post-restart job is never sent to a host
|
|
209
|
+
* that is about to reboot. No-op when no roster store is wired.
|
|
210
|
+
*/
|
|
211
|
+
private filterRebootPending;
|
|
212
|
+
/**
|
|
213
|
+
* Release a reboot-pending host on its real reconnect (down-then-up). Clears
|
|
214
|
+
* the persisted flag so the very next `onAgentAvailable` drain dispatches the
|
|
215
|
+
* held post-restart job. Call this ONLY from the (re-)register path — a fresh
|
|
216
|
+
* connection after the box rebooted — never from a still-connected drain
|
|
217
|
+
* trigger (job completion / agent.status), which must keep the gate closed.
|
|
218
|
+
*/
|
|
219
|
+
releaseRebootPending(agentId: string): Promise<void>;
|
|
184
220
|
onAgentAvailable(agentId: string): Promise<void>;
|
|
185
221
|
/** Record that a job began executing on its agent. */
|
|
186
222
|
markJobStarted(jobId: string): void;
|
|
@@ -239,6 +275,14 @@ export declare class Dispatcher {
|
|
|
239
275
|
* asynchronously when recovery timers expire).
|
|
240
276
|
*/
|
|
241
277
|
onAgentDisconnect(agentId: string): Promise<string[]>;
|
|
278
|
+
/**
|
|
279
|
+
* Reboot-pending agent disconnected: complete its in-flight started job(s) as
|
|
280
|
+
* success (the restart job, which already reported success, may already be
|
|
281
|
+
* terminal — `markCompleted` is a no-op / guarded in that case). Never starts
|
|
282
|
+
* a recovery timer. Untracks the jobs so the reconnect does not reconcile a
|
|
283
|
+
* phantom in-flight set.
|
|
284
|
+
*/
|
|
285
|
+
private completeInFlightForReboot;
|
|
242
286
|
/** Drop grace-window entries owned by an agent. */
|
|
243
287
|
private cleanupGraceEntriesForAgent;
|
|
244
288
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HostRosterStore } from './host-roster.js';
|
|
2
2
|
export interface HostRosterReaperOptions {
|
|
3
|
-
store: Pick<HostRosterStore, 'reapEphemeralPastTtl' | 'countStaticUnreachable'>;
|
|
3
|
+
store: Pick<HostRosterStore, 'reapEphemeralPastTtl' | 'countStaticUnreachable' | 'listExpiredRebootPending' | 'clearRebootPending'>;
|
|
4
4
|
ttlMs: number;
|
|
5
5
|
/** Grace window for the connected-but-stale case in `countStaticUnreachable`. */
|
|
6
6
|
graceMs: number;
|
|
@@ -30,6 +30,7 @@ export declare class HostRosterReaper {
|
|
|
30
30
|
private readonly graceMs;
|
|
31
31
|
private readonly scanIntervalMs;
|
|
32
32
|
private readonly setUnreachableGauge;
|
|
33
|
+
private readonly rebootSweep;
|
|
33
34
|
private timer;
|
|
34
35
|
private isLeader;
|
|
35
36
|
constructor(opts: HostRosterReaperOptions);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Kysely } from 'kysely';
|
|
2
|
-
import { type LabelMatcher } from '@kici-dev/engine';
|
|
2
|
+
import { type HostInventoryEntry, type InventorySelector, type LabelMatcher } from '@kici-dev/engine';
|
|
3
3
|
import type { Database, HostRosterRow } from '../db/types.js';
|
|
4
|
+
/** Typed host-vars bag carried by roster rows (`string | number | boolean`). */
|
|
5
|
+
export type HostProperties = Record<string, string | number | boolean>;
|
|
4
6
|
/**
|
|
5
7
|
* Derived (read-time) status of a roster host. Never a stored mutable column:
|
|
6
8
|
* status is computed from the shared `last_seen` + `connected_instance_id` so
|
|
@@ -33,6 +35,8 @@ export interface MatchedHost {
|
|
|
33
35
|
status: HostStatus;
|
|
34
36
|
platform: string | null;
|
|
35
37
|
arch: string | null;
|
|
38
|
+
/** Typed host-vars bag (parsed from `host_properties`). */
|
|
39
|
+
properties: HostProperties;
|
|
36
40
|
}
|
|
37
41
|
export interface UpsertHostInput {
|
|
38
42
|
agentId: string;
|
|
@@ -43,6 +47,13 @@ export interface UpsertHostInput {
|
|
|
43
47
|
platform: string;
|
|
44
48
|
arch: string;
|
|
45
49
|
instanceId: string;
|
|
50
|
+
/**
|
|
51
|
+
* Agent-reported typed host-vars. Shallow-merged into any existing bag on
|
|
52
|
+
* conflict (agent-reported keys win; operator-declared keys the agent does
|
|
53
|
+
* not report are preserved). Omitted ⇒ no change to the stored bag on update,
|
|
54
|
+
* `{}` on insert.
|
|
55
|
+
*/
|
|
56
|
+
properties?: HostProperties;
|
|
46
57
|
}
|
|
47
58
|
/** Minimal row shape `deriveHostStatus` reads (the store row or the CLI row). */
|
|
48
59
|
export interface HostStatusRow {
|
|
@@ -60,6 +71,12 @@ export interface HostStatusRow {
|
|
|
60
71
|
* `stale` (scaled down, awaiting reap).
|
|
61
72
|
*/
|
|
62
73
|
export declare function deriveHostStatus(row: HostStatusRow, nowMs: number, graceMs: number): HostStatus;
|
|
74
|
+
/**
|
|
75
|
+
* Normalize a stored `host_properties` value into a typed host-vars bag. The pg
|
|
76
|
+
* driver returns parsed JSON for a `jsonb` column, but accept a JSON string too
|
|
77
|
+
* (defensive for non-pg paths / tests). Non-object / null reads back as `{}`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseHostProperties(value: unknown): HostProperties;
|
|
63
80
|
/**
|
|
64
81
|
* Durable, cluster-shared roster of every agent the cluster has ever enrolled.
|
|
65
82
|
*
|
|
@@ -84,6 +101,7 @@ export declare class HostRosterStore {
|
|
|
84
101
|
agentId: string;
|
|
85
102
|
labels: string[];
|
|
86
103
|
hostname?: string;
|
|
104
|
+
properties?: HostProperties;
|
|
87
105
|
}): Promise<void>;
|
|
88
106
|
get(agentId: string): Promise<HostRosterRow | null>;
|
|
89
107
|
listAll(): Promise<HostRosterRow[]>;
|
|
@@ -95,6 +113,23 @@ export declare class HostRosterStore {
|
|
|
95
113
|
* registry alone cannot name an expected-but-absent host.
|
|
96
114
|
*/
|
|
97
115
|
findMatching(include: readonly (readonly LabelMatcher[])[], exclude: readonly LabelMatcher[], graceMs: number): Promise<MatchedHost[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Map a roster row to the canonical {@link HostInventoryEntry} — the queryable
|
|
118
|
+
* shape returned by the `inventory.query`/`inventory.get` RPC and typed on the
|
|
119
|
+
* SDK's `ctx.kici.inventory`. Status is derived the same way `findMatching`
|
|
120
|
+
* derives it (live + fresh ⇒ ready; declared-but-absent static ⇒ unreachable;
|
|
121
|
+
* ephemeral past ttl ⇒ stale).
|
|
122
|
+
*/
|
|
123
|
+
toInventoryEntry(row: HostRosterRow, graceMs: number): HostInventoryEntry;
|
|
124
|
+
/**
|
|
125
|
+
* Query the roster as canonical {@link HostInventoryEntry} records. With a
|
|
126
|
+
* selector, reuses `findMatching`'s label filtering (server-side, glob/regex);
|
|
127
|
+
* property filtering is done client-side in the workflow. Omit the selector ⇒
|
|
128
|
+
* every host.
|
|
129
|
+
*/
|
|
130
|
+
queryInventory(selector: InventorySelector | undefined, graceMs: number): Promise<HostInventoryEntry[]>;
|
|
131
|
+
/** Single-host inventory lookup; null when the agent is not in the roster. */
|
|
132
|
+
getInventory(agentId: string, graceMs: number): Promise<HostInventoryEntry | null>;
|
|
98
133
|
/**
|
|
99
134
|
* Count `static` (declared) hosts whose derived status is `unreachable` —
|
|
100
135
|
* the "declared-but-absent" alarm population. Reuses the single-source
|
|
@@ -104,7 +139,25 @@ export declare class HostRosterStore {
|
|
|
104
139
|
* depends on `graceMs`).
|
|
105
140
|
*/
|
|
106
141
|
countStaticUnreachable(graceMs: number): Promise<number>;
|
|
142
|
+
/** Remove a host from the roster by agent id. Returns rows deleted. */
|
|
143
|
+
removeStatic(agentId: string): Promise<number>;
|
|
107
144
|
/** Delete ephemeral rows whose last_seen is older than ttl. Returns count. */
|
|
108
145
|
reapEphemeralPastTtl(ttlMs: number): Promise<number>;
|
|
146
|
+
/**
|
|
147
|
+
* Mark a host as about-to-reboot until `until`. Set by the `host.requestReboot`
|
|
148
|
+
* API handler when an agent's `restartHost()` step runs. While the value is in
|
|
149
|
+
* the future, the host's disconnect is the expected reboot and its pinned
|
|
150
|
+
* post-restart job is held.
|
|
151
|
+
*/
|
|
152
|
+
setRebootPending(agentId: string, until: Date): Promise<void>;
|
|
153
|
+
/** Clear the reboot-pending flag (on reconnect, deadline expiry, or cancel). */
|
|
154
|
+
clearRebootPending(agentId: string): Promise<void>;
|
|
155
|
+
/** True when the host has a reboot-pending deadline still in the future at `nowMs`. */
|
|
156
|
+
isRebootPending(agentId: string, nowMs: number): Promise<boolean>;
|
|
157
|
+
/**
|
|
158
|
+
* Agent ids whose reboot-pending deadline has passed at `nowMs`. The deadline
|
|
159
|
+
* sweep clears these; the held post-restart job then hits the queue timeout.
|
|
160
|
+
*/
|
|
161
|
+
listExpiredRebootPending(nowMs: number): Promise<string[]>;
|
|
109
162
|
}
|
|
110
163
|
//# sourceMappingURL=host-roster.d.ts.map
|
package/dist/agent/registry.d.ts
CHANGED
|
@@ -120,6 +120,12 @@ interface AgentMetadata {
|
|
|
120
120
|
* `lifecycle_class`. `null` / undefined when auth mode is `none`.
|
|
121
121
|
*/
|
|
122
122
|
tokenAgentType?: 'static' | 'ephemeral' | null;
|
|
123
|
+
/**
|
|
124
|
+
* Agent-reported typed host-vars (the `KICI_PROPERTIES` bag), threaded from
|
|
125
|
+
* the `agent.register` message into the roster upsert (shallow-merged with
|
|
126
|
+
* any operator-declared properties). Undefined ⇒ the agent reported none.
|
|
127
|
+
*/
|
|
128
|
+
properties?: Record<string, string | number | boolean>;
|
|
123
129
|
}
|
|
124
130
|
/**
|
|
125
131
|
* Subset of `HostRosterStore` the registry reconciles into. Optional — when no
|
|
@@ -136,6 +142,7 @@ export interface RosterReconciler {
|
|
|
136
142
|
platform: string;
|
|
137
143
|
arch: string;
|
|
138
144
|
instanceId: string;
|
|
145
|
+
properties?: Record<string, string | number | boolean>;
|
|
139
146
|
}): Promise<void>;
|
|
140
147
|
markDisconnected(agentId: string, instanceId: string): Promise<void>;
|
|
141
148
|
stampLastSeen(agentId: string, instanceId: string): Promise<void>;
|
|
@@ -307,6 +314,21 @@ export declare class AgentRegistry {
|
|
|
307
314
|
* Update the last heartbeat timestamp for an agent.
|
|
308
315
|
*/
|
|
309
316
|
updateHeartbeat(agentId: string): boolean;
|
|
317
|
+
/**
|
|
318
|
+
* Compact, allocation-cheap snapshot of every registered agent's routing
|
|
319
|
+
* facts. Used by the dispatcher to log WHY a job found no backend (required
|
|
320
|
+
* labels vs each agent's labels / capacity), which is otherwise invisible —
|
|
321
|
+
* a `queued-no-backend` outcome alone doesn't say whether the label set
|
|
322
|
+
* mismatched, the agent was at capacity, or no agent was connected at all.
|
|
323
|
+
*/
|
|
324
|
+
agentSummaries(): Array<{
|
|
325
|
+
agentId: string;
|
|
326
|
+
labels: string[];
|
|
327
|
+
platform: string;
|
|
328
|
+
arch: string;
|
|
329
|
+
activeJobs: number;
|
|
330
|
+
maxConcurrency: number;
|
|
331
|
+
}>;
|
|
310
332
|
/**
|
|
311
333
|
* Get a single agent entry by ID.
|
|
312
334
|
*/
|
package/dist/app.d.ts
CHANGED
|
@@ -151,6 +151,11 @@ export interface AppDependencies {
|
|
|
151
151
|
* Platform client + config are in scope; passed into the admin source routes.
|
|
152
152
|
*/
|
|
153
153
|
resolveSourceWebhookUrl?: AdminRouteDeps['resolveSourceWebhookUrl'];
|
|
154
|
+
/**
|
|
155
|
+
* Resolves the org-scoped GitHub webhook URL for the manifest setup
|
|
156
|
+
* pre-flight (before any App exists). Passed into the admin source routes.
|
|
157
|
+
*/
|
|
158
|
+
resolveGithubWebhookUrl?: AdminRouteDeps['resolveGithubWebhookUrl'];
|
|
154
159
|
/** Config admin API route dependencies. Optional -- mounted when config management is available. */
|
|
155
160
|
configRouteDeps?: ConfigRouteDeps;
|
|
156
161
|
/** Event router for internal event delivery. Optional -- if not set, event routing is inactive. */
|
|
@@ -17,6 +17,11 @@ export interface StepApprovalRequest {
|
|
|
17
17
|
reason: string;
|
|
18
18
|
/** Per-gate timeout (seconds); falls back to the org default. */
|
|
19
19
|
timeoutSeconds?: number;
|
|
20
|
+
/** Computed drift payload for a `when: 'drift'` gate; persisted on the hold. */
|
|
21
|
+
payload?: {
|
|
22
|
+
summaryMarkdown: string;
|
|
23
|
+
drift: unknown;
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
/** Dependencies injected into the bridge. */
|
|
22
27
|
export interface StepApprovalBridgeDeps {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kici-admin source add github --manifest` — the one-click GitHub App setup
|
|
3
|
+
* flow. Drives GitHub's App Manifest flow end-to-end: builds a pre-configured
|
|
4
|
+
* manifest (KiCI's exact permissions/events/webhook URL), hands it to GitHub via
|
|
5
|
+
* an auto-submitting form, catches the returned short-lived setup code over a
|
|
6
|
+
* localhost loopback (or copy-paste in --no-browser mode), exchanges it for the
|
|
7
|
+
* App's id + private key + webhook secret, then reuses the existing source
|
|
8
|
+
* storage + Platform-registration path.
|
|
9
|
+
*
|
|
10
|
+
* The private-key-bearing conversion happens entirely here on the orchestrator
|
|
11
|
+
* host — it never transits the Platform (sovereignty invariant).
|
|
12
|
+
*/
|
|
13
|
+
import type { AdminApiClient } from '../api-client.js';
|
|
14
|
+
import { waitForInstallation, verifyRepoAccess, type GithubAppCredentials } from '../../providers/github/manifest.js';
|
|
15
|
+
import { startManifestLoopback } from '../loopback-callback.js';
|
|
16
|
+
export interface ManifestSetupOptions {
|
|
17
|
+
name: string;
|
|
18
|
+
noBrowser?: boolean;
|
|
19
|
+
githubOrg?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Self-hosted webhook URL override. When set, it is baked verbatim into the
|
|
22
|
+
* App manifest's `hook_attributes.url` and the platform-mode webhook-URL
|
|
23
|
+
* resolution is skipped — so the flow works even where the auto-resolved KiCI
|
|
24
|
+
* platform URL is unavailable. KiCI adds no ingress at this URL; the operator
|
|
25
|
+
* owns delivery. Advanced/self-hosted only.
|
|
26
|
+
*/
|
|
27
|
+
webhookUrl?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Injectable boundary so unit tests can stub GitHub + the browser + stdin. */
|
|
30
|
+
export interface ManifestSetupDeps {
|
|
31
|
+
startLoopback: typeof startManifestLoopback;
|
|
32
|
+
openBrowser: (url: string) => void | Promise<void>;
|
|
33
|
+
readLine: (prompt: string) => Promise<string>;
|
|
34
|
+
convert: (code: string) => Promise<GithubAppCredentials>;
|
|
35
|
+
waitForInstallation: typeof waitForInstallation;
|
|
36
|
+
verifyRepoAccess: typeof verifyRepoAccess;
|
|
37
|
+
/** Persist a created App's PEM to a 0600 file for orphan-app recovery. */
|
|
38
|
+
writeRecoveryFile: (appId: string, pem: string) => string;
|
|
39
|
+
}
|
|
40
|
+
export declare const realManifestSetupDeps: ManifestSetupDeps;
|
|
41
|
+
export declare function runGithubManifestSetup(opts: ManifestSetupOptions, client: AdminApiClient, deps?: ManifestSetupDeps): Promise<void>;
|
|
42
|
+
//# sourceMappingURL=source-manifest.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ephemeral localhost server that backs the GitHub App manifest setup flow.
|
|
3
|
+
* Serves the auto-submitting manifest form at `/` and catches GitHub's redirect
|
|
4
|
+
* (`/cb?code=…&state=…`). The setup code is exchanged for credentials in the
|
|
5
|
+
* CLI, never on the Platform — this loopback keeps the whole flow on the
|
|
6
|
+
* orchestrator host (mirrors the `kici login` browser-OAuth loopback).
|
|
7
|
+
*/
|
|
8
|
+
export interface ManifestLoopback {
|
|
9
|
+
/** http://127.0.0.1:<port>/cb — GitHub redirect target. */
|
|
10
|
+
redirectUrl: string;
|
|
11
|
+
/** http://127.0.0.1:<port>/ — serves the manifest form. */
|
|
12
|
+
formUrl: string;
|
|
13
|
+
waitForCode(timeoutMs: number): Promise<{
|
|
14
|
+
code: string;
|
|
15
|
+
state: string;
|
|
16
|
+
}>;
|
|
17
|
+
close(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function startManifestLoopback(opts: {
|
|
20
|
+
state: string;
|
|
21
|
+
manifestJson: string;
|
|
22
|
+
createUrl: string;
|
|
23
|
+
}): Promise<ManifestLoopback>;
|
|
24
|
+
//# sourceMappingURL=loopback-callback.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open a URL in the operator's default browser, best-effort. Used by the GitHub
|
|
3
|
+
* App manifest setup flow to launch the create / install pages. Failure is
|
|
4
|
+
* non-fatal — the caller always prints the URL too, so a headless host (or a
|
|
5
|
+
* blocked launcher) just falls back to copy-paste.
|
|
6
|
+
*
|
|
7
|
+
* `KICI_BROWSER_CMD` overrides the launcher: `none` suppresses it entirely
|
|
8
|
+
* (E2E / headless capture), any other value is run with `{url}` substituted —
|
|
9
|
+
* mirroring the `kici login` convention.
|
|
10
|
+
*/
|
|
11
|
+
export declare function openBrowserBestEffort(url: string): void;
|
|
12
|
+
//# sourceMappingURL=open-browser.d.ts.map
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
* platform with Docker or Podman installed.
|
|
8
8
|
*/
|
|
9
9
|
import type { ServiceManager, ServiceConfig, ServiceStatus, LogOptions, DiscoveredInstance, LaunchSpec } from './types.js';
|
|
10
|
+
/** Container runtime binary (`podman` or `docker`); compose form is `${runtime} compose`. */
|
|
11
|
+
type Runtime = 'podman' | 'docker';
|
|
12
|
+
/**
|
|
13
|
+
* Detect which container runtime is available.
|
|
14
|
+
* Tries podman compose first, then docker compose.
|
|
15
|
+
*
|
|
16
|
+
* Exported so the orchestrator installer can resolve the runtime once when
|
|
17
|
+
* injecting the `KICI_DEPLOY_CONTAINER_RUNTIME` env var for a compose deploy.
|
|
18
|
+
*
|
|
19
|
+
* @throws When neither runtime is found.
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectRuntime(): Runtime;
|
|
10
22
|
export declare class ComposeServiceManager implements ServiceManager {
|
|
11
23
|
private runtime;
|
|
12
24
|
/** Get the runtime binary (`podman` or `docker`), detecting it if not already done. */
|
|
@@ -24,4 +36,5 @@ export declare class ComposeServiceManager implements ServiceManager {
|
|
|
24
36
|
list(isUserLevel: boolean): Promise<DiscoveredInstance[]>;
|
|
25
37
|
readLaunchSpec(_config: ServiceConfig): Promise<LaunchSpec | null>;
|
|
26
38
|
}
|
|
39
|
+
export {};
|
|
27
40
|
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment-identity env injection for the orchestrator installer.
|
|
3
|
+
*
|
|
4
|
+
* The orchestrator reports its own deployment shape (systemd / launchd /
|
|
5
|
+
* windows / compose) in `source.register` so the dashboard can build the
|
|
6
|
+
* correct `kici-admin` invocation. The shape is only knowable at install time
|
|
7
|
+
* (a running container can't learn its own container name), so the installer
|
|
8
|
+
* injects it into the orchestrator's env file via these `KICI_DEPLOY_*` vars.
|
|
9
|
+
*/
|
|
10
|
+
import type { ServicePlatform } from './types.js';
|
|
11
|
+
/** Inputs the installer already has when it writes the env file. */
|
|
12
|
+
export interface DeployEnvInput {
|
|
13
|
+
platform: ServicePlatform;
|
|
14
|
+
/** The service / container name the installer assigns (= ServiceConfig.name). */
|
|
15
|
+
serviceName: string;
|
|
16
|
+
/** Container runtime, only meaningful for the `compose` platform. */
|
|
17
|
+
containerRuntime?: 'podman' | 'docker';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build the `KICI_DEPLOY_*` env lines for a given deployment shape. The mode
|
|
21
|
+
* line is always emitted; container name + runtime are emitted only for the
|
|
22
|
+
* `compose` platform (the only shape with a container to `exec` into).
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildDeployEnvLines(input: DeployEnvInput): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Append the freshly-computed deploy lines to existing env-file content,
|
|
27
|
+
* idempotently: any pre-existing `KICI_DEPLOY_*` line is stripped first so a
|
|
28
|
+
* re-install / upgrade heals the shape rather than duplicating it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function upsertDeployEnvLines(existingContent: string, lines: string[]): string;
|
|
31
|
+
//# sourceMappingURL=deploy-env.d.ts.map
|