lalph 0.1.78 → 0.1.80
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/cli.mjs +1286 -537
- package/package.json +1 -1
- package/src/IssueSources.ts +1 -1
- package/src/Prd.ts +53 -51
- package/src/Tracing.ts +64 -0
- package/src/cli.ts +6 -0
- package/src/commands/root.ts +10 -1
package/package.json
CHANGED
package/src/IssueSources.ts
CHANGED
|
@@ -74,7 +74,7 @@ export class CurrentIssueSource extends ServiceMap.Service<
|
|
|
74
74
|
source.layer,
|
|
75
75
|
yield* Layer.CurrentMemoMap,
|
|
76
76
|
yield* Effect.scope,
|
|
77
|
-
)
|
|
77
|
+
).pipe(Effect.withSpan("CurrentIssueSource.build"))
|
|
78
78
|
return ServiceMap.add(services, CurrentIssueSource, source)
|
|
79
79
|
}),
|
|
80
80
|
)
|
package/src/Prd.ts
CHANGED
|
@@ -136,65 +136,67 @@ export class Prd extends ServiceMap.Service<
|
|
|
136
136
|
|
|
137
137
|
const updatedIssues = new Map<string, PrdIssue>()
|
|
138
138
|
|
|
139
|
-
const sync =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
139
|
+
const sync = Effect.gen(function* () {
|
|
140
|
+
const updated = yield* readPrd
|
|
141
|
+
const anyChanges =
|
|
142
|
+
updated.length !== current.length ||
|
|
143
|
+
updated.some((u, i) => u.isChangedComparedTo(current[i]!))
|
|
144
|
+
if (!anyChanges) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
const githubPrs = new Map<string, number>()
|
|
149
|
+
const toRemove = new Set(
|
|
150
|
+
current.filter((i) => i.id !== null).map((i) => i.id!),
|
|
151
|
+
)
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
for (const issue of updated) {
|
|
154
|
+
toRemove.delete(issue.id!)
|
|
156
155
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
156
|
+
if (issue.id === null) {
|
|
157
|
+
yield* source.createIssue(issue)
|
|
158
|
+
continue
|
|
159
|
+
}
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
if (issue.githubPrNumber) {
|
|
162
|
+
githubPrs.set(issue.id, issue.githubPrNumber)
|
|
163
|
+
}
|
|
165
164
|
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
const existing = current.find((i) => i.id === issue.id)
|
|
166
|
+
if (!existing || !existing.isChangedComparedTo(issue)) continue
|
|
168
167
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
yield* source.updateIssue({
|
|
169
|
+
issueId: issue.id,
|
|
170
|
+
title: issue.title,
|
|
171
|
+
description: issue.description,
|
|
172
|
+
state: issue.state,
|
|
173
|
+
blockedBy: issue.blockedBy,
|
|
174
|
+
})
|
|
176
175
|
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
updatedIssues.set(issue.id, issue)
|
|
177
|
+
}
|
|
179
178
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
yield* Effect.forEach(
|
|
180
|
+
toRemove,
|
|
181
|
+
(issueId) => source.cancelIssue(issueId),
|
|
182
|
+
{ concurrency: "unbounded" },
|
|
183
|
+
)
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
185
|
+
current = yield* source.issues
|
|
186
|
+
yield* fs.writeFileString(
|
|
187
|
+
prdFile,
|
|
188
|
+
PrdIssue.arrayToYaml(
|
|
189
|
+
current.map((issue) => {
|
|
190
|
+
const prNumber = githubPrs.get(issue.id!)
|
|
191
|
+
if (!prNumber) return issue
|
|
192
|
+
return new PrdIssue({ ...issue, githubPrNumber: prNumber })
|
|
193
|
+
}),
|
|
194
|
+
),
|
|
195
|
+
)
|
|
196
|
+
}).pipe(
|
|
197
|
+
Effect.uninterruptible,
|
|
198
|
+
syncSemaphore.withPermit,
|
|
199
|
+
Effect.withSpan("Prd.sync"),
|
|
198
200
|
)
|
|
199
201
|
|
|
200
202
|
const updateSyncHandle = yield* FiberHandle.make()
|
|
@@ -255,7 +257,7 @@ export class Prd extends ServiceMap.Service<
|
|
|
255
257
|
flagUnmergable,
|
|
256
258
|
findById,
|
|
257
259
|
}
|
|
258
|
-
}),
|
|
260
|
+
}).pipe(Effect.withSpan("Prd.build")),
|
|
259
261
|
}) {
|
|
260
262
|
static layerNoWorktree = Layer.effect(this, this.make)
|
|
261
263
|
static layer = this.layerNoWorktree.pipe(Layer.provideMerge(Worktree.layer))
|
package/src/Tracing.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Cause,
|
|
3
|
+
Duration,
|
|
4
|
+
Effect,
|
|
5
|
+
Fiber,
|
|
6
|
+
Layer,
|
|
7
|
+
Logger,
|
|
8
|
+
LogLevel,
|
|
9
|
+
Tracer,
|
|
10
|
+
} from "effect"
|
|
11
|
+
import { CurrentLoggers } from "effect/Logger"
|
|
12
|
+
import { MinimumLogLevel } from "effect/References"
|
|
13
|
+
|
|
14
|
+
export const TracingLayer = Layer.unwrap(
|
|
15
|
+
Effect.gen(function* () {
|
|
16
|
+
const logLevel = yield* MinimumLogLevel
|
|
17
|
+
if (LogLevel.isLessThan("Trace", logLevel)) {
|
|
18
|
+
return Layer.empty
|
|
19
|
+
}
|
|
20
|
+
return TracerLogger
|
|
21
|
+
}),
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const TracerLogger = Effect.gen(function* () {
|
|
25
|
+
const loggers = yield* CurrentLoggers
|
|
26
|
+
const tracer = yield* Tracer.Tracer
|
|
27
|
+
const fiber = Fiber.getCurrent()!
|
|
28
|
+
|
|
29
|
+
const log = (message: string, time: bigint) => {
|
|
30
|
+
const date = new Date(Number(time / BigInt(1e6)))
|
|
31
|
+
const options: Logger.Logger.Options<string> = {
|
|
32
|
+
message,
|
|
33
|
+
fiber,
|
|
34
|
+
date,
|
|
35
|
+
logLevel: "Trace",
|
|
36
|
+
cause: Cause.empty,
|
|
37
|
+
}
|
|
38
|
+
loggers.forEach((logger) => {
|
|
39
|
+
logger.log(options)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return Tracer.make({
|
|
44
|
+
span(name, parent, annotations, links, startTime, kind, options) {
|
|
45
|
+
const span = tracer.span(
|
|
46
|
+
name,
|
|
47
|
+
parent,
|
|
48
|
+
annotations,
|
|
49
|
+
links,
|
|
50
|
+
startTime,
|
|
51
|
+
kind,
|
|
52
|
+
options,
|
|
53
|
+
)
|
|
54
|
+
log(`${name}: started`, startTime)
|
|
55
|
+
const oldEnd = span.end
|
|
56
|
+
span.end = (endTime, cause) => {
|
|
57
|
+
const duration = Duration.nanos(endTime - span.status.startTime)
|
|
58
|
+
log(`${name}: completed. Took ${Duration.format(duration)}`, endTime)
|
|
59
|
+
return oldEnd.call(span, endTime, cause)
|
|
60
|
+
}
|
|
61
|
+
return span
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
}).pipe(Layer.effect(Tracer.Tracer))
|
package/src/cli.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { commandAgent } from "./commands/agent.ts"
|
|
|
14
14
|
import PackageJson from "../package.json" with { type: "json" }
|
|
15
15
|
import { resetCurrentIssueSource } from "./IssueSources.ts"
|
|
16
16
|
import { GithubCli } from "./Github/Cli.ts"
|
|
17
|
+
import { TracingLayer } from "./Tracing.ts"
|
|
18
|
+
import { MinimumLogLevel } from "effect/References"
|
|
17
19
|
|
|
18
20
|
commandRoot.pipe(
|
|
19
21
|
Command.withSubcommands([
|
|
@@ -32,6 +34,10 @@ commandRoot.pipe(
|
|
|
32
34
|
}
|
|
33
35
|
}),
|
|
34
36
|
),
|
|
37
|
+
Command.provide(TracingLayer),
|
|
38
|
+
Command.provide(({ verbose }) =>
|
|
39
|
+
verbose ? Layer.succeed(MinimumLogLevel, "All") : Layer.empty,
|
|
40
|
+
),
|
|
35
41
|
(_) =>
|
|
36
42
|
Command.run(_, {
|
|
37
43
|
version: PackageJson.version,
|
package/src/commands/root.ts
CHANGED
|
@@ -90,6 +90,11 @@ const specsDirectory = Flag.directory("specs").pipe(
|
|
|
90
90
|
Flag.withDefault(".specs"),
|
|
91
91
|
)
|
|
92
92
|
|
|
93
|
+
const verbose = Flag.boolean("verbose").pipe(
|
|
94
|
+
Flag.withDescription("Enable verbose logging"),
|
|
95
|
+
Flag.withAlias("v"),
|
|
96
|
+
)
|
|
97
|
+
|
|
93
98
|
// handled in cli.ts
|
|
94
99
|
const reset = Flag.boolean("reset").pipe(
|
|
95
100
|
Flag.withDescription("Reset the current issue source before running"),
|
|
@@ -104,6 +109,7 @@ export const commandRoot = Command.make("lalph", {
|
|
|
104
109
|
stallMinutes,
|
|
105
110
|
reset,
|
|
106
111
|
specsDirectory,
|
|
112
|
+
verbose,
|
|
107
113
|
}).pipe(
|
|
108
114
|
Command.withHandler(
|
|
109
115
|
Effect.fnUntraced(function* ({
|
|
@@ -124,7 +130,10 @@ export const commandRoot = Command.make("lalph", {
|
|
|
124
130
|
const semaphore = Effect.makeSemaphoreUnsafe(runConcurrency)
|
|
125
131
|
const fibers = yield* FiberSet.make()
|
|
126
132
|
|
|
127
|
-
yield* resetInProgress.pipe(
|
|
133
|
+
yield* resetInProgress.pipe(
|
|
134
|
+
Effect.provide(source),
|
|
135
|
+
Effect.withSpan("Main.resetInProgress"),
|
|
136
|
+
)
|
|
128
137
|
|
|
129
138
|
yield* Effect.log(
|
|
130
139
|
`Executing ${iterationsDisplay} iteration(s) with concurrency ${runConcurrency}`,
|