@urateam/cli 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/dist/__tests__/cli-integration.test.d.ts +2 -0
- package/dist/__tests__/cli-integration.test.d.ts.map +1 -0
- package/dist/__tests__/cli-integration.test.js +91 -0
- package/dist/__tests__/cli-integration.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +92 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/run.test.d.ts +2 -0
- package/dist/__tests__/run.test.d.ts.map +1 -0
- package/dist/__tests__/run.test.js +297 -0
- package/dist/__tests__/run.test.js.map +1 -0
- package/dist/__tests__/webhook.test.d.ts +2 -0
- package/dist/__tests__/webhook.test.d.ts.map +1 -0
- package/dist/__tests__/webhook.test.js +142 -0
- package/dist/__tests__/webhook.test.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +44 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/dev.d.ts +3 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +73 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +119 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/run.d.ts +28 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +283 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +196 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/webhook.d.ts +3 -0
- package/dist/commands/webhook.d.ts.map +1 -0
- package/dist/commands/webhook.js +34 -0
- package/dist/commands/webhook.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Exported helpers (for unit testing)
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Loads a pipeline config module and returns the record of pipeline configs.
|
|
9
|
+
* Supports both `export const pipelines = ...` and `export default ...`.
|
|
10
|
+
*/
|
|
11
|
+
export async function loadPipelineConfigModule(filePath) {
|
|
12
|
+
const url = pathToFileURL(filePath).href;
|
|
13
|
+
const mod = await import(url);
|
|
14
|
+
return mod.pipelines ?? mod.default ?? mod;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Loads a repos config module and returns the record of repo configs.
|
|
18
|
+
* Supports both `export const repos = ...` and `export default ...`.
|
|
19
|
+
*/
|
|
20
|
+
export async function loadRepoConfigModule(filePath) {
|
|
21
|
+
const url = pathToFileURL(filePath).href;
|
|
22
|
+
const mod = await import(url);
|
|
23
|
+
return mod.repos ?? mod.default ?? mod;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns a copy of `config` with `stages` filtered to only include `stage`.
|
|
27
|
+
* Throws if `stage` is not present in the pipeline's stages.
|
|
28
|
+
*/
|
|
29
|
+
export function filterPipelineToStage(config, stage) {
|
|
30
|
+
if (!config.stages.includes(stage)) {
|
|
31
|
+
throw new Error(`Stage "${stage}" is not in pipeline "${config.name}" (stages: ${config.stages.join(", ")})`);
|
|
32
|
+
}
|
|
33
|
+
return { ...config, stages: [stage] };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolves which repo config to use.
|
|
37
|
+
* Prefers a match by teamId, falls back to the first entry.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveRepoConfig(repoConfigs, teamId) {
|
|
40
|
+
if (repoConfigs[teamId])
|
|
41
|
+
return repoConfigs[teamId];
|
|
42
|
+
const keys = Object.keys(repoConfigs);
|
|
43
|
+
if (keys.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
return repoConfigs[keys[0]];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a simple console-based notifier for local runs.
|
|
49
|
+
*/
|
|
50
|
+
export function createConsoleNotifier() {
|
|
51
|
+
return {
|
|
52
|
+
onPipelineStart(run) {
|
|
53
|
+
console.log(`[lag run] Pipeline started — run ${run.id.slice(0, 8)} | branch: ${run.branch}`);
|
|
54
|
+
return Promise.resolve();
|
|
55
|
+
},
|
|
56
|
+
onStageComplete(run, stage, result) {
|
|
57
|
+
const icon = result.status === "completed" ? "✅" : "❌";
|
|
58
|
+
console.log(`[lag run] Stage ${stage} ${icon} | tokens: ${result.inputTokens}in / ${result.outputTokens}out`);
|
|
59
|
+
return Promise.resolve();
|
|
60
|
+
},
|
|
61
|
+
onPipelineComplete(run, result) {
|
|
62
|
+
console.log(`[lag run] Pipeline complete ✅`);
|
|
63
|
+
if (result.prUrl)
|
|
64
|
+
console.log(` PR: ${result.prUrl}`);
|
|
65
|
+
console.log(` Tokens: ${result.totalInputTokens.toLocaleString()}in / ${result.totalOutputTokens.toLocaleString()}out`);
|
|
66
|
+
return Promise.resolve();
|
|
67
|
+
},
|
|
68
|
+
onPipelineFailed(run, error) {
|
|
69
|
+
console.error(`[lag run] Pipeline failed ❌`);
|
|
70
|
+
console.error(` Stage: ${error.stage}`);
|
|
71
|
+
console.error(` Error: ${error.message}`);
|
|
72
|
+
return Promise.resolve();
|
|
73
|
+
},
|
|
74
|
+
onHumanReviewNeeded(run, prUrl, reason) {
|
|
75
|
+
console.log(`[lag run] Human review needed 👀`);
|
|
76
|
+
console.log(` PR: ${prUrl}`);
|
|
77
|
+
console.log(` Reason: ${reason}`);
|
|
78
|
+
return Promise.resolve();
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Command definition
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
export const runCommand = new Command("run")
|
|
86
|
+
.description("Run a pipeline against a Linear issue")
|
|
87
|
+
.requiredOption("--issue <id>", "Linear issue identifier (e.g., LIN-123)")
|
|
88
|
+
.option("--stage <stage>", "Run only this stage")
|
|
89
|
+
.option("--only", "Run only the specified stage (requires --stage)")
|
|
90
|
+
.option("--dry-run", "Show plan without executing")
|
|
91
|
+
.option("--config <path>", "Pipeline config file path", "./pipeline.config.ts")
|
|
92
|
+
.option("--repos <path>", "Repo config file path", "./repos.config.ts")
|
|
93
|
+
.action(async (options) => {
|
|
94
|
+
// --- Validate --only requires --stage -----------------------------------
|
|
95
|
+
if (options.only && !options.stage) {
|
|
96
|
+
console.error("Error: --only requires --stage to be specified.");
|
|
97
|
+
console.error("Usage: lag run --issue LIN-123 --stage implement --only");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
// --- Quick dry-run: show parsed options without needing API key ----------
|
|
101
|
+
if (options.dryRun && !process.env.LINEAR_API_KEY) {
|
|
102
|
+
console.log("=== lag run — Dry Run (no API key) ===");
|
|
103
|
+
console.log(`issue: ${options.issue}`);
|
|
104
|
+
console.log(`config: ${options.config}`);
|
|
105
|
+
console.log(`repos: ${options.repos}`);
|
|
106
|
+
if (options.stage) {
|
|
107
|
+
console.log(`stage: ${options.stage}`);
|
|
108
|
+
console.log(`only: ${!!options.only}`);
|
|
109
|
+
}
|
|
110
|
+
console.log("Set LINEAR_API_KEY for full dry-run with issue resolution.");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// --- Auth check ---------------------------------------------------------
|
|
114
|
+
const apiKey = process.env.LINEAR_API_KEY;
|
|
115
|
+
if (!apiKey) {
|
|
116
|
+
console.error("Error: LINEAR_API_KEY is not set.");
|
|
117
|
+
console.error("Obtain your API key from https://linear.app/settings/api and run:");
|
|
118
|
+
console.error(" export LINEAR_API_KEY=lin_api_...");
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
// --- Load configs -------------------------------------------------------
|
|
122
|
+
const configPath = resolve(options.config);
|
|
123
|
+
const reposPath = resolve(options.repos);
|
|
124
|
+
const { validatePipelineConfigs, validateRepoConfigs, resolvePipeline } = await import("@urateam/core");
|
|
125
|
+
let pipelineConfigs;
|
|
126
|
+
try {
|
|
127
|
+
const raw = await loadPipelineConfigModule(configPath);
|
|
128
|
+
pipelineConfigs = validatePipelineConfigs(raw);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error(`Error loading pipeline config from ${configPath}:`);
|
|
132
|
+
console.error(` ${err?.message ?? String(err)}`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
let repoConfigs;
|
|
136
|
+
try {
|
|
137
|
+
const raw = await loadRepoConfigModule(reposPath);
|
|
138
|
+
repoConfigs = validateRepoConfigs(raw);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
console.error(`Error loading repo config from ${reposPath}:`);
|
|
142
|
+
console.error(` ${err?.message ?? String(err)}`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
// --- Fetch issue from Linear --------------------------------------------
|
|
146
|
+
let issue;
|
|
147
|
+
try {
|
|
148
|
+
const { LinearClient } = await import("@linear/sdk");
|
|
149
|
+
const client = new LinearClient({ apiKey });
|
|
150
|
+
const sdkIssue = await client.issue(options.issue);
|
|
151
|
+
// Resolve lazy relations
|
|
152
|
+
const team = await sdkIssue.team;
|
|
153
|
+
const project = await sdkIssue.project;
|
|
154
|
+
// Labels are a connection in the Linear SDK
|
|
155
|
+
let labelNames = [];
|
|
156
|
+
try {
|
|
157
|
+
const labelsConn = await sdkIssue.labels();
|
|
158
|
+
labelNames = (labelsConn?.nodes ?? []).map((l) => l.name ?? "");
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// labels() not available or empty — proceed without labels
|
|
162
|
+
}
|
|
163
|
+
issue = {
|
|
164
|
+
id: sdkIssue.id,
|
|
165
|
+
identifier: sdkIssue.identifier,
|
|
166
|
+
title: sdkIssue.title,
|
|
167
|
+
description: sdkIssue.description ?? "",
|
|
168
|
+
labels: labelNames.map((name) => ({ name })),
|
|
169
|
+
priority: sdkIssue.priority,
|
|
170
|
+
teamId: team?.id ?? "",
|
|
171
|
+
projectId: project?.id,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
const msg = err?.message ?? String(err);
|
|
176
|
+
if (msg.toLowerCase().includes("unauthorized") ||
|
|
177
|
+
msg.toLowerCase().includes("invalid api key") ||
|
|
178
|
+
msg.toLowerCase().includes("authentication")) {
|
|
179
|
+
console.error("Error: Linear authentication failed.");
|
|
180
|
+
console.error("Verify LINEAR_API_KEY is valid and has read access.");
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
console.error(`Error: Failed to fetch issue "${options.issue}" from Linear:`);
|
|
184
|
+
console.error(` ${msg}`);
|
|
185
|
+
}
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
// --- Resolve pipeline ---------------------------------------------------
|
|
189
|
+
const labelNames = issue.labels.map((l) => l.name);
|
|
190
|
+
const resolved = resolvePipeline(labelNames, pipelineConfigs);
|
|
191
|
+
if (!resolved) {
|
|
192
|
+
console.error(`No pipeline config matches labels: ${labelNames.join(", ") || "(none)"}`);
|
|
193
|
+
console.error(`Available pipelines: ${Object.keys(pipelineConfigs).join(", ")}`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
let pipelineConfig = resolved.config;
|
|
197
|
+
// --- Stage filtering ----------------------------------------------------
|
|
198
|
+
if (options.stage) {
|
|
199
|
+
try {
|
|
200
|
+
pipelineConfig = filterPipelineToStage(pipelineConfig, options.stage);
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
console.error(`Error: ${err?.message ?? String(err)}`);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// --- Resolve repo config ------------------------------------------------
|
|
208
|
+
const repoConfig = resolveRepoConfig(repoConfigs, issue.teamId);
|
|
209
|
+
if (!repoConfig) {
|
|
210
|
+
console.error("Error: No repo configs found in repos.config.ts.");
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
// --- Sanitize issue -----------------------------------------------------
|
|
214
|
+
const { mapIssueToSchema } = await import("@urateam/core");
|
|
215
|
+
const sanitizedIssue = mapIssueToSchema(issue);
|
|
216
|
+
// --- Dry run ------------------------------------------------------------
|
|
217
|
+
if (options.dryRun) {
|
|
218
|
+
console.log("=== lag run — Dry Run ===");
|
|
219
|
+
console.log(`Issue: ${issue.identifier}: ${issue.title}`);
|
|
220
|
+
console.log(`Pipeline: ${resolved.key} (${pipelineConfig.name})`);
|
|
221
|
+
console.log(`Stages: ${pipelineConfig.stages.join(" → ")}`);
|
|
222
|
+
console.log(`Repo: ${repoConfig.url}`);
|
|
223
|
+
console.log(`Branch: ${sanitizedIssue.id}/${sanitizedIssue.slug}`);
|
|
224
|
+
console.log(`Labels: ${labelNames.join(", ") || "(none)"}`);
|
|
225
|
+
console.log(`Priority: ${issue.priority}`);
|
|
226
|
+
console.log(`Config: ${configPath}`);
|
|
227
|
+
console.log(`Repos: ${reposPath}`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// --- Live run -----------------------------------------------------------
|
|
231
|
+
const { createDb, PipelineRunner, CompositeNotifier } = await import("@urateam/core");
|
|
232
|
+
const db = await createDb({
|
|
233
|
+
connectionString: process.env.DATABASE_URL ?? ":memory:",
|
|
234
|
+
});
|
|
235
|
+
const consoleNotifier = createConsoleNotifier();
|
|
236
|
+
// Completion promise — resolves when pipeline finishes or rejects on failure
|
|
237
|
+
let resolveCompletion;
|
|
238
|
+
let rejectCompletion;
|
|
239
|
+
const completionPromise = new Promise((res, rej) => {
|
|
240
|
+
resolveCompletion = res;
|
|
241
|
+
rejectCompletion = rej;
|
|
242
|
+
});
|
|
243
|
+
const completionNotifier = {
|
|
244
|
+
onPipelineStart() { return Promise.resolve(); },
|
|
245
|
+
onStageComplete() { return Promise.resolve(); },
|
|
246
|
+
onPipelineComplete() {
|
|
247
|
+
resolveCompletion();
|
|
248
|
+
return Promise.resolve();
|
|
249
|
+
},
|
|
250
|
+
onPipelineFailed(_run, error) {
|
|
251
|
+
rejectCompletion(new Error(`Pipeline failed at stage "${error.stage}": ${error.message}`));
|
|
252
|
+
return Promise.resolve();
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
const notifier = new CompositeNotifier([consoleNotifier, completionNotifier]);
|
|
256
|
+
const runner = new PipelineRunner({
|
|
257
|
+
db,
|
|
258
|
+
notifier,
|
|
259
|
+
concurrency: 1,
|
|
260
|
+
agentRunDir: process.env.AGENT_RUN_DIR ?? "/tmp/agent-runs",
|
|
261
|
+
repoCloneDir: process.env.REPO_CLONE_DIR ?? "/tmp/agent-repos",
|
|
262
|
+
});
|
|
263
|
+
// Graceful shutdown
|
|
264
|
+
const shutdown = () => {
|
|
265
|
+
console.log("\n[lag run] Aborting pipeline...");
|
|
266
|
+
runner.abort(issue.identifier);
|
|
267
|
+
setTimeout(() => process.exit(0), 5_000).unref();
|
|
268
|
+
};
|
|
269
|
+
process.on("SIGTERM", shutdown);
|
|
270
|
+
process.on("SIGINT", shutdown);
|
|
271
|
+
console.log(`[lag run] Starting pipeline "${resolved.key}" for ${issue.identifier}: ${issue.title}`);
|
|
272
|
+
await runner.start(issue, resolved.key, pipelineConfig, repoConfig, sanitizedIssue);
|
|
273
|
+
// Wait for the queued pipeline to finish
|
|
274
|
+
try {
|
|
275
|
+
await completionPromise;
|
|
276
|
+
process.exit(0);
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
console.error(`\n[lag run] ${err?.message ?? String(err)}`);
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,YAAY,SAkOrB,CAAC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
export const startCommand = new Command("start")
|
|
4
|
+
.description("Start production server (webhook + dashboard)")
|
|
5
|
+
.option("--port <port>", "Webhook server port", "3000")
|
|
6
|
+
.option("--dashboard-port <port>", "Dashboard port", "3001")
|
|
7
|
+
.action(async (options) => {
|
|
8
|
+
try {
|
|
9
|
+
const { createApp, defaultConfigs, cleanupWorktrees, addLogStream, initSlackAlertManager, createSlackAlertStream } = await import("@urateam/core");
|
|
10
|
+
// --- Slack error alerts (opt-in) ---
|
|
11
|
+
if (process.env.SLACK_ERROR_ALERTS === "true" &&
|
|
12
|
+
process.env.SLACK_BOT_TOKEN &&
|
|
13
|
+
process.env.PM_AGENT_SLACK_CHANNEL_ID) {
|
|
14
|
+
const manager = initSlackAlertManager(process.env.SLACK_BOT_TOKEN, process.env.PM_AGENT_SLACK_CHANNEL_ID);
|
|
15
|
+
addLogStream(createSlackAlertStream(manager));
|
|
16
|
+
console.log(`Slack error alerts: enabled (channel ${process.env.PM_AGENT_SLACK_CHANNEL_ID})`);
|
|
17
|
+
}
|
|
18
|
+
const { createDashboard } = await import("@urateam/dashboard");
|
|
19
|
+
const { serve } = await import("@hono/node-server");
|
|
20
|
+
// --- Validate required env vars ---
|
|
21
|
+
if (!process.env.LINEAR_WEBHOOK_SECRET) {
|
|
22
|
+
console.error("LINEAR_WEBHOOK_SECRET is required");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// --- Build config from env vars ---
|
|
26
|
+
const dashboardUser = process.env.DASHBOARD_USER;
|
|
27
|
+
const dashboardPass = process.env.DASHBOARD_PASSWORD;
|
|
28
|
+
if (!dashboardUser || !dashboardPass) {
|
|
29
|
+
console.error("DASHBOARD_USER and DASHBOARD_PASSWORD are required. " +
|
|
30
|
+
"The dashboard exposes sensitive operational data and must not be publicly accessible. " +
|
|
31
|
+
"Set both environment variables and restart.");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const dashboardAuth = { username: dashboardUser, password: dashboardPass };
|
|
35
|
+
const repoConfigs = {};
|
|
36
|
+
if (process.env.REPO_TEAM_ID && process.env.REPO_URL) {
|
|
37
|
+
const repoEntry = {
|
|
38
|
+
url: process.env.REPO_URL,
|
|
39
|
+
defaultBranch: process.env.REPO_DEFAULT_BRANCH ?? "main",
|
|
40
|
+
testCommand: process.env.REPO_TEST_CMD ?? "pnpm test",
|
|
41
|
+
buildCommand: process.env.REPO_BUILD_CMD ?? "pnpm build",
|
|
42
|
+
};
|
|
43
|
+
// GitHub PR review feedback config (optional)
|
|
44
|
+
if (process.env.GITHUB_WEBHOOK_SECRET) {
|
|
45
|
+
repoEntry.githubFeedback = {
|
|
46
|
+
autoTrigger: process.env.GITHUB_FEEDBACK_AUTO_TRIGGER !== "false",
|
|
47
|
+
triggerKeyword: process.env.GITHUB_FEEDBACK_TRIGGER_KEYWORD,
|
|
48
|
+
allowedReviewers: process.env.GITHUB_FEEDBACK_ALLOWED_REVIEWERS
|
|
49
|
+
? process.env.GITHUB_FEEDBACK_ALLOWED_REVIEWERS.split(",").filter(Boolean)
|
|
50
|
+
: undefined,
|
|
51
|
+
botLogins: process.env.GITHUB_FEEDBACK_BOT_LOGINS
|
|
52
|
+
? process.env.GITHUB_FEEDBACK_BOT_LOGINS.split(",").filter(Boolean)
|
|
53
|
+
: undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
repoConfigs[process.env.REPO_TEAM_ID] = repoEntry;
|
|
57
|
+
}
|
|
58
|
+
// GitHub App config (optional)
|
|
59
|
+
let github;
|
|
60
|
+
if (process.env.GITHUB_APP_ID && process.env.GITHUB_PRIVATE_KEY_PATH) {
|
|
61
|
+
github = {
|
|
62
|
+
appId: process.env.GITHUB_APP_ID,
|
|
63
|
+
privateKey: readFileSync(process.env.GITHUB_PRIVATE_KEY_PATH, "utf-8"),
|
|
64
|
+
installationId: process.env.GITHUB_INSTALLATION_ID
|
|
65
|
+
? parseInt(process.env.GITHUB_INSTALLATION_ID, 10)
|
|
66
|
+
: undefined,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// PM Agent Slack interface (optional — requires signing secret)
|
|
70
|
+
const slackSigningSecret = process.env.SLACK_SIGNING_SECRET;
|
|
71
|
+
const pmSlack = (slackSigningSecret && process.env.SLACK_BOT_TOKEN && process.env.PM_AGENT_SLACK_CHANNEL_ID)
|
|
72
|
+
? {
|
|
73
|
+
signingSecret: slackSigningSecret,
|
|
74
|
+
botToken: process.env.SLACK_BOT_TOKEN,
|
|
75
|
+
channelId: process.env.PM_AGENT_SLACK_CHANNEL_ID,
|
|
76
|
+
teamIds: (process.env.PM_AGENT_TEAM_IDS ?? "").split(",").filter(Boolean),
|
|
77
|
+
}
|
|
78
|
+
: undefined;
|
|
79
|
+
const config = {
|
|
80
|
+
webhookSecret: process.env.LINEAR_WEBHOOK_SECRET,
|
|
81
|
+
linearApiKey: process.env.LINEAR_API_KEY ?? "",
|
|
82
|
+
pipelineConfigs: defaultConfigs,
|
|
83
|
+
repoConfigs,
|
|
84
|
+
databaseUrl: process.env.DATABASE_URL,
|
|
85
|
+
slackWebhookUrl: process.env.SLACK_WEBHOOK_URL,
|
|
86
|
+
discordWebhookUrl: process.env.DISCORD_WEBHOOK_URL,
|
|
87
|
+
concurrency: parseInt(process.env.MAX_CONCURRENT_RUNS ?? "3", 10),
|
|
88
|
+
agentRunDir: process.env.AGENT_RUN_DIR,
|
|
89
|
+
repoCloneDir: process.env.REPO_CLONE_DIR,
|
|
90
|
+
github,
|
|
91
|
+
dashboardAuth,
|
|
92
|
+
pmSlack,
|
|
93
|
+
githubWebhookSecret: process.env.GITHUB_WEBHOOK_SECRET,
|
|
94
|
+
};
|
|
95
|
+
// --- Start servers ---
|
|
96
|
+
const { app, runner, db } = await createApp(config);
|
|
97
|
+
// --- Recover runs interrupted by a previous restart ---
|
|
98
|
+
await runner.recoverStuckRuns();
|
|
99
|
+
const port = parseInt(process.env.PORT ?? options.port, 10);
|
|
100
|
+
const dashboardPort = parseInt(process.env.DASHBOARD_PORT ?? options.dashboardPort, 10);
|
|
101
|
+
const dashboardApp = createDashboard({
|
|
102
|
+
db,
|
|
103
|
+
pipelineConfigs: config.pipelineConfigs,
|
|
104
|
+
repoConfigs: config.repoConfigs,
|
|
105
|
+
auth: dashboardAuth,
|
|
106
|
+
});
|
|
107
|
+
console.log(`Linear Agent Framework starting`);
|
|
108
|
+
console.log(`Webhook: http://localhost:${port}`);
|
|
109
|
+
console.log(`Dashboard: http://localhost:${dashboardPort}`);
|
|
110
|
+
console.log(`Database: ${config.databaseUrl?.startsWith("postgres") ? "Postgres" : "SQLite"}`);
|
|
111
|
+
console.log(`Pipelines: ${Object.keys(config.pipelineConfigs).join(", ")}`);
|
|
112
|
+
console.log(`Repos: ${Object.keys(config.repoConfigs).length}`);
|
|
113
|
+
const webhookServer = serve({ fetch: app.fetch, port });
|
|
114
|
+
const dashServer = serve({ fetch: dashboardApp.fetch, port: dashboardPort });
|
|
115
|
+
// --- Worktree cleanup cron ---
|
|
116
|
+
const agentRunDir = config.agentRunDir ?? "/var/agent-runs";
|
|
117
|
+
const _parsedTtl = parseInt(process.env.WORKTREE_TTL_HOURS ?? "24", 10);
|
|
118
|
+
const worktreeTtlHours = Number.isFinite(_parsedTtl) && _parsedTtl > 0 ? _parsedTtl : 24;
|
|
119
|
+
async function runCleanup() {
|
|
120
|
+
const removed = await cleanupWorktrees(agentRunDir, worktreeTtlHours);
|
|
121
|
+
if (removed.length > 0) {
|
|
122
|
+
console.log(`Cleanup: removed ${removed.length} stale worktree(s)`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await runCleanup();
|
|
126
|
+
const cleanupInterval = setInterval(runCleanup, 60 * 60 * 1000);
|
|
127
|
+
cleanupInterval.unref();
|
|
128
|
+
// --- PM Agent (opt-in) ---
|
|
129
|
+
let pmInterval;
|
|
130
|
+
if (process.env.PM_AGENT_ENABLED === "true") {
|
|
131
|
+
const { createPmScheduler, PmAgentConfigSchema } = await import("@urateam/core");
|
|
132
|
+
const slackBotToken = process.env.SLACK_BOT_TOKEN;
|
|
133
|
+
if (!slackBotToken) {
|
|
134
|
+
console.error("SLACK_BOT_TOKEN is required when PM_AGENT_ENABLED=true");
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
const dailyBudgetStr = process.env.PM_AGENT_DAILY_TOKEN_BUDGET;
|
|
138
|
+
if (!dailyBudgetStr) {
|
|
139
|
+
console.error("PM_AGENT_DAILY_TOKEN_BUDGET is required when PM_AGENT_ENABLED=true");
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const slackChannelId = process.env.PM_AGENT_SLACK_CHANNEL_ID;
|
|
143
|
+
if (!slackChannelId) {
|
|
144
|
+
console.error("PM_AGENT_SLACK_CHANNEL_ID is required when PM_AGENT_ENABLED=true");
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
const teamIds = (process.env.PM_AGENT_TEAM_IDS ?? "").split(",").filter(Boolean);
|
|
148
|
+
if (teamIds.length === 0) {
|
|
149
|
+
console.error("PM_AGENT_TEAM_IDS is required when PM_AGENT_ENABLED=true");
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const pmConfig = PmAgentConfigSchema.parse({
|
|
153
|
+
enabled: true,
|
|
154
|
+
cronIntervalMs: parseInt(process.env.PM_AGENT_CRON_INTERVAL_MS ?? "1800000", 10),
|
|
155
|
+
maxInFlight: parseInt(process.env.PM_AGENT_MAX_IN_FLIGHT ?? "3", 10),
|
|
156
|
+
dailyTokenBudget: parseInt(dailyBudgetStr, 10),
|
|
157
|
+
slackChannelId,
|
|
158
|
+
teamIds,
|
|
159
|
+
});
|
|
160
|
+
const pmScheduler = createPmScheduler({
|
|
161
|
+
config: pmConfig,
|
|
162
|
+
db,
|
|
163
|
+
linearApiKey: config.linearApiKey,
|
|
164
|
+
slackBotToken,
|
|
165
|
+
repoCloneDir: config.repoCloneDir,
|
|
166
|
+
runner,
|
|
167
|
+
pipelineConfigs: config.pipelineConfigs,
|
|
168
|
+
repoConfigs: config.repoConfigs,
|
|
169
|
+
});
|
|
170
|
+
pmScheduler.tick().catch((err) => console.error("PM Agent initial tick failed:", err));
|
|
171
|
+
pmInterval = setInterval(() => pmScheduler.tick().catch((err) => console.error("PM Agent tick failed:", err)), pmConfig.cronIntervalMs);
|
|
172
|
+
pmInterval.unref();
|
|
173
|
+
console.log(`PM Agent: enabled (every ${pmConfig.cronIntervalMs / 60000}min, max ${pmConfig.maxInFlight} in-flight)`);
|
|
174
|
+
}
|
|
175
|
+
// --- Graceful shutdown ---
|
|
176
|
+
function shutdown() {
|
|
177
|
+
console.log("Shutting down...");
|
|
178
|
+
clearInterval(cleanupInterval);
|
|
179
|
+
if (pmInterval)
|
|
180
|
+
clearInterval(pmInterval);
|
|
181
|
+
let closed = 0;
|
|
182
|
+
const onClose = () => { if (++closed === 2)
|
|
183
|
+
process.exit(0); };
|
|
184
|
+
dashServer.close(onClose);
|
|
185
|
+
webhookServer.close(onClose);
|
|
186
|
+
setTimeout(() => process.exit(1), 30_000);
|
|
187
|
+
}
|
|
188
|
+
process.on("SIGTERM", shutdown);
|
|
189
|
+
process.on("SIGINT", shutdown);
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
console.error("Failed to start:", err);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/commands/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,cAAc,SAiCvB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
export const webhookCommand = new Command("webhook")
|
|
4
|
+
.description("Simulate a webhook payload against the local server")
|
|
5
|
+
.requiredOption("--file <path>", "Path to JSON webhook payload file")
|
|
6
|
+
.option("--port <port>", "Local server port", "3000")
|
|
7
|
+
.option("--secret <secret>", "Webhook secret for signing", "dev-secret")
|
|
8
|
+
.action(async (options) => {
|
|
9
|
+
const { createHmac } = await import("crypto");
|
|
10
|
+
const payload = readFileSync(options.file, "utf-8");
|
|
11
|
+
const hmac = createHmac("sha256", options.secret);
|
|
12
|
+
hmac.update(payload);
|
|
13
|
+
const signature = hmac.digest("hex");
|
|
14
|
+
const url = `http://localhost:${options.port}/webhooks/linear`;
|
|
15
|
+
console.log(`Sending webhook to ${url}`);
|
|
16
|
+
console.log(`Payload: ${options.file}`);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(url, {
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
"Linear-Signature": signature,
|
|
23
|
+
},
|
|
24
|
+
body: payload,
|
|
25
|
+
});
|
|
26
|
+
const result = await response.json();
|
|
27
|
+
console.log(`Response (${response.status}):`, JSON.stringify(result, null, 2));
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.error(`Failed to send webhook:`, e);
|
|
31
|
+
console.error(`Is the dev server running? Try: lag dev`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/commands/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,qDAAqD,CAAC;KAClE,cAAc,CAAC,eAAe,EAAE,mCAAmC,CAAC;KACpE,MAAM,CAAC,eAAe,EAAE,mBAAmB,EAAE,MAAM,CAAC;KACpD,MAAM,CAAC,mBAAmB,EAAE,4BAA4B,EAAE,YAAY,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE9C,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAErC,MAAM,GAAG,GAAG,oBAAoB,OAAO,CAAC,IAAI,kBAAkB,CAAC;IAE/D,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,kBAAkB,EAAE,SAAS;aAC9B;YACD,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,CAAC,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { runCommand } from "./commands/run.js";
|
|
4
|
+
import { devCommand } from "./commands/dev.js";
|
|
5
|
+
import { webhookCommand } from "./commands/webhook.js";
|
|
6
|
+
import { configCommand } from "./commands/config.js";
|
|
7
|
+
import { startCommand } from "./commands/start.js";
|
|
8
|
+
import { migrateCommand } from "./commands/migrate.js";
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name("ura")
|
|
12
|
+
.description("urateam CLI")
|
|
13
|
+
.version("0.1.0");
|
|
14
|
+
program.addCommand(runCommand);
|
|
15
|
+
program.addCommand(devCommand);
|
|
16
|
+
program.addCommand(webhookCommand);
|
|
17
|
+
program.addCommand(configCommand);
|
|
18
|
+
program.addCommand(startCommand);
|
|
19
|
+
program.addCommand(migrateCommand);
|
|
20
|
+
program.parse();
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,aAAa,CAAC;KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AAEnC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@urateam/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ura": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": ["dist"],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/JonB32/urateam.git",
|
|
14
|
+
"directory": "packages/cli"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"dev": "tsx src/index.ts"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@hono/node-server": "^1.14.0",
|
|
23
|
+
"@urateam/core": "workspace:*",
|
|
24
|
+
"@urateam/dashboard": "workspace:*",
|
|
25
|
+
"@linear/sdk": "^29.0.0",
|
|
26
|
+
"better-sqlite3": "^11.8.0",
|
|
27
|
+
"commander": "^13.1.0",
|
|
28
|
+
"postgres": "^3.4.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/better-sqlite3": "^7.6.0",
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
33
|
+
"vitest": "^3.0.0",
|
|
34
|
+
"typescript": "^5.7.0"
|
|
35
|
+
}
|
|
36
|
+
}
|