standup-mr 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,15 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigError,
4
- GitLabProvider,
5
4
  buildReport,
6
- glabHosts,
7
- glabToken,
5
+ connect,
8
6
  postWebhook,
9
- resolveHost,
10
- resolveToken,
11
7
  toMarkdown
12
- } from "./chunk-SKCJT2AY.js";
8
+ } from "./chunk-MIQ7FQS6.js";
13
9
 
14
10
  // src/cli/cli.ts
15
11
  import { realpathSync } from "fs";
@@ -20,10 +16,15 @@ import { parseArgs } from "util";
20
16
  var USAGE = `standup \u2014 standup notes from merge request state
21
17
 
22
18
  Usage:
23
- standup fetch [--host H] [--token T] [--lang en|tr] [--markdown]
19
+ standup fetch [--provider github|gitlab] [--host H] [--token T]
20
+ [--lang en|tr] [--markdown]
24
21
  standup post (--slack URL | --discord URL) [--text TEXT]
25
22
 
26
- Credentials resolve as: flag, then GITLAB_HOST / GITLAB_TOKEN, then glab config.
23
+ The provider is taken from --provider, then STANDUP_PROVIDER, then whichever of
24
+ GITHUB_* / GITLAB_* is set, then whichever of gh / glab is logged in.
25
+
26
+ Credentials resolve as: flag, then GITHUB_HOST / GITHUB_TOKEN (or GITLAB_HOST /
27
+ GITLAB_TOKEN), then the gh or glab config.
27
28
  --text defaults to '-', meaning read stdin.`;
28
29
 
29
30
  // src/cli/cli.ts
@@ -32,11 +33,6 @@ async function readStdin() {
32
33
  for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
33
34
  return Buffer.concat(chunks).toString("utf8");
34
35
  }
35
- function connect(values) {
36
- const host = resolveHost(values.host, process.env.GITLAB_HOST, glabHosts());
37
- const token = resolveToken(host, values.token, process.env.GITLAB_TOKEN, glabToken);
38
- return new GitLabProvider(host, token);
39
- }
40
36
  async function main(argv) {
41
37
  const [command, ...rest] = argv;
42
38
  if (!command || command === "--help" || command === "-h") {
@@ -49,6 +45,7 @@ async function main(argv) {
49
45
  const { values } = parseArgs({
50
46
  args: rest,
51
47
  options: {
48
+ provider: { type: "string" },
52
49
  host: { type: "string" },
53
50
  token: { type: "string" },
54
51
  lang: { type: "string", default: "en" },
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ interface PipelineInput {
10
10
  pipelineMissing?: boolean;
11
11
  }
12
12
 
13
+ type ProviderKind = 'gitlab' | 'github';
13
14
  type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
14
15
  type Bucket = 'ready' | 'blocked' | 'draft' | 'stale';
15
16
  interface Identity {
@@ -27,6 +28,7 @@ interface ActivityEvent {
27
28
  commitTitle: string;
28
29
  }
29
30
  interface MergeRequest {
31
+ provider: ProviderKind;
30
32
  project: string;
31
33
  projectId: number;
32
34
  iid: number;
@@ -44,6 +46,7 @@ interface MergeRequest {
44
46
  bucket: Bucket;
45
47
  }
46
48
  interface Review {
49
+ provider: ProviderKind;
47
50
  project: string;
48
51
  iid: number;
49
52
  title: string;
@@ -55,6 +58,7 @@ interface Review {
55
58
  approvedByMe: boolean;
56
59
  }
57
60
  interface Blocker {
61
+ provider: ProviderKind;
58
62
  project: string;
59
63
  mr: number;
60
64
  title: string;
@@ -63,19 +67,20 @@ interface Blocker {
63
67
  url: string;
64
68
  errors: string[];
65
69
  }
70
+ interface ActiveDay {
71
+ date: string;
72
+ label: string;
73
+ gapDays: number;
74
+ events: ActivityEvent[];
75
+ }
66
76
  interface StandupReport {
77
+ provider: ProviderKind;
67
78
  user: string;
68
79
  today: {
69
80
  date: string;
70
81
  label: string;
71
82
  };
72
- previous: {
73
- date: string | null;
74
- label: string | null;
75
- gapDays: number | null;
76
- eventCount: number;
77
- };
78
- previousEvents: ActivityEvent[];
83
+ previousDays: ActiveDay[];
79
84
  todayEvents: ActivityEvent[];
80
85
  myMrs: MergeRequest[];
81
86
  reviews: Review[];
@@ -91,17 +96,31 @@ declare const STALE_DAYS = 14;
91
96
  declare class ConfigError extends Error {
92
97
  constructor(message: string);
93
98
  }
94
- declare function resolveHost(cliHost?: string, envHost?: string, glabHostList?: string[]): string;
95
- declare function resolveToken(host: string, cliToken?: string, envToken?: string, glabLookup?: (host: string) => string): string;
99
+ interface ProviderLabels {
100
+ name: string;
101
+ cli: string;
102
+ envHost: string;
103
+ envToken: string;
104
+ login: (host: string) => string;
105
+ }
106
+ declare const GITLAB_LABELS: ProviderLabels;
107
+ declare const GITHUB_LABELS: ProviderLabels;
108
+ declare function resolveHost(cliHost?: string, envHost?: string, hostList?: string[], labels?: ProviderLabels): string;
109
+ declare function resolveToken(host: string, cliToken?: string, envToken?: string, lookup?: (host: string) => string, labels?: ProviderLabels): string;
110
+ declare function parseLoggedInHosts(statusOutput: string): string[];
111
+ declare const parseGlabHosts: typeof parseLoggedInHosts;
96
112
  declare function glabHosts(): string[];
97
113
  declare function glabToken(host: string): string;
114
+ declare function ghHosts(): string[];
115
+ declare function ghToken(host: string): string;
98
116
 
99
117
  declare function isoDay(day: Date): string;
118
+ declare function localAt(iso: string): string;
100
119
  declare function label(day: Date, lang?: string): string;
101
- declare function previousActiveDay(eventDates: Set<string>, today: Date): {
102
- date: string | null;
103
- gapDays: number | null;
104
- };
120
+ declare function previousActiveDays(eventDates: Set<string>, today: Date): Array<{
121
+ date: string;
122
+ gapDays: number;
123
+ }>;
105
124
 
106
125
  declare const PAYLOAD_FIELD: {
107
126
  readonly slack: "text";
@@ -113,21 +132,110 @@ type WebhookKind = keyof typeof PAYLOAD_FIELD;
113
132
  declare function postWebhook(url: string, text: string, kind?: WebhookKind, fetchImpl?: FetchLike): Promise<void>;
114
133
 
115
134
  interface Provider {
135
+ readonly kind: ProviderKind;
136
+ getIdentity(): Promise<Identity>;
137
+ getEvents(since: Date): Promise<ActivityEvent[]>;
138
+ getMyMrs(today: Date): Promise<MergeRequest[]>;
139
+ getReviews(identity: Identity, today: Date): Promise<Review[]>;
140
+ getBlockers(mrs: MergeRequest[]): Promise<Blocker[]>;
141
+ }
142
+
143
+ declare function buildUrl(api: string, path: string, params?: Record<string, string | number>): string;
144
+ declare class ApiError extends Error {
145
+ constructor(message: string);
146
+ }
147
+ declare function assertUsable(response: Response, host: string): void;
148
+ declare function unreachable(host: string, cause: unknown): ApiError;
149
+
150
+ type Params$1 = Record<string, string | number>;
151
+ declare class GitHubProvider implements Provider {
152
+ readonly kind: "github";
153
+ readonly host: string;
154
+ readonly api: string;
155
+ private readonly token;
156
+ private readonly fetchImpl;
157
+ private identity;
158
+ constructor(host: string, token: string, fetchImpl?: FetchLike);
159
+ private headers;
160
+ private send;
161
+ getJson<T>(path: string, params?: Params$1): Promise<T | null>;
162
+ getPaged<T>(path: string, params?: Params$1, cap?: number): Promise<T[]>;
163
+ getSearch<T>(query: string, cap?: number): Promise<T[]>;
164
+ getLogText(path: string): Promise<string>;
116
165
  getIdentity(): Promise<Identity>;
117
166
  getEvents(since: Date): Promise<ActivityEvent[]>;
167
+ private shapePr;
118
168
  getMyMrs(today: Date): Promise<MergeRequest[]>;
119
- getReviews(uid: number, today: Date): Promise<Review[]>;
169
+ getReviews(identity: Identity, today: Date): Promise<Review[]>;
170
+ private actionsBlocker;
171
+ private checkRunBlocker;
172
+ private diagnose;
120
173
  getBlockers(mrs: MergeRequest[]): Promise<Blocker[]>;
121
174
  }
122
175
 
176
+ interface RawCommit {
177
+ message?: string;
178
+ }
179
+ interface RawEvent {
180
+ type?: string;
181
+ created_at: string;
182
+ repo?: {
183
+ name?: string;
184
+ };
185
+ payload?: {
186
+ action?: string;
187
+ ref?: string;
188
+ size?: number;
189
+ commits?: RawCommit[];
190
+ pull_request?: {
191
+ title?: string;
192
+ };
193
+ issue?: {
194
+ title?: string;
195
+ };
196
+ };
197
+ }
198
+ interface PullReview {
199
+ state: string;
200
+ submitted_at?: string;
201
+ user?: {
202
+ login?: string;
203
+ };
204
+ }
205
+ interface CheckRun {
206
+ id: number;
207
+ name: string;
208
+ status: string;
209
+ conclusion: string | null;
210
+ app?: {
211
+ slug?: string;
212
+ } | null;
213
+ output?: {
214
+ summary?: string | null;
215
+ text?: string | null;
216
+ } | null;
217
+ }
218
+
219
+ declare function repoFromUrl(repositoryUrl: string): string;
220
+ declare function mapEvent(raw: RawEvent): ActivityEvent;
221
+
222
+ declare function normalizeChecks(runs: CheckRun[]): {
223
+ pipeline: string | null;
224
+ pipelineId: number | null;
225
+ };
226
+ declare function latestStateByReviewer(reviews: PullReview[]): Map<string, string>;
227
+ declare function countChangesRequested(reviews: PullReview[]): number;
228
+ declare function approvedBy(reviews: PullReview[], login: string): boolean;
229
+
123
230
  type Params = Record<string, string | number>;
124
231
  declare class GitLabProvider implements Provider {
232
+ readonly kind: "gitlab";
125
233
  readonly host: string;
126
234
  readonly api: string;
127
235
  private readonly token;
128
236
  private readonly fetchImpl;
129
237
  constructor(host: string, token: string, fetchImpl?: FetchLike);
130
- private url;
238
+ private send;
131
239
  getJson<T>(path: string, params?: Params): Promise<T | null>;
132
240
  getText(path: string): Promise<string>;
133
241
  getPaged<T>(path: string, params?: Params, cap?: number): Promise<T[]>;
@@ -138,14 +246,27 @@ declare class GitLabProvider implements Provider {
138
246
  private shapeMr;
139
247
  getMyMrs(today: Date): Promise<MergeRequest[]>;
140
248
  private approvedByMe;
141
- getReviews(uid: number, today: Date): Promise<Review[]>;
249
+ getReviews(identity: Identity, today: Date): Promise<Review[]>;
142
250
  getBlockers(mrs: MergeRequest[]): Promise<Blocker[]>;
143
251
  }
144
252
 
253
+ interface SelectOptions {
254
+ provider?: string;
255
+ host?: string;
256
+ token?: string;
257
+ env?: Record<string, string | undefined>;
258
+ probe?: {
259
+ gitlab: () => string[];
260
+ github: () => string[];
261
+ };
262
+ }
263
+ declare function chooseKind(options?: SelectOptions): ProviderKind;
264
+ declare function connect(options?: SelectOptions): Provider;
265
+
145
266
  declare function toMarkdown(report: StandupReport, lang?: string): string;
146
267
 
147
268
  declare function buildReport(provider: Provider, today: Date, lang?: string, lookbackDays?: number): Promise<StandupReport>;
148
269
 
149
270
  declare function extractErrors(rawTrace: string, limit?: number): string[];
150
271
 
151
- export { type ActivityEvent, type Blocker, type Bucket, ConfigError, type FetchLike, GitLabProvider, type Identity, type MergeRequest, type Provider, type Review, STALE_DAYS, type StandupReport, buildReport, classify, extractErrors, glabHosts, glabToken, isoDay, label, markMissingPipelines, postWebhook, previousActiveDay, resolveHost, resolveToken, toMarkdown };
272
+ export { type ActiveDay, type ActivityEvent, ApiError, type Blocker, type Bucket, ConfigError, type FetchLike, GITHUB_LABELS, GITLAB_LABELS, GitHubProvider, GitLabProvider, type Identity, type MergeRequest, type Provider, type ProviderKind, type ProviderLabels, type Review, STALE_DAYS, type SelectOptions, type StandupReport, approvedBy, assertUsable, buildReport, buildUrl, chooseKind, classify, connect, countChangesRequested, extractErrors, ghHosts, ghToken, glabHosts, glabToken, isoDay, label, latestStateByReviewer, localAt, mapEvent, markMissingPipelines, normalizeChecks, parseGlabHosts, parseLoggedInHosts, postWebhook, previousActiveDays, repoFromUrl, resolveHost, resolveToken, toMarkdown, unreachable };
package/dist/index.js CHANGED
@@ -1,37 +1,77 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ ApiError,
3
4
  ConfigError,
5
+ GITHUB_LABELS,
6
+ GITLAB_LABELS,
7
+ GitHubProvider,
4
8
  GitLabProvider,
5
9
  STALE_DAYS,
10
+ approvedBy,
11
+ assertUsable,
6
12
  buildReport,
13
+ buildUrl,
14
+ chooseKind,
7
15
  classify,
16
+ connect,
17
+ countChangesRequested,
8
18
  extractErrors,
19
+ ghHosts,
20
+ ghToken,
9
21
  glabHosts,
10
22
  glabToken,
11
23
  isoDay,
12
24
  label,
25
+ latestStateByReviewer,
26
+ localAt,
27
+ mapEvent,
13
28
  markMissingPipelines,
29
+ normalizeChecks,
30
+ parseGlabHosts,
31
+ parseLoggedInHosts,
14
32
  postWebhook,
15
- previousActiveDay,
33
+ previousActiveDays,
34
+ repoFromUrl,
16
35
  resolveHost,
17
36
  resolveToken,
18
- toMarkdown
19
- } from "./chunk-SKCJT2AY.js";
37
+ toMarkdown,
38
+ unreachable
39
+ } from "./chunk-MIQ7FQS6.js";
20
40
  export {
41
+ ApiError,
21
42
  ConfigError,
43
+ GITHUB_LABELS,
44
+ GITLAB_LABELS,
45
+ GitHubProvider,
22
46
  GitLabProvider,
23
47
  STALE_DAYS,
48
+ approvedBy,
49
+ assertUsable,
24
50
  buildReport,
51
+ buildUrl,
52
+ chooseKind,
25
53
  classify,
54
+ connect,
55
+ countChangesRequested,
26
56
  extractErrors,
57
+ ghHosts,
58
+ ghToken,
27
59
  glabHosts,
28
60
  glabToken,
29
61
  isoDay,
30
62
  label,
63
+ latestStateByReviewer,
64
+ localAt,
65
+ mapEvent,
31
66
  markMissingPipelines,
67
+ normalizeChecks,
68
+ parseGlabHosts,
69
+ parseLoggedInHosts,
32
70
  postWebhook,
33
- previousActiveDay,
71
+ previousActiveDays,
72
+ repoFromUrl,
34
73
  resolveHost,
35
74
  resolveToken,
36
- toMarkdown
75
+ toMarkdown,
76
+ unreachable
37
77
  };