-
Notifications
You must be signed in to change notification settings - Fork 537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(build-cli): New command transform:releaseNotes #22466
Changes from 23 commits
7d9425d
15d36fb
d8a5e18
a8083e1
335f473
58549ea
9b7d2d6
86424b1
8fde443
2e81fa0
5184d18
5d49bb4
712b964
88aafea
3527f83
2221ff1
bd3e3f6
88ac563
fe487b2
7c45b39
62523e9
a72b558
9d65d31
fc88b0a
c8535f2
7849958
1664b8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
`flub transform` | ||
================ | ||
|
||
Transform commands are used to transform code, docs, etc. into alternative forms. | ||
|
||
* [`flub transform releaseNotes`](#flub-transform-releasenotes) | ||
|
||
## `flub transform releaseNotes` | ||
|
||
Transforms a markdown release notes file into a format appropriate for use in a GitHub Release. This is used to transform in-repo release notes such that they can be automatically posted to our GitHub Releases. | ||
|
||
``` | ||
USAGE | ||
$ flub transform releaseNotes --inFile <value> --outFile <value> [-v | --quiet] | ||
|
||
FLAGS | ||
--inFile=<value> (required) A release notes file that was generated using 'flub generate releaseNotes'. | ||
--outFile=<value> (required) Output the transformed content to this file. | ||
|
||
LOGGING FLAGS | ||
-v, --verbose Enable verbose logging. | ||
--quiet Disable all logging. | ||
|
||
EXAMPLES | ||
Transform the release notes from version 2.2.0 and output the results to out.md. | ||
|
||
$ flub transform releaseNotes --inFile RELEASE_NOTES/2.2.0.md --outFile out.md | ||
``` | ||
|
||
_See code: [src/commands/transform/releaseNotes.ts](https://github.com/microsoft/FluidFramework/blob/main/build-tools/packages/build-cli/src/commands/transform/releaseNotes.ts)_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/*! | ||
* Copyright (c) Microsoft Corporation and contributors. All rights reserved. | ||
* Licensed under the MIT License. | ||
*/ | ||
|
||
import { readFile, writeFile } from "node:fs/promises"; | ||
import { Flags } from "@oclif/core"; | ||
import { format as prettier } from "prettier"; | ||
import { remark } from "remark"; | ||
import remarkGfm from "remark-gfm"; | ||
import remarkGithub, { defaultBuildUrl } from "remark-github"; | ||
import admonitions from "remark-github-beta-blockquote-admonitions"; | ||
import remarkToc from "remark-toc"; | ||
|
||
import { BaseCommand } from "../../library/index.js"; | ||
import { | ||
addHeadingLinks, | ||
removeHeadingsAtLevel, | ||
removeSectionContent, | ||
stripSoftBreaks, | ||
updateTocLinks, | ||
// eslint-disable-next-line import/no-internal-modules | ||
} from "../../library/markdown.js"; | ||
// eslint-disable-next-line import/no-internal-modules | ||
import { RELEASE_NOTES_TOC_LINK_TEXT } from "../../library/releaseNotes.js"; | ||
|
||
/** | ||
* Transforms a markdown release notes file into a format appropriate for use in a GitHub Release. | ||
*/ | ||
export default class TransformReleaseNotesCommand extends BaseCommand< | ||
typeof TransformReleaseNotesCommand | ||
> { | ||
static readonly summary = | ||
`Transforms a markdown release notes file into a format appropriate for use in a GitHub Release. This is used to transform in-repo release notes such that they can be automatically posted to our GitHub Releases.`; | ||
|
||
static readonly flags = { | ||
inFile: Flags.file({ | ||
description: `A release notes file that was generated using 'flub generate releaseNotes'.`, | ||
required: true, | ||
exists: true, | ||
}), | ||
outFile: Flags.file({ | ||
description: `Output the transformed content to this file.`, | ||
required: true, | ||
}), | ||
...BaseCommand.flags, | ||
} as const; | ||
|
||
static readonly examples = [ | ||
{ | ||
description: `Transform the release notes from version 2.2.0 and output the results to out.md.`, | ||
command: | ||
"<%= config.bin %> <%= command.id %> --inFile RELEASE_NOTES/2.2.0.md --outFile out.md", | ||
}, | ||
]; | ||
|
||
public async run(): Promise<string> { | ||
const { inFile, outFile } = this.flags; | ||
const input = await readFile(inFile, { encoding: "utf8" }); | ||
const processor = remark() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any chance of refactoring common bits between this and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't found a great way to do that yet, but I am looking. The problem is that the order of the pipeline matters, and the typing is complex enough that I haven't successfully modularized a "chunk" of the pipeline - only the individual plugins/functions. I am positive this is possible and I just haven't found a workable pattern yet. |
||
// Remove the H1 if it exists. | ||
.use(removeHeadingsAtLevel, { level: 1 }) | ||
// Remove the existing TOC section because its links are incorrect; we'll regenerate it. | ||
.use(removeSectionContent, { heading: "Contents" }) | ||
// Update the "back to TOC" links to prepend 'user-content-' because that's what GH Releases does. | ||
.use(updateTocLinks, { | ||
checkValue: RELEASE_NOTES_TOC_LINK_TEXT, | ||
newUrl: "#user-content-contents", | ||
}) | ||
// Parse the markdown as GitHub-Flavored Markdown | ||
.use(remarkGfm) | ||
// Strip any single-line breaks. See the docs for the stripSoftBreaks function for more details. | ||
.use(stripSoftBreaks) | ||
// Parse any GitHub admonitions/alerts/callouts | ||
.use(admonitions, { | ||
titleTextMap: (title) => ({ | ||
// By default the `[!` prefix and `]` suffix are removed; we don't want that, so we override the default and | ||
// return the title as-is. | ||
displayTitle: title, | ||
checkedTitle: title, | ||
}), | ||
}) | ||
// Regenerate the TOC with the user-content- prefix. | ||
.use(remarkToc, { | ||
maxDepth: 3, | ||
skip: ".*Start Building Today.*", | ||
// Add the user-content- prefix to the links when we generate our own headingLinks, because GitHub will | ||
// prepend that to all our custom anchor IDs. | ||
prefix: "user-content-", | ||
}) | ||
// Transform any issue and commit references into links. | ||
.use(remarkGithub, { | ||
buildUrl(values) { | ||
// Disable linking mentions | ||
return values.type === "mention" ? false : defaultBuildUrl(values); | ||
}, | ||
}) | ||
// Add custom anchor tags with IDs to all the headings. | ||
.use(addHeadingLinks); | ||
|
||
const contents = String(await processor.process(input)); | ||
|
||
this.info(`Writing output file: ${outFile}`); | ||
await writeFile( | ||
outFile, | ||
await prettier(contents, { proseWrap: "never", parser: "markdown" }), | ||
); | ||
|
||
return contents; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/*! | ||
* Copyright (c) Microsoft Corporation and contributors. All rights reserved. | ||
* Licensed under the MIT License. | ||
*/ | ||
|
||
/** | ||
* The text used in release notes links that point back to the table of contents in the document. | ||
*/ | ||
export const RELEASE_NOTES_TOC_LINK_TEXT = "⬆️ Table of contents"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the motivation here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had some trouble debugging since all the artifacts were gone. Now that we're releasing ~monthly, this felt like a reasonable time period to ensure there would usually be an artifact around to use for investigation/debugging. The file is also super small. Regardless, though, debugging was my main reason. Probably worth a comment.