@urateam/core 0.1.15 → 0.1.18
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__/agent-stream.test.js +5 -1
- package/dist/__tests__/agent-stream.test.js.map +1 -1
- package/dist/__tests__/agentic-deep-review-provider.test.d.ts +2 -0
- package/dist/__tests__/agentic-deep-review-provider.test.d.ts.map +1 -0
- package/dist/__tests__/agentic-deep-review-provider.test.js +70 -0
- package/dist/__tests__/agentic-deep-review-provider.test.js.map +1 -0
- package/dist/__tests__/audit-immutability.test.js +16 -1
- package/dist/__tests__/audit-immutability.test.js.map +1 -1
- package/dist/__tests__/cost/per-run-multi-model.test.d.ts +2 -0
- package/dist/__tests__/cost/per-run-multi-model.test.d.ts.map +1 -0
- package/dist/__tests__/cost/per-run-multi-model.test.js +102 -0
- package/dist/__tests__/cost/per-run-multi-model.test.js.map +1 -0
- package/dist/__tests__/db-qa-gap-issues.test.d.ts +2 -0
- package/dist/__tests__/db-qa-gap-issues.test.d.ts.map +1 -0
- package/dist/__tests__/db-qa-gap-issues.test.js +113 -0
- package/dist/__tests__/db-qa-gap-issues.test.js.map +1 -0
- package/dist/__tests__/db-release-decisions.test.d.ts +2 -0
- package/dist/__tests__/db-release-decisions.test.d.ts.map +1 -0
- package/dist/__tests__/db-release-decisions.test.js +98 -0
- package/dist/__tests__/db-release-decisions.test.js.map +1 -0
- package/dist/__tests__/db-review-model-runs.test.d.ts +2 -0
- package/dist/__tests__/db-review-model-runs.test.d.ts.map +1 -0
- package/dist/__tests__/db-review-model-runs.test.js +90 -0
- package/dist/__tests__/db-review-model-runs.test.js.map +1 -0
- package/dist/__tests__/e2e-fanout.test.d.ts +17 -0
- package/dist/__tests__/e2e-fanout.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-fanout.test.js +184 -0
- package/dist/__tests__/e2e-fanout.test.js.map +1 -0
- package/dist/__tests__/e2e-pipeline.test.js +1 -0
- package/dist/__tests__/e2e-pipeline.test.js.map +1 -1
- package/dist/__tests__/notifier-discord.test.js +3 -3
- package/dist/__tests__/notifier-discord.test.js.map +1 -1
- package/dist/__tests__/notifier-slack.test.js +2 -2
- package/dist/__tests__/notifier-slack.test.js.map +1 -1
- package/dist/__tests__/notifier.test.js +1 -0
- package/dist/__tests__/notifier.test.js.map +1 -1
- package/dist/__tests__/openrouter-client.test.d.ts +2 -0
- package/dist/__tests__/openrouter-client.test.d.ts.map +1 -0
- package/dist/__tests__/openrouter-client.test.js +56 -0
- package/dist/__tests__/openrouter-client.test.js.map +1 -0
- package/dist/__tests__/openrouter-fanout.test.d.ts +2 -0
- package/dist/__tests__/openrouter-fanout.test.d.ts.map +1 -0
- package/dist/__tests__/openrouter-fanout.test.js +93 -0
- package/dist/__tests__/openrouter-fanout.test.js.map +1 -0
- package/dist/__tests__/post-fanout-comments.test.d.ts +2 -0
- package/dist/__tests__/post-fanout-comments.test.d.ts.map +1 -0
- package/dist/__tests__/post-fanout-comments.test.js +84 -0
- package/dist/__tests__/post-fanout-comments.test.js.map +1 -0
- package/dist/__tests__/qa-audit-events.test.d.ts +2 -0
- package/dist/__tests__/qa-audit-events.test.d.ts.map +1 -0
- package/dist/__tests__/qa-audit-events.test.js +57 -0
- package/dist/__tests__/qa-audit-events.test.js.map +1 -0
- package/dist/__tests__/qa-config.test.d.ts +2 -0
- package/dist/__tests__/qa-config.test.d.ts.map +1 -0
- package/dist/__tests__/qa-config.test.js +80 -0
- package/dist/__tests__/qa-config.test.js.map +1 -0
- package/dist/__tests__/qa-eval.test.d.ts +2 -0
- package/dist/__tests__/qa-eval.test.d.ts.map +1 -0
- package/dist/__tests__/qa-eval.test.js +146 -0
- package/dist/__tests__/qa-eval.test.js.map +1 -0
- package/dist/__tests__/qa-gap.test.d.ts +2 -0
- package/dist/__tests__/qa-gap.test.d.ts.map +1 -0
- package/dist/__tests__/qa-gap.test.js +100 -0
- package/dist/__tests__/qa-gap.test.js.map +1 -0
- package/dist/__tests__/qa-github.test.d.ts +2 -0
- package/dist/__tests__/qa-github.test.d.ts.map +1 -0
- package/dist/__tests__/qa-github.test.js +162 -0
- package/dist/__tests__/qa-github.test.js.map +1 -0
- package/dist/__tests__/ralph-review-fix-regression.test.js +1 -0
- package/dist/__tests__/ralph-review-fix-regression.test.js.map +1 -1
- package/dist/__tests__/release-manager-audit-events.test.d.ts +2 -0
- package/dist/__tests__/release-manager-audit-events.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-audit-events.test.js +64 -0
- package/dist/__tests__/release-manager-audit-events.test.js.map +1 -0
- package/dist/__tests__/release-manager-config.test.d.ts +2 -0
- package/dist/__tests__/release-manager-config.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-config.test.js +56 -0
- package/dist/__tests__/release-manager-config.test.js.map +1 -0
- package/dist/__tests__/release-manager-decide.test.d.ts +2 -0
- package/dist/__tests__/release-manager-decide.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-decide.test.js +102 -0
- package/dist/__tests__/release-manager-decide.test.js.map +1 -0
- package/dist/__tests__/release-manager-github.test.d.ts +2 -0
- package/dist/__tests__/release-manager-github.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-github.test.js +83 -0
- package/dist/__tests__/release-manager-github.test.js.map +1 -0
- package/dist/__tests__/release-manager-license-gate.test.d.ts +2 -0
- package/dist/__tests__/release-manager-license-gate.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-license-gate.test.js +25 -0
- package/dist/__tests__/release-manager-license-gate.test.js.map +1 -0
- package/dist/__tests__/release-manager-scheduler.test.d.ts +2 -0
- package/dist/__tests__/release-manager-scheduler.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-scheduler.test.js +395 -0
- package/dist/__tests__/release-manager-scheduler.test.js.map +1 -0
- package/dist/__tests__/release-manager-slack-handler.test.d.ts +2 -0
- package/dist/__tests__/release-manager-slack-handler.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-slack-handler.test.js +175 -0
- package/dist/__tests__/release-manager-slack-handler.test.js.map +1 -0
- package/dist/__tests__/release-manager-triggers.test.d.ts +2 -0
- package/dist/__tests__/release-manager-triggers.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-triggers.test.js +67 -0
- package/dist/__tests__/release-manager-triggers.test.js.map +1 -0
- package/dist/__tests__/release-manager-versioning.test.d.ts +2 -0
- package/dist/__tests__/release-manager-versioning.test.d.ts.map +1 -0
- package/dist/__tests__/release-manager-versioning.test.js +51 -0
- package/dist/__tests__/release-manager-versioning.test.js.map +1 -0
- package/dist/__tests__/review-feedback.test.js +166 -2
- package/dist/__tests__/review-feedback.test.js.map +1 -1
- package/dist/__tests__/review-prompt.test.d.ts +2 -0
- package/dist/__tests__/review-prompt.test.d.ts.map +1 -0
- package/dist/__tests__/review-prompt.test.js +88 -0
- package/dist/__tests__/review-prompt.test.js.map +1 -0
- package/dist/__tests__/review-provider-registry.test.d.ts +2 -0
- package/dist/__tests__/review-provider-registry.test.d.ts.map +1 -0
- package/dist/__tests__/review-provider-registry.test.js +61 -0
- package/dist/__tests__/review-provider-registry.test.js.map +1 -0
- package/dist/__tests__/runner-fanout-integration.test.d.ts +2 -0
- package/dist/__tests__/runner-fanout-integration.test.d.ts.map +1 -0
- package/dist/__tests__/runner-fanout-integration.test.js +107 -0
- package/dist/__tests__/runner-fanout-integration.test.js.map +1 -0
- package/dist/audit/events.d.ts +54 -0
- package/dist/audit/events.d.ts.map +1 -1
- package/dist/audit/events.js +100 -0
- package/dist/audit/events.js.map +1 -1
- package/dist/audit/writer.d.ts +22 -8
- package/dist/audit/writer.d.ts.map +1 -1
- package/dist/audit/writer.js +22 -8
- package/dist/audit/writer.js.map +1 -1
- package/dist/cost/aggregate.d.ts.map +1 -1
- package/dist/cost/aggregate.js +14 -2
- package/dist/cost/aggregate.js.map +1 -1
- package/dist/cost/csv.d.ts.map +1 -1
- package/dist/cost/csv.js +14 -2
- package/dist/cost/csv.js.map +1 -1
- package/dist/cost/per-run.d.ts +11 -0
- package/dist/cost/per-run.d.ts.map +1 -1
- package/dist/cost/per-run.js +21 -8
- package/dist/cost/per-run.js.map +1 -1
- package/dist/cost/rollup.d.ts.map +1 -1
- package/dist/cost/rollup.js +14 -2
- package/dist/cost/rollup.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +20 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrations/postgres/009_review_model_runs.sql +18 -0
- package/dist/db/migrations/postgres/010_release_manager.sql +38 -0
- package/dist/db/migrations/postgres/011_qa_run_columns.sql +8 -0
- package/dist/db/migrations/postgres/012_qa_gap_issues.sql +18 -0
- package/dist/db/migrations/sqlite/008_review_model_runs.sql +18 -0
- package/dist/db/migrations/sqlite/009_release_manager.sql +43 -0
- package/dist/db/migrations/sqlite/010_qa_run_columns.sql +9 -0
- package/dist/db/migrations/sqlite/011_qa_gap_issues.sql +22 -0
- package/dist/db/review-model-runs.d.ts +4 -0
- package/dist/db/review-model-runs.d.ts.map +1 -0
- package/dist/db/review-model-runs.js +25 -0
- package/dist/db/review-model-runs.js.map +1 -0
- package/dist/db/schema.d.ts +761 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +67 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/executor/executor.d.ts +6 -1
- package/dist/executor/executor.d.ts.map +1 -1
- package/dist/executor/executor.js +3 -1
- package/dist/executor/executor.js.map +1 -1
- package/dist/executor/prompt/assembler.d.ts +5 -2
- package/dist/executor/prompt/assembler.d.ts.map +1 -1
- package/dist/executor/prompt/assembler.js +5 -2
- package/dist/executor/prompt/assembler.js.map +1 -1
- package/dist/executor/prompt/templates.d.ts +2 -2
- package/dist/executor/prompt/templates.d.ts.map +1 -1
- package/dist/executor/prompt/templates.js +21 -2
- package/dist/executor/prompt/templates.js.map +1 -1
- package/dist/executor/review/agentic-deep-review.d.ts +6 -0
- package/dist/executor/review/agentic-deep-review.d.ts.map +1 -0
- package/dist/executor/review/agentic-deep-review.js +37 -0
- package/dist/executor/review/agentic-deep-review.js.map +1 -0
- package/dist/executor/review/openrouter-client.d.ts +23 -0
- package/dist/executor/review/openrouter-client.d.ts.map +1 -0
- package/dist/executor/review/openrouter-client.js +34 -0
- package/dist/executor/review/openrouter-client.js.map +1 -0
- package/dist/executor/review/openrouter-fanout.d.ts +17 -0
- package/dist/executor/review/openrouter-fanout.d.ts.map +1 -0
- package/dist/executor/review/openrouter-fanout.js +84 -0
- package/dist/executor/review/openrouter-fanout.js.map +1 -0
- package/dist/executor/review/post-fanout-comments.d.ts +4 -0
- package/dist/executor/review/post-fanout-comments.d.ts.map +1 -0
- package/dist/executor/review/post-fanout-comments.js +45 -0
- package/dist/executor/review/post-fanout-comments.js.map +1 -0
- package/dist/executor/review/review-prompt.d.ts +21 -0
- package/dist/executor/review/review-prompt.d.ts.map +1 -0
- package/dist/executor/review/review-prompt.js +130 -0
- package/dist/executor/review/review-prompt.js.map +1 -0
- package/dist/executor/review/review-provider.d.ts +27 -0
- package/dist/executor/review/review-provider.d.ts.map +1 -0
- package/dist/executor/review/review-provider.js +36 -0
- package/dist/executor/review/review-provider.js.map +1 -0
- package/dist/executor/review/workdir-snapshot.d.ts +13 -0
- package/dist/executor/review/workdir-snapshot.d.ts.map +1 -0
- package/dist/executor/review/workdir-snapshot.js +24 -0
- package/dist/executor/review/workdir-snapshot.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +1 -0
- package/dist/license.js.map +1 -1
- package/dist/pipeline/review-providers-runner.d.ts +31 -0
- package/dist/pipeline/review-providers-runner.d.ts.map +1 -0
- package/dist/pipeline/review-providers-runner.js +64 -0
- package/dist/pipeline/review-providers-runner.js.map +1 -0
- package/dist/pipeline/runner.d.ts +16 -1
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +137 -43
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pm/actions/promote.js +2 -2
- package/dist/pm/actions/promote.js.map +1 -1
- package/dist/pm/actions/resolve-approvals.js +3 -3
- package/dist/pm/actions/resolve-approvals.js.map +1 -1
- package/dist/pm/actions/triage.js +2 -2
- package/dist/pm/actions/triage.js.map +1 -1
- package/dist/pm/scheduler.js +3 -3
- package/dist/pm/scheduler.js.map +1 -1
- package/dist/pm/slack-interface.d.ts +8 -0
- package/dist/pm/slack-interface.d.ts.map +1 -1
- package/dist/pm/slack-interface.js +20 -3
- package/dist/pm/slack-interface.js.map +1 -1
- package/dist/qa/gap.d.ts +29 -0
- package/dist/qa/gap.d.ts.map +1 -0
- package/dist/qa/gap.js +91 -0
- package/dist/qa/gap.js.map +1 -0
- package/dist/qa/github.d.ts +77 -0
- package/dist/qa/github.d.ts.map +1 -0
- package/dist/qa/github.js +106 -0
- package/dist/qa/github.js.map +1 -0
- package/dist/qa/index.d.ts +4 -0
- package/dist/qa/index.d.ts.map +1 -0
- package/dist/qa/index.js +4 -0
- package/dist/qa/index.js.map +1 -0
- package/dist/qa/types.d.ts +44 -0
- package/dist/qa/types.d.ts.map +1 -0
- package/dist/qa/types.js +12 -0
- package/dist/qa/types.js.map +1 -0
- package/dist/release-manager/decide.d.ts +26 -0
- package/dist/release-manager/decide.d.ts.map +1 -0
- package/dist/release-manager/decide.js +58 -0
- package/dist/release-manager/decide.js.map +1 -0
- package/dist/release-manager/github.d.ts +47 -0
- package/dist/release-manager/github.d.ts.map +1 -0
- package/dist/release-manager/github.js +66 -0
- package/dist/release-manager/github.js.map +1 -0
- package/dist/release-manager/index.d.ts +9 -0
- package/dist/release-manager/index.d.ts.map +1 -0
- package/dist/release-manager/index.js +9 -0
- package/dist/release-manager/index.js.map +1 -0
- package/dist/release-manager/scheduler.d.ts +30 -0
- package/dist/release-manager/scheduler.d.ts.map +1 -0
- package/dist/release-manager/scheduler.js +427 -0
- package/dist/release-manager/scheduler.js.map +1 -0
- package/dist/release-manager/slack-handler.d.ts +39 -0
- package/dist/release-manager/slack-handler.d.ts.map +1 -0
- package/dist/release-manager/slack-handler.js +124 -0
- package/dist/release-manager/slack-handler.js.map +1 -0
- package/dist/release-manager/state.d.ts +18 -0
- package/dist/release-manager/state.d.ts.map +1 -0
- package/dist/release-manager/state.js +154 -0
- package/dist/release-manager/state.js.map +1 -0
- package/dist/release-manager/triggers.d.ts +32 -0
- package/dist/release-manager/triggers.d.ts.map +1 -0
- package/dist/release-manager/triggers.js +82 -0
- package/dist/release-manager/triggers.js.map +1 -0
- package/dist/release-manager/types.d.ts +79 -0
- package/dist/release-manager/types.d.ts.map +1 -0
- package/dist/release-manager/types.js +48 -0
- package/dist/release-manager/types.js.map +1 -0
- package/dist/release-manager/versioning.d.ts +20 -0
- package/dist/release-manager/versioning.d.ts.map +1 -0
- package/dist/release-manager/versioning.js +60 -0
- package/dist/release-manager/versioning.js.map +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Octokit } from "@octokit/rest";
|
|
2
|
+
import type { AnyDb } from "../db/client.js";
|
|
3
|
+
export interface WorkflowFileExistsInput {
|
|
4
|
+
octokit: Octokit;
|
|
5
|
+
owner: string;
|
|
6
|
+
repo: string;
|
|
7
|
+
path: string;
|
|
8
|
+
ref: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Returns true when the workflow file exists at the given ref, false on 404,
|
|
12
|
+
* rethrows on other errors. The workflow file existence check uses the
|
|
13
|
+
* contents API rather than the actions API because the actions API requires
|
|
14
|
+
* the workflow to also be registered (i.e., GitHub must have parsed it on a
|
|
15
|
+
* push event), which can lag behind the file appearing in the repo.
|
|
16
|
+
*/
|
|
17
|
+
export declare function workflowFileExists(input: WorkflowFileExistsInput): Promise<boolean>;
|
|
18
|
+
export interface TriggerWorkflowInput {
|
|
19
|
+
octokit: Octokit;
|
|
20
|
+
db: AnyDb;
|
|
21
|
+
owner: string;
|
|
22
|
+
repo: string;
|
|
23
|
+
repoUrl: string;
|
|
24
|
+
branch: string;
|
|
25
|
+
workflow: string;
|
|
26
|
+
ref: string;
|
|
27
|
+
inputs?: Record<string, string>;
|
|
28
|
+
}
|
|
29
|
+
export type TriggerWorkflowResult = {
|
|
30
|
+
kind: "ok";
|
|
31
|
+
runId: number;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "dispatch_404";
|
|
34
|
+
} | {
|
|
35
|
+
kind: "dispatch_422";
|
|
36
|
+
message: string;
|
|
37
|
+
} | {
|
|
38
|
+
kind: "dispatch_error";
|
|
39
|
+
message: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: "dispatch_pending";
|
|
42
|
+
message: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Trigger a workflow_dispatch and find the resulting run.
|
|
46
|
+
*
|
|
47
|
+
* GitHub's workflow_dispatch API returns 204 No Content on success — it does
|
|
48
|
+
* NOT return the run ID. To discover the run, we list runs for the workflow
|
|
49
|
+
* filtered by SHA + workflow path and take the most-recent. There's a brief
|
|
50
|
+
* eventual-consistency window (typically <5s) where the run may not appear yet;
|
|
51
|
+
* the caller's tick will retry naturally on the next iteration.
|
|
52
|
+
*
|
|
53
|
+
* On dispatch failure, the result is classified into 3 kinds so the scheduler
|
|
54
|
+
* can route appropriately:
|
|
55
|
+
* - dispatch_404: drop into the qa_no_workflow path (file gap issue)
|
|
56
|
+
* - dispatch_422: workflow exists but lacks `on: workflow_dispatch` — write skip
|
|
57
|
+
* - dispatch_error: 5xx / rate limit — retry on next tick (uses retry counter)
|
|
58
|
+
*
|
|
59
|
+
* Emits qa.run_triggered audit event on the "ok" path.
|
|
60
|
+
*/
|
|
61
|
+
export declare function triggerWorkflow(input: TriggerWorkflowInput): Promise<TriggerWorkflowResult>;
|
|
62
|
+
export interface PollWorkflowRunInput {
|
|
63
|
+
octokit: Octokit;
|
|
64
|
+
owner: string;
|
|
65
|
+
repo: string;
|
|
66
|
+
runId: number;
|
|
67
|
+
}
|
|
68
|
+
export type PollWorkflowRunResult = {
|
|
69
|
+
kind: "running";
|
|
70
|
+
} | {
|
|
71
|
+
kind: "completed";
|
|
72
|
+
conclusion: string;
|
|
73
|
+
durationMs: number;
|
|
74
|
+
startedAt: Date;
|
|
75
|
+
};
|
|
76
|
+
export declare function pollWorkflowRun(input: PollWorkflowRunInput): Promise<PollWorkflowRunResult>;
|
|
77
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/qa/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAO7C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CASzF;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,CAAC,CA+ChC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnF,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,CAAC,CAsBhC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { logAuditEventUnchecked } from "../audit/writer.js";
|
|
2
|
+
import { qaRunTriggeredEvent } from "../audit/events.js";
|
|
3
|
+
import { createLogger } from "../logger.js";
|
|
4
|
+
const log = createLogger({ component: "Qa:github" });
|
|
5
|
+
/**
|
|
6
|
+
* Returns true when the workflow file exists at the given ref, false on 404,
|
|
7
|
+
* rethrows on other errors. The workflow file existence check uses the
|
|
8
|
+
* contents API rather than the actions API because the actions API requires
|
|
9
|
+
* the workflow to also be registered (i.e., GitHub must have parsed it on a
|
|
10
|
+
* push event), which can lag behind the file appearing in the repo.
|
|
11
|
+
*/
|
|
12
|
+
export async function workflowFileExists(input) {
|
|
13
|
+
const { octokit, owner, repo, path, ref } = input;
|
|
14
|
+
try {
|
|
15
|
+
await octokit.repos.getContent({ owner, repo, path, ref });
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err?.status === 404)
|
|
20
|
+
return false;
|
|
21
|
+
throw err;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Trigger a workflow_dispatch and find the resulting run.
|
|
26
|
+
*
|
|
27
|
+
* GitHub's workflow_dispatch API returns 204 No Content on success — it does
|
|
28
|
+
* NOT return the run ID. To discover the run, we list runs for the workflow
|
|
29
|
+
* filtered by SHA + workflow path and take the most-recent. There's a brief
|
|
30
|
+
* eventual-consistency window (typically <5s) where the run may not appear yet;
|
|
31
|
+
* the caller's tick will retry naturally on the next iteration.
|
|
32
|
+
*
|
|
33
|
+
* On dispatch failure, the result is classified into 3 kinds so the scheduler
|
|
34
|
+
* can route appropriately:
|
|
35
|
+
* - dispatch_404: drop into the qa_no_workflow path (file gap issue)
|
|
36
|
+
* - dispatch_422: workflow exists but lacks `on: workflow_dispatch` — write skip
|
|
37
|
+
* - dispatch_error: 5xx / rate limit — retry on next tick (uses retry counter)
|
|
38
|
+
*
|
|
39
|
+
* Emits qa.run_triggered audit event on the "ok" path.
|
|
40
|
+
*/
|
|
41
|
+
export async function triggerWorkflow(input) {
|
|
42
|
+
const { octokit, db, owner, repo, repoUrl, branch, workflow, ref, inputs } = input;
|
|
43
|
+
try {
|
|
44
|
+
await octokit.actions.createWorkflowDispatch({
|
|
45
|
+
owner,
|
|
46
|
+
repo,
|
|
47
|
+
workflow_id: workflow,
|
|
48
|
+
ref,
|
|
49
|
+
...(inputs ? { inputs } : {}),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const status = err?.status;
|
|
54
|
+
const msg = err?.message ?? String(err);
|
|
55
|
+
if (status === 404)
|
|
56
|
+
return { kind: "dispatch_404" };
|
|
57
|
+
if (status === 422)
|
|
58
|
+
return { kind: "dispatch_422", message: msg };
|
|
59
|
+
return { kind: "dispatch_error", message: msg };
|
|
60
|
+
}
|
|
61
|
+
// Find the just-triggered run. List the most recent runs for this workflow
|
|
62
|
+
// filtered by head SHA. Take the first match (most recent dispatch on this SHA).
|
|
63
|
+
let runId = null;
|
|
64
|
+
try {
|
|
65
|
+
const list = await octokit.actions.listWorkflowRuns({
|
|
66
|
+
owner,
|
|
67
|
+
repo,
|
|
68
|
+
workflow_id: workflow, // octokit accepts string filename
|
|
69
|
+
head_sha: ref,
|
|
70
|
+
per_page: 5,
|
|
71
|
+
});
|
|
72
|
+
const runs = list.data?.workflow_runs ?? [];
|
|
73
|
+
runId = runs[0]?.id ?? null;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
log.warn({ err, workflow, ref }, "listWorkflowRuns failed after dispatch — run will be picked up next tick");
|
|
77
|
+
}
|
|
78
|
+
if (runId === null) {
|
|
79
|
+
// Eventual-consistency window. Treat as needs-retry without burning the retry budget.
|
|
80
|
+
return { kind: "dispatch_pending", message: "dispatch succeeded but run not found yet" };
|
|
81
|
+
}
|
|
82
|
+
void logAuditEventUnchecked(db, qaRunTriggeredEvent({ repoUrl, branch, workflow, runId, sha: ref }));
|
|
83
|
+
return { kind: "ok", runId };
|
|
84
|
+
}
|
|
85
|
+
export async function pollWorkflowRun(input) {
|
|
86
|
+
const { octokit, owner, repo, runId } = input;
|
|
87
|
+
const res = await octokit.actions.getWorkflowRun({ owner, repo, run_id: runId });
|
|
88
|
+
const data = res.data;
|
|
89
|
+
const status = data?.status ?? "queued";
|
|
90
|
+
const conclusion = data?.conclusion ?? null;
|
|
91
|
+
if (status !== "completed")
|
|
92
|
+
return { kind: "running" };
|
|
93
|
+
// Completed run — compute duration from run_started_at to updated_at.
|
|
94
|
+
const startedAtStr = data?.run_started_at ?? data?.created_at;
|
|
95
|
+
const updatedAtStr = data?.updated_at ?? new Date().toISOString();
|
|
96
|
+
const startedAt = startedAtStr ? new Date(startedAtStr) : new Date();
|
|
97
|
+
const updatedAt = new Date(updatedAtStr);
|
|
98
|
+
const durationMs = Math.max(0, updatedAt.getTime() - startedAt.getTime());
|
|
99
|
+
return {
|
|
100
|
+
kind: "completed",
|
|
101
|
+
conclusion: conclusion ?? "neutral",
|
|
102
|
+
durationMs,
|
|
103
|
+
startedAt,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/qa/github.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;AAUrD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA8B;IACrE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,EAAE,MAAM,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAA2B;IAE3B,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAEnF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC;YAC3C,KAAK;YACL,IAAI;YACJ,WAAW,EAAE,QAAQ;YACrB,GAAG;YACH,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC;QAC3B,MAAM,GAAG,GAAG,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;QACpD,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAClE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAClD,CAAC;IAED,2EAA2E;IAC3E,iFAAiF;IACjF,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAClD,KAAK;YACL,IAAI;YACJ,WAAW,EAAE,QAAe,EAAE,kCAAkC;YAChE,QAAQ,EAAE,GAAG;YACb,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,MAAM,IAAI,GAAI,IAAY,CAAC,IAAI,EAAE,aAAa,IAAI,EAAE,CAAC;QACrD,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,0EAA0E,CAAC,CAAC;IAC/G,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,sFAAsF;QACtF,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC;IAC3F,CAAC;IAED,KAAK,sBAAsB,CACzB,EAAE,EACF,mBAAmB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CACpE,CAAC;IAEF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC;AAaD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAA2B;IAE3B,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACjF,MAAM,IAAI,GAAI,GAAW,CAAC,IAAI,CAAC;IAC/B,MAAM,MAAM,GAAW,IAAI,EAAE,MAAM,IAAI,QAAQ,CAAC;IAChD,MAAM,UAAU,GAAkB,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC;IAE3D,IAAI,MAAM,KAAK,WAAW;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAEvD,sEAAsE;IACtE,MAAM,YAAY,GAAG,IAAI,EAAE,cAAc,IAAI,IAAI,EAAE,UAAU,CAAC;IAC9D,MAAM,YAAY,GAAG,IAAI,EAAE,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClE,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IACrE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,UAAU,EAAE,UAAU,IAAI,SAAS;QACnC,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/qa/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
package/dist/qa/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/qa/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const QaCheckConfigSchema: z.ZodObject<{
|
|
3
|
+
workflow: z.ZodString;
|
|
4
|
+
timeoutMinutes: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
linearTeamId: z.ZodString;
|
|
6
|
+
workflowInputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
export type QaCheckConfig = z.infer<typeof QaCheckConfigSchema>;
|
|
9
|
+
/**
|
|
10
|
+
* Result of evalQaCheck. Six kinds — more nuanced than the other triggers'
|
|
11
|
+
* { pass, reason } because the async lifecycle requires the scheduler to
|
|
12
|
+
* dispatch different actions per kind.
|
|
13
|
+
*/
|
|
14
|
+
export type QaTriggerResult = {
|
|
15
|
+
pass: true;
|
|
16
|
+
reason: string;
|
|
17
|
+
} | {
|
|
18
|
+
pass: false;
|
|
19
|
+
reason: "qa_failed";
|
|
20
|
+
runId: number;
|
|
21
|
+
conclusion: string;
|
|
22
|
+
} | {
|
|
23
|
+
pass: false;
|
|
24
|
+
reason: "qa_running";
|
|
25
|
+
runId: number;
|
|
26
|
+
} | {
|
|
27
|
+
pass: false;
|
|
28
|
+
reason: "qa_timed_out";
|
|
29
|
+
runId: number;
|
|
30
|
+
} | {
|
|
31
|
+
pass: false;
|
|
32
|
+
reason: "qa_needs_trigger";
|
|
33
|
+
} | {
|
|
34
|
+
pass: false;
|
|
35
|
+
reason: "qa_no_workflow";
|
|
36
|
+
};
|
|
37
|
+
/** Snapshot of the most-recent in-flight QA run for (repo, branch). Null when nothing in flight. */
|
|
38
|
+
export interface QaRunSnapshot {
|
|
39
|
+
runId: number;
|
|
40
|
+
runSha: string;
|
|
41
|
+
/** When the run was triggered (decided_at on the persisting row). Used for timeout calculation. */
|
|
42
|
+
triggeredAt: Date;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/qa/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,mBAAmB;;;;;iBAS9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE9C,oGAAoG;AACpG,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,mGAAmG;IACnG,WAAW,EAAE,IAAI,CAAC;CACnB"}
|
package/dist/qa/types.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const QaCheckConfigSchema = z.object({
|
|
3
|
+
/** Path to the workflow file in the repo (e.g., ".github/workflows/smoke.yml"). */
|
|
4
|
+
workflow: z.string().min(1),
|
|
5
|
+
/** Max time to wait for a single workflow run before reporting timed_out. Default 30. */
|
|
6
|
+
timeoutMinutes: z.number().int().positive().default(30),
|
|
7
|
+
/** Linear team UUID for filing gap issues. Required for the gap-issue path. */
|
|
8
|
+
linearTeamId: z.string().min(1),
|
|
9
|
+
/** Optional inputs passed to workflow_dispatch (e.g., { environment: "preview" }). */
|
|
10
|
+
workflowInputs: z.record(z.string(), z.string()).optional(),
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/qa/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,mFAAmF;IACnF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,yFAAyF;IACzF,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACvD,+EAA+E;IAC/E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,sFAAsF;IACtF,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CollectedState, DecisionResult } from "./types.js";
|
|
2
|
+
import type { ReleaseManagerTriggers } from "./types.js";
|
|
3
|
+
export interface DecideQaState {
|
|
4
|
+
/** Whether the configured QA workflow file exists at state.headSha. Computed by scheduler. */
|
|
5
|
+
workflowFileExists: boolean;
|
|
6
|
+
/** When qaRun is for current SHA AND complete: the GitHub conclusion. Null otherwise. */
|
|
7
|
+
runConclusion: string | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Pure decision function. Evaluates triggers in this order:
|
|
11
|
+
* 1. mergedPRsSince
|
|
12
|
+
* 2. timeSinceLastHours
|
|
13
|
+
* 3. ciGreenForMinutes
|
|
14
|
+
* 4. qaCheck (BEC-136 — at slot 4 before requireSlackApproval)
|
|
15
|
+
* 5. requireSlackApproval (last; the "awaiting-approval" terminal kind)
|
|
16
|
+
*
|
|
17
|
+
* QA check is at slot 4 because: if the workflow's failing/missing, that's a
|
|
18
|
+
* regular skip — we don't want it bumping into the awaiting-approval branch.
|
|
19
|
+
* The whole approval flow only triggers when QA has already passed.
|
|
20
|
+
*
|
|
21
|
+
* The optional `qaState` parameter carries IO-derived QA inputs (workflow
|
|
22
|
+
* file existence + run conclusion) that the scheduler computes via Octokit
|
|
23
|
+
* before calling decide(). Null when qaCheck isn't configured.
|
|
24
|
+
*/
|
|
25
|
+
export declare function decide(state: CollectedState, triggers: ReleaseManagerTriggers, now?: Date, qaState?: DecideQaState): DecisionResult;
|
|
26
|
+
//# sourceMappingURL=decide.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decide.d.ts","sourceRoot":"","sources":["../../src/release-manager/decide.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AASzD,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,kBAAkB,EAAE,OAAO,CAAC;IAC5B,yFAAyF;IACzF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,sBAAsB,EAChC,GAAG,GAAE,IAAiB,EACtB,OAAO,CAAC,EAAE,aAAa,GACtB,cAAc,CAuChB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { evalMergedPRsSince, evalTimeSinceLastHours, evalCiGreenForMinutes, evalRequireSlackApproval, evalQaCheck, } from "./triggers.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pure decision function. Evaluates triggers in this order:
|
|
4
|
+
* 1. mergedPRsSince
|
|
5
|
+
* 2. timeSinceLastHours
|
|
6
|
+
* 3. ciGreenForMinutes
|
|
7
|
+
* 4. qaCheck (BEC-136 — at slot 4 before requireSlackApproval)
|
|
8
|
+
* 5. requireSlackApproval (last; the "awaiting-approval" terminal kind)
|
|
9
|
+
*
|
|
10
|
+
* QA check is at slot 4 because: if the workflow's failing/missing, that's a
|
|
11
|
+
* regular skip — we don't want it bumping into the awaiting-approval branch.
|
|
12
|
+
* The whole approval flow only triggers when QA has already passed.
|
|
13
|
+
*
|
|
14
|
+
* The optional `qaState` parameter carries IO-derived QA inputs (workflow
|
|
15
|
+
* file existence + run conclusion) that the scheduler computes via Octokit
|
|
16
|
+
* before calling decide(). Null when qaCheck isn't configured.
|
|
17
|
+
*/
|
|
18
|
+
export function decide(state, triggers, now = new Date(), qaState) {
|
|
19
|
+
if (triggers.mergedPRsSince !== undefined) {
|
|
20
|
+
const r = evalMergedPRsSince(state.mergedCommitsSinceLastTag, triggers.mergedPRsSince);
|
|
21
|
+
if (!r.pass)
|
|
22
|
+
return { kind: "skip", reason: r.reason };
|
|
23
|
+
}
|
|
24
|
+
if (triggers.timeSinceLastHours !== undefined) {
|
|
25
|
+
const r = evalTimeSinceLastHours(state.lastTagAt, triggers.timeSinceLastHours, now);
|
|
26
|
+
if (!r.pass)
|
|
27
|
+
return { kind: "skip", reason: r.reason };
|
|
28
|
+
}
|
|
29
|
+
if (triggers.ciGreenForMinutes !== undefined) {
|
|
30
|
+
const r = evalCiGreenForMinutes(state.ciStatus, state.ciGreenSince, triggers.ciGreenForMinutes, now);
|
|
31
|
+
if (!r.pass)
|
|
32
|
+
return { kind: "skip", reason: r.reason };
|
|
33
|
+
}
|
|
34
|
+
// BEC-136: QA check at slot 4 (before requireSlackApproval).
|
|
35
|
+
if (triggers.qaCheck !== undefined) {
|
|
36
|
+
const qa = qaState ?? { workflowFileExists: false, runConclusion: null };
|
|
37
|
+
const r = evalQaCheck({
|
|
38
|
+
qaConfig: triggers.qaCheck,
|
|
39
|
+
headSha: state.headSha,
|
|
40
|
+
workflowFileExists: qa.workflowFileExists,
|
|
41
|
+
qaRun: state.qaRun,
|
|
42
|
+
runConclusion: qa.runConclusion,
|
|
43
|
+
now,
|
|
44
|
+
});
|
|
45
|
+
if (!r.pass)
|
|
46
|
+
return { kind: "skip", reason: r.reason, qaActionNeeded: r };
|
|
47
|
+
}
|
|
48
|
+
if (triggers.requireSlackApproval === true) {
|
|
49
|
+
const r = evalRequireSlackApproval(true, state.hasFreshApproval);
|
|
50
|
+
// Spec §5: when this is the ONLY failing trigger, the decision kind is
|
|
51
|
+
// "awaiting-approval" (not "skip") so the scheduler posts a "Release
|
|
52
|
+
// ready: /release approve to fire" prompt instead of a cooldown skip.
|
|
53
|
+
if (!r.pass)
|
|
54
|
+
return { kind: "awaiting-approval", reason: r.reason };
|
|
55
|
+
}
|
|
56
|
+
return { kind: "fire", reason: "all triggers passed" };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=decide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decide.js","sourceRoot":"","sources":["../../src/release-manager/decide.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,GACZ,MAAM,eAAe,CAAC;AASvB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,MAAM,CACpB,KAAqB,EACrB,QAAgC,EAChC,MAAY,IAAI,IAAI,EAAE,EACtB,OAAuB;IAEvB,IAAI,QAAQ,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,yBAAyB,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;QACvF,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACzD,CAAC;IAED,IAAI,QAAQ,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,sBAAsB,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QACpF,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACzD,CAAC;IAED,IAAI,QAAQ,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACrG,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACzD,CAAC;IAED,6DAA6D;IAC7D,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,OAAO,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QACzE,MAAM,CAAC,GAAG,WAAW,CAAC;YACpB,QAAQ,EAAE,QAAQ,CAAC,OAAO;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,kBAAkB,EAAE,EAAE,CAAC,kBAAkB;YACzC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,aAAa,EAAE,EAAE,CAAC,aAAa;YAC/B,GAAG;SACJ,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;IAC5E,CAAC;IAED,IAAI,QAAQ,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,wBAAwB,CAAC,IAAI,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACjE,uEAAuE;QACvE,qEAAqE;QACrE,sEAAsE;QACtE,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACtE,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Octokit } from "@octokit/rest";
|
|
2
|
+
export interface CreateTagAndReleaseInput {
|
|
3
|
+
octokit: Octokit;
|
|
4
|
+
owner: string;
|
|
5
|
+
repo: string;
|
|
6
|
+
tag: string;
|
|
7
|
+
sha: string;
|
|
8
|
+
}
|
|
9
|
+
export type CreateTagAndReleaseResult = {
|
|
10
|
+
kind: "ok";
|
|
11
|
+
releaseUrl: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "tag_exists";
|
|
14
|
+
} | {
|
|
15
|
+
kind: "release_create_failed";
|
|
16
|
+
message: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "other_error";
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Parse owner/repo from a GitHub URL. Accepts both https and ssh forms.
|
|
23
|
+
*
|
|
24
|
+
* Examples:
|
|
25
|
+
* https://github.com/org/repo → { owner: "org", repo: "repo" }
|
|
26
|
+
* https://github.com/org/repo.git → { owner: "org", repo: "repo" }
|
|
27
|
+
* git@github.com:org/repo.git → { owner: "org", repo: "repo" }
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseRepoFromUrl(url: string): {
|
|
30
|
+
owner: string;
|
|
31
|
+
repo: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Create a git tag and a release with auto-generated notes.
|
|
35
|
+
*
|
|
36
|
+
* Two-step:
|
|
37
|
+
* 1. octokit.git.createRef('refs/tags/<tag>', sha)
|
|
38
|
+
* 2. octokit.repos.createRelease({ tag_name, target_commitish: sha, generate_release_notes: true })
|
|
39
|
+
*
|
|
40
|
+
* Errors are classified — the caller persists a different decision row for
|
|
41
|
+
* each kind:
|
|
42
|
+
* - tag_exists → skip with reason="tag_exists"
|
|
43
|
+
* - release_create_failed → fire-pending with attempt_count++ (retryable)
|
|
44
|
+
* - other_error → tick error (logged, not a decision row)
|
|
45
|
+
*/
|
|
46
|
+
export declare function createTagAndRelease(input: CreateTagAndReleaseInput): Promise<CreateTagAndReleaseResult>;
|
|
47
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/release-manager/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQ7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,yBAAyB,CAAC,CAiCpC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse owner/repo from a GitHub URL. Accepts both https and ssh forms.
|
|
3
|
+
*
|
|
4
|
+
* Examples:
|
|
5
|
+
* https://github.com/org/repo → { owner: "org", repo: "repo" }
|
|
6
|
+
* https://github.com/org/repo.git → { owner: "org", repo: "repo" }
|
|
7
|
+
* git@github.com:org/repo.git → { owner: "org", repo: "repo" }
|
|
8
|
+
*/
|
|
9
|
+
export function parseRepoFromUrl(url) {
|
|
10
|
+
// ssh
|
|
11
|
+
const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
12
|
+
if (ssh)
|
|
13
|
+
return { owner: ssh[1], repo: ssh[2] };
|
|
14
|
+
// https
|
|
15
|
+
const https = url.match(/^https?:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/);
|
|
16
|
+
if (https)
|
|
17
|
+
return { owner: https[1], repo: https[2] };
|
|
18
|
+
throw new Error(`unparseable GitHub URL: ${url}`);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a git tag and a release with auto-generated notes.
|
|
22
|
+
*
|
|
23
|
+
* Two-step:
|
|
24
|
+
* 1. octokit.git.createRef('refs/tags/<tag>', sha)
|
|
25
|
+
* 2. octokit.repos.createRelease({ tag_name, target_commitish: sha, generate_release_notes: true })
|
|
26
|
+
*
|
|
27
|
+
* Errors are classified — the caller persists a different decision row for
|
|
28
|
+
* each kind:
|
|
29
|
+
* - tag_exists → skip with reason="tag_exists"
|
|
30
|
+
* - release_create_failed → fire-pending with attempt_count++ (retryable)
|
|
31
|
+
* - other_error → tick error (logged, not a decision row)
|
|
32
|
+
*/
|
|
33
|
+
export async function createTagAndRelease(input) {
|
|
34
|
+
const { octokit, owner, repo, tag, sha } = input;
|
|
35
|
+
try {
|
|
36
|
+
await octokit.git.createRef({
|
|
37
|
+
owner,
|
|
38
|
+
repo,
|
|
39
|
+
ref: `refs/tags/${tag}`,
|
|
40
|
+
sha,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
const msg = err?.message ?? String(err);
|
|
45
|
+
const status = err?.status;
|
|
46
|
+
if (status === 422 || /already exists/i.test(msg)) {
|
|
47
|
+
return { kind: "tag_exists" };
|
|
48
|
+
}
|
|
49
|
+
return { kind: "other_error", message: msg };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const res = await octokit.repos.createRelease({
|
|
53
|
+
owner,
|
|
54
|
+
repo,
|
|
55
|
+
tag_name: tag,
|
|
56
|
+
target_commitish: sha,
|
|
57
|
+
generate_release_notes: true,
|
|
58
|
+
});
|
|
59
|
+
const releaseUrl = res?.data?.html_url ?? `https://github.com/${owner}/${repo}/releases/tag/${tag}`;
|
|
60
|
+
return { kind: "ok", releaseUrl };
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
return { kind: "release_create_failed", message: err?.message ?? String(err) };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/release-manager/github.ts"],"names":[],"mappings":"AAgBA;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM;IACN,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACpE,IAAI,GAAG;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,QAAQ;IACR,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC9E,IAAI,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA+B;IAE/B,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;YAC1B,KAAK;YACL,IAAI;YACJ,GAAG,EAAE,aAAa,GAAG,EAAE;YACvB,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC;QAC3B,IAAI,MAAM,KAAK,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;YAC5C,KAAK;YACL,IAAI;YACJ,QAAQ,EAAE,GAAG;YACb,gBAAgB,EAAE,GAAG;YACrB,sBAAsB,EAAE,IAAI;SAC7B,CAAC,CAAC;QACH,MAAM,UAAU,GACb,GAAW,EAAE,IAAI,EAAE,QAAQ,IAAI,sBAAsB,KAAK,IAAI,IAAI,iBAAiB,GAAG,EAAE,CAAC;QAC5F,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACjF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./triggers.js";
|
|
3
|
+
export * from "./decide.js";
|
|
4
|
+
export * from "./versioning.js";
|
|
5
|
+
export * from "./github.js";
|
|
6
|
+
export * from "./state.js";
|
|
7
|
+
export * from "./slack-handler.js";
|
|
8
|
+
export * from "./scheduler.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release-manager/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./triggers.js";
|
|
3
|
+
export * from "./decide.js";
|
|
4
|
+
export * from "./versioning.js";
|
|
5
|
+
export * from "./github.js";
|
|
6
|
+
export * from "./state.js";
|
|
7
|
+
export * from "./slack-handler.js";
|
|
8
|
+
export * from "./scheduler.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/release-manager/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Octokit } from "@octokit/rest";
|
|
2
|
+
import type { LinearClient } from "@linear/sdk";
|
|
3
|
+
import type { AnyDb } from "../db/client.js";
|
|
4
|
+
import type { ReleaseManagerConfig } from "./types.js";
|
|
5
|
+
export interface SlackPoster {
|
|
6
|
+
postMessage: (channel: string, text: string) => Promise<boolean>;
|
|
7
|
+
}
|
|
8
|
+
export interface ReleaseManagerSchedulerInput {
|
|
9
|
+
config: ReleaseManagerConfig;
|
|
10
|
+
db: AnyDb;
|
|
11
|
+
octokit: Octokit;
|
|
12
|
+
/** BEC-136: Linear client for filing QA gap issues. Required when qaCheck is configured. */
|
|
13
|
+
linear?: LinearClient;
|
|
14
|
+
repoUrl: string;
|
|
15
|
+
/** Injectable license check — production passes `() => isFeatureLicensed("release-manager")`. */
|
|
16
|
+
isLicensed: () => boolean;
|
|
17
|
+
slack?: SlackPoster;
|
|
18
|
+
}
|
|
19
|
+
export interface ReleaseManagerScheduler {
|
|
20
|
+
/** Run a single decision cycle. Used directly from tests + by the cron driver. */
|
|
21
|
+
tick(): Promise<void>;
|
|
22
|
+
/** Start the cron driver (no-op until called). */
|
|
23
|
+
start(): void;
|
|
24
|
+
/** Stop the cron driver (idempotent). */
|
|
25
|
+
stop(): void;
|
|
26
|
+
/** /release skip → pause future ticks until this timestamp. */
|
|
27
|
+
pauseUntil(ts: Date): void;
|
|
28
|
+
}
|
|
29
|
+
export declare function createReleaseManagerScheduler(input: ReleaseManagerSchedulerInput): ReleaseManagerScheduler;
|
|
30
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/release-manager/scheduler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAgB7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMvD,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,oBAAoB,CAAC;IAC7B,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,kFAAkF;IAClF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,kDAAkD;IAClD,KAAK,IAAI,IAAI,CAAC;IACd,yCAAyC;IACzC,IAAI,IAAI,IAAI,CAAC;IACb,+DAA+D;IAC/D,UAAU,CAAC,EAAE,EAAE,IAAI,GAAG,IAAI,CAAC;CAC5B;AAID,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,4BAA4B,GAClC,uBAAuB,CAoezB"}
|