diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f719ae..316ec91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,3 +143,39 @@ jobs: RELEASE_NOTES: ${{ steps.extract-release-notes-9.outputs.release_notes }} run: | diff RELEASE_NOTES.md test/testdata/expected/RELEASE_NOTES_3.md + - name: Run action + id: extract-release-notes-10 + uses: ./ + with: + changelog_file: test/testdata/CHANGELOG_5.md + version_prefix: v + - name: Assert that release_notes contains expected content + shell: bash + env: + RELEASE_NOTES: ${{ steps.extract-release-notes-10.outputs.release_notes }} + run: | + diff <(echo -n "${RELEASE_NOTES}") test/testdata/expected/RELEASE_NOTES_1.md + - name: Run action + id: extract-release-notes-11 + uses: ./ + with: + changelog_file: test/testdata/CHANGELOG_6.md + header_level: 3 + - name: Assert that release_notes contains expected content + shell: bash + env: + RELEASE_NOTES: ${{ steps.extract-release-notes-11.outputs.release_notes }} + run: | + diff <(echo -n "${RELEASE_NOTES}") test/testdata/expected/RELEASE_NOTES_6.md + - name: Run action + id: extract-release-notes-12 + uses: ./ + with: + changelog_file: test/testdata/CHANGELOG_7.md + version_prefix: version + - name: Assert that release_notes contains expected content + shell: bash + env: + RELEASE_NOTES: ${{ steps.extract-release-notes-12.outputs.release_notes }} + run: | + diff <(echo -n "${RELEASE_NOTES}") test/testdata/expected/RELEASE_NOTES_1.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6204dd5..9764605 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -103,6 +103,18 @@ jobs: - changelog_file: CHANGELOG_4.md expected_release_notes_file: RELEASE_NOTES_4.md prerelease: true + - changelog_file: CHANGELOG_5.md + expected_release_notes_file: RELEASE_NOTES_1.md + prerelease: false + version_prefix: v + - changelog_file: CHANGELOG_6.md + expected_release_notes_file: RELEASE_NOTES_6.md + prerelease: false + header_level: 3 + - changelog_file: CHANGELOG_7.md + expected_release_notes_file: RELEASE_NOTES_1.md + prerelease: false + version_prefix: version runs-on: ${{ matrix.os }} steps: - name: Checkout @@ -137,6 +149,18 @@ jobs: - changelog_file: CHANGELOG_4.md expected_release_notes_file: RELEASE_NOTES_4.md prerelease: true + - changelog_file: CHANGELOG_5.md + expected_release_notes_file: RELEASE_NOTES_1.md + prerelease: false + version_prefix: v + - changelog_file: CHANGELOG_6.md + expected_release_notes_file: RELEASE_NOTES_6.md + prerelease: false + header_level: 3 + - changelog_file: CHANGELOG_7.md + expected_release_notes_file: RELEASE_NOTES_1.md + prerelease: false + version_prefix: version runs-on: ${{ matrix.os }} steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c049e0..1340bb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added +- Allow for version number prefix in the changelog header tag, e.g. `version` as in [version x.y.z] +- Allow for changing the header level (default 2) where the version description is expected +- Allow for omitting enclosing brackets of version number + ### Changed ### Deprecated diff --git a/README.md b/README.md index 99242d8..6a35128 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,12 @@ This GitHub Action extracts release notes from a [Keep a Changelog](https://keep ### Inputs -| Input | Description | -|-----------------------------------|---------------------------------------------------------------| -| `changelog_file` _(optional)_ | The input path of the changelog file. Default: `CHANGELOG.md` | -| `release_notes_file` _(optional)_ | The output path of the (optional) release notes file. | +| Input | Description | +| --------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `changelog_file` _(optional)_ | The input path of the changelog file. Default: `CHANGELOG.md` | +| `release_notes_file` _(optional)_ | The output path of the (optional) release notes file. | +| `version_prefix` _(optional)_ | A prefix before the version number in the changelog header tag, e.g. `version` as in [version x.y.z]. | +| `header_level` _(optional)_ | The header level where the version description is expected. Default: `2` | ### Outputs @@ -78,6 +80,38 @@ jobs: changelog_file: MY_CHANGELOG.md ``` +### Change expected version header level to H3 + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Extract release notes + id: extract-release-notes + uses: ffurrer2/extract-release-notes@v2 + with: + header_level: 3 +``` + +### Accept CHANGELOG.md files with [Version x.y.z] titles + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Extract release notes + id: extract-release-notes + uses: ffurrer2/extract-release-notes@v2 + with: + version_prefix: Version +``` + ### Create a release notes file ```yaml diff --git a/action.yml b/action.yml index 394eeb4..c89c162 100644 --- a/action.yml +++ b/action.yml @@ -17,6 +17,14 @@ inputs: description: '`true` to get release notes from the `[Unreleased]` section. `false` to get release notes for the latest release. Default: `false`' required: false default: 'false' + version_prefix: + description: 'A prefix before the version number in the changelog.md header tag, e.g. `version` as in [version x.y.z]. Default: ``' + required: false + default: '' + header_level: + description: 'The header level where the version description is expected. Default: `2`' + required: false + default: 2 outputs: release_notes: description: 'The escaped release notes.' diff --git a/src/index.js b/src/index.js index b419e24..31ef4e6 100644 --- a/src/index.js +++ b/src/index.js @@ -20,7 +20,13 @@ async function main() { const prerelease = core.getInput('prerelease') core.debug(`prerelease = '${prerelease}'`) - const releaseNotes = await extractReleaseNotes(changelogFile, prerelease) + const versionPrefix = core.getInput('version_prefix') + core.debug(`version-prefix = '${versionPrefix}'`) + + const headerLevel = parseInt(core.getInput('header_level')) + core.debug(`header_level = '${headerLevel}'`) + + const releaseNotes = await extractReleaseNotes(changelogFile, prerelease, versionPrefix, headerLevel) core.debug(`release-notes = '${releaseNotes}'`) writeReleaseNotesFile(releaseNotesFile, releaseNotes) @@ -28,18 +34,27 @@ async function main() { core.setOutput("release_notes", releaseNotes) } -async function extractReleaseNotes(changelogFile, prerelease) { +async function extractReleaseNotes(changelogFile, prerelease, versionPrefix, headerLevel) { const fileStream = fs.createReadStream(changelogFile, {encoding: encoding}) const rl = readline.createInterface({ input: fileStream }) const lines = [] let inside_release = false + const header_level = (Number.isInteger(headerLevel) && (headerLevel > 0) && (headerLevel < 7)) ? +headerLevel : 2 + const level_match_regex = "^#{" + header_level + "}\\s+" + const levelup_match_regex = (header_level > 1) ? "^#{1," + (header_level - 1) + "}\\s+" : level_match_regex + const version_match_regex = "\\[?" + escapeRegex(versionPrefix) + "\\s*[0-9]" + const unreleases_match_regex = "\\[?Unreleased\\]?" + core.debug(`version_match_regex: '${version_match_regex}'`) + core.debug(`unrelease_match_regex: '${unreleases_match_regex}'`) for await (const line of rl) { - const start_of_release = (!!line.match("^#+ \\[[0-9]") || (prerelease === 'true' && !!line.match("^#+ \\[Unreleased\\]"))) + let header_match = (!!line.match(level_match_regex)) + let headerup_match = (!!line.match(levelup_match_regex)) + let start_of_release = (!!line.match(level_match_regex + version_match_regex) || (prerelease === 'true' && !!line.match(level_match_regex + unreleases_match_regex))) if (inside_release) { - if (start_of_release) { - core.debug(`next version found: '${line}'`) + if (header_match || headerup_match) { + core.debug(`end of version block: '${line}'`) break } else { lines.push(line) @@ -78,3 +93,7 @@ function writeReleaseNotesFile(releaseNotesFile, releaseNotes) { }) } } + +function escapeRegex(string) { + return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&'); +} diff --git a/test/testdata/CHANGELOG_5.md b/test/testdata/CHANGELOG_5.md new file mode 100644 index 0000000..1653298 --- /dev/null +++ b/test/testdata/CHANGELOG_5.md @@ -0,0 +1,48 @@ + + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security + +## [v1.0.0] - 2024-05-15 + +### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +### Changed + +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +### Removed + +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +## [v0.1.0] - 2019-12-01 + +### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/testdata/CHANGELOG_6.md b/test/testdata/CHANGELOG_6.md new file mode 100644 index 0000000..9fa564a --- /dev/null +++ b/test/testdata/CHANGELOG_6.md @@ -0,0 +1,52 @@ + + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Version 1.0.x + +### [Unreleased] + +#### Added + +#### Changed + +#### Deprecated + +#### Removed + +#### Fixed + +#### Security + +### [1.0.0] - 2024-05-15 + +#### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +#### Changed + +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +#### Removed + +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +## Version 0.1.x + +### [0.1.0] - 2019-12-01 + +#### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/testdata/CHANGELOG_7.md b/test/testdata/CHANGELOG_7.md new file mode 100644 index 0000000..e09d188 --- /dev/null +++ b/test/testdata/CHANGELOG_7.md @@ -0,0 +1,48 @@ + + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security + +## version 1.0 - 2024-05-21 + +### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +### Changed + +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +### Removed + +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +## version 0.1 - 2019-12-01 + +### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/testdata/expected/RELEASE_NOTES_6.md b/test/testdata/expected/RELEASE_NOTES_6.md new file mode 100644 index 0000000..d60258d --- /dev/null +++ b/test/testdata/expected/RELEASE_NOTES_6.md @@ -0,0 +1,16 @@ +#### Added + +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +#### Changed + +- At vero eos et accusam et justo duo dolores et ea rebum. +- Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +#### Removed + +- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \ No newline at end of file