mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
The publish job now renders release-notes/studio/<semver>.md before it
signs anything. A #N that is a pull request gains "by @author"; a #N that
is an issue gains "fixed in #M by @author" for each merged pull request
GitHub links as closing it (the ClosedEvent closer and
closedByPullRequestsReferences, read over GraphQL; mentions are not
fixes). An issue fixed by a direct push stays plain. A 贡献者 list of the
credited humans, in first-appearance order, closes the notes. Bot authors
are never credited; the source file is not rewritten.
scripts/markdown-refs.mjs decides what is a reference: #N at a line start
or after whitespace, "(", "(" or a list separator, outside code spans,
backtick and tilde fences (each closed only by its own kind), indented
code, HTML comments and link targets. A number that names a discussion or
nothing stays plain with a warning instead of failing the release.
Lookups retry with backoff on 5xx, rate limits and dropped connections. A
failure that persists, or an authorisation failure, fails the job with a
release_credits.* code before signing. The publish job gains
issues: read and pull-requests: read.
CI gains a release-notes-scripts job, gated on scripts/ and
release-notes/studio/, that runs the three test files with contents: read.
scripts/release-credits.mjs is the same module the 1.x renderer uses.
67 lines
2.3 KiB
JavaScript
67 lines
2.3 KiB
JavaScript
import assert from "node:assert/strict";
|
||
import { readdir, readFile } from "node:fs/promises";
|
||
import { test } from "node:test";
|
||
import { annotateMarkdown, markdownRefs } from "./markdown-refs.mjs";
|
||
|
||
const tag = (ref) => `<${ref}>`;
|
||
|
||
test("a reference is written at line start or after whitespace, a parenthesis or a list separator", () => {
|
||
const source = ["#1 修复", "- 见 #2", "- 修复(#3、#4)与 (#5, #6),#7", "- 列表(#8,#9)"].join("\n");
|
||
assert.deepEqual(markdownRefs(source), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||
assert.equal(
|
||
annotateMarkdown(source, tag),
|
||
["#1<1> 修复", "- 见 #2<2>", "- 修复(#3<3>、#4<4>)与 (#5<5>, #6<6>),#7<7>", "- 列表(#8<8>,#9<9>)"].join("\n"),
|
||
);
|
||
});
|
||
|
||
test("colours, entities, paths, anchors and escapes are not references", () => {
|
||
const source = [
|
||
"- 颜色#333 与 color:#123456 与 #333abc 与 #12-a",
|
||
"- 与 a/#11 与 \\#12 与 [段落](#13) 与 [见](https://x/#14)",
|
||
].join("\n");
|
||
assert.deepEqual(markdownRefs(source), []);
|
||
assert.equal(annotateMarkdown(source, tag), source);
|
||
});
|
||
|
||
test("code spans, fences of either kind and indented code are skipped", () => {
|
||
const source = [
|
||
"- `#1` 与 ``a `#2` b`` 之外 #3",
|
||
"```",
|
||
"#4",
|
||
"~~~",
|
||
"#5",
|
||
"```",
|
||
"#6",
|
||
"~~~~",
|
||
"#7",
|
||
"```",
|
||
"#8",
|
||
"~~~~~",
|
||
"#9",
|
||
"",
|
||
" #10 indented code",
|
||
" #11 still code",
|
||
"#12",
|
||
].join("\n");
|
||
assert.deepEqual(markdownRefs(source), [3, 6, 9, 12]);
|
||
});
|
||
|
||
test("indentation inside a list item is a continuation, not code", () => {
|
||
const source = ["- 第一项", "", " 续行提到 #1", "", "段落", "", " #2 is code"].join("\n");
|
||
assert.deepEqual(markdownRefs(source), [1]);
|
||
});
|
||
|
||
test("HTML comments hide references on one line or across several", () => {
|
||
const source = ["- 可见 #1 <!-- 隐藏 #2 --> 可见 #3", "<!--", "#4", "隐藏 #5 -->", "#6 <!-- #7"].join("\n");
|
||
assert.deepEqual(markdownRefs(source), [1, 3, 6]);
|
||
});
|
||
|
||
test("annotating leaves every other byte in place", async () => {
|
||
const dir = new URL("../release-notes/studio/", import.meta.url);
|
||
for (const name of await readdir(dir)) {
|
||
const source = await readFile(new URL(name, dir), "utf8");
|
||
assert.equal(annotateMarkdown(source, () => ""), source, name);
|
||
assert.equal(annotateMarkdown(source, tag).replace(/<\d+>/g, ""), source, name);
|
||
}
|
||
});
|