@mastra/factory 0.0.0-esbuild-bundle-worker-20260807173433
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1008 -0
- package/LICENSE.md +30 -0
- package/README.md +27 -0
- package/dist/auth.d.ts +183 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +507 -0
- package/dist/auth.js.map +1 -0
- package/dist/capabilities/connection.d.ts +9 -0
- package/dist/capabilities/connection.d.ts.map +1 -0
- package/dist/capabilities/connection.js +1 -0
- package/dist/capabilities/intake.d.ts +141 -0
- package/dist/capabilities/intake.d.ts.map +1 -0
- package/dist/capabilities/intake.js +1 -0
- package/dist/capabilities/version-control.d.ts +247 -0
- package/dist/capabilities/version-control.d.ts.map +1 -0
- package/dist/capabilities/version-control.js +1 -0
- package/dist/factory.d.ts +159 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +491 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/integrations/base.d.ts +254 -0
- package/dist/integrations/base.d.ts.map +1 -0
- package/dist/integrations/base.js +1 -0
- package/dist/integrations/github/config.d.ts +60 -0
- package/dist/integrations/github/config.d.ts.map +1 -0
- package/dist/integrations/github/config.js +42 -0
- package/dist/integrations/github/config.js.map +1 -0
- package/dist/integrations/github/integration.d.ts +220 -0
- package/dist/integrations/github/integration.d.ts.map +1 -0
- package/dist/integrations/github/integration.js +1162 -0
- package/dist/integrations/github/integration.js.map +1 -0
- package/dist/integrations/github/issue-triage.d.ts +27 -0
- package/dist/integrations/github/issue-triage.d.ts.map +1 -0
- package/dist/integrations/github/issue-triage.js +82 -0
- package/dist/integrations/github/issue-triage.js.map +1 -0
- package/dist/integrations/github/pat.d.ts +38 -0
- package/dist/integrations/github/pat.d.ts.map +1 -0
- package/dist/integrations/github/pat.js +59 -0
- package/dist/integrations/github/pat.js.map +1 -0
- package/dist/integrations/github/provenance.d.ts +27 -0
- package/dist/integrations/github/provenance.d.ts.map +1 -0
- package/dist/integrations/github/provenance.js +75 -0
- package/dist/integrations/github/provenance.js.map +1 -0
- package/dist/integrations/github/reconcile-worker.d.ts +41 -0
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -0
- package/dist/integrations/github/reconcile-worker.js +125 -0
- package/dist/integrations/github/reconcile-worker.js.map +1 -0
- package/dist/integrations/github/routes.d.ts +69 -0
- package/dist/integrations/github/routes.d.ts.map +1 -0
- package/dist/integrations/github/routes.js +1335 -0
- package/dist/integrations/github/routes.js.map +1 -0
- package/dist/integrations/github/rules.d.ts +105 -0
- package/dist/integrations/github/rules.d.ts.map +1 -0
- package/dist/integrations/github/rules.js +551 -0
- package/dist/integrations/github/rules.js.map +1 -0
- package/dist/integrations/github/sandbox-release.d.ts +53 -0
- package/dist/integrations/github/sandbox-release.d.ts.map +1 -0
- package/dist/integrations/github/sandbox-release.js +115 -0
- package/dist/integrations/github/sandbox-release.js.map +1 -0
- package/dist/integrations/github/sandbox.d.ts +281 -0
- package/dist/integrations/github/sandbox.d.ts.map +1 -0
- package/dist/integrations/github/sandbox.js +547 -0
- package/dist/integrations/github/sandbox.js.map +1 -0
- package/dist/integrations/github/session-subscriptions.d.ts +26 -0
- package/dist/integrations/github/session-subscriptions.d.ts.map +1 -0
- package/dist/integrations/github/session-subscriptions.js +192 -0
- package/dist/integrations/github/session-subscriptions.js.map +1 -0
- package/dist/integrations/github/subscriptions.d.ts +54 -0
- package/dist/integrations/github/subscriptions.d.ts.map +1 -0
- package/dist/integrations/github/subscriptions.js +62 -0
- package/dist/integrations/github/subscriptions.js.map +1 -0
- package/dist/integrations/github/token-refresh.d.ts +12 -0
- package/dist/integrations/github/token-refresh.d.ts.map +1 -0
- package/dist/integrations/github/token-refresh.js +24 -0
- package/dist/integrations/github/token-refresh.js.map +1 -0
- package/dist/integrations/github/webhook.d.ts +107 -0
- package/dist/integrations/github/webhook.d.ts.map +1 -0
- package/dist/integrations/github/webhook.js +371 -0
- package/dist/integrations/github/webhook.js.map +1 -0
- package/dist/integrations/linear/agent-tools.d.ts +34 -0
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -0
- package/dist/integrations/linear/agent-tools.js +85 -0
- package/dist/integrations/linear/agent-tools.js.map +1 -0
- package/dist/integrations/linear/integration.d.ts +235 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -0
- package/dist/integrations/linear/integration.js +676 -0
- package/dist/integrations/linear/integration.js.map +1 -0
- package/dist/integrations/linear/routes.d.ts +61 -0
- package/dist/integrations/linear/routes.d.ts.map +1 -0
- package/dist/integrations/linear/routes.js +240 -0
- package/dist/integrations/linear/routes.js.map +1 -0
- package/dist/integrations/linear/rules.d.ts +44 -0
- package/dist/integrations/linear/rules.d.ts.map +1 -0
- package/dist/integrations/linear/rules.js +133 -0
- package/dist/integrations/linear/rules.js.map +1 -0
- package/dist/integrations/linear/storage.d.ts +65 -0
- package/dist/integrations/linear/storage.d.ts.map +1 -0
- package/dist/integrations/linear/storage.js +1 -0
- package/dist/integrations/platform/api-client.d.ts +26 -0
- package/dist/integrations/platform/api-client.d.ts.map +1 -0
- package/dist/integrations/platform/api-client.js +156 -0
- package/dist/integrations/platform/api-client.js.map +1 -0
- package/dist/integrations/platform/github/event-worker.d.ts +44 -0
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/github/event-worker.js +349 -0
- package/dist/integrations/platform/github/event-worker.js.map +1 -0
- package/dist/integrations/platform/github/integration.d.ts +64 -0
- package/dist/integrations/platform/github/integration.d.ts.map +1 -0
- package/dist/integrations/platform/github/integration.js +1006 -0
- package/dist/integrations/platform/github/integration.js.map +1 -0
- package/dist/integrations/platform/linear/integration.d.ts +46 -0
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -0
- package/dist/integrations/platform/linear/integration.js +483 -0
- package/dist/integrations/platform/linear/integration.js.map +1 -0
- package/dist/integrations/slack/connect-route.d.ts +46 -0
- package/dist/integrations/slack/connect-route.d.ts.map +1 -0
- package/dist/integrations/slack/connect-route.js +186 -0
- package/dist/integrations/slack/connect-route.js.map +1 -0
- package/dist/integrations/slack/integration.d.ts +62 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -0
- package/dist/integrations/slack/integration.js +68 -0
- package/dist/integrations/slack/integration.js.map +1 -0
- package/dist/integrations/slack/slack.d.ts +200 -0
- package/dist/integrations/slack/slack.d.ts.map +1 -0
- package/dist/integrations/slack/slack.js +411 -0
- package/dist/integrations/slack/slack.js.map +1 -0
- package/dist/integrations/workos/integration.d.ts +39 -0
- package/dist/integrations/workos/integration.d.ts.map +1 -0
- package/dist/integrations/workos/integration.js +91 -0
- package/dist/integrations/workos/integration.js.map +1 -0
- package/dist/routes/config.d.ts +235 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +972 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/custom-provider-source.d.ts +52 -0
- package/dist/routes/custom-provider-source.d.ts.map +1 -0
- package/dist/routes/custom-provider-source.js +124 -0
- package/dist/routes/custom-provider-source.js.map +1 -0
- package/dist/routes/fs.d.ts +151 -0
- package/dist/routes/fs.d.ts.map +1 -0
- package/dist/routes/fs.js +708 -0
- package/dist/routes/fs.js.map +1 -0
- package/dist/routes/intake.d.ts +23 -0
- package/dist/routes/intake.d.ts.map +1 -0
- package/dist/routes/intake.js +179 -0
- package/dist/routes/intake.js.map +1 -0
- package/dist/routes/oauth.d.ts +43 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +463 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/projects.d.ts +19 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +461 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/provider-credentials.d.ts +81 -0
- package/dist/routes/provider-credentials.d.ts.map +1 -0
- package/dist/routes/provider-credentials.js +86 -0
- package/dist/routes/provider-credentials.js.map +1 -0
- package/dist/routes/route.d.ts +48 -0
- package/dist/routes/route.d.ts.map +1 -0
- package/dist/routes/route.js +15 -0
- package/dist/routes/route.js.map +1 -0
- package/dist/routes/skills.d.ts +30 -0
- package/dist/routes/skills.d.ts.map +1 -0
- package/dist/routes/skills.js +168 -0
- package/dist/routes/skills.js.map +1 -0
- package/dist/routes/surface.d.ts +107 -0
- package/dist/routes/surface.d.ts.map +1 -0
- package/dist/routes/surface.js +297 -0
- package/dist/routes/surface.js.map +1 -0
- package/dist/routes/tenant-credentials.d.ts +74 -0
- package/dist/routes/tenant-credentials.d.ts.map +1 -0
- package/dist/routes/tenant-credentials.js +156 -0
- package/dist/routes/tenant-credentials.js.map +1 -0
- package/dist/routes/work-items.d.ts +40 -0
- package/dist/routes/work-items.d.ts.map +1 -0
- package/dist/routes/work-items.js +695 -0
- package/dist/routes/work-items.js.map +1 -0
- package/dist/rules/binding-context.d.ts +5 -0
- package/dist/rules/binding-context.d.ts.map +1 -0
- package/dist/rules/binding-context.js +28 -0
- package/dist/rules/binding-context.js.map +1 -0
- package/dist/rules/defaults.d.ts +9 -0
- package/dist/rules/defaults.d.ts.map +1 -0
- package/dist/rules/defaults.js +322 -0
- package/dist/rules/defaults.js.map +1 -0
- package/dist/rules/dispatcher.d.ts +43 -0
- package/dist/rules/dispatcher.d.ts.map +1 -0
- package/dist/rules/dispatcher.js +547 -0
- package/dist/rules/dispatcher.js.map +1 -0
- package/dist/rules/index.d.ts +7 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +5 -0
- package/dist/rules/processor.d.ts +54 -0
- package/dist/rules/processor.d.ts.map +1 -0
- package/dist/rules/processor.js +378 -0
- package/dist/rules/processor.js.map +1 -0
- package/dist/rules/resolve.d.ts +17 -0
- package/dist/rules/resolve.d.ts.map +1 -0
- package/dist/rules/resolve.js +30 -0
- package/dist/rules/resolve.js.map +1 -0
- package/dist/rules/start-coordinator.d.ts +60 -0
- package/dist/rules/start-coordinator.d.ts.map +1 -0
- package/dist/rules/start-coordinator.js +175 -0
- package/dist/rules/start-coordinator.js.map +1 -0
- package/dist/rules/tools.d.ts +10 -0
- package/dist/rules/tools.d.ts.map +1 -0
- package/dist/rules/tools.js +59 -0
- package/dist/rules/tools.js.map +1 -0
- package/dist/rules/transition-service.d.ts +49 -0
- package/dist/rules/transition-service.d.ts.map +1 -0
- package/dist/rules/transition-service.js +232 -0
- package/dist/rules/transition-service.js.map +1 -0
- package/dist/rules/types.d.ts +261 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +43 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/validation.d.ts +11 -0
- package/dist/rules/validation.d.ts.map +1 -0
- package/dist/rules/validation.js +308 -0
- package/dist/rules/validation.js.map +1 -0
- package/dist/sandbox/fleet.d.ts +222 -0
- package/dist/sandbox/fleet.d.ts.map +1 -0
- package/dist/sandbox/fleet.js +322 -0
- package/dist/sandbox/fleet.js.map +1 -0
- package/dist/sandbox/reattach.d.ts +3 -0
- package/dist/sandbox/reattach.d.ts.map +1 -0
- package/dist/sandbox/reattach.js +16 -0
- package/dist/sandbox/reattach.js.map +1 -0
- package/dist/server-error.d.ts +12 -0
- package/dist/server-error.d.ts.map +1 -0
- package/dist/server-error.js +16 -0
- package/dist/server-error.js.map +1 -0
- package/dist/session/factory-session.d.ts +116 -0
- package/dist/session/factory-session.d.ts.map +1 -0
- package/dist/session/factory-session.js +162 -0
- package/dist/session/factory-session.js.map +1 -0
- package/dist/skills/service.d.ts +48 -0
- package/dist/skills/service.d.ts.map +1 -0
- package/dist/skills/service.js +40 -0
- package/dist/skills/service.js.map +1 -0
- package/dist/spa-static.d.ts +33 -0
- package/dist/spa-static.d.ts.map +1 -0
- package/dist/spa-static.js +104 -0
- package/dist/spa-static.js.map +1 -0
- package/dist/state-signing.d.ts +59 -0
- package/dist/state-signing.d.ts.map +1 -0
- package/dist/state-signing.js +83 -0
- package/dist/state-signing.js.map +1 -0
- package/dist/storage/domains/audit/agent-audit.d.ts +27 -0
- package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -0
- package/dist/storage/domains/audit/agent-audit.js +66 -0
- package/dist/storage/domains/audit/agent-audit.js.map +1 -0
- package/dist/storage/domains/audit/base.d.ts +140 -0
- package/dist/storage/domains/audit/base.d.ts.map +1 -0
- package/dist/storage/domains/audit/base.js +184 -0
- package/dist/storage/domains/audit/base.js.map +1 -0
- package/dist/storage/domains/audit/domain.d.ts +76 -0
- package/dist/storage/domains/audit/domain.d.ts.map +1 -0
- package/dist/storage/domains/audit/domain.js +269 -0
- package/dist/storage/domains/audit/domain.js.map +1 -0
- package/dist/storage/domains/channel-identity/base.d.ts +96 -0
- package/dist/storage/domains/channel-identity/base.d.ts.map +1 -0
- package/dist/storage/domains/channel-identity/base.js +149 -0
- package/dist/storage/domains/channel-identity/base.js.map +1 -0
- package/dist/storage/domains/credentials/base.d.ts +134 -0
- package/dist/storage/domains/credentials/base.d.ts.map +1 -0
- package/dist/storage/domains/credentials/base.js +273 -0
- package/dist/storage/domains/credentials/base.js.map +1 -0
- package/dist/storage/domains/custom-providers/base.d.ts +57 -0
- package/dist/storage/domains/custom-providers/base.d.ts.map +1 -0
- package/dist/storage/domains/custom-providers/base.js +145 -0
- package/dist/storage/domains/custom-providers/base.js.map +1 -0
- package/dist/storage/domains/intake/base.d.ts +38 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -0
- package/dist/storage/domains/intake/base.js +80 -0
- package/dist/storage/domains/intake/base.js.map +1 -0
- package/dist/storage/domains/integrations/base.d.ts +126 -0
- package/dist/storage/domains/integrations/base.d.ts.map +1 -0
- package/dist/storage/domains/integrations/base.js +317 -0
- package/dist/storage/domains/integrations/base.js.map +1 -0
- package/dist/storage/domains/memory-settings/base.d.ts +62 -0
- package/dist/storage/domains/memory-settings/base.d.ts.map +1 -0
- package/dist/storage/domains/memory-settings/base.js +126 -0
- package/dist/storage/domains/memory-settings/base.js.map +1 -0
- package/dist/storage/domains/model-packs/base.d.ts +49 -0
- package/dist/storage/domains/model-packs/base.d.ts.map +1 -0
- package/dist/storage/domains/model-packs/base.js +96 -0
- package/dist/storage/domains/model-packs/base.js.map +1 -0
- package/dist/storage/domains/projects/base.d.ts +58 -0
- package/dist/storage/domains/projects/base.d.ts.map +1 -0
- package/dist/storage/domains/projects/base.js +111 -0
- package/dist/storage/domains/projects/base.js.map +1 -0
- package/dist/storage/domains/queue-health/base.d.ts +52 -0
- package/dist/storage/domains/queue-health/base.d.ts.map +1 -0
- package/dist/storage/domains/queue-health/base.js +122 -0
- package/dist/storage/domains/queue-health/base.js.map +1 -0
- package/dist/storage/domains/source-control/base.d.ts +360 -0
- package/dist/storage/domains/source-control/base.d.ts.map +1 -0
- package/dist/storage/domains/source-control/base.js +914 -0
- package/dist/storage/domains/source-control/base.js.map +1 -0
- package/dist/storage/domains/source-control/inmemory.d.ts +175 -0
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -0
- package/dist/storage/domains/source-control/inmemory.js +380 -0
- package/dist/storage/domains/source-control/inmemory.js.map +1 -0
- package/dist/storage/domains/work-items/base.d.ts +412 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -0
- package/dist/storage/domains/work-items/base.js +1320 -0
- package/dist/storage/domains/work-items/base.js.map +1 -0
- package/dist/storage/domains/work-items/metrics.d.ts +101 -0
- package/dist/storage/domains/work-items/metrics.d.ts.map +1 -0
- package/dist/storage/domains/work-items/metrics.js +221 -0
- package/dist/storage/domains/work-items/metrics.js.map +1 -0
- package/dist/timing.d.ts +15 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +34 -0
- package/dist/timing.js.map +1 -0
- package/dist/workspace.d.ts +24 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +287 -0
- package/dist/workspace.js.map +1 -0
- package/factory-skills/configure-factory-rules/SKILL.md +67 -0
- package/factory-skills/factory-plan/SKILL.md +61 -0
- package/factory-skills/factory-review/SKILL.md +157 -0
- package/factory-skills/factory-triage/SKILL.md +99 -0
- package/package.json +83 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import { NoopLeaseProvider, isLeaseProvider } from "@mastra/core/events";
|
|
3
|
+
import { MastraWorker } from "@mastra/core/worker";
|
|
4
|
+
//#region src/integrations/github/reconcile-worker.ts
|
|
5
|
+
const DEFAULT_GITHUB_RECONCILE_INTERVAL_MS = 5 * 6e4;
|
|
6
|
+
const MIN_LEASE_TTL_MS = 3e4;
|
|
7
|
+
const LEASE_KEY = "github:pull-request-reconcile";
|
|
8
|
+
/**
|
|
9
|
+
* Periodic merge-state sweep for the self-hosted GitHub integration: webhooks
|
|
10
|
+
* are the only other writer of merge state, and a deployment GitHub cannot
|
|
11
|
+
* reach never receives one, so cards would stay open forever.
|
|
12
|
+
*/
|
|
13
|
+
var GithubReconcileWorker = class extends MastraWorker {
|
|
14
|
+
name = "github-pull-request-reconcile";
|
|
15
|
+
#reconcile;
|
|
16
|
+
#sourceControl;
|
|
17
|
+
#intervalMs;
|
|
18
|
+
#leaseTtlMs;
|
|
19
|
+
#leaseOwner = randomUUID();
|
|
20
|
+
#running = false;
|
|
21
|
+
#timer;
|
|
22
|
+
#inFlight;
|
|
23
|
+
#leaseProvider = NoopLeaseProvider;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
super();
|
|
26
|
+
this.#reconcile = config.reconcile;
|
|
27
|
+
this.#sourceControl = config.sourceControl;
|
|
28
|
+
this.#intervalMs = config.intervalMs ?? 3e5;
|
|
29
|
+
if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) throw new Error("GitHub pull request reconcile interval must be a positive number.");
|
|
30
|
+
this.#leaseTtlMs = Math.max(MIN_LEASE_TTL_MS, this.#intervalMs * 3);
|
|
31
|
+
}
|
|
32
|
+
async init(deps) {
|
|
33
|
+
await super.init(deps);
|
|
34
|
+
this.#leaseProvider = getLeaseProvider(deps.pubsub);
|
|
35
|
+
}
|
|
36
|
+
async start() {
|
|
37
|
+
if (this.#running) return;
|
|
38
|
+
if (!this.deps) throw new Error("GithubReconcileWorker: call init() before start()");
|
|
39
|
+
this.#running = true;
|
|
40
|
+
this.deps.logger.info("GitHub pull request reconcile worker started", { intervalMs: this.#intervalMs });
|
|
41
|
+
this.#schedule(0);
|
|
42
|
+
}
|
|
43
|
+
async stop() {
|
|
44
|
+
if (!this.#running) return;
|
|
45
|
+
this.#running = false;
|
|
46
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
47
|
+
this.#timer = void 0;
|
|
48
|
+
await this.#inFlight;
|
|
49
|
+
}
|
|
50
|
+
get isRunning() {
|
|
51
|
+
return this.#running;
|
|
52
|
+
}
|
|
53
|
+
#schedule(delayMs) {
|
|
54
|
+
if (!this.#running) return;
|
|
55
|
+
this.#timer = setTimeout(() => {
|
|
56
|
+
this.#timer = void 0;
|
|
57
|
+
const run = this.#tick().finally(() => {
|
|
58
|
+
this.#inFlight = void 0;
|
|
59
|
+
this.#schedule(this.#intervalMs);
|
|
60
|
+
});
|
|
61
|
+
this.#inFlight = run;
|
|
62
|
+
}, delayMs);
|
|
63
|
+
this.#timer.unref?.();
|
|
64
|
+
}
|
|
65
|
+
async #tick() {
|
|
66
|
+
if (!(await this.#leaseProvider.acquireLease(LEASE_KEY, this.#leaseOwner, this.#leaseTtlMs).catch(() => ({ acquired: false }))).acquired) return;
|
|
67
|
+
try {
|
|
68
|
+
const targets = await this.#targets();
|
|
69
|
+
if (targets.length === 0) return;
|
|
70
|
+
const startedAt = Date.now();
|
|
71
|
+
const { errors, ...counts } = await this.#reconcile(targets);
|
|
72
|
+
const context = {
|
|
73
|
+
...counts,
|
|
74
|
+
candidateRepositories: targets.length,
|
|
75
|
+
durationMs: Date.now() - startedAt
|
|
76
|
+
};
|
|
77
|
+
if (counts.failed > 0) this.deps?.logger.warn("GitHub pull request reconcile sweep completed with failures", {
|
|
78
|
+
...context,
|
|
79
|
+
errors
|
|
80
|
+
});
|
|
81
|
+
else if (counts.merged > 0 || counts.closed > 0) this.deps?.logger.info("GitHub pull request reconcile replayed missed merges/closes", context);
|
|
82
|
+
else this.deps?.logger.debug("GitHub pull request reconcile sweep completed", context);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
this.deps?.logger.warn("GitHub pull request reconcile sweep failed", { error: error instanceof Error ? error.message : String(error) });
|
|
85
|
+
} finally {
|
|
86
|
+
await this.#leaseProvider.releaseLease(LEASE_KEY, this.#leaseOwner).catch(() => void 0);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Configured (installation, repository) pairs resolved to the numeric ids and
|
|
91
|
+
* slug the sweep addresses GitHub with. A pair whose repository row is gone
|
|
92
|
+
* is skipped rather than failing the sweep for the others.
|
|
93
|
+
*/
|
|
94
|
+
async #targets() {
|
|
95
|
+
const keys = await this.#sourceControl.projectRepositories.listConfiguredExternalKeys();
|
|
96
|
+
const targets = [];
|
|
97
|
+
for (const key of keys) {
|
|
98
|
+
const installationId = Number(key.installationExternalId);
|
|
99
|
+
const repositoryId = Number(key.repositoryExternalId);
|
|
100
|
+
if (!Number.isSafeInteger(installationId) || !Number.isSafeInteger(repositoryId)) continue;
|
|
101
|
+
const orgId = (await this.#sourceControl.projectRepositories.listByExternalRepository(key))[0]?.orgId;
|
|
102
|
+
if (!orgId) continue;
|
|
103
|
+
const repository = await this.#sourceControl.repositories.findByExternalId({
|
|
104
|
+
orgId,
|
|
105
|
+
externalId: key.repositoryExternalId
|
|
106
|
+
});
|
|
107
|
+
if (!repository?.slug) continue;
|
|
108
|
+
targets.push({
|
|
109
|
+
id: repositoryId,
|
|
110
|
+
fullName: repository.slug,
|
|
111
|
+
installationId
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return targets;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
function getLeaseProvider(pubsub) {
|
|
118
|
+
const getProvider = pubsub.getLeaseProvider;
|
|
119
|
+
if (typeof getProvider === "function") return getProvider.call(pubsub) ?? NoopLeaseProvider;
|
|
120
|
+
return isLeaseProvider(pubsub) ? pubsub : NoopLeaseProvider;
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
export { DEFAULT_GITHUB_RECONCILE_INTERVAL_MS, GithubReconcileWorker };
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=reconcile-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile-worker.js","names":["#reconcile","#sourceControl","#intervalMs","#leaseTtlMs","#leaseOwner","#leaseProvider","#running","#schedule","#timer","#inFlight","#tick","#targets"],"sources":["../../../src/integrations/github/reconcile-worker.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { isLeaseProvider, NoopLeaseProvider } from '@mastra/core/events';\nimport type { LeaseProvider, PubSub } from '@mastra/core/events';\nimport { MastraWorker } from '@mastra/core/worker';\nimport type { WorkerDeps } from '@mastra/core/worker';\n\nimport type {\n ConfiguredExternalRepositoryKey,\n ExternalRepositoryProjectTarget,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport type { GithubPullRequestReconciler, ReconcileRepository } from './rules.js';\n\nexport const DEFAULT_GITHUB_RECONCILE_INTERVAL_MS = 5 * 60_000;\nconst MIN_LEASE_TTL_MS = 30_000;\nconst LEASE_KEY = 'github:pull-request-reconcile';\n\n/** Storage slice the sweep needs to turn configured repositories into targets. */\nexport interface GithubReconcileRepositorySource {\n projectRepositories: {\n listConfiguredExternalKeys(): Promise<ConfiguredExternalRepositoryKey[]>;\n listByExternalRepository(args: {\n installationExternalId: string;\n repositoryExternalId: string;\n }): Promise<ExternalRepositoryProjectTarget[]>;\n };\n repositories: {\n findByExternalId(args: { orgId: string; externalId: string }): Promise<SourceControlRepository | null>;\n };\n}\n\nexport interface GithubReconcileWorkerConfig {\n reconcile: GithubPullRequestReconciler;\n sourceControl: GithubReconcileRepositorySource;\n intervalMs?: number;\n}\n\n/**\n * Periodic merge-state sweep for the self-hosted GitHub integration: webhooks\n * are the only other writer of merge state, and a deployment GitHub cannot\n * reach never receives one, so cards would stay open forever.\n */\nexport class GithubReconcileWorker extends MastraWorker {\n readonly name = 'github-pull-request-reconcile';\n\n readonly #reconcile: GithubPullRequestReconciler;\n readonly #sourceControl: GithubReconcileRepositorySource;\n readonly #intervalMs: number;\n readonly #leaseTtlMs: number;\n readonly #leaseOwner = randomUUID();\n\n #running = false;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #inFlight: Promise<void> | undefined;\n #leaseProvider: LeaseProvider = NoopLeaseProvider;\n\n constructor(config: GithubReconcileWorkerConfig) {\n super();\n this.#reconcile = config.reconcile;\n this.#sourceControl = config.sourceControl;\n this.#intervalMs = config.intervalMs ?? DEFAULT_GITHUB_RECONCILE_INTERVAL_MS;\n if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) {\n throw new Error('GitHub pull request reconcile interval must be a positive number.');\n }\n this.#leaseTtlMs = Math.max(MIN_LEASE_TTL_MS, this.#intervalMs * 3);\n }\n\n async init(deps: WorkerDeps): Promise<void> {\n await super.init(deps);\n this.#leaseProvider = getLeaseProvider(deps.pubsub);\n }\n\n async start(): Promise<void> {\n if (this.#running) return;\n if (!this.deps) throw new Error('GithubReconcileWorker: call init() before start()');\n this.#running = true;\n this.deps.logger.info('GitHub pull request reconcile worker started', { intervalMs: this.#intervalMs });\n // Sweep on boot: a restart is exactly when webhooks were most likely missed.\n this.#schedule(0);\n }\n\n async stop(): Promise<void> {\n if (!this.#running) return;\n this.#running = false;\n if (this.#timer) clearTimeout(this.#timer);\n this.#timer = undefined;\n await this.#inFlight;\n }\n\n get isRunning(): boolean {\n return this.#running;\n }\n\n #schedule(delayMs: number): void {\n if (!this.#running) return;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n const run = this.#tick().finally(() => {\n this.#inFlight = undefined;\n this.#schedule(this.#intervalMs);\n });\n this.#inFlight = run;\n }, delayMs);\n this.#timer.unref?.();\n }\n\n async #tick(): Promise<void> {\n // Replicas share one sweep: the ingress dedupes duplicate writes, but the\n // reads still burn the installation's rate limit.\n const lease = await this.#leaseProvider\n .acquireLease(LEASE_KEY, this.#leaseOwner, this.#leaseTtlMs)\n .catch(() => ({ acquired: false }));\n if (!lease.acquired) return;\n\n try {\n const targets = await this.#targets();\n if (targets.length === 0) return;\n const startedAt = Date.now();\n const { errors, ...counts } = await this.#reconcile(targets);\n const context = { ...counts, candidateRepositories: targets.length, durationMs: Date.now() - startedAt };\n if (counts.failed > 0) {\n this.deps?.logger.warn('GitHub pull request reconcile sweep completed with failures', { ...context, errors });\n } else if (counts.merged > 0 || counts.closed > 0) {\n this.deps?.logger.info('GitHub pull request reconcile replayed missed merges/closes', context);\n } else {\n this.deps?.logger.debug('GitHub pull request reconcile sweep completed', context);\n }\n } catch (error) {\n this.deps?.logger.warn('GitHub pull request reconcile sweep failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n } finally {\n await this.#leaseProvider.releaseLease(LEASE_KEY, this.#leaseOwner).catch(() => undefined);\n }\n }\n\n /**\n * Configured (installation, repository) pairs resolved to the numeric ids and\n * slug the sweep addresses GitHub with. A pair whose repository row is gone\n * is skipped rather than failing the sweep for the others.\n */\n async #targets(): Promise<ReconcileRepository[]> {\n const keys = await this.#sourceControl.projectRepositories.listConfiguredExternalKeys();\n const targets: ReconcileRepository[] = [];\n for (const key of keys) {\n const installationId = Number(key.installationExternalId);\n const repositoryId = Number(key.repositoryExternalId);\n if (!Number.isSafeInteger(installationId) || !Number.isSafeInteger(repositoryId)) continue;\n const projects = await this.#sourceControl.projectRepositories.listByExternalRepository(key);\n const orgId = projects[0]?.orgId;\n if (!orgId) continue;\n const repository = await this.#sourceControl.repositories.findByExternalId({\n orgId,\n externalId: key.repositoryExternalId,\n });\n if (!repository?.slug) continue;\n targets.push({ id: repositoryId, fullName: repository.slug, installationId });\n }\n return targets;\n }\n}\n\nfunction getLeaseProvider(pubsub: PubSub): LeaseProvider {\n const getProvider = (pubsub as PubSub & { getLeaseProvider?: () => LeaseProvider | undefined }).getLeaseProvider;\n if (typeof getProvider === 'function') return getProvider.call(pubsub) ?? NoopLeaseProvider;\n return isLeaseProvider(pubsub) ? pubsub : NoopLeaseProvider;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mastra `apiRoutes` for the GitHub App project feature.
|
|
3
|
+
*
|
|
4
|
+
* Registered alongside the other `/web/*` routes, behind the host auth gate.
|
|
5
|
+
* Every route additionally re-checks the authenticated user via the injected
|
|
6
|
+
* `RouteAuth` seam and scopes all rows by that user's stable id, so a user can
|
|
7
|
+
* only ever see and operate on their own installations and projects.
|
|
8
|
+
*
|
|
9
|
+
* When the feature is disabled (`isGithubFeatureEnabled()` false), `buildGithubRoutes`
|
|
10
|
+
* returns only `GET /web/github/status`, which reports `enabled:false`
|
|
11
|
+
* so the SPA can cleanly hide all GitHub UI.
|
|
12
|
+
*/
|
|
13
|
+
import type { MountedMastraCode } from '@mastra/code-sdk';
|
|
14
|
+
import type { ApiRoute } from '@mastra/core/server';
|
|
15
|
+
import type { FactoryStorage } from '@mastra/core/storage';
|
|
16
|
+
import type { RouteAuth } from '../../routes/route.js';
|
|
17
|
+
import type { SandboxFleet } from '../../sandbox/fleet.js';
|
|
18
|
+
import type { StateSigner } from '../../state-signing.js';
|
|
19
|
+
import type { AuditEmitter } from '../../storage/domains/audit/domain.js';
|
|
20
|
+
import type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';
|
|
21
|
+
import type { GithubIntegration } from './integration.js';
|
|
22
|
+
import type { GithubIssueTriageRunInput, GithubIssueTriageRunResult, ParsedGithubWebhook } from './webhook.js';
|
|
23
|
+
export interface MountGithubRoutesOptions {
|
|
24
|
+
/** Host auth seam — resolves the signed-in user/tenant for each request. */
|
|
25
|
+
auth: RouteAuth;
|
|
26
|
+
/**
|
|
27
|
+
* Sandbox fleet for per-project sandboxes. A fleet constructed without a
|
|
28
|
+
* machine config reports `enabled: false` and the sandbox-backed routes
|
|
29
|
+
* respond 503.
|
|
30
|
+
*/
|
|
31
|
+
fleet: SandboxFleet;
|
|
32
|
+
/** Factory storage backend used for the `appDbConfigured` diagnostic. */
|
|
33
|
+
storage?: FactoryStorage;
|
|
34
|
+
/**
|
|
35
|
+
* The GitHub App integration the handlers operate on (Octokit access, token
|
|
36
|
+
* minting, OAuth URLs). Normally supplied by `GithubIntegration.routes()`;
|
|
37
|
+
* when absent, only the disabled `status` route is served.
|
|
38
|
+
*/
|
|
39
|
+
github?: GithubIntegration;
|
|
40
|
+
/**
|
|
41
|
+
* Shared OAuth/install `state` signer (created once per boot by the
|
|
42
|
+
* factory). Required for the OAuth/install flow; when absent, only the
|
|
43
|
+
* disabled `status` route is served.
|
|
44
|
+
*/
|
|
45
|
+
stateSigner?: StateSigner;
|
|
46
|
+
/**
|
|
47
|
+
* Absolute base URL of the web server (e.g. `http://localhost:4111`), used to
|
|
48
|
+
* build the OAuth/install redirect URI when one isn't explicitly configured.
|
|
49
|
+
*/
|
|
50
|
+
baseUrl?: string;
|
|
51
|
+
/** Explicit OAuth callback URI; defaults to `<baseUrl>/auth/github/callback`. */
|
|
52
|
+
redirectUri?: string;
|
|
53
|
+
/** Controller used to route verified webhook notifications to exact subscribed sessions. */
|
|
54
|
+
controller?: MountedMastraCode['controller'];
|
|
55
|
+
/** Run seam used by GitHub webhooks and manual Intake triage. */
|
|
56
|
+
runIssueTriage?: (input: GithubIssueTriageRunInput) => Promise<GithubIssueTriageRunResult>;
|
|
57
|
+
/** Best-effort audit emission supplied by the factory-owned audit domain. */
|
|
58
|
+
emitAudit?: AuditEmitter['emit'];
|
|
59
|
+
/** Factory projects domain — resolves a project's default triage model. */
|
|
60
|
+
projects?: FactoryProjectsStorage;
|
|
61
|
+
/** Authoritative Factory rule ingress for normalized, signature-verified GitHub deliveries. */
|
|
62
|
+
ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build the GitHub routes as Mastra `apiRoutes`. When the feature is disabled,
|
|
66
|
+
* returns only the `status` route so the SPA can detect the disabled state.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildGithubRoutes(options: MountGithubRoutesOptions): ApiRoute[];
|
|
69
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAuD,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEhH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AASrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AA4C1D,OAAO,KAAK,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAgB/G,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,IAAI,EAAE,SAAS,CAAC;IAChB;;;;OAIG;IACH,KAAK,EAAE,YAAY,CAAC;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAC7C,iEAAiE;IACjE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC3F,6EAA6E;IAC7E,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,+FAA+F;IAC/F,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AAuPD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,EAAE,CAkqB/E"}
|