standup-mr 0.2.0 → 0.2.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.
- package/CHANGELOG.md +17 -0
- package/dist/{chunk-MIQ7FQS6.js → chunk-DL2P3XR6.js} +14 -3
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/server.js +15 -4
- package/package.json +28 -7
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ All notable changes to standup-mr are recorded here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
5
|
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.2.1] - 2026-08-31
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- A pull request whose CI timed out was reported as ready to merge. GitHub
|
|
12
|
+
reports a timed-out job with the conclusion `cancelled`, not `timed_out`, so
|
|
13
|
+
it normalised to a `canceled` pipeline — and a canceled pipeline was treated
|
|
14
|
+
as a green light. A canceled pipeline now blocks, on both providers: GitLab's
|
|
15
|
+
`canceled` status took the same path.
|
|
16
|
+
- Every error line in a GitHub blocker was reported twice. GitHub Actions echoes
|
|
17
|
+
a step's script inside a `##[group]Run …` block before running it, and those
|
|
18
|
+
echoed lines matched the error patterns. The body of a `Run` group is now
|
|
19
|
+
suppressed; other groups are still scanned, since they carry real output.
|
|
20
|
+
|
|
21
|
+
Both were found by testing 0.2.0 against the real GitHub Actions API — neither
|
|
22
|
+
was reachable from the test fixtures.
|
|
23
|
+
|
|
7
24
|
## [0.2.0] - 2026-08-31
|
|
8
25
|
|
|
9
26
|
GitHub joins GitLab as a first-class provider, and the previous-day report
|
|
@@ -80,7 +80,7 @@ function previousActiveDays(eventDates, today) {
|
|
|
80
80
|
// src/buckets/buckets.ts
|
|
81
81
|
function classify(mr, today, staleDays = STALE_DAYS) {
|
|
82
82
|
if (mr.draft) return "draft";
|
|
83
|
-
if (mr.pipeline === "failed" || mr.unresolved > 0) return "blocked";
|
|
83
|
+
if (mr.pipeline === "failed" || mr.pipeline === "canceled" || mr.unresolved > 0) return "blocked";
|
|
84
84
|
const age = Math.round(
|
|
85
85
|
(Date.parse(`${isoDay(today)}T00:00:00Z`) - Date.parse(`${mr.updated}T00:00:00Z`)) / MS_PER_DAY
|
|
86
86
|
);
|
|
@@ -274,7 +274,9 @@ var NOISE = /^(Cleaning up|Job failed: exit status|ERROR: Job failed|Uploading a
|
|
|
274
274
|
var MAX_LINE = 200;
|
|
275
275
|
var TIMESTAMP = /^\d{4}-\d{2}-\d{2}T[\d:.]+Z\s+/;
|
|
276
276
|
var ERROR_MARKER = /^##\[error\]\s*/;
|
|
277
|
-
var
|
|
277
|
+
var GROUP_START = /^##\[group\]/;
|
|
278
|
+
var GROUP_END = /^##\[endgroup\]/;
|
|
279
|
+
var RUN_GROUP = /^##\[group\]Run\s/;
|
|
278
280
|
|
|
279
281
|
// src/trace/trace.ts
|
|
280
282
|
function extractErrors(rawTrace, limit = 8) {
|
|
@@ -282,9 +284,18 @@ function extractErrors(rawTrace, limit = 8) {
|
|
|
282
284
|
const cleaned = rawTrace.replace(ANSI, "").replace(SECTION, "");
|
|
283
285
|
const seen = /* @__PURE__ */ new Set();
|
|
284
286
|
const hits = [];
|
|
287
|
+
let suppressing = false;
|
|
285
288
|
for (const rawLine of cleaned.split("\n")) {
|
|
286
289
|
const stamped = rawLine.trim().replace(TIMESTAMP, "");
|
|
287
|
-
if (
|
|
290
|
+
if (GROUP_START.test(stamped)) {
|
|
291
|
+
suppressing = RUN_GROUP.test(stamped);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (GROUP_END.test(stamped)) {
|
|
295
|
+
suppressing = false;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (suppressing) continue;
|
|
288
299
|
if (!stamped || NOISE.test(stamped) || !SIGNAL.test(stamped)) continue;
|
|
289
300
|
const line = stamped.replace(ERROR_MARKER, "").trim();
|
|
290
301
|
if (!line) continue;
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/dist/mcp/server.js
CHANGED
|
@@ -176,7 +176,7 @@ function previousActiveDays(eventDates, today) {
|
|
|
176
176
|
// src/buckets/buckets.ts
|
|
177
177
|
function classify(mr, today, staleDays = STALE_DAYS) {
|
|
178
178
|
if (mr.draft) return "draft";
|
|
179
|
-
if (mr.pipeline === "failed" || mr.unresolved > 0) return "blocked";
|
|
179
|
+
if (mr.pipeline === "failed" || mr.pipeline === "canceled" || mr.unresolved > 0) return "blocked";
|
|
180
180
|
const age = Math.round(
|
|
181
181
|
(Date.parse(`${isoDay(today)}T00:00:00Z`) - Date.parse(`${mr.updated}T00:00:00Z`)) / MS_PER_DAY
|
|
182
182
|
);
|
|
@@ -197,7 +197,9 @@ var NOISE = /^(Cleaning up|Job failed: exit status|ERROR: Job failed|Uploading a
|
|
|
197
197
|
var MAX_LINE = 200;
|
|
198
198
|
var TIMESTAMP = /^\d{4}-\d{2}-\d{2}T[\d:.]+Z\s+/;
|
|
199
199
|
var ERROR_MARKER = /^##\[error\]\s*/;
|
|
200
|
-
var
|
|
200
|
+
var GROUP_START = /^##\[group\]/;
|
|
201
|
+
var GROUP_END = /^##\[endgroup\]/;
|
|
202
|
+
var RUN_GROUP = /^##\[group\]Run\s/;
|
|
201
203
|
|
|
202
204
|
// src/trace/trace.ts
|
|
203
205
|
function extractErrors(rawTrace, limit = 8) {
|
|
@@ -205,9 +207,18 @@ function extractErrors(rawTrace, limit = 8) {
|
|
|
205
207
|
const cleaned = rawTrace.replace(ANSI, "").replace(SECTION, "");
|
|
206
208
|
const seen = /* @__PURE__ */ new Set();
|
|
207
209
|
const hits = [];
|
|
210
|
+
let suppressing = false;
|
|
208
211
|
for (const rawLine of cleaned.split("\n")) {
|
|
209
212
|
const stamped = rawLine.trim().replace(TIMESTAMP, "");
|
|
210
|
-
if (
|
|
213
|
+
if (GROUP_START.test(stamped)) {
|
|
214
|
+
suppressing = RUN_GROUP.test(stamped);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (GROUP_END.test(stamped)) {
|
|
218
|
+
suppressing = false;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (suppressing) continue;
|
|
211
222
|
if (!stamped || NOISE.test(stamped) || !SIGNAL.test(stamped)) continue;
|
|
212
223
|
const line = stamped.replace(ERROR_MARKER, "").trim();
|
|
213
224
|
if (!line) continue;
|
|
@@ -955,7 +966,7 @@ async function collect(options = {}) {
|
|
|
955
966
|
async function main() {
|
|
956
967
|
const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
|
|
957
968
|
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
958
|
-
const server = new McpServer({ name: "standup-mr", version: "0.2.
|
|
969
|
+
const server = new McpServer({ name: "standup-mr", version: "0.2.1" });
|
|
959
970
|
server.tool(
|
|
960
971
|
"get_standup_data",
|
|
961
972
|
"Collect merge-request-based standup data from GitLab or GitHub. Returns the previous working day activity, open merge requests or pull requests bucketed by state (ready / blocked / draft / stale), pending reviews, and the error lines from any failed pipeline or check.",
|
package/package.json
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "standup-mr",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Standup notes from merge request state, not commit logs.",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"standup",
|
|
7
|
+
"gitlab",
|
|
8
|
+
"github",
|
|
9
|
+
"merge-request",
|
|
10
|
+
"pull-request",
|
|
11
|
+
"cli",
|
|
12
|
+
"mcp"
|
|
13
|
+
],
|
|
6
14
|
"license": "MIT",
|
|
7
15
|
"author": {
|
|
8
|
-
"name": "
|
|
16
|
+
"name": "\u0130lker Balc\u0131lar",
|
|
9
17
|
"email": "ilkerbalcilartr@gmail.com"
|
|
10
18
|
},
|
|
11
19
|
"repository": {
|
|
@@ -27,11 +35,22 @@
|
|
|
27
35
|
}
|
|
28
36
|
],
|
|
29
37
|
"type": "module",
|
|
30
|
-
"engines": {
|
|
31
|
-
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
},
|
|
41
|
+
"bin": {
|
|
42
|
+
"standup": "./dist/cli.js"
|
|
43
|
+
},
|
|
32
44
|
"main": "./dist/index.js",
|
|
33
45
|
"types": "./dist/index.d.ts",
|
|
34
|
-
"files": [
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"skills",
|
|
49
|
+
"mcp/README.md",
|
|
50
|
+
"README.md",
|
|
51
|
+
"CHANGELOG.md",
|
|
52
|
+
"LICENSE"
|
|
53
|
+
],
|
|
35
54
|
"scripts": {
|
|
36
55
|
"build": "tsup",
|
|
37
56
|
"test": "bun test",
|
|
@@ -50,6 +69,8 @@
|
|
|
50
69
|
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
51
70
|
},
|
|
52
71
|
"peerDependenciesMeta": {
|
|
53
|
-
"@modelcontextprotocol/sdk": {
|
|
72
|
+
"@modelcontextprotocol/sdk": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
54
75
|
}
|
|
55
76
|
}
|