@usine/core 0.3.0 → 0.5.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/LICENSE +661 -21
- package/README.md +43 -18
- package/dist/agent/agent.d.ts +12 -8
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +14 -10
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/brain.d.ts +2 -6
- package/dist/agent/brain.d.ts.map +1 -1
- package/dist/agent/brain.js +3 -7
- package/dist/agent/brain.js.map +1 -1
- package/dist/agent/capability.d.ts +4 -4
- package/dist/agent/capability.d.ts.map +1 -1
- package/dist/agent/capability.js +4 -4
- package/dist/agent/capability.js.map +1 -1
- package/dist/agent/session.d.ts +90 -28
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +103 -28
- package/dist/agent/session.js.map +1 -1
- package/dist/attempt/attempt.d.ts +92 -12
- package/dist/attempt/attempt.d.ts.map +1 -1
- package/dist/attempt/attempt.js +114 -13
- package/dist/attempt/attempt.js.map +1 -1
- package/dist/attempt/channel.d.ts +91 -51
- package/dist/attempt/channel.d.ts.map +1 -1
- package/dist/attempt/channel.js +74 -45
- package/dist/attempt/channel.js.map +1 -1
- package/dist/attempt/failure.d.ts +27 -14
- package/dist/attempt/failure.d.ts.map +1 -1
- package/dist/attempt/failure.js +27 -14
- package/dist/attempt/failure.js.map +1 -1
- package/dist/attempt/outcome.d.ts +3 -5
- package/dist/attempt/outcome.d.ts.map +1 -1
- package/dist/attempt/outcome.js +2 -4
- package/dist/attempt/outcome.js.map +1 -1
- package/dist/attempt/salvage.d.ts +77 -0
- package/dist/attempt/salvage.d.ts.map +1 -0
- package/dist/attempt/salvage.js +49 -0
- package/dist/attempt/salvage.js.map +1 -0
- package/dist/attempt/start.d.ts +35 -0
- package/dist/attempt/start.d.ts.map +1 -0
- package/dist/attempt/start.js +30 -0
- package/dist/attempt/start.js.map +1 -0
- package/dist/closed-struct.d.ts +7 -0
- package/dist/closed-struct.d.ts.map +1 -0
- package/dist/closed-struct.js +12 -0
- package/dist/closed-struct.js.map +1 -0
- package/dist/cycle-budget.d.ts +7 -8
- package/dist/cycle-budget.d.ts.map +1 -1
- package/dist/cycle-budget.js +16 -20
- package/dist/cycle-budget.js.map +1 -1
- package/dist/event.d.ts +4 -8
- package/dist/event.d.ts.map +1 -1
- package/dist/event.js +4 -8
- package/dist/event.js.map +1 -1
- package/dist/instance.d.ts +7 -1
- package/dist/instance.d.ts.map +1 -1
- package/dist/instance.js +6 -1
- package/dist/instance.js.map +1 -1
- package/dist/item.d.ts +1 -2
- package/dist/item.d.ts.map +1 -1
- package/dist/item.js +1 -2
- package/dist/item.js.map +1 -1
- package/dist/loop.d.ts +10 -2
- package/dist/loop.d.ts.map +1 -1
- package/dist/loop.js +9 -2
- package/dist/loop.js.map +1 -1
- package/dist/operator.d.ts +8 -0
- package/dist/operator.d.ts.map +1 -0
- package/dist/operator.js +9 -0
- package/dist/operator.js.map +1 -0
- package/dist/repository.d.ts +6 -8
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +8 -10
- package/dist/repository.js.map +1 -1
- package/dist/run/again.d.ts +13 -0
- package/dist/run/again.d.ts.map +1 -0
- package/dist/run/again.js +14 -0
- package/dist/run/again.js.map +1 -0
- package/dist/run/approval.d.ts +27 -0
- package/dist/run/approval.d.ts.map +1 -0
- package/dist/run/approval.js +25 -0
- package/dist/run/approval.js.map +1 -0
- package/dist/run/run.d.ts +2 -2
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +2 -2
- package/dist/run/run.js.map +1 -1
- package/dist/run/state.d.ts +22 -31
- package/dist/run/state.d.ts.map +1 -1
- package/dist/run/state.js +23 -36
- package/dist/run/state.js.map +1 -1
- package/dist/step/harvest.d.ts +44 -0
- package/dist/step/harvest.d.ts.map +1 -0
- package/dist/step/harvest.js +368 -0
- package/dist/step/harvest.js.map +1 -0
- package/dist/step/result.d.ts +15 -4
- package/dist/step/result.d.ts.map +1 -1
- package/dist/step/result.js +14 -4
- package/dist/step/result.js.map +1 -1
- package/dist/step/step.d.ts +2 -8
- package/dist/step/step.d.ts.map +1 -1
- package/dist/step/step.js +2 -8
- package/dist/step/step.js.map +1 -1
- package/dist/worker.d.ts +160 -4
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +171 -4
- package/dist/worker.js.map +1 -1
- package/package.json +32 -7
package/dist/run/state.js
CHANGED
|
@@ -12,91 +12,78 @@ import { EventId } from "../event.js";
|
|
|
12
12
|
* pending | waiting | queued ──► canceled (supersede, revoke: a started
|
|
13
13
|
* attempt always finishes, ADR 0007)
|
|
14
14
|
*
|
|
15
|
-
* Each transition accepts only
|
|
16
|
-
*
|
|
17
|
-
* decoding a stored row with `RunState`.
|
|
15
|
+
* Each transition accepts only its legal source states, so an illegal transition is a type
|
|
16
|
+
* error. States come from the transitions or from decoding a stored row with `RunState`.
|
|
18
17
|
*/
|
|
19
|
-
/** The operator closed the run by hand. */
|
|
20
18
|
export class OperatorCanceled extends Schema.TaggedClass("CancelReason/OperatorCanceled")("OperatorCanceled", {}) {
|
|
21
19
|
}
|
|
22
|
-
/**
|
|
20
|
+
/** Cancellation because a newer Event for the same Item arrived before any Attempt started. */
|
|
23
21
|
export class Superseded extends Schema.TaggedClass("CancelReason/Superseded")("Superseded", { by: EventId }) {
|
|
24
22
|
}
|
|
25
|
-
/**
|
|
23
|
+
/** Cancellation because the Item stopped matching the Loop's trigger before any Attempt started. */
|
|
26
24
|
export class Revoked extends Schema.TaggedClass("CancelReason/Revoked")("Revoked", {}) {
|
|
27
25
|
}
|
|
28
26
|
export const CancelReason = Schema.Union([OperatorCanceled, Superseded, Revoked]);
|
|
29
|
-
/**
|
|
27
|
+
/** A new Run with no Attempt started and no approval gate passed. */
|
|
30
28
|
export class Pending extends Schema.TaggedClass("RunState/Pending")("Pending", {}) {
|
|
31
29
|
}
|
|
32
|
-
/**
|
|
30
|
+
/** A Run waiting for its Loop's approval Event. */
|
|
33
31
|
export class Waiting extends Schema.TaggedClass("RunState/Waiting")("Waiting", {}) {
|
|
34
32
|
}
|
|
35
|
-
/**
|
|
33
|
+
/** An approved Run waiting for a Worker slot. */
|
|
36
34
|
export class Queued extends Schema.TaggedClass("RunState/Queued")("Queued", {}) {
|
|
37
35
|
}
|
|
38
|
-
/**
|
|
36
|
+
/** A Run with an Attempt running on a Worker. */
|
|
39
37
|
export class Running extends Schema.TaggedClass("RunState/Running")("Running", {}) {
|
|
40
38
|
}
|
|
41
|
-
/**
|
|
39
|
+
/** A Run whose Step finished with a stored result. */
|
|
42
40
|
export class Succeeded extends Schema.TaggedClass("RunState/Succeeded")("Succeeded", {}) {
|
|
43
41
|
}
|
|
44
|
-
/**
|
|
42
|
+
/** A Run whose last Attempt failed without an auto-retry; the failure is stored on the Attempt. */
|
|
45
43
|
export class Failed extends Schema.TaggedClass("RunState/Failed")("Failed", {}) {
|
|
46
44
|
}
|
|
47
|
-
/** Canceled, with the reason recorded. */
|
|
48
45
|
export class Canceled extends Schema.TaggedClass("RunState/Canceled")("Canceled", {
|
|
49
46
|
reason: CancelReason,
|
|
50
47
|
}) {
|
|
51
48
|
}
|
|
52
|
-
/**
|
|
49
|
+
/** The states of a Run that isn't closed. */
|
|
53
50
|
export const Open = Schema.Union([Pending, Waiting, Queued, Running]);
|
|
54
|
-
/** A Run's progress from creation through approval and execution to a recorded outcome. */
|
|
55
51
|
export const RunState = Schema.Union([...Open.members, Succeeded, Failed, Canceled]);
|
|
56
|
-
/** The states
|
|
52
|
+
/** The states before any Attempt starts, accepted by `supersede` and `revoke`. */
|
|
57
53
|
export const Unstarted = Schema.Union([Pending, Waiting, Queued]);
|
|
58
|
-
/** The states an
|
|
54
|
+
/** The states from which an Attempt can start. */
|
|
59
55
|
export const Startable = Schema.Union([Pending, Queued]);
|
|
60
56
|
export const isOpen = Schema.is(Open);
|
|
61
57
|
export const isUnstarted = Schema.is(Unstarted);
|
|
62
58
|
export const isStartable = Schema.is(Startable);
|
|
63
|
-
/**
|
|
59
|
+
/** Returns the operator actions allowed in `state`. */
|
|
64
60
|
export const operatorActions = (state) => ({
|
|
65
61
|
canApprove: state._tag === "Waiting",
|
|
66
62
|
canRetry: state._tag === "Failed",
|
|
63
|
+
canResolveFailure: state._tag === "Failed",
|
|
67
64
|
canCancel: isOpen(state),
|
|
65
|
+
canRunAgain: state._tag === "Succeeded" || state._tag === "Canceled",
|
|
68
66
|
});
|
|
69
|
-
/**
|
|
70
|
-
* Builds a tag tuple that must name every `_tag` of `State` and nothing else,
|
|
71
|
-
* so the SQL-side lists below cannot drift from the unions above. A foreign tag
|
|
72
|
-
* fails the `Tags` constraint; a missing tag collapses the parameters to `[never]`.
|
|
73
|
-
*/
|
|
67
|
+
/** Returns its arguments, which must be exactly the `_tag` values of `State`; a missing or extra tag is a type error. */
|
|
74
68
|
const tagsOf = () => (...tags) => tags;
|
|
75
|
-
/** The
|
|
69
|
+
/** The `_tag` values of `Open`, for SQL filters. */
|
|
76
70
|
export const OPEN_STATE_TAGS = tagsOf()("Pending", "Waiting", "Queued", "Running");
|
|
77
|
-
/**
|
|
71
|
+
/** The `_tag` values of `RunState`. */
|
|
78
72
|
export const STATE_TAGS = tagsOf()("Pending", "Waiting", "Queued", "Running", "Succeeded", "Failed", "Canceled");
|
|
79
|
-
/** The
|
|
73
|
+
/** The `_tag` values of `Unstarted`, for SQL filters. */
|
|
80
74
|
export const UNSTARTED_STATE_TAGS = tagsOf()("Pending", "Waiting", "Queued");
|
|
81
|
-
/** Parks a pending run on its loop's approval gate. */
|
|
82
75
|
export const awaitApproval = (_state) => new Waiting();
|
|
83
|
-
/** Returns the approved state; the Run still waits for a Worker slot before execution. */
|
|
84
76
|
export const approve = (_state) => new Queued();
|
|
85
|
-
/** Returns the running state for a first Attempt after any required approval has been granted. */
|
|
86
77
|
export const start = (_state) => new Running();
|
|
87
|
-
/** Closes the run after a successful attempt. */
|
|
88
78
|
export const succeed = (_state) => new Succeeded();
|
|
89
|
-
/**
|
|
79
|
+
/** Returns `Failed`. Callers use it only if `shouldAutoRetry` returns `false`. */
|
|
90
80
|
export const fail = (_state) => new Failed();
|
|
91
|
-
/** Returns the reopened state for operator retry; attempt N+1 belongs to the same Run and Step. */
|
|
92
81
|
export const retry = (_state) => new Running();
|
|
93
|
-
/** Cancels from any open state. */
|
|
94
82
|
export const cancelByOperator = (_state) => new Canceled({ reason: new OperatorCanceled() });
|
|
95
83
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
84
|
+
* Returns `Canceled` for a Run replaced by the newer Event `by`. A running Run isn't
|
|
85
|
+
* superseded; the engine evaluates the newer Event after its Attempt ends (ADR 0007).
|
|
98
86
|
*/
|
|
99
87
|
export const supersede = (_state, by) => new Canceled({ reason: new Superseded({ by }) });
|
|
100
|
-
/** Cancels an unstarted run because its Item stopped matching the loop's trigger. */
|
|
101
88
|
export const revoke = (_state) => new Canceled({ reason: new Revoked() });
|
|
102
89
|
//# sourceMappingURL=state.js.map
|
package/dist/run/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/run/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/run/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { AttemptWindows } from "../attempt/attempt.ts";
|
|
3
|
+
import type { RunSpec } from "../attempt/channel.ts";
|
|
4
|
+
import { Comment, Commit, PullRequest } from "./result.ts";
|
|
5
|
+
/** The fields of `RunSpec` that harvesting reads. */
|
|
6
|
+
export type HarvestSpec = Pick<RunSpec, "attemptId" | "repository" | "revision" | "baseCommit" | "payload" | "preparedAt" | "botLogin" | "agent">;
|
|
7
|
+
/**
|
|
8
|
+
* An effect that reads the harvested Attempt's `AttemptWindows`. Harvesting runs it after
|
|
9
|
+
* GitHub lists the comments, so the result includes Attempts that started during the harvest.
|
|
10
|
+
*/
|
|
11
|
+
export type AttemptWindowsRead<W> = Effect.Effect<AttemptWindows, W>;
|
|
12
|
+
/**
|
|
13
|
+
* A function that runs a read-only `git` or `gh` command in the checkout and returns its
|
|
14
|
+
* stdout lines. Fails with `E` on a non-zero exit.
|
|
15
|
+
*/
|
|
16
|
+
export type HarvestCommand<E> = (command: "git" | "gh", args: ReadonlyArray<string>) => Effect.Effect<ReadonlyArray<string>, E>;
|
|
17
|
+
declare const HarvestError_base: Schema.Class<HarvestError, Schema.TaggedStruct<"HarvestError", {
|
|
18
|
+
readonly stage: Schema.Literals<readonly ["git", "github", "windows"]>;
|
|
19
|
+
readonly message: Schema.NonEmptyString;
|
|
20
|
+
readonly cause: Schema.Defect;
|
|
21
|
+
}>, import("effect/Cause").YieldableError>;
|
|
22
|
+
/** An error for invalid `git` or GitHub output, or for Attempt windows that can't be read. */
|
|
23
|
+
export declare class HarvestError extends HarvestError_base {
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the facts from a finished Attempt's checkout: new commits, the pull requests at the
|
|
27
|
+
* final commit, and the comments and reviews attributed to the Attempt. A GitHub failure or
|
|
28
|
+
* 10-second timeout drops only the GitHub facts. Fails with `HarvestError` if git output is
|
|
29
|
+
* invalid or the windows can't be read.
|
|
30
|
+
*/
|
|
31
|
+
export declare const harvestFacts: <E extends {
|
|
32
|
+
readonly _tag: string;
|
|
33
|
+
readonly message: string;
|
|
34
|
+
}, W>(spec: HarvestSpec, run: HarvestCommand<E>, windows: AttemptWindowsRead<W>) => Effect.Effect<readonly (Comment | Commit | PullRequest)[], E | HarvestError, never>;
|
|
35
|
+
/**
|
|
36
|
+
* Returns the comments and reviews that an unsuccessful Attempt posted on the Run's Item,
|
|
37
|
+
* attributed as in `harvestFacts`. Never fails; on any error, returns an empty list.
|
|
38
|
+
*/
|
|
39
|
+
export declare const harvestPostedComments: <E extends {
|
|
40
|
+
readonly _tag: string;
|
|
41
|
+
readonly message: string;
|
|
42
|
+
}, W>(spec: HarvestSpec, run: HarvestCommand<E>, windows: AttemptWindowsRead<W>) => Effect.Effect<readonly Comment[], never, never>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=harvest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest.d.ts","sourceRoot":"","sources":["../../src/step/harvest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE1D,OAAO,EAAsB,cAAc,EAAe,MAAM,uBAAuB,CAAC;AACxF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,EAAE,OAAO,EAAoB,MAAM,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAElG,qDAAqD;AACrD,MAAM,MAAM,WAAW,GAAG,IAAI,CAC5B,OAAO,EACL,WAAW,GACX,YAAY,GACZ,UAAU,GACV,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,UAAU,GACV,OAAO,CACV,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAC9B,OAAO,EAAE,KAAK,GAAG,IAAI,EACrB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,KACxB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;;;;;;AAE7C,8FAA8F;AAC9F,qBAAa,YAAa,SAAQ,iBAOjC;CAAG;AAohBJ;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACvB,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7D,CAAC,mKAUD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAChC,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7D,CAAC,+HAUD,CAAC"}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { DateTime, Effect, Option, Schema } from "effect";
|
|
2
|
+
import { githubSignature } from "../agent/agent.js";
|
|
3
|
+
import { AttemptWindows, windowHolds } from "../attempt/attempt.js";
|
|
4
|
+
import { ItemNumber } from "../item.js";
|
|
5
|
+
import { CommitSha, RepositoryRevision } from "../repository.js";
|
|
6
|
+
import { Comment, Commit, PullRequest } from "./result.js";
|
|
7
|
+
/** An error for invalid `git` or GitHub output, or for Attempt windows that can't be read. */
|
|
8
|
+
export class HarvestError extends Schema.TaggedError("@usine/core/HarvestError")("HarvestError", {
|
|
9
|
+
stage: Schema.Literals(["git", "github", "windows"]),
|
|
10
|
+
message: Schema.NonEmptyString,
|
|
11
|
+
cause: Schema.Defect(),
|
|
12
|
+
}) {
|
|
13
|
+
}
|
|
14
|
+
const PullRequestResponse = Schema.Struct({
|
|
15
|
+
number: PullRequest.fields.number,
|
|
16
|
+
url: Schema.URLFromString,
|
|
17
|
+
head: Schema.Struct({ sha: CommitSha }),
|
|
18
|
+
}).pipe(Schema.encodeKeys({ url: "html_url" }));
|
|
19
|
+
const decodePullRequestPages = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Array(Schema.Array(PullRequestResponse))));
|
|
20
|
+
const decodeCommit = Schema.decodeUnknownEffect(CommitSha);
|
|
21
|
+
/** Decodes the Item `number` and `url` from a payload. Returns `None` for a schedule payload. */
|
|
22
|
+
const decodePayloadItem = Schema.decodeUnknownOption(Schema.Struct({ number: ItemNumber, url: Schema.URLFromString }));
|
|
23
|
+
/** The GraphQL query for the credential's login, used only if the `RunSpec` has no bot login. */
|
|
24
|
+
const VIEWER_QUERY = "query=query { viewer { login } }";
|
|
25
|
+
const decodeViewer = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Struct({
|
|
26
|
+
data: Schema.Struct({ viewer: Schema.Struct({ login: Schema.NonEmptyString }) }),
|
|
27
|
+
})));
|
|
28
|
+
const Author = Schema.NullOr(Schema.Struct({ login: Schema.String }));
|
|
29
|
+
// GitHub's schema has an optional body for issue comments and a required body for reviews and
|
|
30
|
+
// review comments; a review without text has an empty body.
|
|
31
|
+
const IssueCommentResponse = Schema.Struct({
|
|
32
|
+
url: Schema.URLFromString,
|
|
33
|
+
user: Author,
|
|
34
|
+
body: Schema.optionalKey(Schema.String),
|
|
35
|
+
createdAt: Schema.DateTimeUtcFromString,
|
|
36
|
+
updatedAt: Schema.DateTimeUtcFromString,
|
|
37
|
+
}).pipe(Schema.encodeKeys({ url: "html_url", createdAt: "created_at", updatedAt: "updated_at" }));
|
|
38
|
+
const decodeIssueCommentPages = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Array(Schema.Array(IssueCommentResponse))));
|
|
39
|
+
const ReviewResponse = Schema.Struct({
|
|
40
|
+
id: Schema.Int,
|
|
41
|
+
url: Schema.URLFromString,
|
|
42
|
+
user: Author,
|
|
43
|
+
body: Schema.String,
|
|
44
|
+
state: Schema.String,
|
|
45
|
+
submittedAt: Schema.optionalKey(Schema.NullOr(Schema.DateTimeUtcFromString)),
|
|
46
|
+
}).pipe(Schema.encodeKeys({ url: "html_url", submittedAt: "submitted_at" }));
|
|
47
|
+
const decodeReviewPages = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Array(Schema.Array(ReviewResponse))));
|
|
48
|
+
const ReviewCommentResponse = Schema.Struct({
|
|
49
|
+
url: Schema.URLFromString,
|
|
50
|
+
user: Author,
|
|
51
|
+
body: Schema.String,
|
|
52
|
+
createdAt: Schema.DateTimeUtcFromString,
|
|
53
|
+
updatedAt: Schema.DateTimeUtcFromString,
|
|
54
|
+
reviewId: Schema.NullOr(Schema.Int),
|
|
55
|
+
}).pipe(Schema.encodeKeys({
|
|
56
|
+
url: "html_url",
|
|
57
|
+
createdAt: "created_at",
|
|
58
|
+
updatedAt: "updated_at",
|
|
59
|
+
reviewId: "pull_request_review_id",
|
|
60
|
+
}));
|
|
61
|
+
const decodeReviewCommentPages = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Array(Schema.Array(ReviewCommentResponse))));
|
|
62
|
+
/** Runs a `gh` command and decodes its output. Fails with a `github` `HarvestError` if the output is invalid. */
|
|
63
|
+
const askGitHub = (run, args, decode, what) => run("gh", args).pipe(Effect.flatMap((lines) => decode(lines.join("\n")).pipe(Effect.mapError((cause) => new HarvestError({
|
|
64
|
+
stage: "github",
|
|
65
|
+
message: `GitHub returned invalid ${what}`,
|
|
66
|
+
cause,
|
|
67
|
+
})))));
|
|
68
|
+
/** Returns the commits from the checkout's base to its final HEAD, oldest first. */
|
|
69
|
+
const harvestCommits = Effect.fn("StepResult.harvestCommits")(function* (spec, run) {
|
|
70
|
+
yield* Effect.annotateCurrentSpan({ attemptId: spec.attemptId, repository: spec.repository });
|
|
71
|
+
// The first space ends the commit ID.
|
|
72
|
+
const lines = yield* run("git", [
|
|
73
|
+
"log",
|
|
74
|
+
"--reverse",
|
|
75
|
+
"--format=%H %s",
|
|
76
|
+
`${spec.baseCommit}..HEAD`,
|
|
77
|
+
]);
|
|
78
|
+
return yield* Effect.forEach(lines, (line) => Effect.gen(function* () {
|
|
79
|
+
const separator = line.indexOf(" ");
|
|
80
|
+
const sha = yield* decodeCommit(separator < 0 ? line : line.slice(0, separator)).pipe(Effect.mapError((cause) => new HarvestError({ stage: "git", message: "Git returned an invalid commit ID", cause })));
|
|
81
|
+
const summary = separator < 0 ? "" : line.slice(separator + 1).trim();
|
|
82
|
+
if (summary.length === 0) {
|
|
83
|
+
return yield* new HarvestError({
|
|
84
|
+
stage: "git",
|
|
85
|
+
message: `Commit ${sha} has no summary`,
|
|
86
|
+
cause: new Error("empty commit summary"),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return new Commit({ sha, summary });
|
|
90
|
+
}));
|
|
91
|
+
});
|
|
92
|
+
/** Returns the pull requests whose head is the checkout's final commit, without duplicates. */
|
|
93
|
+
const harvestPullRequests = Effect.fn("StepResult.harvestPullRequests")(function* (spec, run) {
|
|
94
|
+
yield* Effect.annotateCurrentSpan({ attemptId: spec.attemptId, repository: spec.repository });
|
|
95
|
+
const head = yield* decodeCommit((yield* run("git", ["rev-parse", "HEAD"])).join("")).pipe(Effect.mapError((cause) => new HarvestError({ stage: "git", message: "Git returned an invalid final HEAD", cause })));
|
|
96
|
+
const branch = (yield* run("git", ["branch", "--show-current"])).join("");
|
|
97
|
+
// Checkouts start detached. There's no candidate if HEAD is unchanged, no branch was created,
|
|
98
|
+
// and the revision isn't a fixed commit.
|
|
99
|
+
if (head === spec.baseCommit &&
|
|
100
|
+
spec.revision !== RepositoryRevision.make(spec.baseCommit) &&
|
|
101
|
+
branch === "") {
|
|
102
|
+
yield* Effect.logDebug("No pull request candidate in the Attempt checkout", {
|
|
103
|
+
attemptId: spec.attemptId,
|
|
104
|
+
});
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
// GitHub returns HTTP 422 for a commit that was never pushed, so first check that a branch or
|
|
108
|
+
// `refs/pull/<n>/head` points at it.
|
|
109
|
+
if (head !== spec.baseCommit) {
|
|
110
|
+
const refs = yield* run("git", ["ls-remote", "origin", "refs/heads/*", "refs/pull/*/head"]);
|
|
111
|
+
if (!refs.some((ref) => ref.startsWith(`${head}\t`))) {
|
|
112
|
+
yield* Effect.logDebug("No remote branch or pull request has the Attempt's final commit", {
|
|
113
|
+
attemptId: spec.attemptId,
|
|
114
|
+
head,
|
|
115
|
+
});
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const pages = yield* askGitHub(run, ["api", `repos/${spec.repository}/commits/${head}/pulls?per_page=100`, "--paginate", "--slurp"], decodePullRequestPages, "pull request results");
|
|
120
|
+
// The response also has pull requests that contain the commit as an ancestor.
|
|
121
|
+
const facts = new Map();
|
|
122
|
+
for (const pr of pages.flat()) {
|
|
123
|
+
if (pr.head.sha === head)
|
|
124
|
+
facts.set(pr.number, new PullRequest({ number: pr.number, url: pr.url }));
|
|
125
|
+
}
|
|
126
|
+
yield* Effect.logInfo("Collected Attempt pull request results", {
|
|
127
|
+
attemptId: spec.attemptId,
|
|
128
|
+
head,
|
|
129
|
+
pullRequests: [...facts.keys()],
|
|
130
|
+
});
|
|
131
|
+
return [...facts.values()];
|
|
132
|
+
});
|
|
133
|
+
/** Returns the login of the Attempt's credential, as reported by GitHub. */
|
|
134
|
+
const credentialLogin = Effect.fn("StepResult.credentialLogin")(function* (spec, item, run) {
|
|
135
|
+
yield* Effect.logInfo("The RunSpec names no bot login, so harvesting asks GitHub for the login of the Attempt's credential", { attemptId: spec.attemptId, repository: spec.repository, item });
|
|
136
|
+
const { data } = yield* askGitHub(run, ["api", "graphql", "-f", VIEWER_QUERY], decodeViewer, "the credential's login");
|
|
137
|
+
return { login: data.viewer.login, source: "viewer" };
|
|
138
|
+
});
|
|
139
|
+
/**
|
|
140
|
+
* Lists the comments, and for a pull request the submitted reviews and diff comments, that the
|
|
141
|
+
* bot login posted on the Run's Item since preparation. Returns `None` if the Run has no Item
|
|
142
|
+
* or no preparation time.
|
|
143
|
+
*/
|
|
144
|
+
const listComments = Effect.fn("StepResult.listComments")(function* (spec, run) {
|
|
145
|
+
yield* Effect.annotateCurrentSpan({ attemptId: spec.attemptId, repository: spec.repository });
|
|
146
|
+
const item = decodePayloadItem(spec.payload);
|
|
147
|
+
if (Option.isNone(item)) {
|
|
148
|
+
yield* Effect.logDebug("The Run has no GitHub Item, so no comment is collected", {
|
|
149
|
+
attemptId: spec.attemptId,
|
|
150
|
+
});
|
|
151
|
+
return Option.none();
|
|
152
|
+
}
|
|
153
|
+
const { number, url } = item.value;
|
|
154
|
+
if (Option.isNone(spec.preparedAt)) {
|
|
155
|
+
yield* Effect.logInfo("The Attempt was prepared before preparation times were recorded, so no comment is collected", { attemptId: spec.attemptId, repository: spec.repository, item: number });
|
|
156
|
+
return Option.none();
|
|
157
|
+
}
|
|
158
|
+
// GitHub records times to the second, and `since` takes YYYY-MM-DDTHH:MM:SSZ.
|
|
159
|
+
const prepared = DateTime.toEpochMillis(spec.preparedAt.value);
|
|
160
|
+
const since = prepared - (prepared % 1_000);
|
|
161
|
+
const sinceParameter = `${DateTime.formatIso(DateTime.makeUnsafe(since)).slice(0, 19)}Z`;
|
|
162
|
+
const author = Option.isSome(spec.botLogin)
|
|
163
|
+
? { login: spec.botLogin.value, source: "run-spec" }
|
|
164
|
+
: yield* credentialLogin(spec, number, run);
|
|
165
|
+
const { login } = author;
|
|
166
|
+
yield* Effect.annotateCurrentSpan({
|
|
167
|
+
item: number,
|
|
168
|
+
author: login,
|
|
169
|
+
authorSource: author.source,
|
|
170
|
+
agent: spec.agent.name,
|
|
171
|
+
});
|
|
172
|
+
const list = (path) => [
|
|
173
|
+
"api",
|
|
174
|
+
`repos/${spec.repository}/${path}`,
|
|
175
|
+
"--paginate",
|
|
176
|
+
"--slurp",
|
|
177
|
+
];
|
|
178
|
+
// GitHub's pull request URLs are /<owner>/<repo>/pull/<number>; an issue's use `issues`.
|
|
179
|
+
const pullRequest = url.pathname.split("/")[3] === "pull";
|
|
180
|
+
const [conversation, reviews, diffComments] = yield* Effect.all([
|
|
181
|
+
askGitHub(run, list(`issues/${number}/comments?since=${sinceParameter}&per_page=100`), decodeIssueCommentPages, "issue comments"),
|
|
182
|
+
pullRequest
|
|
183
|
+
? askGitHub(run, list(`pulls/${number}/reviews?per_page=100`), decodeReviewPages, "pull request reviews")
|
|
184
|
+
: Effect.succeed([]),
|
|
185
|
+
pullRequest
|
|
186
|
+
? askGitHub(run, list(`pulls/${number}/comments?since=${sinceParameter}&per_page=100`), decodeReviewCommentPages, "review comments")
|
|
187
|
+
: Effect.succeed([]),
|
|
188
|
+
], { concurrency: "unbounded" });
|
|
189
|
+
const byLogin = (user) => user !== null && user.login === login;
|
|
190
|
+
const sincePrepared = (at) => DateTime.toEpochMillis(at) >= since;
|
|
191
|
+
// A pending review and its comments are a draft visible only to its author.
|
|
192
|
+
const pending = new Set(reviews.flat().flatMap(({ id, state }) => (state === "PENDING" ? [id] : [])));
|
|
193
|
+
// A comment's post time is its creation time and a review's is its submission time. The
|
|
194
|
+
// reviews endpoint ignores `since`, so reviews are filtered by submission time.
|
|
195
|
+
const written = [
|
|
196
|
+
...conversation.flat().flatMap(({ url, user, body, createdAt }) => byLogin(user)
|
|
197
|
+
? [
|
|
198
|
+
{
|
|
199
|
+
body,
|
|
200
|
+
at: createdAt,
|
|
201
|
+
fact: new Comment({ url, kind: "issue-comment", at: Option.some(createdAt) }),
|
|
202
|
+
},
|
|
203
|
+
]
|
|
204
|
+
: []),
|
|
205
|
+
...reviews.flat().flatMap(({ url, user, body, state, submittedAt }) => state !== "PENDING" &&
|
|
206
|
+
submittedAt !== undefined &&
|
|
207
|
+
submittedAt !== null &&
|
|
208
|
+
byLogin(user) &&
|
|
209
|
+
sincePrepared(submittedAt)
|
|
210
|
+
? [
|
|
211
|
+
{
|
|
212
|
+
body,
|
|
213
|
+
at: submittedAt,
|
|
214
|
+
fact: new Comment({ url, kind: "review", at: Option.some(submittedAt) }),
|
|
215
|
+
},
|
|
216
|
+
]
|
|
217
|
+
: []),
|
|
218
|
+
...diffComments.flat().flatMap(({ url, user, body, createdAt, reviewId }) => (reviewId === null || !pending.has(reviewId)) && byLogin(user)
|
|
219
|
+
? [
|
|
220
|
+
{
|
|
221
|
+
body,
|
|
222
|
+
at: createdAt,
|
|
223
|
+
fact: new Comment({ url, kind: "review-comment", at: Option.some(createdAt) }),
|
|
224
|
+
},
|
|
225
|
+
]
|
|
226
|
+
: []),
|
|
227
|
+
];
|
|
228
|
+
// `since` filters by update time, so it also returns comments created before preparation and
|
|
229
|
+
// edited later; those are dropped (#429).
|
|
230
|
+
const posted = written.filter(({ at }) => sincePrepared(at));
|
|
231
|
+
// Attempts that write as the same bot login are distinguished by the Agent's signature
|
|
232
|
+
// (ADR 0006, #394). Trailing whitespace is ignored.
|
|
233
|
+
const signature = githubSignature(spec.agent.name);
|
|
234
|
+
const signed = posted.filter(({ body }) => body !== undefined && body.trimEnd().endsWith(signature));
|
|
235
|
+
return Option.some({
|
|
236
|
+
item: number,
|
|
237
|
+
author,
|
|
238
|
+
since: sinceParameter,
|
|
239
|
+
signed,
|
|
240
|
+
unsigned: posted.length - signed.length,
|
|
241
|
+
edited: written.length - posted.length,
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
/** Formats `window` as an ISO interval for logs, with the end `open` while running. Returns `unrecorded` for `None`. */
|
|
245
|
+
const describeWindow = (window) => Option.match(window, {
|
|
246
|
+
onNone: () => "unrecorded",
|
|
247
|
+
onSome: ({ startedAt, endedAt }) => {
|
|
248
|
+
const end = Option.match(endedAt, { onNone: () => "open", onSome: DateTime.formatIso });
|
|
249
|
+
return `${DateTime.formatIso(startedAt)}/${end}`;
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
/**
|
|
253
|
+
* Returns the signed comments in `listing` that are inside the Attempt's own window and outside
|
|
254
|
+
* the overlapping windows (#429). Reads `windows` only if a comment is signed. Fails with a
|
|
255
|
+
* `windows` `HarvestError` if the read fails.
|
|
256
|
+
*/
|
|
257
|
+
const attributeComments = Effect.fn("StepResult.attributeComments")(function* (spec, listing, windows) {
|
|
258
|
+
yield* Effect.annotateCurrentSpan({
|
|
259
|
+
attemptId: spec.attemptId,
|
|
260
|
+
repository: spec.repository,
|
|
261
|
+
item: listing.item,
|
|
262
|
+
});
|
|
263
|
+
// Read after the listing so the result includes every Attempt that could have posted a comment.
|
|
264
|
+
const { own, overlapping } = listing.signed.length === 0
|
|
265
|
+
? new AttemptWindows({ own: Option.none(), overlapping: [] })
|
|
266
|
+
: yield* windows.pipe(Effect.mapError((cause) => new HarvestError({
|
|
267
|
+
stage: "windows",
|
|
268
|
+
message: "Can't read the windows of this attempt and of the agent's other attempts on the item",
|
|
269
|
+
cause,
|
|
270
|
+
})));
|
|
271
|
+
const placed = listing.signed.map(({ at, fact }) => ({
|
|
272
|
+
at,
|
|
273
|
+
fact,
|
|
274
|
+
inside: Option.exists(own, (window) => windowHolds(window, at)),
|
|
275
|
+
others: overlapping.filter((window) => windowHolds(window, at)),
|
|
276
|
+
}));
|
|
277
|
+
const outside = placed.filter(({ inside }) => !inside);
|
|
278
|
+
const ambiguous = placed.filter(({ inside, others }) => inside && others.length > 0);
|
|
279
|
+
const posted = placed.flatMap(({ inside, others, fact }) => inside && others.length === 0 ? [fact] : []);
|
|
280
|
+
yield* Effect.forEach(outside, ({ at, fact }) => Effect.logInfo("Left out a comment posted outside the Attempt's own window on the Item", {
|
|
281
|
+
attemptId: spec.attemptId,
|
|
282
|
+
window: describeWindow(own),
|
|
283
|
+
postedAt: DateTime.formatIso(at),
|
|
284
|
+
comment: fact.url.href,
|
|
285
|
+
kind: fact.kind,
|
|
286
|
+
}), { discard: true });
|
|
287
|
+
yield* Effect.forEach(ambiguous, ({ fact, others }) => Effect.logInfo("Left out a comment that another open Attempt of the Agent on the Item could have posted", {
|
|
288
|
+
attemptId: spec.attemptId,
|
|
289
|
+
overlapping: others.map(({ attemptId }) => attemptId),
|
|
290
|
+
comment: fact.url.href,
|
|
291
|
+
kind: fact.kind,
|
|
292
|
+
}), { discard: true });
|
|
293
|
+
const counted = (kind) => posted.filter((comment) => comment.kind === kind).length;
|
|
294
|
+
yield* Effect.logInfo("Collected the comments and reviews the Attempt posted on its Item", {
|
|
295
|
+
attemptId: spec.attemptId,
|
|
296
|
+
repository: spec.repository,
|
|
297
|
+
item: listing.item,
|
|
298
|
+
author: listing.author.login,
|
|
299
|
+
authorSource: listing.author.source,
|
|
300
|
+
agent: spec.agent.name,
|
|
301
|
+
since: listing.since,
|
|
302
|
+
issueComments: counted("issue-comment"),
|
|
303
|
+
reviews: counted("review"),
|
|
304
|
+
reviewComments: counted("review-comment"),
|
|
305
|
+
// Posted since preparation without the Agent's signature.
|
|
306
|
+
unsigned: listing.unsigned,
|
|
307
|
+
// Posted before preparation and edited since.
|
|
308
|
+
edited: listing.edited,
|
|
309
|
+
// Signed, but posted outside the Attempt's own window, for example after a cancel.
|
|
310
|
+
outside: outside.length,
|
|
311
|
+
// Signed, but posted while another Attempt of the Agent was open on the Item.
|
|
312
|
+
ambiguous: ambiguous.length,
|
|
313
|
+
// Empty if no listed comment is signed.
|
|
314
|
+
overlapping: overlapping.map(({ attemptId }) => attemptId),
|
|
315
|
+
});
|
|
316
|
+
return posted;
|
|
317
|
+
});
|
|
318
|
+
/**
|
|
319
|
+
* Runs `discovery` with a 10-second timeout. If it fails or times out, logs a warning that ends
|
|
320
|
+
* with `retaining` and returns `nothing`.
|
|
321
|
+
*/
|
|
322
|
+
const enrichment = (spec, subject, discovery, nothing, retaining = "retaining the completed agent result") => discovery.pipe(Effect.timeout("10 seconds"), Effect.catch((error) => Effect.logWarning(error._tag === "TimeoutError"
|
|
323
|
+
? `${subject} discovery timed out; ${retaining}`
|
|
324
|
+
: `${subject} discovery failed; ${retaining}`, {
|
|
325
|
+
attemptId: spec.attemptId,
|
|
326
|
+
repository: spec.repository,
|
|
327
|
+
errorTag: error._tag,
|
|
328
|
+
message: error.message,
|
|
329
|
+
}).pipe(Effect.as(nothing))));
|
|
330
|
+
/**
|
|
331
|
+
* Returns the comments and reviews attributed to the Attempt. If GitHub discovery fails, returns
|
|
332
|
+
* an empty list. Fails with `HarvestError` if the windows can't be read.
|
|
333
|
+
*/
|
|
334
|
+
const harvestComments = (spec, run, windows, retaining) => enrichment(spec, "Comment", listComments(spec, run), Option.none(), retaining).pipe(Effect.flatMap(Option.match({
|
|
335
|
+
onNone: () => Effect.succeed([]),
|
|
336
|
+
onSome: (listing) => attributeComments(spec, listing, windows),
|
|
337
|
+
})));
|
|
338
|
+
/** Logs a warning that the windows couldn't be read, ending with `outcome`. */
|
|
339
|
+
const windowsUnread = (spec, outcome) => (error) => Effect.logWarning(`Could not read the Attempt's window and those of the Agent's other Attempts on the Item, so the Attempt's comments cannot be told from theirs; ${outcome}`, {
|
|
340
|
+
attemptId: spec.attemptId,
|
|
341
|
+
repository: spec.repository,
|
|
342
|
+
cause: String(error.cause),
|
|
343
|
+
});
|
|
344
|
+
/**
|
|
345
|
+
* Returns the facts from a finished Attempt's checkout: new commits, the pull requests at the
|
|
346
|
+
* final commit, and the comments and reviews attributed to the Attempt. A GitHub failure or
|
|
347
|
+
* 10-second timeout drops only the GitHub facts. Fails with `HarvestError` if git output is
|
|
348
|
+
* invalid or the windows can't be read.
|
|
349
|
+
*/
|
|
350
|
+
export const harvestFacts = Effect.fn("StepResult.harvest")(function* (spec, run, windows) {
|
|
351
|
+
yield* Effect.annotateCurrentSpan({ attemptId: spec.attemptId, repository: spec.repository });
|
|
352
|
+
const commits = yield* harvestCommits(spec, run);
|
|
353
|
+
const pullRequests = yield* enrichment(spec, "Pull request", harvestPullRequests(spec, run), []);
|
|
354
|
+
const comments = yield* harvestComments(spec, run, windows).pipe(Effect.tapError(windowsUnread(spec, "the harvest fails")));
|
|
355
|
+
const facts = [...commits, ...pullRequests, ...comments];
|
|
356
|
+
return facts;
|
|
357
|
+
});
|
|
358
|
+
/**
|
|
359
|
+
* Returns the comments and reviews that an unsuccessful Attempt posted on the Run's Item,
|
|
360
|
+
* attributed as in `harvestFacts`. Never fails; on any error, returns an empty list.
|
|
361
|
+
*/
|
|
362
|
+
export const harvestPostedComments = Effect.fn("StepResult.harvestPostedComments")(function* (spec, run, windows) {
|
|
363
|
+
yield* Effect.annotateCurrentSpan({ attemptId: spec.attemptId, repository: spec.repository });
|
|
364
|
+
const outcome = "the Attempt that ended without success records no comment";
|
|
365
|
+
const comments = yield* harvestComments(spec, run, windows, outcome).pipe(Effect.catch((error) => windowsUnread(spec, outcome)(error).pipe(Effect.as([]))));
|
|
366
|
+
return comments;
|
|
367
|
+
});
|
|
368
|
+
//# sourceMappingURL=harvest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest.js","sourceRoot":"","sources":["../../src/step/harvest.ts"],"names":[],"mappings":"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"}
|