Skip to content

Commit b8e68c1

Browse files
nzakasbtmills
andauthored
docs: Update release process (#16036)
* docs: Update release process * Removed dateformat dependency * Ensure blog post is published * Update templates/formatter-examples.md.ejs Co-authored-by: Brandon Mills <[email protected]> Co-authored-by: Brandon Mills <[email protected]>
1 parent 48904fb commit b8e68c1

File tree

8 files changed

+845
-186
lines changed

8 files changed

+845
-186
lines changed

Makefile.js

Lines changed: 48 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
const checker = require("npm-license"),
1414
ReleaseOps = require("eslint-release"),
15-
dateformat = require("dateformat"),
1615
fs = require("fs"),
1716
glob = require("glob"),
1817
marked = require("marked"),
@@ -33,7 +32,7 @@ require("shelljs/make");
3332
* @see https://github.com/shelljs/shelljs/blob/124d3349af42cb794ae8f78fc9b0b538109f7ca7/make.js#L4
3433
* @see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3aa2d09b6408380598cfb802743b07e1edb725f3/types/shelljs/make.d.ts#L8-L11
3534
*/
36-
const { cat, cd, cp, echo, exec, exit, find, ls, mkdir, pwd, rm, test } = require("shelljs");
35+
const { cat, cd, echo, exec, exit, find, ls, mkdir, pwd, test } = require("shelljs");
3736

3837
//------------------------------------------------------------------------------
3938
// Settings
@@ -60,8 +59,10 @@ const NODE = "node ", // intentional extra space
6059
TEMP_DIR = "./tmp/",
6160
DEBUG_DIR = "./debug/",
6261
BUILD_DIR = "build",
63-
DOCS_DIR = "../website/docs",
64-
SITE_DIR = "../website/",
62+
SITE_DIR = "../eslint.org",
63+
DOCS_DIR = "./docs",
64+
DOCS_SRC_DIR = path.join(DOCS_DIR, "src"),
65+
DOCS_DATA_DIR = path.join(DOCS_SRC_DIR, "_data"),
6566
PERF_TMP_DIR = path.join(TEMP_DIR, "eslint", "performance"),
6667

6768
// Utilities - intentional extra space at the end of each string
@@ -144,32 +145,27 @@ function generateBlogPost(releaseInfo, prereleaseMajorVersion) {
144145
now = new Date(),
145146
month = now.getMonth() + 1,
146147
day = now.getDate(),
147-
filename = `../website/_posts/${now.getFullYear()}-${
148+
filename = path.join(SITE_DIR, `src/content/blog/${now.getFullYear()}-${
148149
month < 10 ? `0${month}` : month}-${
149150
day < 10 ? `0${day}` : day}-eslint-v${
150-
releaseInfo.version}-released.md`;
151+
releaseInfo.version}-released.md`);
151152

152153
output.to(filename);
153154
}
154155

155156
/**
156157
* Generates a doc page with formatter result examples
157158
* @param {Object} formatterInfo Linting results from each formatter
158-
* @param {string} [prereleaseVersion] The version used for a prerelease. This
159-
* changes where the output is stored.
160159
* @returns {void}
161160
*/
162-
function generateFormatterExamples(formatterInfo, prereleaseVersion) {
161+
function generateFormatterExamples(formatterInfo) {
163162
const output = ejs.render(cat("./templates/formatter-examples.md.ejs"), formatterInfo);
164-
let filename = "../website/docs/user-guide/formatters/index.md",
165-
htmlFilename = "../website/docs/user-guide/formatters/html-formatter-example.html";
166-
167-
if (prereleaseVersion) {
168-
filename = filename.replace("/docs", `/docs/${prereleaseVersion}`);
169-
htmlFilename = htmlFilename.replace("/docs", `/docs/${prereleaseVersion}`);
170-
if (!test("-d", path.dirname(filename))) {
171-
mkdir(path.dirname(filename));
172-
}
163+
const outputDir = path.join(DOCS_SRC_DIR, "user-guide/formatters/"),
164+
filename = path.join(outputDir, "index.md"),
165+
htmlFilename = path.join(outputDir, "html-formatter-example.html");
166+
167+
if (!test("-d", outputDir)) {
168+
mkdir(outputDir);
173169
}
174170

175171
output.to(filename);
@@ -181,9 +177,8 @@ function generateFormatterExamples(formatterInfo, prereleaseVersion) {
181177
* @returns {void}
182178
*/
183179
function generateRuleIndexPage() {
184-
const legacyWebsiteOutputFile = "../website/_data/rules.yml",
185-
docsSiteOutputFile = "docs/src/_data/rules.json",
186-
docsSiteMetaOutputFile = "docs/src/_data/rules_meta.json",
180+
const docsSiteOutputFile = path.join(DOCS_DATA_DIR, "rules.json"),
181+
docsSiteMetaOutputFile = path.join(DOCS_DATA_DIR, "rules_meta.json"),
187182
ruleTypes = "conf/rule-type-list.json",
188183
ruleTypesData = JSON.parse(cat(path.resolve(ruleTypes)));
189184

@@ -240,9 +235,6 @@ function generateRuleIndexPage() {
240235
JSON.stringify(ruleTypesData, null, 4).to(docsSiteOutputFile);
241236
JSON.stringify(meta, null, 4).to(docsSiteMetaOutputFile);
242237

243-
const legacyOutput = yaml.dump(ruleTypesData, { sortKeys: true });
244-
245-
legacyOutput.to(legacyWebsiteOutputFile);
246238
}
247239

248240
/**
@@ -256,26 +248,22 @@ function commitSiteToGit(tag) {
256248

257249
cd(SITE_DIR);
258250
exec("git add -A .");
259-
exec(`git commit -m "Autogenerated new docs and demo at ${dateformat(new Date())}"`);
260-
261-
if (tag) {
262-
exec(`git tag ${tag}`);
263-
}
264-
265-
exec("git fetch origin && git rebase origin/master");
251+
exec(`git commit -m "Added release blog post for ${tag}"`);
252+
exec(`git tag ${tag}`);
253+
exec("git fetch origin && git rebase origin/main");
266254
cd(currentDir);
267255
}
268256

269257
/**
270-
* Publishes the changes in an adjacent `website` repository to the remote. The
258+
* Publishes the changes in an adjacent `eslint.org` repository to the remote. The
271259
* site should already have local commits (e.g. from running `commitSiteToGit`).
272260
* @returns {void}
273261
*/
274262
function publishSite() {
275263
const currentDir = pwd();
276264

277265
cd(SITE_DIR);
278-
exec("git push origin master --tags");
266+
exec("git push origin HEAD --tags");
279267
cd(currentDir);
280268
}
281269

@@ -294,7 +282,7 @@ function generateRelease() {
294282
commitSiteToGit(`v${releaseInfo.version}`);
295283

296284
echo("Updating commit with docs data");
297-
exec("git add docs/src/_data && git commit --amend --no-edit");
285+
exec("git add docs/ && git commit --amend --no-edit");
298286
exec(`git tag -a -f v${releaseInfo.version} -m ${releaseInfo.version}`);
299287
}
300288

@@ -636,60 +624,14 @@ target.test = function() {
636624
target.checkLicenses();
637625
};
638626

639-
target.gensite = function(prereleaseVersion) {
640-
echo("Generating eslint.org");
641-
642-
let docFiles = [
643-
"/rules/",
644-
"/user-guide/",
645-
"/maintainer-guide/",
646-
"/developer-guide/",
647-
"/about/"
648-
];
649-
650-
// append version
651-
if (prereleaseVersion) {
652-
docFiles = docFiles.map(docFile => `/${prereleaseVersion}${docFile}`);
653-
}
654-
655-
// 1. create temp and build directory
656-
echo("> Creating a temporary directory (Step 1)");
657-
if (!test("-d", TEMP_DIR)) {
658-
mkdir(TEMP_DIR);
659-
}
660-
661-
// 2. remove old files from the site
662-
echo("> Removing old files (Step 2)");
663-
docFiles.forEach(filePath => {
664-
const fullPath = path.join(DOCS_DIR, filePath),
665-
htmlFullPath = fullPath.replace(".md", ".html");
666-
667-
if (test("-f", fullPath)) {
668-
rm("-rf", fullPath);
627+
target.gensite = function() {
628+
echo("Generating documentation");
669629

670-
if (filePath.includes(".md") && test("-f", htmlFullPath)) {
671-
rm("-rf", htmlFullPath);
672-
}
673-
}
674-
});
675-
676-
// 3. Copy docs folder to a temporary directory
677-
echo("> Copying the docs folder (Step 3)");
678-
docFiles.forEach(filePath => {
679-
const pathToCopy = path.join("docs/src", filePath, "*"),
680-
tempPath = path.join(TEMP_DIR, filePath);
681-
682-
if (!test("-d", tempPath)) {
683-
mkdir(tempPath);
684-
}
685-
686-
cp("-rf", pathToCopy, tempPath);
687-
});
630+
const DOCS_RULES_DIR = path.join(DOCS_SRC_DIR, "rules");
631+
const RULE_VERSIONS_FILE = path.join(DOCS_SRC_DIR, "_data/rule_versions.json");
688632

689-
// special case (for now)
690-
rm("-rf", path.join(TEMP_DIR, "pages"));
691-
692-
let versions = test("-f", "./versions.json") ? JSON.parse(cat("./versions.json")) : {};
633+
// Set up rule version information
634+
let versions = test("-f", RULE_VERSIONS_FILE) ? JSON.parse(cat(RULE_VERSIONS_FILE)) : {};
693635

694636
if (!versions.added) {
695637
versions = {
@@ -698,117 +640,41 @@ target.gensite = function(prereleaseVersion) {
698640
};
699641
}
700642

701-
const { Linter } = require(".");
702-
const rules = new Linter().getRules();
703-
704-
const RECOMMENDED_TEXT = "\n\n(recommended) The `\"extends\": \"eslint:recommended\"` property in a configuration file enables this rule.";
705-
const FIXABLE_TEXT = "\n\n(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.";
706-
const HAS_SUGGESTIONS_TEXT = "\n\n(hasSuggestions) Some problems reported by this rule are manually fixable by editor [suggestions](../developer-guide/working-with-rules#providing-suggestions).";
707-
708-
// 4. Loop through all files in temporary directory
709-
process.stdout.write("> Updating files (Steps 4-9): 0/... - ...\r");
710-
const tempFiles = find(TEMP_DIR);
711-
const length = tempFiles.length;
643+
// 1. Update rule meta data by checking rule docs - important to catch removed rules
644+
echo("> Updating rule version meta data (Step 1)");
645+
const ruleDocsFiles = find(DOCS_RULES_DIR);
712646

713-
tempFiles.forEach((filename, i) => {
647+
ruleDocsFiles.forEach((filename, i) => {
714648
if (test("-f", filename) && path.extname(filename) === ".md") {
715649

716-
const rulesUrl = "https://github.com/eslint/eslint/tree/HEAD/lib/rules/",
717-
testsUrl = "https://github.com/eslint/eslint/tree/HEAD/tests/lib/rules/",
718-
docsUrl = "https://github.com/eslint/eslint/tree/HEAD/docs/src/rules/",
719-
baseName = path.basename(filename),
720-
sourceBaseName = `${path.basename(filename, ".md")}.js`,
721-
sourcePath = path.join("lib/rules", sourceBaseName),
722-
ruleName = path.basename(filename, ".md"),
723-
filePath = path.posix.join("docs", path.relative("tmp", filename));
724-
let text = cat(filename);
725-
726-
process.stdout.write(`> Updating files (Steps 4-9): ${i}/${length} - ${filePath + " ".repeat(30)}\r`);
727-
728-
// 5. Prepend page title and layout variables at the top of rules
729-
if (path.dirname(filename).includes("rules")) {
730-
731-
// Find out if the rule requires a special docs portion (e.g. if it is recommended and/or fixable)
732-
const rule = rules.get(ruleName);
733-
const isRecommended = rule && rule.meta.docs.recommended;
734-
const isFixable = rule && rule.meta.fixable;
735-
const hasSuggestions = rule && rule.meta.hasSuggestions;
650+
echo(`> Updating rule version meta data (Step 1: ${i + 1}/${ruleDocsFiles.length}): ${filename}`);
736651

737-
text = text.replace("<!--FIXABLE-->", isFixable ? FIXABLE_TEXT : "")
738-
.replace("<!--SUGGESTIONS-->", hasSuggestions ? HAS_SUGGESTIONS_TEXT : "")
739-
.replace("<!--RECOMMENDED-->", isRecommended ? RECOMMENDED_TEXT : "");
652+
const baseName = path.basename(filename, ".md"),
653+
sourceBaseName = `${baseName}.js`,
654+
sourcePath = path.join("lib/rules", sourceBaseName);
740655

656+
if (!versions.added[baseName]) {
657+
versions.added[baseName] = getFirstVersionOfFile(sourcePath);
741658
}
742659

743-
// 6. Remove .md extension for relative links and change README to empty string
744-
text = text.replace(/\((?!https?:\/\/)([^)]*?)\.md(.*?)\)/gu, "($1$2)").replace("README.html", "");
745-
746-
// 7. Check if there's a trailing white line at the end of the file, if there isn't one, add it
747-
if (!/\n$/u.test(text)) {
748-
text = `${text}\n`;
660+
if (!versions.removed[baseName] && !test("-f", sourcePath)) {
661+
versions.removed[baseName] = getFirstVersionOfDeletion(sourcePath);
749662
}
750663

751-
// 8. Append first version of ESLint rule was added at.
752-
if (filename.includes("rules/")) {
753-
if (!versions.added[baseName]) {
754-
versions.added[baseName] = getFirstVersionOfFile(sourcePath);
755-
}
756-
const added = versions.added[baseName];
757-
758-
if (!versions.removed[baseName] && !test("-f", sourcePath)) {
759-
versions.removed[baseName] = getFirstVersionOfDeletion(sourcePath);
760-
}
761-
const removed = versions.removed[baseName];
762-
763-
text += "\n## Version\n\n";
764-
text += removed
765-
? `This rule was introduced in ESLint ${added} and removed in ${removed}.\n`
766-
: `This rule was introduced in ESLint ${added}.\n`;
767-
768-
text += "\n## Resources\n\n";
769-
if (!removed) {
770-
text += `* [Rule source](${rulesUrl}${sourceBaseName})\n`;
771-
text += `* [Test source](${testsUrl}${sourceBaseName})\n`;
772-
}
773-
text += `* [Documentation source](${docsUrl}${baseName})\n`;
774-
}
775-
776-
// 9. Update content of the file with changes
777-
text.to(filename.replace("README.md", "index.md"));
778664
}
779665
});
780-
JSON.stringify(versions).to("./versions.json");
781-
echo(`> Updating files (Steps 4-9)${" ".repeat(50)}`);
782-
783-
// 10. Copy temporary directory to site's docs folder
784-
echo("> Copying the temporary directory into the site's docs folder (Step 10)");
785-
let outputDir = DOCS_DIR;
786666

787-
if (prereleaseVersion) {
788-
outputDir += `/${prereleaseVersion}`;
789-
if (!test("-d", outputDir)) {
790-
mkdir(outputDir);
791-
}
792-
}
793-
cp("-rf", `${TEMP_DIR}*`, outputDir);
794-
795-
// 11. Generate rules index page
796-
if (prereleaseVersion) {
797-
echo("> Skipping generating rules index page because this is a prerelease (Step 11)");
798-
} else {
799-
echo("> Generating the rules index page (Step 11)");
800-
generateRuleIndexPage();
801-
}
667+
JSON.stringify(versions, null, 4).to(RULE_VERSIONS_FILE);
802668

803-
// 12. Delete temporary directory
804-
echo("> Removing the temporary directory (Step 12)");
805-
rm("-rf", TEMP_DIR);
669+
// 2. Generate rules index page meta data
670+
echo("> Generating the rules index page (Step 2)");
671+
generateRuleIndexPage();
806672

807-
// 13. Create Example Formatter Output Page
808-
echo("> Creating the formatter examples (Step 14)");
809-
generateFormatterExamples(getFormatterResults(), prereleaseVersion);
673+
// 3. Create Example Formatter Output Page
674+
echo("> Creating the formatter examples (Step 3)");
675+
generateFormatterExamples(getFormatterResults());
810676

811-
echo("Done generating eslint.org");
677+
echo("Done generating documentation");
812678
};
813679

814680
target.generateRuleIndexPage = generateRuleIndexPage;

0 commit comments

Comments
 (0)