@mergifyio/ci-core 0.1.1

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.
@@ -0,0 +1,189 @@
1
+ import { Attributes, Span, Tracer } from "@opentelemetry/api";
2
+ import { Resource } from "@opentelemetry/resources";
3
+ import { BasicTracerProvider, ReadableSpan, SpanExporter, SpanProcessor } from "@opentelemetry/sdk-trace-base";
4
+
5
+ //#region src/flaky-detection.d.ts
6
+ type FlakyDetectionContext = {
7
+ budget_ratio_for_new_tests: number;
8
+ budget_ratio_for_unhealthy_tests: number;
9
+ existing_test_names: string[];
10
+ existing_tests_mean_duration_ms: number;
11
+ unhealthy_test_names: string[];
12
+ max_test_execution_count: number;
13
+ max_test_name_length: number;
14
+ min_budget_duration_ms: number;
15
+ min_test_execution_count: number;
16
+ };
17
+ type FlakyDetectionMode = 'new' | 'unhealthy';
18
+ type FlakyDetectionConfig = {
19
+ apiUrl: string;
20
+ token: string;
21
+ repoName: string;
22
+ };
23
+ declare function fetchFlakyDetectionContext(config: FlakyDetectionConfig, logger: (msg: string) => void): Promise<FlakyDetectionContext | null>;
24
+ declare class FlakyDetector {
25
+ private context;
26
+ private mode;
27
+ private candidates;
28
+ private existingTestsInSession;
29
+ private budgetMs;
30
+ private perTestDeadlineMs;
31
+ private testMetrics;
32
+ private tooSlowTests;
33
+ constructor(context: FlakyDetectionContext, mode: FlakyDetectionMode, allTestNames: string[]);
34
+ isCandidate(testName: string): boolean;
35
+ /** Calculate max repeats for a candidate test. Call after first execution to use actual duration. */
36
+ getMaxRepeats(testName: string, initialDurationMs: number): number;
37
+ recordOutcome(testName: string, outcome: 'pass' | 'fail'): void;
38
+ isFlaky(testName: string): boolean;
39
+ getRerunCount(testName: string): number;
40
+ isTooSlow(testName: string): boolean;
41
+ /** Get summary data for the terminal report. */
42
+ getSummary(): {
43
+ mode: FlakyDetectionMode;
44
+ budgetMs: number;
45
+ candidateCount: number;
46
+ rerunTests: Array<{
47
+ name: string;
48
+ rerunCount: number;
49
+ flaky: boolean;
50
+ outcomes: string[];
51
+ }>;
52
+ tooSlowTests: string[];
53
+ };
54
+ private getOrCreateMetrics;
55
+ }
56
+ //#endregion
57
+ //#region src/quarantine.d.ts
58
+ interface QuarantineConfig {
59
+ apiUrl: string;
60
+ token: string;
61
+ repoName: string;
62
+ branch: string;
63
+ }
64
+ declare function fetchQuarantineList(config: QuarantineConfig, logger: (msg: string) => void): Promise<Set<string>>;
65
+ //#endregion
66
+ //#region src/resources/index.d.ts
67
+ declare function detectResources(frameworkAttributes: Attributes, testRunId: string): Resource;
68
+ //#endregion
69
+ //#region src/tracing.d.ts
70
+ interface TracingConfig {
71
+ token: string | undefined;
72
+ repoName: string | undefined;
73
+ apiUrl: string;
74
+ testRunId: string;
75
+ frameworkAttributes: Attributes;
76
+ tracerName: string;
77
+ /** Injected exporter — bypasses CI and token checks. */
78
+ exporter?: SpanExporter;
79
+ }
80
+ interface TracingContext {
81
+ tracer: Tracer;
82
+ tracerProvider: BasicTracerProvider;
83
+ exporter: SpanExporter;
84
+ resource: Resource;
85
+ /** Whether the provider should be shut down on test run end. */
86
+ ownsExporter: boolean;
87
+ }
88
+ declare class SynchronousBatchSpanProcessor implements SpanProcessor {
89
+ private exporter;
90
+ private queue;
91
+ constructor(exporter: SpanExporter);
92
+ onStart(): void;
93
+ onEnd(span: ReadableSpan): void;
94
+ forceFlush(): Promise<void>;
95
+ shutdown(): Promise<void>;
96
+ }
97
+ declare function createTracing(config: TracingConfig): TracingContext | null;
98
+ //#endregion
99
+ //#region src/types.d.ts
100
+ interface TestCaseError {
101
+ type: string;
102
+ message: string;
103
+ stacktrace: string;
104
+ }
105
+ interface TestCaseFlakyDetection {
106
+ new: boolean;
107
+ flaky: boolean;
108
+ rerunCount: number;
109
+ }
110
+ interface TestCaseResult {
111
+ /** Relative file path (e.g. Vitest TestModule.relativeModuleId) */
112
+ filepath: string;
113
+ /** Absolute file path (e.g. Vitest TestModule.moduleId) */
114
+ absoluteFilepath: string;
115
+ /** Test name (e.g. Vitest TestCase.name) */
116
+ function: string;
117
+ /** Line number in the file (Vitest requires includeTaskLocation) */
118
+ lineno: number;
119
+ /** Parent suite chain (e.g. derived from Vitest fullName) */
120
+ namespace: string;
121
+ scope: 'case';
122
+ status: 'passed' | 'failed' | 'skipped';
123
+ error?: TestCaseError;
124
+ /** Duration in ms */
125
+ duration: number;
126
+ /** Start time in ms */
127
+ startTime: number;
128
+ /** Number of retries */
129
+ retryCount: number;
130
+ /** Whether the test passed on a retry (native framework flaky) */
131
+ flaky: boolean;
132
+ /** Framework sub-identity (Playwright project name). Optional. */
133
+ project?: string;
134
+ /** Whether the test is quarantined. Set by Vitest runner when the quarantine feature is active. */
135
+ quarantined?: boolean;
136
+ /** Flaky-detection metadata. Set by Vitest runner when flaky detection is active. */
137
+ flakyDetection?: TestCaseFlakyDetection;
138
+ }
139
+ interface TestRunSession {
140
+ /** 16-char hex ID (8 random bytes), matching Mergify CI Insights API format */
141
+ testRunId: string;
142
+ scope: 'session';
143
+ startTime: number;
144
+ endTime?: number;
145
+ status: 'passed' | 'failed' | 'interrupted';
146
+ testCases: TestCaseResult[];
147
+ }
148
+ //#endregion
149
+ //#region src/spans.d.ts
150
+ declare function startSessionSpan(tracing: TracingContext, name: string): Span;
151
+ declare function endSessionSpan(tracing: TracingContext, sessionSpan: Span, reason: 'passed' | 'failed' | 'interrupted'): Promise<void>;
152
+ declare function emitTestCaseSpan(tracer: Tracer, sessionSpan: Span, result: TestCaseResult): void;
153
+ //#endregion
154
+ //#region src/utils.d.ts
155
+ type CIProvider = 'github_actions' | 'jenkins' | 'circleci' | 'buildkite';
156
+ /**
157
+ * Generate a 16-character hex test run ID (8 random bytes).
158
+ */
159
+ declare function generateTestRunId(): string;
160
+ /** Convert a string to a boolean. */
161
+ declare function strtobool(value: string): boolean;
162
+ declare function envToBool(value: string | undefined, fallback: boolean): boolean;
163
+ /** Check if running in a CI environment. */
164
+ declare function isInCI(): boolean;
165
+ /** Detect the current CI provider from environment variables. */
166
+ declare function getCIProvider(): CIProvider | null;
167
+ /** Execute a git command and return trimmed stdout, or null on failure. */
168
+ declare function git(...args: string[]): string | null;
169
+ /** Split an "owner/repo" string into parts. */
170
+ declare function splitRepoName(fullName: string): {
171
+ owner: string;
172
+ repo: string;
173
+ };
174
+ /**
175
+ * Resolve the repository name ("owner/repo") from env vars or the git remote.
176
+ * Checks GITHUB_REPOSITORY, then GIT_URL, then falls back to `git config`.
177
+ */
178
+ declare function getRepoName(): string | undefined;
179
+ /** Parse a repository name from a git remote URL (SSH or HTTPS). */
180
+ declare function getRepositoryNameFromUrl(url: string): string | null;
181
+ /**
182
+ * Resolve the branch name for quarantine/flaky-detection lookups from OTel
183
+ * resource attributes: `vcs.ref.base.name` (PR target) preferred, then
184
+ * `vcs.ref.head.name` (push branch / PR head). Empty strings fall through.
185
+ */
186
+ declare function resolveBranchFromAttributes(attrs: Attributes): string | undefined;
187
+ //#endregion
188
+ export { type CIProvider, type FlakyDetectionConfig, type FlakyDetectionContext, type FlakyDetectionMode, FlakyDetector, type QuarantineConfig, SynchronousBatchSpanProcessor, type TestCaseError, type TestCaseFlakyDetection, type TestCaseResult, type TestRunSession, type TracingConfig, type TracingContext, createTracing, detectResources, emitTestCaseSpan, endSessionSpan, envToBool, fetchFlakyDetectionContext, fetchQuarantineList, generateTestRunId, getCIProvider, getRepoName, getRepositoryNameFromUrl, git, isInCI, resolveBranchFromAttributes, splitRepoName, startSessionSpan, strtobool };
189
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1,189 @@
1
+ import { Resource } from "@opentelemetry/resources";
2
+ import { Attributes, Span, Tracer } from "@opentelemetry/api";
3
+ import { BasicTracerProvider, ReadableSpan, SpanExporter, SpanProcessor } from "@opentelemetry/sdk-trace-base";
4
+
5
+ //#region src/flaky-detection.d.ts
6
+ type FlakyDetectionContext = {
7
+ budget_ratio_for_new_tests: number;
8
+ budget_ratio_for_unhealthy_tests: number;
9
+ existing_test_names: string[];
10
+ existing_tests_mean_duration_ms: number;
11
+ unhealthy_test_names: string[];
12
+ max_test_execution_count: number;
13
+ max_test_name_length: number;
14
+ min_budget_duration_ms: number;
15
+ min_test_execution_count: number;
16
+ };
17
+ type FlakyDetectionMode = 'new' | 'unhealthy';
18
+ type FlakyDetectionConfig = {
19
+ apiUrl: string;
20
+ token: string;
21
+ repoName: string;
22
+ };
23
+ declare function fetchFlakyDetectionContext(config: FlakyDetectionConfig, logger: (msg: string) => void): Promise<FlakyDetectionContext | null>;
24
+ declare class FlakyDetector {
25
+ private context;
26
+ private mode;
27
+ private candidates;
28
+ private existingTestsInSession;
29
+ private budgetMs;
30
+ private perTestDeadlineMs;
31
+ private testMetrics;
32
+ private tooSlowTests;
33
+ constructor(context: FlakyDetectionContext, mode: FlakyDetectionMode, allTestNames: string[]);
34
+ isCandidate(testName: string): boolean;
35
+ /** Calculate max repeats for a candidate test. Call after first execution to use actual duration. */
36
+ getMaxRepeats(testName: string, initialDurationMs: number): number;
37
+ recordOutcome(testName: string, outcome: 'pass' | 'fail'): void;
38
+ isFlaky(testName: string): boolean;
39
+ getRerunCount(testName: string): number;
40
+ isTooSlow(testName: string): boolean;
41
+ /** Get summary data for the terminal report. */
42
+ getSummary(): {
43
+ mode: FlakyDetectionMode;
44
+ budgetMs: number;
45
+ candidateCount: number;
46
+ rerunTests: Array<{
47
+ name: string;
48
+ rerunCount: number;
49
+ flaky: boolean;
50
+ outcomes: string[];
51
+ }>;
52
+ tooSlowTests: string[];
53
+ };
54
+ private getOrCreateMetrics;
55
+ }
56
+ //#endregion
57
+ //#region src/quarantine.d.ts
58
+ interface QuarantineConfig {
59
+ apiUrl: string;
60
+ token: string;
61
+ repoName: string;
62
+ branch: string;
63
+ }
64
+ declare function fetchQuarantineList(config: QuarantineConfig, logger: (msg: string) => void): Promise<Set<string>>;
65
+ //#endregion
66
+ //#region src/resources/index.d.ts
67
+ declare function detectResources(frameworkAttributes: Attributes, testRunId: string): Resource;
68
+ //#endregion
69
+ //#region src/tracing.d.ts
70
+ interface TracingConfig {
71
+ token: string | undefined;
72
+ repoName: string | undefined;
73
+ apiUrl: string;
74
+ testRunId: string;
75
+ frameworkAttributes: Attributes;
76
+ tracerName: string;
77
+ /** Injected exporter — bypasses CI and token checks. */
78
+ exporter?: SpanExporter;
79
+ }
80
+ interface TracingContext {
81
+ tracer: Tracer;
82
+ tracerProvider: BasicTracerProvider;
83
+ exporter: SpanExporter;
84
+ resource: Resource;
85
+ /** Whether the provider should be shut down on test run end. */
86
+ ownsExporter: boolean;
87
+ }
88
+ declare class SynchronousBatchSpanProcessor implements SpanProcessor {
89
+ private exporter;
90
+ private queue;
91
+ constructor(exporter: SpanExporter);
92
+ onStart(): void;
93
+ onEnd(span: ReadableSpan): void;
94
+ forceFlush(): Promise<void>;
95
+ shutdown(): Promise<void>;
96
+ }
97
+ declare function createTracing(config: TracingConfig): TracingContext | null;
98
+ //#endregion
99
+ //#region src/types.d.ts
100
+ interface TestCaseError {
101
+ type: string;
102
+ message: string;
103
+ stacktrace: string;
104
+ }
105
+ interface TestCaseFlakyDetection {
106
+ new: boolean;
107
+ flaky: boolean;
108
+ rerunCount: number;
109
+ }
110
+ interface TestCaseResult {
111
+ /** Relative file path (e.g. Vitest TestModule.relativeModuleId) */
112
+ filepath: string;
113
+ /** Absolute file path (e.g. Vitest TestModule.moduleId) */
114
+ absoluteFilepath: string;
115
+ /** Test name (e.g. Vitest TestCase.name) */
116
+ function: string;
117
+ /** Line number in the file (Vitest requires includeTaskLocation) */
118
+ lineno: number;
119
+ /** Parent suite chain (e.g. derived from Vitest fullName) */
120
+ namespace: string;
121
+ scope: 'case';
122
+ status: 'passed' | 'failed' | 'skipped';
123
+ error?: TestCaseError;
124
+ /** Duration in ms */
125
+ duration: number;
126
+ /** Start time in ms */
127
+ startTime: number;
128
+ /** Number of retries */
129
+ retryCount: number;
130
+ /** Whether the test passed on a retry (native framework flaky) */
131
+ flaky: boolean;
132
+ /** Framework sub-identity (Playwright project name). Optional. */
133
+ project?: string;
134
+ /** Whether the test is quarantined. Set by Vitest runner when the quarantine feature is active. */
135
+ quarantined?: boolean;
136
+ /** Flaky-detection metadata. Set by Vitest runner when flaky detection is active. */
137
+ flakyDetection?: TestCaseFlakyDetection;
138
+ }
139
+ interface TestRunSession {
140
+ /** 16-char hex ID (8 random bytes), matching Mergify CI Insights API format */
141
+ testRunId: string;
142
+ scope: 'session';
143
+ startTime: number;
144
+ endTime?: number;
145
+ status: 'passed' | 'failed' | 'interrupted';
146
+ testCases: TestCaseResult[];
147
+ }
148
+ //#endregion
149
+ //#region src/spans.d.ts
150
+ declare function startSessionSpan(tracing: TracingContext, name: string): Span;
151
+ declare function endSessionSpan(tracing: TracingContext, sessionSpan: Span, reason: 'passed' | 'failed' | 'interrupted'): Promise<void>;
152
+ declare function emitTestCaseSpan(tracer: Tracer, sessionSpan: Span, result: TestCaseResult): void;
153
+ //#endregion
154
+ //#region src/utils.d.ts
155
+ type CIProvider = 'github_actions' | 'jenkins' | 'circleci' | 'buildkite';
156
+ /**
157
+ * Generate a 16-character hex test run ID (8 random bytes).
158
+ */
159
+ declare function generateTestRunId(): string;
160
+ /** Convert a string to a boolean. */
161
+ declare function strtobool(value: string): boolean;
162
+ declare function envToBool(value: string | undefined, fallback: boolean): boolean;
163
+ /** Check if running in a CI environment. */
164
+ declare function isInCI(): boolean;
165
+ /** Detect the current CI provider from environment variables. */
166
+ declare function getCIProvider(): CIProvider | null;
167
+ /** Execute a git command and return trimmed stdout, or null on failure. */
168
+ declare function git(...args: string[]): string | null;
169
+ /** Split an "owner/repo" string into parts. */
170
+ declare function splitRepoName(fullName: string): {
171
+ owner: string;
172
+ repo: string;
173
+ };
174
+ /**
175
+ * Resolve the repository name ("owner/repo") from env vars or the git remote.
176
+ * Checks GITHUB_REPOSITORY, then GIT_URL, then falls back to `git config`.
177
+ */
178
+ declare function getRepoName(): string | undefined;
179
+ /** Parse a repository name from a git remote URL (SSH or HTTPS). */
180
+ declare function getRepositoryNameFromUrl(url: string): string | null;
181
+ /**
182
+ * Resolve the branch name for quarantine/flaky-detection lookups from OTel
183
+ * resource attributes: `vcs.ref.base.name` (PR target) preferred, then
184
+ * `vcs.ref.head.name` (push branch / PR head). Empty strings fall through.
185
+ */
186
+ declare function resolveBranchFromAttributes(attrs: Attributes): string | undefined;
187
+ //#endregion
188
+ export { type CIProvider, type FlakyDetectionConfig, type FlakyDetectionContext, type FlakyDetectionMode, FlakyDetector, type QuarantineConfig, SynchronousBatchSpanProcessor, type TestCaseError, type TestCaseFlakyDetection, type TestCaseResult, type TestRunSession, type TracingConfig, type TracingContext, createTracing, detectResources, emitTestCaseSpan, endSessionSpan, envToBool, fetchFlakyDetectionContext, fetchQuarantineList, generateTestRunId, getCIProvider, getRepoName, getRepositoryNameFromUrl, git, isInCI, resolveBranchFromAttributes, splitRepoName, startSessionSpan, strtobool };
189
+ //# sourceMappingURL=index.d.mts.map