From a858fade68261d33b8c91977bbe3c77f1d39521d Mon Sep 17 00:00:00 2001 From: Charles Lehnert Date: Thu, 15 Jun 2023 12:22:51 -0400 Subject: [PATCH 1/2] feat: Add 'infile' option --- README.md | 3 ++- action.yml | 6 ++++- src/helpers/generateChangelog.js | 44 ++++++++++++++++++++++++++++---- src/index.js | 7 ++++- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d520c87..780a549 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ This action will bump version, tag commit and generate a changelog with conventi - **Optional** `git-path`: Path filter for the logs. If set, only commits that match the path filter will be considered. By default, we won't use this feature(empty string). - **Optional** `preset`: Preset that is used from conventional commits. Default `angular`. - **Optional** `tag-prefix`: Prefix for the git tags. Default `v`. +- **Optional** `input-file`: Read the changelog from this file. This will prepend the newly generated changelogs to the file's content. - **Optional** `output-file`: File to output the changelog to. Default `CHANGELOG.md`, when providing `'false'` no file will be generated / updated. -- **Optional** `release-count`: Number of releases to preserve in changelog. Default `5`, use `0` to regenerate all. +- **Optional** `release-count`: Number of releases to preserve in changelog. Default `5`, use `0` to regenerate all. This input has no effect if `input-file` is used. - **Optional** `version-file`: The path to the file that contains the version to bump (supports comma-separated list of file paths). Default `./package.json`. - **Optional** `version-path`: The place inside the version file to bump. Default `version`. - **Optional** `skip-git-pull`: Do not pull the repo before tagging. Ensure you full cloned the repo in the first place to get tags. Default `'false'`. diff --git a/action.yml b/action.yml index db96c6a..54ebd0c 100644 --- a/action.yml +++ b/action.yml @@ -56,13 +56,17 @@ inputs: default: "v" required: false + input-file: + description: "Read the changelog from this file. This will prepend the newly generated changelogs to the file's content" + required: false + output-file: description: "File to output the changelog to" default: "CHANGELOG.md" required: false release-count: - description: "Number of releases to preserve in changelog" + description: "Number of releases to preserve in changelog. Default `5`, use `0` to regenerate all. This input has no effect if input-file is used" default: "5" required: false diff --git a/src/helpers/generateChangelog.js b/src/helpers/generateChangelog.js index 3f18142..9b7c22e 100644 --- a/src/helpers/generateChangelog.js +++ b/src/helpers/generateChangelog.js @@ -1,4 +1,5 @@ const fs = require('fs') +const { Readable } = require('stream'); const conventionalChangelog = require('conventional-changelog') /** @@ -67,12 +68,45 @@ module.exports.generateStringChangelog = (tagPrefix, preset, version, releaseCou * @param releaseCount * @param config * @param gitPath + * @param infile * @returns {Promise<>} */ -module.exports.generateFileChangelog = (tagPrefix, preset, version, fileName, releaseCount, config, gitPath) => new Promise((resolve) => { - const changelogStream = getChangelogStream(tagPrefix, preset, version, releaseCount, config, gitPath) +module.exports.generateFileChangelog = (tagPrefix, preset, version, fileName, releaseCount, config, gitPath, infile) => new Promise((resolve) => { + const changelogStream = getChangelogStream(tagPrefix, preset, version, infile ? 1 : releaseCount, config, gitPath) + + // The default changelog output to be streamed first + const readStreams = [changelogStream] + + // If an input-file is provided and release count is not 0 + if (infile) { + // The infile is read synchronously to avoid repeatedly reading newly written content while it is being written + const buffer = fs.readFileSync(infile); + const readableStream = Readable.from(buffer); + // We add the stream as the next item for later pipe + readStreams.push(readableStream) + } + + const writeStream = fs.createWriteStream(fileName) + + let currentIndex = 0; + + function pipeNextStream() { + if (currentIndex < readStreams.length) { + const currentStream = readStreams[currentIndex]; + + currentStream.pipe(writeStream, { end: false }); + + currentStream.once('end', () => { + currentIndex++; + pipeNextStream(); + }); + } else { + // All stream pipes have completed + writeStream.end(); + resolve(); + } + } + + pipeNextStream(); - changelogStream - .pipe(fs.createWriteStream(fileName)) - .on('finish', resolve) }) diff --git a/src/index.js b/src/index.js index 0cb1d5c..0fc5960 100644 --- a/src/index.js +++ b/src/index.js @@ -46,6 +46,7 @@ async function run() { const preChangelogGenerationFile = core.getInput('pre-changelog-generation') const gitUrl = core.getInput('git-url') const gitPath = core.getInput('git-path') + const infile = core.getInput('input-file') const skipCi = core.getBooleanInput('skip-ci') const createSummary = core.getBooleanInput('create-summary') const prerelease = core.getBooleanInput('pre-release') @@ -72,6 +73,10 @@ async function run() { core.info(`Using "${preCommitFile}" as pre-commit script`) } + if (infile) { + core.info(`Using "${infile}" as input file`) + } + if (preChangelogGenerationFile) { core.info(`Using "${preChangelogGenerationFile}" as pre-changelog-generation script`) } @@ -172,7 +177,7 @@ async function run() { // If output file === 'false' we don't write it to file if (outputFile !== 'false') { // Generate the changelog - await changelog.generateFileChangelog(tagPrefix, preset, newVersion, outputFile, releaseCount, config, gitPath) + await changelog.generateFileChangelog(tagPrefix, preset, newVersion, outputFile, releaseCount, config, gitPath, infile) } if (!skipCommit) { From b2bec20afa7ea2503fc58daa9ec97e1075681394 Mon Sep 17 00:00:00 2001 From: Charles Lehnert Date: Wed, 21 Jun 2023 18:21:53 -0400 Subject: [PATCH 2/2] test: Add test for input-file usage --- .github/workflows/test.yml | 33 +++++++++++++++++++++++++++++++++ node_modules/.package-lock.json | 2 +- test-file-content.js | 30 ++++++++++++++++++++++++++++++ test-input-file.md | 11 +++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 test-file-content.js create mode 100644 test-input-file.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cca630e..e581848 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -864,3 +864,36 @@ jobs: env: FILES: "test-file-pre-release.json" EXPECTED_VERSION: "1.5.0" + + test-input-file: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + path: "./" + + - run: npm ci --prod + + - run: "git config --global user.email 'changelog@github.com'" + - run: "git config --global user.name 'Awesome Github action'" + - run: "git add . && git commit --allow-empty -m 'feat: Added fake file so version will be bumped'" + + - name: Generate changelog + id: changelog + uses: ./ + env: + ENV: "dont-use-git" + EXPECTED_TAG: "v6.5.0" + with: + input-file: "./test-input-file.md" + github-token: ${{ secrets.github_token }} + version-file: "./test-file-empty.toml" + version-path: "package.version" + fallback-version: "6.5.0" + + - name: Test output + run: node ./test-file-content.js + env: + OUTPUT_FILE: "CHANGELOG.md" + EXPECTED_FILE: "test-input-file.md" diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 34868f0..5f4e450 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1,6 +1,6 @@ { "name": "conventional-changelog-action", - "version": "3.17.0", + "version": "3.18.1", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/test-file-content.js b/test-file-content.js new file mode 100644 index 0000000..48579be --- /dev/null +++ b/test-file-content.js @@ -0,0 +1,30 @@ +const fs = require('fs') +const assert = require('assert') +const yaml = require('yaml') + +const actionConfig = yaml.parse(fs.readFileSync('./action.yml', 'utf8')) + +const { + OUTPUT_FILE = 'CHANGELOG.md', + EXPECTED_FILE = 'test-input-file.md', +} = process.env + +assert.ok(OUTPUT_FILE, 'Output file is not defined!') +assert.ok(EXPECTED_FILE, 'Expected file is not defined!') + +/** + * Test that the generated logs match the expected output + */ +console.log(`Going to test file "${OUTPUT_FILE}" against expected "${EXPECTED_FILE}"`) + +const outputFileContent = fs.readFileSync(OUTPUT_FILE.trim(), 'utf8').split('\n'); +assert.ok(outputFileContent, 'Content could not be parsed!') +console.log(`"${OUTPUT_FILE}" has valid content`, outputFileContent) + +const expectedFileContent = fs.readFileSync(EXPECTED_FILE.trim(), 'utf8').split('\n'); +assert.ok(expectedFileContent, 'Content could not be parsed!') +console.log(`"${EXPECTED_FILE}" has valid content`, expectedFileContent) + +const linesToCompare = 11 +assert.deepStrictEqual(outputFileContent.slice(linesToCompare * -1), expectedFileContent.slice(linesToCompare * -1), 'Output-file does not contain the expected input-file content') +console.log('The input-file\'s content exists at the end of the generated logs') diff --git a/test-input-file.md b/test-input-file.md new file mode 100644 index 0000000..6efdfd3 --- /dev/null +++ b/test-input-file.md @@ -0,0 +1,11 @@ +# This is content that will remain in the changelogs throughout all future releases + +## [1.0.0](https://github.com/TriPSs/conventional-changelog-action/compare/v3.18.0...v3.18.1) (2023-05-18) + +### Features + +* Make another commit + +### Bug Fixes + +* Make a preexisting commit