@@ -28,6 +28,7 @@
|
||||
<a href="#full-sample-%EF%B8%8F">Sample 🖥️</a> •
|
||||
<a href="#customization-%EF%B8%8F">Customization 🖍️</a> •
|
||||
<a href="#contribute-">Contribute 🧬</a> •
|
||||
<a href="#local-testing-">Local Testing 🧪</a> •
|
||||
<a href="#license">License 📓</a>
|
||||
</p>
|
||||
|
||||
@@ -86,6 +87,11 @@ A full set list of possible output values for this action.
|
||||
| `outputs.categorized_prs` | Count of PRs which were successfully categorized as part of the action. |
|
||||
| `outputs.open_prs` | Count of open PRs. Only fetched if `includeOpen` is enabled. |
|
||||
| `outputs.uncategorized_prs` | Count of PRs which were not categorized as part of the action. |
|
||||
| `outputs.changed_files` | Count of changed files in this release. |
|
||||
| `outputs.additions` | Count of code additions in this release (lines). |
|
||||
| `outputs.deletions` | Count of code deletions in this release (lines). |
|
||||
| `outputs.changes` | Total count of changes in this release (lines). |
|
||||
| `outputs.commits` | Count of commits which have been added in this release. |
|
||||
|
||||
|
||||
## Full Sample 🖥️
|
||||
@@ -291,8 +297,9 @@ Table of supported placeholders allowed to be used in the `pr_template` configur
|
||||
| `${{MILESTONE}}` | Milestone this PR was part of, as assigned on GitHub |
|
||||
| `${{BODY}}` | Description/Body of the pull request as specified on GitHub |
|
||||
| `${{ASSIGNEES}}` | Login names of assigned GitHub users, joined by `,` |
|
||||
| `${{REVIEWERS}}` | GitHub Login names of specified reviewers, joined by `,` |
|
||||
| `${{REVIEWERS}}` | GitHub Login names of specified reviewers, joined by `,`. Requires `fetchReviewers` to be enabled. |
|
||||
| `${{APPROVERS}}` | GitHub Login names of users who approved the PR, joined by `,` |
|
||||
| `${{DAYS_SINCE}}` | Days between the 2 releases. Requires `fetchReleaseInformation` to be enabled. |
|
||||
|
||||
### Template placeholders
|
||||
|
||||
@@ -307,14 +314,20 @@ Table of supported placeholders allowed to be used in the `template` and `empty_
|
||||
| `${{OWNER}}` | Describes the owner of the repository the changelog was generated for | x |
|
||||
| `${{REPO}}` | The repository name of the repo the changelog was generated for | x |
|
||||
| `${{FROM_TAG}}` | Defines the 'start' from where the changelog did consider merged pull requests | x |
|
||||
| `${{FROM_TAG_DATE}}` | Defines the date at which the 'start' tag was created | x |
|
||||
| `${{TO_TAG}}` | Defines until which tag the changelog did consider merged pull requests | x |
|
||||
| `${{TO_TAG_DATE}}` | Defines the date at which the 'until' tag was created | x |
|
||||
| `${{RELEASE_DIFF}}` | Introduces a link to the full diff between from tag and to tag releases | x |
|
||||
| `${{CHANGED_FILES}}` | The count of changed files. | |
|
||||
| `${{ADDITIONS}}` | The count of code additions (lines). | |
|
||||
| `${{DELETIONS}}` | The count of code deletions (lines). | |
|
||||
| `${{CHANGES}}` | The count of total changes (lines). | |
|
||||
| `${{COMMITS}}` | The count of commits in this release. | |
|
||||
| `${{CATEGORIZED_COUNT}}` | The count of PRs which were categorized | |
|
||||
| `${{UNCATEGORIZED_COUNT}}` | The count of PRs and changes which were not categorized. No label overlapping with category labels | |
|
||||
| `${{OPEN_COUNT}}` | The count of open PRs. Will only be fetched if `includeOpen` is configured. | |
|
||||
| `${{IGNORED_COUNT}}` | The count of PRs and changes which were specifically ignored from the changelog. | |
|
||||
|
||||
|
||||
### Configuration Specification
|
||||
|
||||
Table of descriptions for the `configuration.json` options to configure the resulting release notes / changelog.
|
||||
@@ -377,6 +390,65 @@ It's suggested to export the token to your path before running the tests so that
|
||||
export GITHUB_TOKEN=your_personal_github_pat
|
||||
```
|
||||
|
||||
## Local Testing 🧪
|
||||
|
||||
This GitHub action is fully developed in Typescript and can be run locally via npm. Doing so is a great way to test the action and/or your custom configurations locally, without the need to push and re-run GitHub actions over and over again.
|
||||
|
||||
To run this action locally, first make sure you provide a `GITHUB_TOKEN` with enough permissions to access the repository.
|
||||
|
||||
```
|
||||
# GitHub token for the action
|
||||
export GITHUB_TOKEN=your_read_only_github_token
|
||||
```
|
||||
|
||||
Afterwards run the testcases with:
|
||||
|
||||
```bash
|
||||
npm test -- custom.test.ts
|
||||
```
|
||||
|
||||
<details><summary><b>custom.test.ts</b></summary>
|
||||
<p>
|
||||
|
||||
```typescript
|
||||
import {resolveConfiguration} from '../src/utils'
|
||||
import {ReleaseNotesBuilder} from '../src/releaseNotesBuilder'
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
it('Test custom changelog builder', async () => {
|
||||
const configuration = resolveConfiguration(
|
||||
'',
|
||||
'configs_test/configuration_approvers.json'
|
||||
)
|
||||
const releaseNotesBuilder = new ReleaseNotesBuilder(
|
||||
null, // baseUrl
|
||||
null, // token
|
||||
'.', // repoPath
|
||||
'mikepenz', // user
|
||||
'release-changelog-builder-action-playground', // repo
|
||||
'1.5.0', // fromTag
|
||||
'2.0.0', // toTag
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
true, // enable to fetch reviewers
|
||||
false, // commitMode
|
||||
configuration // configuration
|
||||
)
|
||||
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(``)
|
||||
})
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
Additionally it is possible to do full debugging including the option of breakpoints via (for example) Visual Code.
|
||||
Open the project in Visual code -> open the terminal -> use the `+` and start a new `JavaScript Debug Terminal`. Afterwards run the tests as described above.
|
||||
|
||||
## Developed By
|
||||
|
||||
* Mike Penz
|
||||
@@ -404,7 +476,7 @@ export GITHUB_TOKEN=your_personal_github_pat
|
||||
|
||||
All patches and changes applied to the original source are licensed under the Apache 2.0 license.
|
||||
|
||||
Copyright 2021 Mike Penz
|
||||
Copyright 2022 Mike Penz
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -14,18 +14,19 @@ it('Should have empty changelog (tags)', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v0.0.1',
|
||||
toTag: 'v0.0.2',
|
||||
fromTag: { name: 'v0.0.1' },
|
||||
toTag: { name: 'v0.0.2' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
|
||||
const changeLog = await releaseNotes.pull()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(null)
|
||||
expect(changeLog).toStrictEqual("- no changes")
|
||||
})
|
||||
|
||||
it('Should match generated changelog (tags)', async () => {
|
||||
@@ -33,11 +34,12 @@ it('Should match generated changelog (tags)', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v0.0.1',
|
||||
toTag: 'v0.0.3',
|
||||
fromTag: { name: 'v0.0.1'},
|
||||
toTag: { name: 'v0.0.3' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -60,11 +62,12 @@ it('Should match generated changelog (refs)', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3',
|
||||
toTag: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa',
|
||||
fromTag: { name: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3' },
|
||||
toTag: { name: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -95,11 +98,12 @@ it('Should match generated changelog and replace all occurrences (refs)', async
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3',
|
||||
toTag: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa',
|
||||
fromTag: { name: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3' },
|
||||
toTag: { name: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -132,11 +136,12 @@ it('Should match ordered ASC', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v0.3.0',
|
||||
toTag: 'v0.5.0',
|
||||
fromTag: { name: 'v0.3.0' },
|
||||
toTag: { name: 'v0.5.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -156,11 +161,12 @@ it('Should match ordered DESC', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v0.3.0',
|
||||
toTag: 'v0.5.0',
|
||||
fromTag: { name: 'v0.3.0' },
|
||||
toTag: { name: 'v0.5.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -180,11 +186,12 @@ it('Should match ordered by title ASC', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v0.3.0',
|
||||
toTag: 'v0.5.0',
|
||||
fromTag: { name: 'v0.3.0' },
|
||||
toTag: { name: 'v0.5.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -204,11 +211,12 @@ it('Should match ordered by title DESC', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v0.3.0',
|
||||
toTag: 'v0.5.0',
|
||||
fromTag: { name: 'v0.3.0' },
|
||||
toTag: { name: 'v0.5.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -228,11 +236,12 @@ it('Should ignore PRs not merged into develop branch', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v1.3.1',
|
||||
toTag: 'v1.4.0',
|
||||
fromTag: { name: 'v1.3.1' },
|
||||
toTag: { name: 'v1.4.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -250,11 +259,12 @@ it('Should ignore PRs not merged into main branch', async () => {
|
||||
const releaseNotes = new ReleaseNotes(octokit, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v1.3.1',
|
||||
toTag: 'v1.4.0',
|
||||
fromTag: { name: 'v1.3.1' },
|
||||
toTag: { name: 'v1.4.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
|
||||
@@ -17,6 +17,7 @@ it('Should match generated changelog (unspecified fromTag)', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -45,6 +46,7 @@ it('Should match generated changelog (unspecified tags)', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -70,6 +72,7 @@ it('Should use empty placeholder', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -96,6 +99,7 @@ it('Should fill empty placeholders', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -103,7 +107,7 @@ it('Should fill empty placeholders', async () => {
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(
|
||||
`mikepenz\nrelease-changelog-builder-action\nv0.0.2\nv0.0.3`
|
||||
`mikepenz\nrelease-changelog-builder-action\nv0.0.2\nv0.0.3\nhttps://github.com/mikepenz/release-changelog-builder-action/compare/v0.0.2...v0.0.3`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -124,6 +128,7 @@ it('Should fill `template` placeholders', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -131,7 +136,7 @@ it('Should fill `template` placeholders', async () => {
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(
|
||||
`## 🧪 Tests\n\n- [CI] Specify Test Case\n - PR: #10\n\n\n\n\nmikepenz\nrelease-changelog-builder-action\nv0.0.1\nv0.0.3\n1\n0\n0`
|
||||
`## 🧪 Tests\n\n- [CI] Specify Test Case\n - PR: #10\n\n\n\n\nmikepenz\nrelease-changelog-builder-action\nv0.0.1\nv0.0.3\nhttps://github.com/mikepenz/release-changelog-builder-action/compare/v0.0.1...v0.0.3\n1\n0\n0\n19\n14827\n444\n15271\n3`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -152,6 +157,7 @@ it('Should fill `template` placeholders, ignore', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -159,7 +165,7 @@ it('Should fill `template` placeholders, ignore', async () => {
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(
|
||||
`## 🚀 Features\n\n- Enhance sorting by using proper semver\n - PR: #51\n\n## 🧪 Tests\n\n- Improve test cases\n - PR: #49\n\n\n- Bump @types/node from 14.11.8 to 14.11.10\n - PR: #47\n- Adjust code to move fromTag resolving to main.ts\n - PR: #48\n- dev -> main\n - PR: #52\n- Update package.json to updated description\n - PR: #53\n- dev -> main\n - PR: #54\n\n- New additional placeholders for \`template\` and \`empty_template\`\n - PR: #50\n\nmikepenz\nrelease-changelog-builder-action\nv0.9.1\nv0.9.5\n2\n5\n1`
|
||||
`## 🚀 Features\n\n- Enhance sorting by using proper semver\n - PR: #51\n\n## 🧪 Tests\n\n- Improve test cases\n - PR: #49\n\n\n- Bump @types/node from 14.11.8 to 14.11.10\n - PR: #47\n- Adjust code to move fromTag resolving to main.ts\n - PR: #48\n- dev -> main\n - PR: #52\n- Update package.json to updated description\n - PR: #53\n- dev -> main\n - PR: #54\n\n- New additional placeholders for \`template\` and \`empty_template\`\n - PR: #50\n\nmikepenz\nrelease-changelog-builder-action\nv0.9.1\nv0.9.5\nhttps://github.com/mikepenz/release-changelog-builder-action/compare/v0.9.1...v0.9.5\n2\n5\n1\n16\n2931\n450\n3381\n26`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -180,6 +186,7 @@ it('Uncategorized category', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false,
|
||||
configuration
|
||||
)
|
||||
@@ -208,6 +215,7 @@ it('Verify commit based changelog', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
true,
|
||||
configuration
|
||||
)
|
||||
@@ -236,6 +244,7 @@ it('Verify commit based changelog, with emoji categorisation', async () => {
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
true,
|
||||
configuration
|
||||
)
|
||||
@@ -264,6 +273,7 @@ it('Verify default inclusion of open PRs', async () => {
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // commitMode
|
||||
configuration // configuration
|
||||
)
|
||||
@@ -292,6 +302,7 @@ it('Verify custom categorisation of open PRs', async () => {
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // commitMode
|
||||
configuration // configuration
|
||||
)
|
||||
@@ -303,7 +314,7 @@ it('Verify custom categorisation of open PRs', async () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('Verify reviewers who approved are fetched', async () => {
|
||||
it('Verify reviewers who approved are fetched and also release information', async () => {
|
||||
const configuration = resolveConfiguration(
|
||||
'',
|
||||
'configs_test/configuration_approvers.json'
|
||||
@@ -320,6 +331,7 @@ it('Verify reviewers who approved are fetched', async () => {
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
true, // enable to fetch reviewers
|
||||
true, // enable to fetch tag release information
|
||||
false, // commitMode
|
||||
configuration // configuration
|
||||
)
|
||||
@@ -327,6 +339,65 @@ it('Verify reviewers who approved are fetched', async () => {
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(
|
||||
`## 🚀 Features\n\n- A feature to be going to v2 (nr3) -- (#3) [merged] --- \n- New feature to keep open (nr5) -- (#7) [open] --- gabrielpopa\n\n`
|
||||
`## 🚀 Features\n\n- A feature to be going to v2 (nr3) -- (#3) [merged] --- \n- New feature to keep open (nr5) -- (#7) [open] --- gabrielpopa\n\n\n\n0`
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
it('Fetch release information', async () => {
|
||||
const configuration = resolveConfiguration(
|
||||
'',
|
||||
'configs_test/configuration_approvers.json'
|
||||
)
|
||||
configuration.template = "${{FROM_TAG}}-${{FROM_TAG_DATE}}\n${{TO_TAG}}-${{TO_TAG_DATE}}\n${{DAYS_SINCE}}"
|
||||
const releaseNotesBuilder = new ReleaseNotesBuilder(
|
||||
null, // baseUrl
|
||||
null, // token
|
||||
'.', // repoPath
|
||||
'mikepenz', // user
|
||||
'release-changelog-builder-action-playground', // repo
|
||||
'2.0.0', // fromTag
|
||||
'3.0.0-a01', // toTag
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch reviewers
|
||||
true, // enable to fetch tag release information
|
||||
false, // commitMode
|
||||
configuration // configuration
|
||||
)
|
||||
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(
|
||||
`2.0.0-2022-04-08T07:52:40.000Z\n3.0.0-a01-2022-07-26T14:28:36.000Z\n109`
|
||||
)
|
||||
})
|
||||
|
||||
it('Fetch release information for non existing tag / release', async () => {
|
||||
const configuration = resolveConfiguration(
|
||||
'',
|
||||
'configs_test/configuration_approvers.json'
|
||||
)
|
||||
configuration.template = "${{FROM_TAG}}-${{FROM_TAG_DATE}}\n${{TO_TAG}}-${{TO_TAG_DATE}}\n${{DAYS_SINCE}}"
|
||||
const releaseNotesBuilder = new ReleaseNotesBuilder(
|
||||
null, // baseUrl
|
||||
null, // token
|
||||
'.', // repoPath
|
||||
'mikepenz', // user
|
||||
'release-changelog-builder-action-playground', // repo
|
||||
'2.0.0', // fromTag
|
||||
'3.0.1', // toTag
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch reviewers
|
||||
true, // enable to fetch tag release information
|
||||
false, // commitMode
|
||||
configuration // configuration
|
||||
)
|
||||
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(`- no changes`)
|
||||
})
|
||||
+55
-41
@@ -2,6 +2,7 @@ import {buildChangelog} from '../src/transform'
|
||||
import {PullRequestInfo} from '../src/pullRequests'
|
||||
import moment from 'moment'
|
||||
import { DefaultConfiguration, Configuration } from '../src/configuration';
|
||||
import { DefaultDiffInfo } from '../src/commits';
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
@@ -130,14 +131,15 @@ it('Extract label from title, combined regex', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -159,14 +161,15 @@ it('Extract label from title and body, combined regex', async () => {
|
||||
|
||||
let prs = Array.from(mergedPullRequests)
|
||||
prs.push(pullRequestWithLabelInBody)
|
||||
const resultChangelog = buildChangelog(prs, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, prs, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -190,14 +193,15 @@ it('Extract label from title, split regex', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -221,14 +225,15 @@ it('Extract label from title, match', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -247,14 +252,15 @@ it('Extract label from title, match multiple', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -274,14 +280,15 @@ it('Extract label from title, match multiple, custon non matching label', async
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration
|
||||
})
|
||||
@@ -388,14 +395,15 @@ it('Match multiple labels exhaustive for category', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration: customConfig
|
||||
})
|
||||
@@ -413,14 +421,15 @@ it('Deduplicate duplicated PRs', async () => {
|
||||
method: 'match'
|
||||
}
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration: customConfig
|
||||
})
|
||||
@@ -439,14 +448,15 @@ it('Deduplicate duplicated PRs DESC', async () => {
|
||||
method: 'match'
|
||||
}
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration: customConfig
|
||||
})
|
||||
@@ -471,14 +481,15 @@ it('Use empty_content for empty category', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration: customConfig
|
||||
})
|
||||
@@ -493,14 +504,15 @@ it('Commit SHA-1 in commitMode', async () => {
|
||||
customConfig.sort = "DESC"
|
||||
customConfig.pr_template = "${{MERGE_SHA}}"
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: true,
|
||||
configuration: customConfig
|
||||
})
|
||||
@@ -512,22 +524,23 @@ it('Commit SHA-1 in commitMode', async () => {
|
||||
|
||||
it('Release Diff', async () => {
|
||||
const customConfig = Object.assign({}, DefaultConfiguration)
|
||||
customConfig.template = "${{RELEASE_DIFF}}"
|
||||
customConfig.template = "${{RELEASE_DIFF}}\n${{DAYS_SINCE}}"
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v2.8.0',
|
||||
toTag: 'v2.8.1',
|
||||
fromTag: { name: 'v2.8.0' },
|
||||
toTag: { name: 'v2.8.1' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: true,
|
||||
commitMode: true,
|
||||
configuration: customConfig
|
||||
})
|
||||
|
||||
expect(resultChangelog).toStrictEqual(
|
||||
`https://github.com/mikepenz/release-changelog-builder-action/compare/v2.8.0...v2.8.1`
|
||||
`https://github.com/mikepenz/release-changelog-builder-action/compare/v2.8.0...v2.8.1\n`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -553,14 +566,15 @@ it('Use exclude labels to not include a PR within a category.', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
toTag: '2.0.0',
|
||||
fromTag: { name: '1.0.0' },
|
||||
toTag: { name: '2.0.0' },
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
commitMode: false,
|
||||
configuration: customConfig
|
||||
})
|
||||
|
||||
@@ -29,6 +29,9 @@ inputs:
|
||||
fetchReviewers:
|
||||
description: 'Will enable fetching the users/reviewers who approved the PR'
|
||||
default: "false"
|
||||
fetchReleaseInformation:
|
||||
description: 'Will enable fetching release information for the tags. E.g. creation date'
|
||||
default: "false"
|
||||
commitMode:
|
||||
description: 'Enables a `light` commit based mode. This mode generates changelogs based on the commits. Please note that this is not officially supported, and lacks a lot of features only possible with PRs.'
|
||||
default: "false"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"template": "${{CHANGELOG}}",
|
||||
"template": "${{CHANGELOG}}\n\n${{DAYS_SINCE}}",
|
||||
"pr_template": "- ${{TITLE}} -- (#${{NUMBER}}) [${{STATUS}}] ${{REVIEWERS}} --- ${{APPROVERS}}"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"template": "${{CHANGELOG}}\n${{UNCATEGORIZED}}\n${{IGNORED}}\n${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{CATEGORIZED_COUNT}}\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}",
|
||||
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}",
|
||||
"template": "${{CHANGELOG}}\n${{UNCATEGORIZED}}\n${{IGNORED}}\n${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{RELEASE_DIFF}}\n${{CATEGORIZED_COUNT}}\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}\n${{CHANGED_FILES}}\n${{ADDITIONS}}\n${{DELETIONS}}\n${{CHANGES}}\n${{COMMITS}}",
|
||||
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{RELEASE_DIFF}}",
|
||||
"max_pull_requests": 1000,
|
||||
"max_back_track_time_days": 1000
|
||||
}
|
||||
+160
-44
@@ -42,21 +42,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.filterCommits = exports.Commits = void 0;
|
||||
exports.filterCommits = exports.Commits = exports.DefaultDiffInfo = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const moment_1 = __importDefault(__nccwpck_require__(9623));
|
||||
exports.DefaultDiffInfo = {
|
||||
changedFiles: 0,
|
||||
additions: 0,
|
||||
deletions: 0,
|
||||
changes: 0,
|
||||
commits: 0,
|
||||
commitInfo: []
|
||||
};
|
||||
class Commits {
|
||||
constructor(octokit) {
|
||||
this.octokit = octokit;
|
||||
}
|
||||
getDiff(owner, repo, base, head) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const commits = yield this.getDiffRemote(owner, repo, base, head);
|
||||
return this.sortCommits(commits);
|
||||
const diff = yield this.getDiffRemote(owner, repo, base, head);
|
||||
diff.commitInfo = this.sortCommits(diff.commitInfo);
|
||||
return diff;
|
||||
});
|
||||
}
|
||||
getDiffRemote(owner, repo, base, head) {
|
||||
var _a, _b;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let changedFilesCount = 0;
|
||||
let additionCount = 0;
|
||||
let deletionCount = 0;
|
||||
let changeCount = 0;
|
||||
let commitCount = 0;
|
||||
// Fetch comparisons recursively until we don't find any commits
|
||||
// This is because the GitHub API limits the number of commits returned in a single response.
|
||||
let commits = [];
|
||||
@@ -72,11 +87,27 @@ class Commits {
|
||||
if (compareResult.data.total_commits === 0) {
|
||||
break;
|
||||
}
|
||||
changedFilesCount += (_b = (_a = compareResult.data.files) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
||||
const files = compareResult.data.files;
|
||||
if (files !== undefined) {
|
||||
for (const file of files) {
|
||||
additionCount += file.additions;
|
||||
deletionCount += file.deletions;
|
||||
changeCount += file.changes;
|
||||
}
|
||||
}
|
||||
commitCount += compareResult.data.commits.length;
|
||||
commits = compareResult.data.commits.concat(commits);
|
||||
compareHead = `${commits[0].sha}^`;
|
||||
}
|
||||
core.info(`ℹ️ Found ${commits.length} commits from the GitHub API for ${owner}/${repo}`);
|
||||
return commits
|
||||
return {
|
||||
changedFiles: changedFilesCount,
|
||||
additions: additionCount,
|
||||
deletions: deletionCount,
|
||||
changes: changeCount,
|
||||
commits: commitCount,
|
||||
commitInfo: commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => {
|
||||
var _a, _b;
|
||||
@@ -88,7 +119,8 @@ class Commits {
|
||||
author: ((_b = commit.commit.author) === null || _b === void 0 ? void 0 : _b.name) || '',
|
||||
prNumber: undefined
|
||||
});
|
||||
});
|
||||
})
|
||||
};
|
||||
});
|
||||
}
|
||||
sortCommits(commits) {
|
||||
@@ -275,6 +307,16 @@ class GitCommandManager {
|
||||
return revListOutput.stdout.trim();
|
||||
});
|
||||
}
|
||||
tagCreation(tagName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const creationDate = yield this.execGit([
|
||||
'for-each-ref',
|
||||
'--format="%(creatordate:rfc)"',
|
||||
`refs/tags/${tagName}`
|
||||
]);
|
||||
return creationDate.stdout.trim().replace(/"/g, '');
|
||||
});
|
||||
}
|
||||
static createCommandManager(workingDirectory) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const result = new GitCommandManager();
|
||||
@@ -385,8 +427,9 @@ function run() {
|
||||
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true';
|
||||
const failOnError = core.getInput('failOnError') === 'true';
|
||||
const fetchReviewers = core.getInput('fetchReviewers') === 'true';
|
||||
const fetchReleaseInformation = core.getInput('fetchReleaseInformation') === 'true';
|
||||
const commitMode = core.getInput('commitMode') === 'true';
|
||||
const result = yield new releaseNotesBuilder_1.ReleaseNotesBuilder(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, fetchReviewers, commitMode, configuration).build();
|
||||
const result = yield new releaseNotesBuilder_1.ReleaseNotesBuilder(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, fetchReviewers, fetchReleaseInformation, commitMode, configuration).build();
|
||||
core.setOutput('changelog', result);
|
||||
// write the result in changelog to file if possible
|
||||
const outputFile = core.getInput('outputFile');
|
||||
@@ -718,9 +761,12 @@ class ReleaseNotes {
|
||||
pull() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let mergedPullRequests;
|
||||
let diffInfo;
|
||||
if (!this.options.commitMode) {
|
||||
core.startGroup(`🚀 Load pull requests`);
|
||||
mergedPullRequests = yield this.getMergedPullRequests(this.octokit);
|
||||
const [info, prs] = yield this.getMergedPullRequests(this.octokit);
|
||||
mergedPullRequests = prs;
|
||||
diffInfo = info;
|
||||
// define the included PRs within this release as output
|
||||
core.setOutput('pull_requests', mergedPullRequests
|
||||
.map(pr => {
|
||||
@@ -732,15 +778,23 @@ class ReleaseNotes {
|
||||
else {
|
||||
core.startGroup(`🚀 Load commit history`);
|
||||
core.info(`⚠️ Executing experimental commit mode`);
|
||||
mergedPullRequests = yield this.generateCommitPRs(this.octokit);
|
||||
const [info, prs] = yield this.generateCommitPRs(this.octokit);
|
||||
mergedPullRequests = prs;
|
||||
diffInfo = info;
|
||||
core.endGroup();
|
||||
}
|
||||
core.setOutput('changed_files', diffInfo.changedFiles);
|
||||
core.setOutput('additions', diffInfo.additions);
|
||||
core.setOutput('deletions', diffInfo.deletions);
|
||||
core.setOutput('changes', diffInfo.changes);
|
||||
core.setOutput('commits', diffInfo.commits);
|
||||
if (mergedPullRequests.length === 0) {
|
||||
core.warning(`⚠️ No pull requests found`);
|
||||
return null;
|
||||
return (0, transform_1.fillAdditionalPlaceholders)(this.options.configuration.empty_template ||
|
||||
configuration_1.DefaultConfiguration.empty_template, this.options);
|
||||
}
|
||||
core.startGroup('📦 Build changelog');
|
||||
const resultChangelog = (0, transform_1.buildChangelog)(mergedPullRequests, this.options);
|
||||
const resultChangelog = (0, transform_1.buildChangelog)(diffInfo, mergedPullRequests, this.options);
|
||||
core.endGroup();
|
||||
return resultChangelog;
|
||||
});
|
||||
@@ -748,29 +802,30 @@ class ReleaseNotes {
|
||||
getCommitHistory(octokit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { owner, repo, fromTag, toTag, failOnError } = this.options;
|
||||
core.info(`ℹ️ Comparing ${owner}/${repo} - '${fromTag}...${toTag}'`);
|
||||
core.info(`ℹ️ Comparing ${owner}/${repo} - '${fromTag.name}...${toTag.name}'`);
|
||||
const commitsApi = new commits_1.Commits(octokit);
|
||||
let commits;
|
||||
let diffInfo;
|
||||
try {
|
||||
commits = yield commitsApi.getDiff(owner, repo, fromTag, toTag);
|
||||
diffInfo = yield commitsApi.getDiff(owner, repo, fromTag.name, toTag.name);
|
||||
}
|
||||
catch (error) {
|
||||
(0, utils_1.failOrError)(`💥 Failed to retrieve - Invalid tag? - Because of: ${error}`, failOnError);
|
||||
return [];
|
||||
return commits_1.DefaultDiffInfo;
|
||||
}
|
||||
if (commits.length === 0) {
|
||||
core.warning(`⚠️ No commits found between - ${fromTag}...${toTag}`);
|
||||
return [];
|
||||
if (diffInfo.commitInfo.length === 0) {
|
||||
core.warning(`⚠️ No commits found between - ${fromTag.name}...${toTag.name}`);
|
||||
return commits_1.DefaultDiffInfo;
|
||||
}
|
||||
return commits;
|
||||
return diffInfo;
|
||||
});
|
||||
}
|
||||
getMergedPullRequests(octokit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { owner, repo, includeOpen, fetchReviewers, configuration } = this.options;
|
||||
const commits = yield this.getCommitHistory(octokit);
|
||||
const diffInfo = yield this.getCommitHistory(octokit);
|
||||
const commits = diffInfo.commitInfo;
|
||||
if (commits.length === 0) {
|
||||
return [];
|
||||
return [diffInfo, []];
|
||||
}
|
||||
const firstCommit = commits[0];
|
||||
const lastCommit = commits[commits.length - 1];
|
||||
@@ -832,20 +887,24 @@ class ReleaseNotes {
|
||||
}
|
||||
}
|
||||
}
|
||||
return finalPrs;
|
||||
else {
|
||||
core.debug(`ℹ️ Fetching reviewers was disabled`);
|
||||
}
|
||||
return [diffInfo, finalPrs];
|
||||
});
|
||||
}
|
||||
generateCommitPRs(octokit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { owner, repo, configuration } = this.options;
|
||||
const commits = yield this.getCommitHistory(octokit);
|
||||
const diffInfo = yield this.getCommitHistory(octokit);
|
||||
const commits = diffInfo.commitInfo;
|
||||
if (commits.length === 0) {
|
||||
return [];
|
||||
return [diffInfo, []];
|
||||
}
|
||||
const prCommits = (0, commits_1.filterCommits)(commits, configuration.exclude_merge_branches ||
|
||||
configuration_1.DefaultConfiguration.exclude_merge_branches);
|
||||
core.info(`ℹ️ Retrieved ${prCommits.length} commits for ${owner}/${repo}`);
|
||||
return prCommits.map(function (commit) {
|
||||
const prs = prCommits.map(function (commit) {
|
||||
return {
|
||||
number: 0,
|
||||
title: commit.summary,
|
||||
@@ -865,6 +924,7 @@ class ReleaseNotes {
|
||||
status: 'merged'
|
||||
};
|
||||
});
|
||||
return [diffInfo, prs];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -918,9 +978,8 @@ const rest_1 = __nccwpck_require__(5375);
|
||||
const releaseNotes_1 = __nccwpck_require__(5882);
|
||||
const tags_1 = __nccwpck_require__(7532);
|
||||
const utils_1 = __nccwpck_require__(918);
|
||||
const transform_1 = __nccwpck_require__(1644);
|
||||
class ReleaseNotesBuilder {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchReviewers = false, commitMode, configuration) {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchReviewers = false, fetchReleaseInformation = false, commitMode, configuration) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.token = token;
|
||||
this.repositoryPath = repositoryPath;
|
||||
@@ -932,11 +991,11 @@ class ReleaseNotesBuilder {
|
||||
this.failOnError = failOnError;
|
||||
this.ignorePreReleases = ignorePreReleases;
|
||||
this.fetchReviewers = fetchReviewers;
|
||||
this.fetchReleaseInformation = fetchReleaseInformation;
|
||||
this.commitMode = commitMode;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
build() {
|
||||
var _a, _b;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!this.owner) {
|
||||
(0, utils_1.failOrError)(`💥 Missing or couldn't resolve 'owner'`, this.failOnError);
|
||||
@@ -965,40 +1024,46 @@ class ReleaseNotesBuilder {
|
||||
const tagsApi = new tags_1.Tags(octokit);
|
||||
const tagRange = yield tagsApi.retrieveRange(this.repositoryPath, this.owner, this.repo, this.fromTag, this.toTag, this.ignorePreReleases, this.configuration.max_tags_to_fetch ||
|
||||
configuration_1.DefaultConfiguration.max_tags_to_fetch, this.configuration.tag_resolver || configuration_1.DefaultConfiguration.tag_resolver);
|
||||
const thisTag = (_a = tagRange.to) === null || _a === void 0 ? void 0 : _a.name;
|
||||
let thisTag = tagRange.to;
|
||||
if (!thisTag) {
|
||||
(0, utils_1.failOrError)(`💥 Missing or couldn't resolve 'toTag'`, this.failOnError);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
this.toTag = thisTag;
|
||||
core.setOutput('toTag', thisTag);
|
||||
core.debug(`Resolved 'toTag' as ${thisTag}`);
|
||||
core.setOutput('toTag', thisTag.name);
|
||||
core.debug(`Resolved 'toTag' as ${thisTag.name}`);
|
||||
}
|
||||
const previousTag = (_b = tagRange.from) === null || _b === void 0 ? void 0 : _b.name;
|
||||
let previousTag = tagRange.from;
|
||||
if (previousTag == null) {
|
||||
(0, utils_1.failOrError)(`💥 Unable to retrieve previous tag given ${this.toTag}`, this.failOnError);
|
||||
return null;
|
||||
}
|
||||
this.fromTag = previousTag;
|
||||
core.setOutput('fromTag', previousTag);
|
||||
core.debug(`fromTag resolved via previousTag as: ${previousTag}`);
|
||||
core.setOutput('fromTag', previousTag.name);
|
||||
core.debug(`fromTag resolved via previousTag as: ${previousTag.name}`);
|
||||
if (this.fetchReleaseInformation) {
|
||||
// load release information from the GitHub API
|
||||
core.info(`ℹ️ Fetching release information was enabled`);
|
||||
thisTag = yield tagsApi.fillTagInformation(this.repositoryPath, this.owner, this.repo, thisTag);
|
||||
previousTag = yield tagsApi.fillTagInformation(this.repositoryPath, this.owner, this.repo, previousTag);
|
||||
}
|
||||
else {
|
||||
core.debug(`ℹ️ Fetching release information was disabled`);
|
||||
}
|
||||
core.endGroup();
|
||||
const options = {
|
||||
owner: this.owner,
|
||||
repo: this.repo,
|
||||
fromTag: this.fromTag,
|
||||
toTag: this.toTag,
|
||||
fromTag: previousTag,
|
||||
toTag: thisTag,
|
||||
includeOpen: this.includeOpen,
|
||||
failOnError: this.failOnError,
|
||||
fetchReviewers: this.fetchReviewers,
|
||||
fetchReleaseInformation: this.fetchReleaseInformation,
|
||||
commitMode: this.commitMode,
|
||||
configuration: this.configuration
|
||||
};
|
||||
const releaseNotes = new releaseNotes_1.ReleaseNotes(octokit, options);
|
||||
return ((yield releaseNotes.pull()) ||
|
||||
(0, transform_1.fillAdditionalPlaceholders)(this.configuration.empty_template ||
|
||||
configuration_1.DefaultConfiguration.empty_template, options));
|
||||
return yield releaseNotes.pull();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1051,6 +1116,9 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
||||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
||||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.sortTags = exports.filterTags = exports.Tags = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
@@ -1059,6 +1127,7 @@ const semver = __importStar(__nccwpck_require__(1383));
|
||||
const semver_1 = __nccwpck_require__(1383);
|
||||
const gitHelper_1 = __nccwpck_require__(353);
|
||||
const transform_1 = __nccwpck_require__(1644);
|
||||
const moment_1 = __importDefault(__nccwpck_require__(9623));
|
||||
class Tags {
|
||||
constructor(octokit) {
|
||||
this.octokit = octokit;
|
||||
@@ -1100,6 +1169,35 @@ class Tags {
|
||||
return tagsInfo;
|
||||
});
|
||||
}
|
||||
fillTagInformation(repositoryPath, owner, repo, tagInfo) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const options = this.octokit.repos.getReleaseByTag.endpoint.merge({
|
||||
owner,
|
||||
repo,
|
||||
tag: tagInfo.name
|
||||
});
|
||||
try {
|
||||
const response = yield this.octokit.request(options);
|
||||
const release = response.data;
|
||||
tagInfo.date = (0, moment_1.default)(release.created_at);
|
||||
core.info(`ℹ️ Retrieved information about the release associated with ${tagInfo.name} from the GitHub API`);
|
||||
}
|
||||
catch (error) {
|
||||
core.info(`⚠️ No release information found for ${tagInfo.name}, trying to retrieve tag creation time as fallback.`);
|
||||
const gitHelper = yield (0, gitHelper_1.createCommandManager)(repositoryPath);
|
||||
const creationTimeString = yield gitHelper.tagCreation(tagInfo.name);
|
||||
const creationTime = (0, moment_1.default)(creationTimeString);
|
||||
if (creationTimeString !== null && creationTime.isValid()) {
|
||||
tagInfo.date = creationTime;
|
||||
core.info(`ℹ️ Resolved tag creation time (${creationTimeString}) from 'git for-each-ref --format="%(creatordate:rfc)" "refs/tags/${tagInfo.name}`);
|
||||
}
|
||||
else {
|
||||
core.info(`⚠️ Could not retrieve tag creation time via git cli 'git for-each-ref --format="%(creatordate:rfc)" "refs/tags/${tagInfo.name}'`);
|
||||
}
|
||||
}
|
||||
return tagInfo;
|
||||
});
|
||||
}
|
||||
findPredecessorTag(sortedTags, repositoryPath, tag, ignorePreReleases) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const tags = sortedTags;
|
||||
@@ -1364,7 +1462,7 @@ exports.validateTransformer = exports.fillAdditionalPlaceholders = exports.build
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const configuration_1 = __nccwpck_require__(5527);
|
||||
const pullRequests_1 = __nccwpck_require__(4217);
|
||||
function buildChangelog(prs, options) {
|
||||
function buildChangelog(diffInfo, prs, options) {
|
||||
// sort to target order
|
||||
const config = options.configuration;
|
||||
const sort = config.sort || configuration_1.DefaultConfiguration.sort;
|
||||
@@ -1546,18 +1644,36 @@ function buildChangelog(prs, options) {
|
||||
transformedChangelog = transformedChangelog.replace(/\${{UNCATEGORIZED_COUNT}}/g, uncategorizedPrs.length.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{OPEN_COUNT}}/g, openPrs.length.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{IGNORED_COUNT}}/g, ignoredPrs.length.toString());
|
||||
// code change placeholders
|
||||
transformedChangelog = transformedChangelog.replace(/\${{CHANGED_FILES}}/g, diffInfo.changedFiles.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{ADDITIONS}}/g, diffInfo.additions.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{DELETIONS}}/g, diffInfo.deletions.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{CHANGES}}/g, diffInfo.changes.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{COMMITS}}/g, diffInfo.commits.toString());
|
||||
transformedChangelog = fillAdditionalPlaceholders(transformedChangelog, options);
|
||||
core.info(`ℹ️ Filled template`);
|
||||
return transformedChangelog;
|
||||
}
|
||||
exports.buildChangelog = buildChangelog;
|
||||
function fillAdditionalPlaceholders(text, options) {
|
||||
var _a, _b;
|
||||
let transformed = text;
|
||||
// repository placeholders
|
||||
transformed = transformed.replace(/\${{OWNER}}/g, options.owner);
|
||||
transformed = transformed.replace(/\${{REPO}}/g, options.repo);
|
||||
transformed = transformed.replace(/\${{FROM_TAG}}/g, options.fromTag);
|
||||
transformed = transformed.replace(/\${{TO_TAG}}/g, options.toTag);
|
||||
transformed = transformed.replace(/\${{RELEASE_DIFF}}/g, `https://github.com/${options.owner}/${options.repo}/compare/${options.fromTag}...${options.toTag}`);
|
||||
transformed = transformed.replace(/\${{FROM_TAG}}/g, options.fromTag.name);
|
||||
transformed = transformed.replace(/\${{FROM_TAG_DATE}}/g, ((_a = options.fromTag.date) === null || _a === void 0 ? void 0 : _a.toISOString()) || '');
|
||||
transformed = transformed.replace(/\${{TO_TAG}}/g, options.toTag.name);
|
||||
transformed = transformed.replace(/\${{TO_TAG_DATE}}/g, ((_b = options.toTag.date) === null || _b === void 0 ? void 0 : _b.toISOString()) || '');
|
||||
const fromDate = options.fromTag.date;
|
||||
const toDate = options.toTag.date;
|
||||
if (fromDate !== undefined && toDate !== undefined) {
|
||||
transformed = transformed.replace(/\${{DAYS_SINCE}}/g, toDate.diff(fromDate, 'days').toString() || '');
|
||||
}
|
||||
else {
|
||||
transformed = transformed.replace(/\${{DAYS_SINCE}}/g, '');
|
||||
}
|
||||
transformed = transformed.replace(/\${{RELEASE_DIFF}}/g, `https://github.com/${options.owner}/${options.repo}/compare/${options.fromTag.name}...${options.toTag.name}`);
|
||||
return transformed;
|
||||
}
|
||||
exports.fillAdditionalPlaceholders = fillAdditionalPlaceholders;
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+438
-40
@@ -17,15 +17,15 @@
|
||||
"moment": "^2.29.4",
|
||||
"semver": "^7.3.7",
|
||||
"tunnel": "^0.0.6",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.74.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/node": "^18.0.6",
|
||||
"@typescript-eslint/parser": "^5.30.7",
|
||||
"@types/node": "^18.6.1",
|
||||
"@typescript-eslint/parser": "^5.31.0",
|
||||
"@vercel/ncc": "^0.34.0",
|
||||
"eslint": "^8.20.0",
|
||||
"eslint-plugin-github": "^4.3.6",
|
||||
"eslint-plugin-github": "^4.3.7",
|
||||
"eslint-plugin-jest": "^26.6.0",
|
||||
"jest": "^28.1.3",
|
||||
"jest-circus": "^28.1.3",
|
||||
@@ -592,6 +592,31 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
|
||||
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime-corejs3": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz",
|
||||
"integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"core-js-pure": "^3.20.2",
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
|
||||
@@ -1569,9 +1594,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz",
|
||||
"integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw=="
|
||||
"version": "18.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz",
|
||||
"integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg=="
|
||||
},
|
||||
"node_modules/@types/prettier": {
|
||||
"version": "2.6.3",
|
||||
@@ -1639,14 +1664,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.30.7",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz",
|
||||
"integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==",
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz",
|
||||
"integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.30.7",
|
||||
"@typescript-eslint/types": "5.30.7",
|
||||
"@typescript-eslint/typescript-estree": "5.30.7",
|
||||
"@typescript-eslint/scope-manager": "5.31.0",
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"@typescript-eslint/typescript-estree": "5.31.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1665,6 +1690,80 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz",
|
||||
"integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"@typescript-eslint/visitor-keys": "5.31.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz",
|
||||
"integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz",
|
||||
"integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"@typescript-eslint/visitor-keys": "5.31.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.7",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz",
|
||||
"integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.30.7",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz",
|
||||
@@ -2082,6 +2181,19 @@
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/aria-query": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz",
|
||||
"integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.10.2",
|
||||
"@babel/runtime-corejs3": "^7.10.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/array-includes": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
|
||||
@@ -2128,6 +2240,27 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-types-flow": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
||||
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/axe-core": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
|
||||
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
||||
"integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
"version": "28.1.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz",
|
||||
@@ -2461,6 +2594,17 @@
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js-pure": {
|
||||
"version": "3.24.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.24.0.tgz",
|
||||
"integrity": "sha512-uzMmW8cRh7uYw4JQtzqvGWRyC2T5+4zipQLQdi2FmiRqP83k3d6F3stv2iAlNhOs6cXN401FCD5TL0vvleuHgA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
@@ -2475,6 +2619,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -2869,9 +3019,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-github": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.3.6.tgz",
|
||||
"integrity": "sha512-W4l9CV1DdSaWYZXWiuH/v0bh3c55iFyyhw2EgIwdAeRxogn7svsI5MLBRA9YZ0cdQyekWMZUfAHEeFhDpOyzWg==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.3.7.tgz",
|
||||
"integrity": "sha512-tYZdXvAEz4JCMrC4NHIUoJTsLUvydCxff5OqB5hgU0vQbLmMkw6VOipN2KNe+T06pEhAWs1KBEwyq9cmMWRe7A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.1.0",
|
||||
@@ -2882,9 +3032,11 @@
|
||||
"eslint-plugin-filenames": "^1.3.2",
|
||||
"eslint-plugin-i18n-text": "^1.0.1",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.0",
|
||||
"eslint-plugin-no-only-tests": "^2.6.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-rule-documentation": ">=1.0.0",
|
||||
"jsx-ast-utils": "^3.3.2",
|
||||
"prettier": "^2.2.1",
|
||||
"svg-element-attributes": "^1.3.1"
|
||||
},
|
||||
@@ -2982,6 +3134,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y": {
|
||||
"version": "6.6.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz",
|
||||
"integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.9",
|
||||
"aria-query": "^4.2.2",
|
||||
"array-includes": "^3.1.5",
|
||||
"ast-types-flow": "^0.0.7",
|
||||
"axe-core": "^4.4.3",
|
||||
"axobject-query": "^2.2.0",
|
||||
"damerau-levenshtein": "^1.0.8",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"has": "^1.0.3",
|
||||
"jsx-ast-utils": "^3.3.2",
|
||||
"language-tags": "^1.0.5",
|
||||
"minimatch": "^3.1.2",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-no-only-tests": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-2.6.0.tgz",
|
||||
@@ -4619,6 +4813,19 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsx-ast-utils": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz",
|
||||
"integrity": "sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"array-includes": "^3.1.5",
|
||||
"object.assign": "^4.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
@@ -4628,6 +4835,21 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/language-subtag-registry": {
|
||||
"version": "0.3.22",
|
||||
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
|
||||
"integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/language-tags": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
|
||||
"integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"language-subtag-registry": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
@@ -5351,6 +5573,12 @@
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||
@@ -6195,20 +6423,20 @@
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.73.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
|
||||
"integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
|
||||
"version": "5.74.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
|
||||
"integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^0.0.51",
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/wasm-edit": "1.11.1",
|
||||
"@webassemblyjs/wasm-parser": "1.11.1",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-assertions": "^1.7.6",
|
||||
"browserslist": "^4.14.5",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.9.3",
|
||||
"enhanced-resolve": "^5.10.0",
|
||||
"es-module-lexer": "^0.9.0",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
@@ -6221,7 +6449,7 @@
|
||||
"schema-utils": "^3.1.0",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.1.3",
|
||||
"watchpack": "^2.3.1",
|
||||
"watchpack": "^2.4.0",
|
||||
"webpack-sources": "^3.2.3"
|
||||
},
|
||||
"bin": {
|
||||
@@ -6836,6 +7064,25 @@
|
||||
"@babel/helper-plugin-utils": "^7.18.6"
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
|
||||
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@babel/runtime-corejs3": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz",
|
||||
"integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-js-pure": "^3.20.2",
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
|
||||
@@ -7653,9 +7900,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz",
|
||||
"integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw=="
|
||||
"version": "18.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz",
|
||||
"integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg=="
|
||||
},
|
||||
"@types/prettier": {
|
||||
"version": "2.6.3",
|
||||
@@ -7707,15 +7954,58 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "5.30.7",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz",
|
||||
"integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==",
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz",
|
||||
"integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "5.30.7",
|
||||
"@typescript-eslint/types": "5.30.7",
|
||||
"@typescript-eslint/typescript-estree": "5.30.7",
|
||||
"@typescript-eslint/scope-manager": "5.31.0",
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"@typescript-eslint/typescript-estree": "5.31.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz",
|
||||
"integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"@typescript-eslint/visitor-keys": "5.31.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz",
|
||||
"integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz",
|
||||
"integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"@typescript-eslint/visitor-keys": "5.31.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.7",
|
||||
"tsutils": "^3.21.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "5.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz",
|
||||
"integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.31.0",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
@@ -8032,6 +8322,16 @@
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"aria-query": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz",
|
||||
"integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.10.2",
|
||||
"@babel/runtime-corejs3": "^7.10.2"
|
||||
}
|
||||
},
|
||||
"array-includes": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
|
||||
@@ -8063,6 +8363,24 @@
|
||||
"es-shim-unscopables": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ast-types-flow": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
||||
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
||||
"dev": true
|
||||
},
|
||||
"axe-core": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
|
||||
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==",
|
||||
"dev": true
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
||||
"integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-jest": {
|
||||
"version": "28.1.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz",
|
||||
@@ -8315,6 +8633,12 @@
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"core-js-pure": {
|
||||
"version": "3.24.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.24.0.tgz",
|
||||
"integrity": "sha512-uzMmW8cRh7uYw4JQtzqvGWRyC2T5+4zipQLQdi2FmiRqP83k3d6F3stv2iAlNhOs6cXN401FCD5TL0vvleuHgA==",
|
||||
"dev": true
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
@@ -8326,6 +8650,12 @@
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -8632,9 +8962,9 @@
|
||||
}
|
||||
},
|
||||
"eslint-plugin-github": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.3.6.tgz",
|
||||
"integrity": "sha512-W4l9CV1DdSaWYZXWiuH/v0bh3c55iFyyhw2EgIwdAeRxogn7svsI5MLBRA9YZ0cdQyekWMZUfAHEeFhDpOyzWg==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.3.7.tgz",
|
||||
"integrity": "sha512-tYZdXvAEz4JCMrC4NHIUoJTsLUvydCxff5OqB5hgU0vQbLmMkw6VOipN2KNe+T06pEhAWs1KBEwyq9cmMWRe7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.1.0",
|
||||
@@ -8645,9 +8975,11 @@
|
||||
"eslint-plugin-filenames": "^1.3.2",
|
||||
"eslint-plugin-i18n-text": "^1.0.1",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.0",
|
||||
"eslint-plugin-no-only-tests": "^2.6.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-rule-documentation": ">=1.0.0",
|
||||
"jsx-ast-utils": "^3.3.2",
|
||||
"prettier": "^2.2.1",
|
||||
"svg-element-attributes": "^1.3.1"
|
||||
}
|
||||
@@ -8715,6 +9047,41 @@
|
||||
"@typescript-eslint/utils": "^5.10.0"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-jsx-a11y": {
|
||||
"version": "6.6.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz",
|
||||
"integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.18.9",
|
||||
"aria-query": "^4.2.2",
|
||||
"array-includes": "^3.1.5",
|
||||
"ast-types-flow": "^0.0.7",
|
||||
"axe-core": "^4.4.3",
|
||||
"axobject-query": "^2.2.0",
|
||||
"damerau-levenshtein": "^1.0.8",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"has": "^1.0.3",
|
||||
"jsx-ast-utils": "^3.3.2",
|
||||
"language-tags": "^1.0.5",
|
||||
"minimatch": "^3.1.2",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-no-only-tests": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-2.6.0.tgz",
|
||||
@@ -9909,12 +10276,37 @@
|
||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"dev": true
|
||||
},
|
||||
"jsx-ast-utils": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz",
|
||||
"integrity": "sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-includes": "^3.1.5",
|
||||
"object.assign": "^4.1.2"
|
||||
}
|
||||
},
|
||||
"kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
||||
"dev": true
|
||||
},
|
||||
"language-subtag-registry": {
|
||||
"version": "0.3.22",
|
||||
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
|
||||
"integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
|
||||
"dev": true
|
||||
},
|
||||
"language-tags": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
|
||||
"integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"language-subtag-registry": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
@@ -10444,6 +10836,12 @@
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||
"dev": true
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
||||
"dev": true
|
||||
},
|
||||
"regexp.prototype.flags": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||
@@ -11024,20 +11422,20 @@
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.73.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
|
||||
"integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
|
||||
"version": "5.74.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
|
||||
"integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
|
||||
"requires": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^0.0.51",
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/wasm-edit": "1.11.1",
|
||||
"@webassemblyjs/wasm-parser": "1.11.1",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-assertions": "^1.7.6",
|
||||
"browserslist": "^4.14.5",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.9.3",
|
||||
"enhanced-resolve": "^5.10.0",
|
||||
"es-module-lexer": "^0.9.0",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
@@ -11050,7 +11448,7 @@
|
||||
"schema-utils": "^3.1.0",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.1.3",
|
||||
"watchpack": "^2.3.1",
|
||||
"watchpack": "^2.4.0",
|
||||
"webpack-sources": "^3.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+4
-4
@@ -40,15 +40,15 @@
|
||||
"moment": "^2.29.4",
|
||||
"semver": "^7.3.7",
|
||||
"tunnel": "^0.0.6",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.74.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/node": "^18.0.6",
|
||||
"@typescript-eslint/parser": "^5.30.7",
|
||||
"@types/node": "^18.6.1",
|
||||
"@typescript-eslint/parser": "^5.31.0",
|
||||
"@vercel/ncc": "^0.34.0",
|
||||
"eslint": "^8.20.0",
|
||||
"eslint-plugin-github": "^4.3.6",
|
||||
"eslint-plugin-github": "^4.3.7",
|
||||
"eslint-plugin-jest": "^26.6.0",
|
||||
"jest": "^28.1.3",
|
||||
"jest-circus": "^28.1.3",
|
||||
|
||||
+47
-10
@@ -2,6 +2,24 @@ import * as core from '@actions/core'
|
||||
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
|
||||
import moment from 'moment'
|
||||
|
||||
export interface DiffInfo {
|
||||
changedFiles: number
|
||||
additions: number
|
||||
deletions: number
|
||||
changes: number
|
||||
commits: number
|
||||
commitInfo: CommitInfo[]
|
||||
}
|
||||
|
||||
export const DefaultDiffInfo: DiffInfo = {
|
||||
changedFiles: 0,
|
||||
additions: 0,
|
||||
deletions: 0,
|
||||
changes: 0,
|
||||
commits: 0,
|
||||
commitInfo: []
|
||||
}
|
||||
|
||||
export interface CommitInfo {
|
||||
sha: string
|
||||
summary: string
|
||||
@@ -18,14 +36,10 @@ export class Commits {
|
||||
repo: string,
|
||||
base: string,
|
||||
head: string
|
||||
): Promise<CommitInfo[]> {
|
||||
const commits: CommitInfo[] = await this.getDiffRemote(
|
||||
owner,
|
||||
repo,
|
||||
base,
|
||||
head
|
||||
)
|
||||
return this.sortCommits(commits)
|
||||
): Promise<DiffInfo> {
|
||||
const diff: DiffInfo = await this.getDiffRemote(owner, repo, base, head)
|
||||
diff.commitInfo = this.sortCommits(diff.commitInfo)
|
||||
return diff
|
||||
}
|
||||
|
||||
private async getDiffRemote(
|
||||
@@ -33,7 +47,13 @@ export class Commits {
|
||||
repo: string,
|
||||
base: string,
|
||||
head: string
|
||||
): Promise<CommitInfo[]> {
|
||||
): Promise<DiffInfo> {
|
||||
let changedFilesCount = 0
|
||||
let additionCount = 0
|
||||
let deletionCount = 0
|
||||
let changeCount = 0
|
||||
let commitCount = 0
|
||||
|
||||
// Fetch comparisons recursively until we don't find any commits
|
||||
// This is because the GitHub API limits the number of commits returned in a single response.
|
||||
let commits: RestEndpointMethodTypes['repos']['compareCommits']['response']['data']['commits'] =
|
||||
@@ -50,6 +70,16 @@ export class Commits {
|
||||
if (compareResult.data.total_commits === 0) {
|
||||
break
|
||||
}
|
||||
changedFilesCount += compareResult.data.files?.length ?? 0
|
||||
const files = compareResult.data.files
|
||||
if (files !== undefined) {
|
||||
for (const file of files) {
|
||||
additionCount += file.additions
|
||||
deletionCount += file.deletions
|
||||
changeCount += file.changes
|
||||
}
|
||||
}
|
||||
commitCount += compareResult.data.commits.length
|
||||
commits = compareResult.data.commits.concat(commits)
|
||||
compareHead = `${commits[0].sha}^`
|
||||
}
|
||||
@@ -58,7 +88,13 @@ export class Commits {
|
||||
`ℹ️ Found ${commits.length} commits from the GitHub API for ${owner}/${repo}`
|
||||
)
|
||||
|
||||
return commits
|
||||
return {
|
||||
changedFiles: changedFilesCount,
|
||||
additions: additionCount,
|
||||
deletions: deletionCount,
|
||||
changes: changeCount,
|
||||
commits: commitCount,
|
||||
commitInfo: commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => ({
|
||||
sha: commit.sha || '',
|
||||
@@ -69,6 +105,7 @@ export class Commits {
|
||||
prNumber: undefined
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
private sortCommits(commits: CommitInfo[]): CommitInfo[] {
|
||||
const commitsResult = []
|
||||
|
||||
@@ -44,6 +44,15 @@ class GitCommandManager {
|
||||
return revListOutput.stdout.trim()
|
||||
}
|
||||
|
||||
async tagCreation(tagName: string): Promise<string> {
|
||||
const creationDate = await this.execGit([
|
||||
'for-each-ref',
|
||||
'--format="%(creatordate:rfc)"',
|
||||
`refs/tags/${tagName}`
|
||||
])
|
||||
return creationDate.stdout.trim().replace(/"/g, '')
|
||||
}
|
||||
|
||||
static async createCommandManager(
|
||||
workingDirectory: string
|
||||
): Promise<GitCommandManager> {
|
||||
|
||||
@@ -36,6 +36,8 @@ async function run(): Promise<void> {
|
||||
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true'
|
||||
const failOnError = core.getInput('failOnError') === 'true'
|
||||
const fetchReviewers = core.getInput('fetchReviewers') === 'true'
|
||||
const fetchReleaseInformation =
|
||||
core.getInput('fetchReleaseInformation') === 'true'
|
||||
const commitMode = core.getInput('commitMode') === 'true'
|
||||
|
||||
const result = await new ReleaseNotesBuilder(
|
||||
@@ -50,6 +52,7 @@ async function run(): Promise<void> {
|
||||
failOnError,
|
||||
ignorePreReleases,
|
||||
fetchReviewers,
|
||||
fetchReleaseInformation,
|
||||
commitMode,
|
||||
configuration
|
||||
).build()
|
||||
|
||||
+57
-26
@@ -1,19 +1,21 @@
|
||||
import * as core from '@actions/core'
|
||||
import {CommitInfo, Commits, filterCommits} from './commits'
|
||||
import {Commits, filterCommits, DiffInfo, DefaultDiffInfo} from './commits'
|
||||
import {Configuration, DefaultConfiguration} from './configuration'
|
||||
import {PullRequestInfo, PullRequests} from './pullRequests'
|
||||
import {Octokit} from '@octokit/rest'
|
||||
import {buildChangelog} from './transform'
|
||||
import {buildChangelog, fillAdditionalPlaceholders} from './transform'
|
||||
import {failOrError} from './utils'
|
||||
import {TagInfo} from './tags'
|
||||
|
||||
export interface ReleaseNotesOptions {
|
||||
owner: string // the owner of the repository
|
||||
repo: string // the repository
|
||||
fromTag: string // the tag/ref to start from
|
||||
toTag: string // the tag/ref up to
|
||||
fromTag: TagInfo // the tag/ref to start from
|
||||
toTag: TagInfo // the tag/ref up to
|
||||
includeOpen: boolean // defines if we should also fetch open pull requests
|
||||
failOnError: boolean // defines if we should fail the action in case of an error
|
||||
fetchReviewers: boolean // defines if the action should fetch the reviewers for PRs - approved reviewers are not included in the default PR listing
|
||||
fetchReleaseInformation: boolean // defines if the action should fetch the release information for the from and to tag - e.g. the creation date for the associated release
|
||||
commitMode: boolean // defines if we use the alternative commit based mode. note: this is only partially supported
|
||||
configuration: Configuration // the configuration as defined in `configuration.ts`
|
||||
}
|
||||
@@ -21,11 +23,15 @@ export interface ReleaseNotesOptions {
|
||||
export class ReleaseNotes {
|
||||
constructor(private octokit: Octokit, private options: ReleaseNotesOptions) {}
|
||||
|
||||
async pull(): Promise<string | null> {
|
||||
async pull(): Promise<string> {
|
||||
let mergedPullRequests: PullRequestInfo[]
|
||||
let diffInfo: DiffInfo
|
||||
if (!this.options.commitMode) {
|
||||
core.startGroup(`🚀 Load pull requests`)
|
||||
mergedPullRequests = await this.getMergedPullRequests(this.octokit)
|
||||
|
||||
const [info, prs] = await this.getMergedPullRequests(this.octokit)
|
||||
mergedPullRequests = prs
|
||||
diffInfo = info
|
||||
|
||||
// define the included PRs within this release as output
|
||||
core.setOutput(
|
||||
@@ -41,53 +47,74 @@ export class ReleaseNotes {
|
||||
} else {
|
||||
core.startGroup(`🚀 Load commit history`)
|
||||
core.info(`⚠️ Executing experimental commit mode`)
|
||||
mergedPullRequests = await this.generateCommitPRs(this.octokit)
|
||||
const [info, prs] = await this.generateCommitPRs(this.octokit)
|
||||
mergedPullRequests = prs
|
||||
diffInfo = info
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
core.setOutput('changed_files', diffInfo.changedFiles)
|
||||
core.setOutput('additions', diffInfo.additions)
|
||||
core.setOutput('deletions', diffInfo.deletions)
|
||||
core.setOutput('changes', diffInfo.changes)
|
||||
core.setOutput('commits', diffInfo.commits)
|
||||
|
||||
if (mergedPullRequests.length === 0) {
|
||||
core.warning(`⚠️ No pull requests found`)
|
||||
return null
|
||||
return fillAdditionalPlaceholders(
|
||||
this.options.configuration.empty_template ||
|
||||
DefaultConfiguration.empty_template,
|
||||
this.options
|
||||
)
|
||||
}
|
||||
|
||||
core.startGroup('📦 Build changelog')
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, this.options)
|
||||
const resultChangelog = buildChangelog(
|
||||
diffInfo,
|
||||
mergedPullRequests,
|
||||
this.options
|
||||
)
|
||||
core.endGroup()
|
||||
return resultChangelog
|
||||
}
|
||||
|
||||
private async getCommitHistory(octokit: Octokit): Promise<CommitInfo[]> {
|
||||
private async getCommitHistory(octokit: Octokit): Promise<DiffInfo> {
|
||||
const {owner, repo, fromTag, toTag, failOnError} = this.options
|
||||
core.info(`ℹ️ Comparing ${owner}/${repo} - '${fromTag}...${toTag}'`)
|
||||
core.info(
|
||||
`ℹ️ Comparing ${owner}/${repo} - '${fromTag.name}...${toTag.name}'`
|
||||
)
|
||||
|
||||
const commitsApi = new Commits(octokit)
|
||||
let commits: CommitInfo[]
|
||||
let diffInfo: DiffInfo
|
||||
try {
|
||||
commits = await commitsApi.getDiff(owner, repo, fromTag, toTag)
|
||||
diffInfo = await commitsApi.getDiff(owner, repo, fromTag.name, toTag.name)
|
||||
} catch (error) {
|
||||
failOrError(
|
||||
`💥 Failed to retrieve - Invalid tag? - Because of: ${error}`,
|
||||
failOnError
|
||||
)
|
||||
return []
|
||||
return DefaultDiffInfo
|
||||
}
|
||||
if (commits.length === 0) {
|
||||
core.warning(`⚠️ No commits found between - ${fromTag}...${toTag}`)
|
||||
return []
|
||||
if (diffInfo.commitInfo.length === 0) {
|
||||
core.warning(
|
||||
`⚠️ No commits found between - ${fromTag.name}...${toTag.name}`
|
||||
)
|
||||
return DefaultDiffInfo
|
||||
}
|
||||
|
||||
return commits
|
||||
return diffInfo
|
||||
}
|
||||
|
||||
private async getMergedPullRequests(
|
||||
octokit: Octokit
|
||||
): Promise<PullRequestInfo[]> {
|
||||
): Promise<[DiffInfo, PullRequestInfo[]]> {
|
||||
const {owner, repo, includeOpen, fetchReviewers, configuration} =
|
||||
this.options
|
||||
|
||||
const commits = await this.getCommitHistory(octokit)
|
||||
const diffInfo = await this.getCommitHistory(octokit)
|
||||
const commits = diffInfo.commitInfo
|
||||
if (commits.length === 0) {
|
||||
return []
|
||||
return [diffInfo, []]
|
||||
}
|
||||
|
||||
const firstCommit = commits[0]
|
||||
@@ -191,19 +218,22 @@ export class ReleaseNotes {
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.debug(`ℹ️ Fetching reviewers was disabled`)
|
||||
}
|
||||
|
||||
return finalPrs
|
||||
return [diffInfo, finalPrs]
|
||||
}
|
||||
|
||||
private async generateCommitPRs(
|
||||
octokit: Octokit
|
||||
): Promise<PullRequestInfo[]> {
|
||||
): Promise<[DiffInfo, PullRequestInfo[]]> {
|
||||
const {owner, repo, configuration} = this.options
|
||||
|
||||
const commits = await this.getCommitHistory(octokit)
|
||||
const diffInfo = await this.getCommitHistory(octokit)
|
||||
const commits = diffInfo.commitInfo
|
||||
if (commits.length === 0) {
|
||||
return []
|
||||
return [diffInfo, []]
|
||||
}
|
||||
|
||||
const prCommits = filterCommits(
|
||||
@@ -214,7 +244,7 @@ export class ReleaseNotes {
|
||||
|
||||
core.info(`ℹ️ Retrieved ${prCommits.length} commits for ${owner}/${repo}`)
|
||||
|
||||
return prCommits.map(function (commit): PullRequestInfo {
|
||||
const prs = prCommits.map(function (commit): PullRequestInfo {
|
||||
return {
|
||||
number: 0,
|
||||
title: commit.summary,
|
||||
@@ -234,5 +264,6 @@ export class ReleaseNotes {
|
||||
status: 'merged'
|
||||
}
|
||||
})
|
||||
return [diffInfo, prs]
|
||||
}
|
||||
}
|
||||
|
||||
+31
-19
@@ -4,7 +4,6 @@ import {Octokit} from '@octokit/rest'
|
||||
import {ReleaseNotes} from './releaseNotes'
|
||||
import {Tags} from './tags'
|
||||
import {failOrError} from './utils'
|
||||
import {fillAdditionalPlaceholders} from './transform'
|
||||
|
||||
export class ReleaseNotesBuilder {
|
||||
constructor(
|
||||
@@ -19,6 +18,7 @@ export class ReleaseNotesBuilder {
|
||||
private failOnError: boolean,
|
||||
private ignorePreReleases: boolean,
|
||||
private fetchReviewers: boolean = false,
|
||||
private fetchReleaseInformation: boolean = false,
|
||||
private commitMode: boolean,
|
||||
private configuration: Configuration
|
||||
) {}
|
||||
@@ -62,17 +62,16 @@ export class ReleaseNotesBuilder {
|
||||
this.configuration.tag_resolver || DefaultConfiguration.tag_resolver
|
||||
)
|
||||
|
||||
const thisTag = tagRange.to?.name
|
||||
let thisTag = tagRange.to
|
||||
if (!thisTag) {
|
||||
failOrError(`💥 Missing or couldn't resolve 'toTag'`, this.failOnError)
|
||||
return null
|
||||
} else {
|
||||
this.toTag = thisTag
|
||||
core.setOutput('toTag', thisTag)
|
||||
core.debug(`Resolved 'toTag' as ${thisTag}`)
|
||||
core.setOutput('toTag', thisTag.name)
|
||||
core.debug(`Resolved 'toTag' as ${thisTag.name}`)
|
||||
}
|
||||
|
||||
const previousTag = tagRange.from?.name
|
||||
let previousTag = tagRange.from
|
||||
if (previousTag == null) {
|
||||
failOrError(
|
||||
`💥 Unable to retrieve previous tag given ${this.toTag}`,
|
||||
@@ -80,31 +79,44 @@ export class ReleaseNotesBuilder {
|
||||
)
|
||||
return null
|
||||
}
|
||||
this.fromTag = previousTag
|
||||
core.setOutput('fromTag', previousTag)
|
||||
core.debug(`fromTag resolved via previousTag as: ${previousTag}`)
|
||||
core.setOutput('fromTag', previousTag.name)
|
||||
core.debug(`fromTag resolved via previousTag as: ${previousTag.name}`)
|
||||
|
||||
if (this.fetchReleaseInformation) {
|
||||
// load release information from the GitHub API
|
||||
core.info(`ℹ️ Fetching release information was enabled`)
|
||||
thisTag = await tagsApi.fillTagInformation(
|
||||
this.repositoryPath,
|
||||
this.owner,
|
||||
this.repo,
|
||||
thisTag
|
||||
)
|
||||
previousTag = await tagsApi.fillTagInformation(
|
||||
this.repositoryPath,
|
||||
this.owner,
|
||||
this.repo,
|
||||
previousTag
|
||||
)
|
||||
} else {
|
||||
core.debug(`ℹ️ Fetching release information was disabled`)
|
||||
}
|
||||
|
||||
core.endGroup()
|
||||
|
||||
const options = {
|
||||
owner: this.owner,
|
||||
repo: this.repo,
|
||||
fromTag: this.fromTag,
|
||||
toTag: this.toTag,
|
||||
fromTag: previousTag,
|
||||
toTag: thisTag,
|
||||
includeOpen: this.includeOpen,
|
||||
failOnError: this.failOnError,
|
||||
fetchReviewers: this.fetchReviewers,
|
||||
fetchReleaseInformation: this.fetchReleaseInformation,
|
||||
commitMode: this.commitMode,
|
||||
configuration: this.configuration
|
||||
}
|
||||
const releaseNotes = new ReleaseNotes(octokit, options)
|
||||
|
||||
return (
|
||||
(await releaseNotes.pull()) ||
|
||||
fillAdditionalPlaceholders(
|
||||
this.configuration.empty_template ||
|
||||
DefaultConfiguration.empty_template,
|
||||
options
|
||||
)
|
||||
)
|
||||
return await releaseNotes.pull()
|
||||
}
|
||||
}
|
||||
|
||||
+46
-1
@@ -6,6 +6,7 @@ import {SemVer} from 'semver'
|
||||
import {TagResolver} from './configuration'
|
||||
import {createCommandManager} from './gitHelper'
|
||||
import {RegexTransformer, validateTransformer} from './transform'
|
||||
import moment from 'moment'
|
||||
|
||||
export interface TagResult {
|
||||
from: TagInfo | null
|
||||
@@ -14,7 +15,8 @@ export interface TagResult {
|
||||
|
||||
export interface TagInfo {
|
||||
name: string
|
||||
commit: string
|
||||
commit?: string
|
||||
date?: moment.Moment
|
||||
}
|
||||
|
||||
export interface SortableTagInfo extends TagInfo {
|
||||
@@ -61,6 +63,49 @@ export class Tags {
|
||||
return tagsInfo
|
||||
}
|
||||
|
||||
async fillTagInformation(
|
||||
repositoryPath: string,
|
||||
owner: string,
|
||||
repo: string,
|
||||
tagInfo: TagInfo
|
||||
): Promise<TagInfo> {
|
||||
const options = this.octokit.repos.getReleaseByTag.endpoint.merge({
|
||||
owner,
|
||||
repo,
|
||||
tag: tagInfo.name
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await this.octokit.request(options)
|
||||
type ReleaseInformation =
|
||||
RestEndpointMethodTypes['repos']['getReleaseByTag']['response']['data']
|
||||
|
||||
const release: ReleaseInformation = response.data as ReleaseInformation
|
||||
tagInfo.date = moment(release.created_at)
|
||||
core.info(
|
||||
`ℹ️ Retrieved information about the release associated with ${tagInfo.name} from the GitHub API`
|
||||
)
|
||||
} catch (error) {
|
||||
core.info(
|
||||
`⚠️ No release information found for ${tagInfo.name}, trying to retrieve tag creation time as fallback.`
|
||||
)
|
||||
const gitHelper = await createCommandManager(repositoryPath)
|
||||
const creationTimeString = await gitHelper.tagCreation(tagInfo.name)
|
||||
const creationTime = moment(creationTimeString)
|
||||
if (creationTimeString !== null && creationTime.isValid()) {
|
||||
tagInfo.date = creationTime
|
||||
core.info(
|
||||
`ℹ️ Resolved tag creation time (${creationTimeString}) from 'git for-each-ref --format="%(creatordate:rfc)" "refs/tags/${tagInfo.name}`
|
||||
)
|
||||
} else {
|
||||
core.info(
|
||||
`⚠️ Could not retrieve tag creation time via git cli 'git for-each-ref --format="%(creatordate:rfc)" "refs/tags/${tagInfo.name}'`
|
||||
)
|
||||
}
|
||||
}
|
||||
return tagInfo
|
||||
}
|
||||
|
||||
async findPredecessorTag(
|
||||
sortedTags: TagInfo[],
|
||||
repositoryPath: string,
|
||||
|
||||
+45
-3
@@ -7,8 +7,10 @@ import {
|
||||
} from './configuration'
|
||||
import {PullRequestInfo, sortPullRequests} from './pullRequests'
|
||||
import {ReleaseNotesOptions} from './releaseNotes'
|
||||
import {DiffInfo} from './commits'
|
||||
|
||||
export function buildChangelog(
|
||||
diffInfo: DiffInfo,
|
||||
prs: PullRequestInfo[],
|
||||
options: ReleaseNotesOptions
|
||||
): string {
|
||||
@@ -272,6 +274,27 @@ export function buildChangelog(
|
||||
/\${{IGNORED_COUNT}}/g,
|
||||
ignoredPrs.length.toString()
|
||||
)
|
||||
// code change placeholders
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{CHANGED_FILES}}/g,
|
||||
diffInfo.changedFiles.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{ADDITIONS}}/g,
|
||||
diffInfo.additions.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{DELETIONS}}/g,
|
||||
diffInfo.deletions.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{CHANGES}}/g,
|
||||
diffInfo.changes.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{COMMITS}}/g,
|
||||
diffInfo.commits.toString()
|
||||
)
|
||||
transformedChangelog = fillAdditionalPlaceholders(
|
||||
transformedChangelog,
|
||||
options
|
||||
@@ -286,13 +309,32 @@ export function fillAdditionalPlaceholders(
|
||||
options: ReleaseNotesOptions
|
||||
): string {
|
||||
let transformed = text
|
||||
// repository placeholders
|
||||
transformed = transformed.replace(/\${{OWNER}}/g, options.owner)
|
||||
transformed = transformed.replace(/\${{REPO}}/g, options.repo)
|
||||
transformed = transformed.replace(/\${{FROM_TAG}}/g, options.fromTag)
|
||||
transformed = transformed.replace(/\${{TO_TAG}}/g, options.toTag)
|
||||
transformed = transformed.replace(/\${{FROM_TAG}}/g, options.fromTag.name)
|
||||
transformed = transformed.replace(
|
||||
/\${{FROM_TAG_DATE}}/g,
|
||||
options.fromTag.date?.toISOString() || ''
|
||||
)
|
||||
transformed = transformed.replace(/\${{TO_TAG}}/g, options.toTag.name)
|
||||
transformed = transformed.replace(
|
||||
/\${{TO_TAG_DATE}}/g,
|
||||
options.toTag.date?.toISOString() || ''
|
||||
)
|
||||
const fromDate = options.fromTag.date
|
||||
const toDate = options.toTag.date
|
||||
if (fromDate !== undefined && toDate !== undefined) {
|
||||
transformed = transformed.replace(
|
||||
/\${{DAYS_SINCE}}/g,
|
||||
toDate.diff(fromDate, 'days').toString() || ''
|
||||
)
|
||||
} else {
|
||||
transformed = transformed.replace(/\${{DAYS_SINCE}}/g, '')
|
||||
}
|
||||
transformed = transformed.replace(
|
||||
/\${{RELEASE_DIFF}}/g,
|
||||
`https://github.com/${options.owner}/${options.repo}/compare/${options.fromTag}...${options.toTag}`
|
||||
`https://github.com/${options.owner}/${options.repo}/compare/${options.fromTag.name}...${options.toTag.name}`
|
||||
)
|
||||
return transformed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user