@storyshelf/notify-git 0.0.0-stage → 0.6.2
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/LICENSE +21 -0
- package/README.md +89 -2
- package/dist/describe.mjs +21 -0
- package/dist/describe.mjs.map +1 -0
- package/dist/github-api.mjs +25 -0
- package/dist/github-api.mjs.map +1 -0
- package/dist/github-app.mjs +67 -0
- package/dist/github-app.mjs.map +1 -0
- package/dist/github-check-mapper.mjs +69 -0
- package/dist/github-check-mapper.mjs.map +1 -0
- package/dist/github-check.mjs +86 -0
- package/dist/github-check.mjs.map +1 -0
- package/dist/github-comment.mjs +58 -0
- package/dist/github-comment.mjs.map +1 -0
- package/dist/github-config.d.mts +24 -0
- package/dist/github-config.mjs +31 -0
- package/dist/github-config.mjs.map +1 -0
- package/dist/github-mapper.mjs +22 -0
- package/dist/github-mapper.mjs.map +1 -0
- package/dist/github-pr.mjs +20 -0
- package/dist/github-pr.mjs.map +1 -0
- package/dist/github-status.mjs +44 -0
- package/dist/github-status.mjs.map +1 -0
- package/dist/github.d.mts +13 -0
- package/dist/github.mjs +66 -0
- package/dist/github.mjs.map +1 -0
- package/dist/gitlab-api.mjs +23 -0
- package/dist/gitlab-api.mjs.map +1 -0
- package/dist/gitlab-comment.mjs +65 -0
- package/dist/gitlab-comment.mjs.map +1 -0
- package/dist/gitlab-config.d.mts +14 -0
- package/dist/gitlab-config.mjs +17 -0
- package/dist/gitlab-config.mjs.map +1 -0
- package/dist/gitlab-mapper.mjs +19 -0
- package/dist/gitlab-mapper.mjs.map +1 -0
- package/dist/gitlab-pr.mjs +19 -0
- package/dist/gitlab-pr.mjs.map +1 -0
- package/dist/gitlab-status.mjs +47 -0
- package/dist/gitlab-status.mjs.map +1 -0
- package/dist/gitlab.d.mts +9 -0
- package/dist/gitlab.mjs +50 -0
- package/dist/gitlab.mjs.map +1 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.mjs +23 -0
- package/dist/index.mjs.map +1 -0
- package/dist/log.d.mts +12 -0
- package/dist/log.mjs +42 -0
- package/dist/log.mjs.map +1 -0
- package/dist/prefix.mjs +14 -0
- package/dist/prefix.mjs.map +1 -0
- package/dist/review-comment.mjs +54 -0
- package/dist/review-comment.mjs.map +1 -0
- package/dist/state-adapter.mjs +43 -0
- package/dist/state-adapter.mjs.map +1 -0
- package/dist/version.mjs +12 -0
- package/dist/version.mjs.map +1 -0
- package/package.json +80 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-comment.mjs","names":[],"sources":["../src/review-comment.ts"],"sourcesContent":["import type { Logger } from \"@storyshelf/core/logger\";\nimport { commentMarker } from \"./describe.ts\";\n\n/** A review thread (PR or MR) hosting a single StoryShelf comment. */\nexport interface ReviewThread {\n /** List existing comments as id/body pairs. */\n list(): Promise<{ id: string | number; body: string }[]>;\n /** Replace the body of an existing comment, returning its id. */\n update(id: string | number, body: string): Promise<string>;\n /** Create a comment, returning its id. */\n create(body: string): Promise<string>;\n}\n\n/** Dependencies for an idempotent review-comment upsert. */\nexport interface UpsertReviewCommentOptions {\n /** Canonical build/review URL — anchors the idempotency marker. */\n url: string;\n /** Markdown body appended below the marker. */\n markdown: string;\n /** Known thread number, skipping the lookup when provided. */\n prNumber?: number;\n /** Commit SHA used for the thread lookup and log context. */\n sha: string;\n logger?: Logger;\n /** Resolve the thread number for the commit (PR number or MR iid). */\n resolveNumber: () => Promise<number | undefined>;\n /** Open the thread's comment store once the number is known. */\n thread: (number: number) => ReviewThread;\n}\n\n/** Resolve the thread number, preferring the explicit value. */\nasync function resolveThreadNumber(opts: UpsertReviewCommentOptions): Promise<number | undefined> {\n return opts.prNumber ?? (await opts.resolveNumber());\n}\n\n/** Update the marked comment if present, else create it. */\nasync function findOrCreateComment(\n thread: ReviewThread,\n marker: string,\n body: string,\n prNumber: number,\n logger?: Logger,\n): Promise<string> {\n const existing = (await thread.list()).find((comment) => comment.body.includes(marker));\n if (existing) {\n const id = await thread.update(existing.id, body);\n logger?.info({ prNumber, commentId: id }, \"review comment updated\");\n return id;\n }\n const id = await thread.create(body);\n logger?.info({ prNumber, commentId: id }, \"review comment created\");\n return id;\n}\n\n/**\n * Create or update the single StoryShelf review comment for a build,\n * idempotent via the url marker. Returns the comment id, or `\"\"` when no\n * review thread exists for the commit.\n */\nexport async function upsertReviewComment(opts: UpsertReviewCommentOptions): Promise<string> {\n const marker = commentMarker(opts.url);\n const body = `${marker}\\n${opts.markdown}`;\n const number = await resolveThreadNumber(opts);\n if (number === undefined) {\n opts.logger?.debug({ sha: opts.sha }, \"no review thread found for comment, skipping\");\n return \"\";\n }\n try {\n return await findOrCreateComment(opts.thread(number), marker, body, number, opts.logger);\n } catch (error) {\n opts.logger?.error({ err: error, prNumber: number }, \"failed to upsert review comment\");\n throw error;\n }\n}\n"],"mappings":";;;;;;AA+BA,eAAe,oBAAoB,MAA+D;CAChG,OAAO,KAAK,YAAa,MAAM,KAAK,cAAc;AACpD;;AAGA,eAAe,oBACb,QACA,QACA,MACA,UACA,QACiB;CACjB,MAAM,YAAY,MAAM,OAAO,KAAK,EAAA,CAAG,MAAM,YAAY,QAAQ,KAAK,SAAS,MAAM,CAAC;CACtF,IAAI,UAAU;EACZ,MAAM,KAAK,MAAM,OAAO,OAAO,SAAS,IAAI,IAAI;EAChD,QAAQ,KAAK;GAAE;GAAU,WAAW;EAAG,GAAG,wBAAwB;EAClE,OAAO;CACT;CACA,MAAM,KAAK,MAAM,OAAO,OAAO,IAAI;CACnC,QAAQ,KAAK;EAAE;EAAU,WAAW;CAAG,GAAG,wBAAwB;CAClE,OAAO;AACT;;;;;;AAOA,eAAsB,oBAAoB,MAAmD;CAC3F,MAAM,SAAS,cAAc,KAAK,GAAG;CACrC,MAAM,OAAO,GAAG,OAAO,IAAI,KAAK;CAChC,MAAM,SAAS,MAAM,oBAAoB,IAAI;CAC7C,IAAI,WAAW,KAAA,GAAW;EACxB,KAAK,QAAQ,MAAM,EAAE,KAAK,KAAK,IAAI,GAAG,8CAA8C;EACpF,OAAO;CACT;CACA,IAAI;EACF,OAAO,MAAM,oBAAoB,KAAK,OAAO,MAAM,GAAG,QAAQ,MAAM,QAAQ,KAAK,MAAM;CACzF,SAAS,OAAO;EACd,KAAK,QAAQ,MAAM;GAAE,KAAK;GAAO,UAAU;EAAO,GAAG,iCAAiC;EACtF,MAAM;CACR;AACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { describeState } from "./describe.mjs";
|
|
5
|
+
//#region src/state-adapter.ts
|
|
6
|
+
/** Build the runtime adapter that routes a target kind to the writer. */
|
|
7
|
+
function createStateAdapter(metadata, writer, logger) {
|
|
8
|
+
return {
|
|
9
|
+
metadata,
|
|
10
|
+
async setState({ target, state, url }) {
|
|
11
|
+
if (target.kind === "status") {
|
|
12
|
+
await writer.status({
|
|
13
|
+
sha: target.sha,
|
|
14
|
+
context: target.context,
|
|
15
|
+
state,
|
|
16
|
+
description: target.description ?? describeState(state),
|
|
17
|
+
url,
|
|
18
|
+
progress: target.progress,
|
|
19
|
+
informational: target.informational,
|
|
20
|
+
annotations: target.annotations,
|
|
21
|
+
omitted: target.omitted
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (url === void 0) return;
|
|
26
|
+
logger?.debug({ sha: target.sha }, "upserting review comment");
|
|
27
|
+
await writer.comment({
|
|
28
|
+
sha: target.sha,
|
|
29
|
+
url,
|
|
30
|
+
markdown: target.markdown
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** The channel's secret (token or private key), or an error naming the provider when the channel has none. */
|
|
36
|
+
function requireToken(secret, provider, what = "a token") {
|
|
37
|
+
if (!secret) throw new Error(`${provider} channel needs ${what}`);
|
|
38
|
+
return secret;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { createStateAdapter, requireToken };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=state-adapter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-adapter.mjs","names":[],"sources":["../src/state-adapter.ts"],"sourcesContent":["/** Shared `setState` routing for providers that write commit statuses and review comments. */\nimport type {\n NotifierState,\n StateAnnotation,\n StateNotifierAdapter,\n StateNotifierMetadata,\n} from \"@storyshelf/core/adapter/notifier\";\nimport type { Logger } from \"@storyshelf/core/logger\";\nimport { describeState } from \"./describe.ts\";\n\n/** What a host-specific writer does for each target kind. */\nexport interface StateWriter {\n /** Set the commit status `context` on `sha`. */\n status(input: {\n sha: string;\n context: string;\n state: NotifierState;\n description: string;\n /** Absent while no public origin is known: the status has no link. */\n url?: string | undefined;\n /** For a `pending` state: not started (`queued`) or under way. */\n progress?: \"queued\" | \"running\" | undefined;\n /** Never a gate: a host with a neutral outcome shows a failure as neutral. */\n informational?: boolean | undefined;\n annotations?: StateAnnotation[] | undefined;\n /** Changed snapshots left out of `annotations`. */\n omitted?: number | undefined;\n }): Promise<void>;\n /** Create or update the single review comment of the build keyed by `url`. */\n comment(input: { sha: string; url: string; markdown: string }): Promise<unknown>;\n}\n\n/** Build the runtime adapter that routes a target kind to the writer. */\nexport function createStateAdapter(\n metadata: StateNotifierMetadata,\n writer: StateWriter,\n logger?: Logger,\n): StateNotifierAdapter {\n return {\n metadata,\n async setState({ target, state, url }): Promise<void> {\n if (target.kind === \"status\") {\n await writer.status({\n sha: target.sha,\n context: target.context,\n state,\n description: target.description ?? describeState(state),\n url,\n progress: target.progress,\n informational: target.informational,\n annotations: target.annotations,\n omitted: target.omitted,\n });\n return;\n }\n if (url === undefined) {\n // The comment is keyed by the build's link; without a public origin there is none.\n return;\n }\n logger?.debug({ sha: target.sha }, \"upserting review comment\");\n await writer.comment({ sha: target.sha, url, markdown: target.markdown });\n },\n };\n}\n\n/** The channel's secret (token or private key), or an error naming the provider when the channel has none. */\nexport function requireToken(\n secret: string | undefined,\n provider: string,\n what = \"a token\",\n): string {\n if (!secret) {\n throw new Error(`${provider} channel needs ${what}`);\n }\n return secret;\n}\n"],"mappings":";;;;;;AAiCA,SAAgB,mBACd,UACA,QACA,QACsB;CACtB,OAAO;EACL;EACA,MAAM,SAAS,EAAE,QAAQ,OAAO,OAAsB;GACpD,IAAI,OAAO,SAAS,UAAU;IAC5B,MAAM,OAAO,OAAO;KAClB,KAAK,OAAO;KACZ,SAAS,OAAO;KAChB;KACA,aAAa,OAAO,eAAe,cAAc,KAAK;KACtD;KACA,UAAU,OAAO;KACjB,eAAe,OAAO;KACtB,aAAa,OAAO;KACpB,SAAS,OAAO;IAClB,CAAC;IACD;GACF;GACA,IAAI,QAAQ,KAAA,GAEV;GAEF,QAAQ,MAAM,EAAE,KAAK,OAAO,IAAI,GAAG,0BAA0B;GAC7D,MAAM,OAAO,QAAQ;IAAE,KAAK,OAAO;IAAK;IAAK,UAAU,OAAO;GAAS,CAAC;EAC1E;CACF;AACF;;AAGA,SAAgB,aACd,QACA,UACA,OAAO,WACC;CACR,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,GAAG,SAAS,iBAAiB,MAAM;CAErD,OAAO;AACT"}
|
package/dist/version.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
//#region src/version.ts
|
|
5
|
+
/** The package version injected at build time (tsdown `define`), `0.0.0` in tests. */
|
|
6
|
+
function packageVersion() {
|
|
7
|
+
return "0.6.2";
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { packageVersion };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=version.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["/** Package version for provider metadata. */\ndeclare const __PKG_VERSION__: string | undefined;\n\n/** The package version injected at build time (tsdown `define`), `0.0.0` in tests. */\nexport function packageVersion(): string {\n return typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\";\n}\n"],"mappings":";;;;;AAIA,SAAgB,iBAAyB;CACvC,OAAA;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,82 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyshelf/notify-git",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.6.2",
|
|
4
|
+
"description": "Git notification providers for StoryShelf: commit statuses and pull-request comments on GitHub and GitLab.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ci",
|
|
7
|
+
"github",
|
|
8
|
+
"gitlab",
|
|
9
|
+
"merge-gate",
|
|
10
|
+
"notifications",
|
|
11
|
+
"self-hosted",
|
|
12
|
+
"storybook"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/GuptaSiddhant/StoryShelf#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/GuptaSiddhant/StoryShelf/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": {
|
|
20
|
+
"name": "Siddhant Gupta",
|
|
21
|
+
"url": "https://guptasiddhant.com"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/GuptaSiddhant/StoryShelf.git",
|
|
26
|
+
"directory": "packages/notify-git"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"type": "module",
|
|
32
|
+
"sideEffects": false,
|
|
33
|
+
"types": "./dist/index.d.mts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"source": "./src/index.ts",
|
|
37
|
+
"default": "./dist/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"exports": {
|
|
43
|
+
".": "./dist/index.mjs",
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsdown",
|
|
50
|
+
"dev": "tsdown -w",
|
|
51
|
+
"fmt": "oxfmt ./src",
|
|
52
|
+
"lint": "oxlint --type-aware --type-check ./src",
|
|
53
|
+
"test": "vitest run",
|
|
54
|
+
"prepublishOnly": "nub run build"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@storyshelf/core": "0.6.2",
|
|
58
|
+
"zod": "^4.2.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/node": "^26.0.0",
|
|
62
|
+
"@vitest/coverage-v8": "^4.0.0",
|
|
63
|
+
"oxfmt": "^0.65.0",
|
|
64
|
+
"oxlint": "^1.80.0",
|
|
65
|
+
"oxlint-tsgolint": "^7.0.2001",
|
|
66
|
+
"tsdown": "^0.22.14",
|
|
67
|
+
"typescript": "^7.0.2",
|
|
68
|
+
"vitest": "^5.0.0"
|
|
69
|
+
},
|
|
70
|
+
"engines": {
|
|
71
|
+
"node": ">=24"
|
|
72
|
+
},
|
|
73
|
+
"jsr": {
|
|
74
|
+
"runtimeCompat": {
|
|
75
|
+
"node": true,
|
|
76
|
+
"deno": true,
|
|
77
|
+
"browser": false,
|
|
78
|
+
"workerd": false,
|
|
79
|
+
"bun": true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|