MCPcopy Create free account
hub / github.com/dmno-dev/bumpy / createGithubFormatter

Function createGithubFormatter

packages/bumpy/src/core/changelog-github.ts:49–151  ·  view source on GitHub ↗
(options: GithubChangelogOptions = {})

Source from the content-addressed store, hash-verified

47 * "changelog": ["github", { "internalAuthors": ["theoephraim"] }]
48 */
49export function createGithubFormatter(options: GithubChangelogOptions = {}): ChangelogFormatter {
50 const includeCommitLink = options.includeCommitLink ?? false;
51 const thankContributors = options.thankContributors ?? true;
52 const internalAuthorsSet = new Set(
53 [...DEFAULT_INTERNAL_AUTHORS, ...(options.internalAuthors ?? [])].map((a) => a.toLowerCase()),
54 );
55
56 return async (ctx: ChangelogContext) => {
57 const { release, bumpFiles, date } = ctx;
58 const repoSlug = options.repo ?? detectRepo();
59 const serverUrl = process.env.GITHUB_SERVER_URL || 'https://github.com';
60
61 const lines: string[] = [];
62 lines.push(`## ${release.newVersion}`);
63 lines.push(`<sub>${date}</sub>`);
64 lines.push('');
65
66 const relevantBumpFiles = bumpFiles.filter((bf) => release.bumpFiles.includes(bf.id));
67 const sorted = sortBumpFilesByType(relevantBumpFiles, release.name);
68
69 for (const bf of sorted) {
70 if (!bf.summary || isChangelogSuppressed(bf, release.name)) continue;
71
72 const type = getBumpTypeForPackage(bf, release.name);
73 const tag = ` *(${type})*`;
74
75 // Extract metadata overrides from summary (pr, commit, author lines)
76 const { cleanSummary, overrides } = extractSummaryMeta(bf.summary);
77
78 // Look up git/PR info, with overrides taking precedence
79 const gitInfo = resolveBumpFileInfo(bf.id, repoSlug, serverUrl, overrides);
80
81 const summaryLines = trimBlankEdges(cleanSummary.split('\n'));
82 const linkify = (s: string) => linkifyIssueRefs(s, serverUrl, repoSlug);
83
84 // Build the prefix: PR link, commit link, thanks
85 const { links, thanks } = formatPrefix(
86 gitInfo,
87 serverUrl,
88 repoSlug,
89 includeCommitLink,
90 thankContributors,
91 internalAuthorsSet,
92 );
93
94 // Assemble metadata: links, tag, thanks
95 const parts = [links, tag, thanks].filter(Boolean);
96 const hasMeta = parts.length > 0;
97 const meta = parts.join(' ');
98
99 if (summaryLines.length === 0) {
100 // Metadata only (e.g. summary was just `pr:`/`author:` lines)
101 if (hasMeta) lines.push(`- ${meta}`);
102 } else if (hasMeta && summaryNeedsBlockLayout(cleanSummary)) {
103 // Long/multiline/markdown summary reads poorly inline — put it on its own
104 // line(s) below the metadata.
105 lines.push(`- ${meta}`);
106 for (const sl of summaryLines) {

Callers 3

changelog.tsFile · 0.85
loadFormatterFunction · 0.85

Calls 11

sortBumpFilesByTypeFunction · 0.90
isChangelogSuppressedFunction · 0.90
getBumpTypeForPackageFunction · 0.90
trimBlankEdgesFunction · 0.90
summaryNeedsBlockLayoutFunction · 0.90
maxBumpFunction · 0.90
extractSummaryMetaFunction · 0.85
resolveBumpFileInfoFunction · 0.85
formatPrefixFunction · 0.85
linkifyFunction · 0.85
detectRepoFunction · 0.70

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…