-
Notifications
You must be signed in to change notification settings - Fork 43
feat(#857): readme-automation #887
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
base: master
Are you sure you want to change the base?
Changes from 4 commits
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,44 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2022-2026 Objectionary.com | ||
| # SPDX-License-Identifier: MIT | ||
| --- | ||
| # yamllint disable rule:line-length | ||
| name: readme-automation | ||
|
|
||
| 'on': | ||
| workflow_dispatch: | ||
| push: | ||
| paths: | ||
| - "src/eoc.js" | ||
| concurrency: | ||
| group: readmeautomation-${{ github.ref }} | ||
| cancel-in-progress: true | ||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-24.04 | ||
|
|
||
| steps: | ||
| - name: Check out repo | ||
| uses: actions/checkout@v6 | ||
| - name: Use Node | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: "18.x" | ||
| check-latest: false | ||
| - name: Clean install | ||
| run: npm ci | ||
| - name: Install global | ||
| run: npm install -g | ||
| - name: Run readme_automation script | ||
| run: |- | ||
| node scripts/readme_automation/readme_automation_run.js | ||
| - name: Create Pull Request | ||
| uses: peter-evans/create-pull-request@v8 | ||
| with: | ||
| commit-message: "chore(readme): insert sections into README from CLI help" | ||
| branch: chore/readme-automation | ||
| title: "chore(readme): insert sections into README from CLI help" | ||
| body: | | ||
| This PR was automatically generated by GitHub Actions. | ||
|
|
||
| - Insert sections into README from CLI help output | ||
| - Keeps documentation in sync with the CLI |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/usr/bin/env node | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2022-2026 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
|
|
||
| function escapeRegex(str) { | ||
| return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); | ||
| } | ||
|
|
||
| function updateSection(sectionName, newContent, readMeContent) { | ||
| const start = `<!-- BEGIN ${sectionName.toUpperCase()} SECTION -->`; | ||
| const end = `<!-- END ${sectionName.toUpperCase()} SECTION -->`; | ||
| const regex = new RegExp( | ||
| `(${escapeRegex(start)})([\\s\\S]*?)(${escapeRegex(end)})`, | ||
| "g" | ||
| ); | ||
| return readMeContent.replace(regex, `$1\n${newContent}$3`); | ||
| } | ||
|
|
||
| function bulletListTemplate(rows) { | ||
| const list = rows.map(([cmd, desc]) => `* \`${cmd}\` ${desc}`); | ||
|
Member
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. @paskhalov Is it possible to inline redundant variables? https://www.yegor256.com/2015/09/01/redundant-variables-are-evil.html
Author
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 will think about it. |
||
| return `${list.join("\n") }\n`; | ||
| } | ||
|
|
||
| function parseBlock(block_name,text) { | ||
| const lines = text.split("\n"); | ||
| let inBlock = false; | ||
| const rows = []; | ||
| for (const line of lines) { | ||
| if (line.trim() === block_name) { | ||
| inBlock = true; | ||
| } | ||
| else if (inBlock) { | ||
| if (!line.trim()) {break;} | ||
| const parts = line.trim().split(/\s{2,}/); | ||
| const cmd = parts[0]; | ||
| const desc = parts.slice(1).join(" ") || ""; | ||
| rows.push([cmd, desc]); | ||
| } | ||
| } | ||
| if (!rows.length) { | ||
| throw new Error('no data something wrong'); | ||
| } | ||
| return rows; | ||
| } | ||
|
|
||
| module.exports = { | ||
| parseBlock, bulletListTemplate, updateSection | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #!/usr/bin/env node | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2022-2026 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
|
|
||
| const fs = require("fs"); | ||
| const assert = require('assert'); | ||
| const { parseBlock, bulletListTemplate, updateSection } = require("./help_to_markdown"); | ||
| const { getHelp } = require("../../src/eoc"); | ||
|
|
||
| function main () { | ||
| let help_text = getHelp(); | ||
| help_text = help_text.replace(/\r\n/g, "\n"); | ||
| assert.ok(["Options:","Commands:"].every(sub => help_text.includes(sub)),'"eoc --help" should includes Commands and Options'); | ||
| const commands = parseBlock('Commands:',help_text); | ||
| assert.ok(commands.length > 0,'Commands should have rows') | ||
| const commandsMarkdown = bulletListTemplate(commands); | ||
| assert.ok(commandsMarkdown.length > 0,"commandsMarkdown result should have text") | ||
| let readMeContent = fs.readFileSync('README.md', "utf8"); | ||
| assert.ok(readMeContent.length > 0,"readMeContent should have text") | ||
| readMeContent = updateSection('commands', commandsMarkdown, readMeContent); | ||
| assert.ok(readMeContent.length > 0,"readMeContent should sill have text after modification") | ||
| fs.writeFileSync('README.md',readMeContent); | ||
| } | ||
|
|
||
| if (require.main === module) { | ||
| main(); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -394,12 +394,18 @@ program.command('fmt') | |
| }); | ||
| }); | ||
|
|
||
| try { | ||
| program.parse(process.argv); | ||
| } catch (e) { | ||
| console.error(e.message); | ||
| console.debug(e.stack); | ||
| process.exit(1); | ||
| if (require.main === module) { | ||
| try { | ||
| program.parse(process.argv); | ||
| } catch (e) { | ||
| console.error(e.message); | ||
| console.debug(e.stack); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| module.exports.getHelp = function getHelp() { | ||
|
Member
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. @paskhalov can we just name it https://www.yegor256.com/2015/01/12/compound-name-is-code-smell.html
Author
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. Ok, I understand the idea. I will put a comment section that will notice that methods follow CLI interface. |
||
| return program.helpInformation(); | ||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2022-2026 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
|
|
||
| const assert = require("assert"); | ||
| const path = require("path"); | ||
| const { parseBlock, updateSection, bulletListTemplate } = require(path.join(__dirname, "../scripts/readme_automation/help_to_markdown.js")); | ||
|
|
||
| describe("readme_automation scripts", () => { | ||
|
Member
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. @paskhalov In these tests, you check how
Author
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. Just one test, delete the rest?
Member
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. @paskhalov I'm not sure about a single test, but we need one function.
Author
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. Ok, got it |
||
| it("parseBlock builds a markdown table from a help block", () => { | ||
| const text = `\nUsage: eoc [options] [command]\nCommands:\n foo does foo\n bar does bar\n\nOptions:\n -h, --help output help`; | ||
| const res = parseBlock("Commands:", text); | ||
| assert.deepEqual(res,[['foo','does foo'],['bar','does bar']]); | ||
| const res2 = parseBlock("Options:", text); | ||
|
Member
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. @paskhalov Please, give more meaningful variable names rather than
Author
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. Ok, sure |
||
| assert.deepEqual(res2,[['-h, --help','output help']] ); | ||
| }); | ||
| it("parseBlock throws when no rows are found", () => { | ||
| assert.throws( | ||
| () => parseBlock("Commands:", ""), | ||
| /no data/ | ||
| ); | ||
| }); | ||
| it("updateSection replaces only the requested section", () => { | ||
| const readme = `before\n<!-- BEGIN COMMANDS SECTION -->\nold\n<!-- END COMMANDS SECTION -->\n<!-- BEGIN OPTIONS SECTION -->\nkeep\n<!-- END OPTIONS SECTION -->\nafter` | ||
| const updated = updateSection("commands", "new content", readme); | ||
| assert.ok(!updated.includes("old")); | ||
| assert.ok(["new content","keep","after","before","<!-- BEGIN COMMANDS SECTION -->"].every(sub => updated.includes(sub))); | ||
| }); | ||
| it("bulletListTemplate renders a list", async () => { | ||
| const output = bulletListTemplate([['one','a'],['two','b'],['three','c']]); | ||
| assert.strictEqual(output, "* `one` a\n* `two` b\n* `three` c\n"); | ||
| }); | ||
| }); | ||
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.
@paskhalov I don't think a separate file for
help_to_markdown.jsis necessary. Can we put everything insidereadme_automation.js?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.
Yea sure, I will follow YAGNI more. Basically the separated file exists if the code is needed in another projects.