Merge pull request #1229 from mikepenz/develop

dev -> main
This commit is contained in:
Mike Penz
2023-08-25 13:27:47 +02:00
committed by GitHub
46 changed files with 13904 additions and 11181 deletions
+2 -2
View File
@@ -5,7 +5,7 @@
"image": "mcr.microsoft.com/devcontainers/typescript-node:16-bullseye",
"features": {
"ghcr.io/devcontainers/features/node:1": {},
"ghcr.io/devcontainers-contrib/features/typescript:1": {}
"ghcr.io/devcontainers-contrib/features/typescript:2.0.9": {}
},
// Features to add to the dev container. More info: https://containers.dev/features.
@@ -15,7 +15,7 @@
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "npm install",
"postCreateCommand": "./.devcontainer/postCreateCommand.sh",
// Configure tool-specific properties.
// "customizations": {},
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
npm install
# also install dependencies for `pr-collector`
cd pr-collector
npm install
npm run build && npm run package
cd ..
+10 -5
View File
@@ -32,11 +32,16 @@ jobs:
with:
node-version: 16.x
- name: Install dependencies
run: npm ci
- name: Rebuild the dist/ directory
- name: Build PR-Collector
run: |
cd pr-collector
npm ci
npm run build
npm run package
- name: Build Action
run: |
npm ci
npm run build
npm run package
@@ -44,7 +49,7 @@ jobs:
run: |
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build. See status below:"
git diff
git diff -a
exit 1
fi
id: diff
+50 -6
View File
@@ -24,10 +24,18 @@ jobs:
- name: Install NPM
run: |
cd pr-collector
npm install
cd ..
npm install
- name: Run NPM
run: |
cd pr-collector
npm run all
cd ..
npm run all
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -113,6 +121,19 @@ jobs:
run: echo "CHANGELOG"
# Showcases the capability to generate the changelog for an external repository provided
# Showcase ability to only fetch data first, and then continue with exported data later
- name: "External Repo Configuration Collect Report"
id: external_changelog_collect
uses: ./
with:
owner: "mikepenz"
repo: "MaterialDrawer"
fromTag: "v8.1.0"
toTag: "v8.1.6"
token: ${{ secrets.PERSONAL_TOKEN }}
exportCache: true
exportOnly: true
- name: "External Repo Configuration"
id: external_changelog
uses: ./
@@ -120,14 +141,37 @@ jobs:
configuration: "configs/configuration_complex.json"
owner: "mikepenz"
repo: "MaterialDrawer"
fromTag: "v8.1.0"
toTag: "v8.1.6"
token: ${{ secrets.PERSONAL_TOKEN }}
cache: ${{ steps.external_changelog_collect.outputs.cache }}
- name: "External Repo Configuration Second"
id: external_changelog_second
uses: ./
with:
configurationJson: |
{
"template": "#{{CHANGELOG}}",
"pr_template": "PR: ##{{NUMBER}}",
"categories": [
{
"title": "## Everything",
"labels": []
}
]
}
owner: "mikepenz"
repo: "MaterialDrawer"
cache: ${{ steps.external_changelog_collect.outputs.cache }}
- name: Echo External Repo Configuration Changelog
env:
CHANGELOG: ${{ steps.external_changelog.outputs.changelog }}
run: echo "$CHANGELOG"
CHANGELOG_SECOND: ${{ steps.external_changelog_second.outputs.changelog }}
run: |
echo "First:"
echo "$CHANGELOG"
echo "Second:"
echo "$CHANGELOG_SECOND"
release:
if: startsWith(github.ref, 'refs/tags/')
@@ -138,14 +182,14 @@ jobs:
- name: "Build Changelog"
id: github_release
uses: mikepenz/release-changelog-builder-action@v2
uses: mikepenz/release-changelog-builder-action@v4
with:
configuration: "configs/configuration_repo.json"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
uses: softprops/action-gh-release@6034af24fba4e5a8e975aaa6056554efe4c794d0
uses: mikepenz/action-gh-release@v1
with:
body: ${{steps.github_release.outputs.changelog}}
prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-b') || contains(github.ref, '-a') }}
+3
View File
@@ -97,3 +97,6 @@ Thumbs.db
# Ignore built ts files
__tests__/runner/*
lib/**/*
lib
pr-collector/dist
+39 -11
View File
@@ -90,7 +90,8 @@ A full set list of possible output values for this action.
| `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. |
| `outputs.categorized` | The categorized pull requests used to build the changelog as serialized JSON. |
| `outputs.cache` | The file pointing to the cache for the current fetched data. Can be provided to another action step. |
## Full Sample 🖥️
@@ -99,7 +100,7 @@ Below is a complete example showcasing how to define a build, which is executed
- Build changelog, given the tag
- Create release on GitHub - specifying body with constructed changelog
> Note: PRs will only show up in the changelog if assigned one of the default label categories "feature", "fix" or "test"
> Note: Pre v4 PRs will only show up in the changelog if assigned one of the default label categories "feature", "fix" or "test". Starting with v4 these PRs will be in the `Uncategorized` section.
<details><summary><b>Example</b></summary>
<p>
@@ -211,6 +212,7 @@ This configuration is a `JSON` in the following format. (The below showcases *ex
"labels": ["fix"]
},
{
"key": "tests",
"title": "## 🧪 Tests",
"labels": ["test"]
},
@@ -257,6 +259,12 @@ This configuration is a `JSON` in the following format. (The below showcases *ex
"on_property": "title",
"method": "match"
},
"reference": {
"pattern": ".*\\ \\#(.).*",
"on_property": "body",
"method": "replace",
"target": "$1"
},
"transformers": [
{
"pattern": "[\\-\\*] (\\[(...|TEST|CI|SKIP)\\])( )?(.+?)\n(.+?[\\-\\*] )(.+)",
@@ -325,10 +333,14 @@ For advanced use cases additional settings can be provided to the action
| `includeOpen` | Enables to also fetch currently open PRs. Default: false |
| `ignorePreReleases` | Allows to ignore pre-releases for changelog generation (E.g. for 1.0.1... 1.0.0-rc02 <- ignore, 1.0.0 <- pick). Only used if `fromTag` was not specified. Default: false |
| `failOnError` | Defines if the action will result in a build failure if problems occurred. Default: false |
| `fetchViaCommits` | Enables PRs to get fetched via the commits identified between from->to tag. This will do 1 API request per commit -> Best for scenarios with squash merges | Or shorter from->to diffs (< 10 commits) | Also effective for shorters diffs for very old PRs. Default: false |
| `fetchReviewers` | Will enable fetching the users/reviewers who approved the PR. Default: false |
| `fetchReleaseInformation` | Will enable fetching additional release information from tags. Default: false |
| `fetchReviews` | Will enable fetching the reviews on of the PR. Default: false |
| `commitMode` | Special configuration for projects which work without PRs. Uses commit messages as changelog. This mode looses access to information only available for PRs. Default: false |
| `exportCache` | Will enable exporting the fetched PR information to a cache, which can be re-used by later runs. Default: false |
| `exportOnly` | When enabled, will result in only exporting the cache, without genearting a changelog. Default: false (Requires `exportCache` to be enabled) |
| `cache` | The file path to write/read the cache to/from. |
> **Warning**: `${{ secrets.GITHUB_TOKEN }}` only grants rights to the current repository, for other repositories please use a PAT (Personal Access Token).
@@ -368,8 +380,10 @@ When using `*` values are joined by `,`.
| `${{REVIEWERS[*]}}` | GitHub Login names of specified reviewers. Requires `fetchReviewers` to be enabled. |
| `${{APPROVERS[*]}}` | GitHub Login names of users who approved the PR. |
Additionally there is a special array placeholder `REVIEWS` which allows access to it's properties:
`(KEY)[(*/index)].(property)` for example: `REVIEWS[*].author` or `REVIEWS[*].body`
Additionally there are special array placeholders like `REVIEWS` which allows access to it's properties via
`(KEY)[(*/index)].(property)`.
For example: `REVIEWS[*].author` or `REVIEWS[*].body`
| **Placeholder** | **Description** |
|-------------------------------|--------------------------------------------|
@@ -379,6 +393,14 @@ Additionally there is a special array placeholder `REVIEWS` which allows access
| `${{REVIEWS[*].submittedAt}}` | The date whent he review was submitted. |
| `${{REVIEWS[*].state}}` | The state of the given review. |
Similar to `REVIEWS`, `REFERENCED` PRs also offer special placeholders.
| **Placeholder** | **Description** |
|-------------------------------|---------------------------------------------------------------------------|
| `${{REFERENCED[*].number}}` | The PR number of the referenced PR. |
| `${{REFERENCED[*].title}}` | The title of the referenced PR. |
| `${{REFERENCED[*]."..."}}` | Allows to use most other PR properties as placeholder. |
</p>
</details>
@@ -419,6 +441,7 @@ Table of descriptions for the `configuration.json` options to configure the resu
| **Input** | **Description** |
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| categories | An array of `category` specifications, offering a flexible way to group changes into categories. |
| category.key | Optional key used for the `categorized` json output. |
| category.title | The display name of a category in the changelog. |
| category.labels | An array of labels, to match pull request labels against. If any PR label matches any category label, the pull request will show up under this category. (See `exhaustive` to change this) |
| category.exclude_labels | Similar to `labels`, an array of labels to match PRs against, but if a match occurs the PR is excluded from this category. |
@@ -444,6 +467,7 @@ Table of descriptions for the `configuration.json` options to configure the resu
| label_extractor.flags | Defines the regex flags specified for the pattern. Default: `gu`. |
| label_extractor.on_empty | Defines the placeholder to be filled in, if the regex does not lead to a result. |
| duplicate_filter | Defines the `Extractor` to use for retrieving the identifier for a PR. In case of duplicates will keep the last matching pull request (depends on `sort`). See `label_extractor` for details on `Extractor` properties. |
| reference | Defines the `Extractor` to use for resolving the "PR-number" for a parent PR. In case of a match, the child PR will not be included in the release notes. See `label_extractor` for details on `Extractor` properties. |
| transformers | An array of `transform` specifications, offering a flexible API to modify the text per pull request. This is applied on the change text created with `pr_template`. `transformers` are executed per change, in the order specified |
| transformer.pattern | A `regex` pattern, extracting values of the change message. |
| transformer.target | The result pattern, the regex groups will be filled into. Allows for full transformation of a pull request message. Including potentially specified texts |
@@ -548,16 +572,16 @@ npm test -- custom.test.ts
<p>
```typescript
import {resolveConfiguration} from '../src/utils'
import {mergeConfiguration, resolveConfiguration} from '../src/utils'
import {ReleaseNotesBuilder} from '../src/releaseNotesBuilder'
jest.setTimeout(180000)
it('Test custom changelog builder', async () => {
const configuration = resolveConfiguration(
const configuration = mergeConfiguration(undefined, resolveConfiguration(
'',
'configs_test/configuration_approvers.json'
)
))
const releaseNotesBuilder = new ReleaseNotesBuilder(
null, // baseUrl
null, // token
@@ -566,19 +590,23 @@ it('Test custom changelog builder', async () => {
'release-changelog-builder-action-playground', // repo
'1.5.0', // fromTag
'2.0.0', // toTag
true, // includeOpen
false, // includeOpen
false, // failOnError
false, // ignorePrePrelease
true, // enable to fetch reviewers
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch release information
false, // enable to fetch reviews
false, // commitMode
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration // configuration
)
const changeLog = await releaseNotesBuilder.build()
console.log(changeLog)
expect(changeLog).toStrictEqual(``)
expect(changeLog).toStrictEqual(`define-expected-output`)
})
```
+3 -1
View File
@@ -13,5 +13,7 @@ it('Configurations are merged correctly', async () => {
const mergedConfiguration = mergeConfiguration(configurationJson, configurationFile)
console.log(mergedConfiguration)
expect(JSON.stringify(mergedConfiguration)).toEqual(`{\"max_tags_to_fetch\":200,\"max_pull_requests\":1000,\"max_back_track_time_days\":1000,\"exclude_merge_branches\":[],\"sort\":\"DESC\",\"template\":\"$\{\{CHANGELOG}}\",\"pr_template\":\"- $\{\{TITLE}}\\n - PR: #$\{\{NUMBER}}\",\"empty_template\":\"- no magic changes\",\"categories\":[{\"title\":\"## 🚀 Features\",\"labels\":[\"feature\"]},{\"title\":\"## 🐛 Fixes\",\"labels\":[\"fix\"]},{\"title\":\"## 🧪 Tests\",\"labels\":[\"test\"]}],\"ignore_labels\":[\"ignore\"],\"label_extractor\":[],\"transformers\":[],\"tag_resolver\":{\"method\":\"semver\"},\"base_branches\":[],\"custom_placeholders\":[],\"trim_values\":true}`)
expect(JSON.stringify(mergedConfiguration)).toEqual(
`{\"max_tags_to_fetch\":200,\"max_pull_requests\":1000,\"max_back_track_time_days\":1000,\"exclude_merge_branches\":[],\"sort\":\"DESC\",\"template\":\"$\{\{CHANGELOG}}\",\"pr_template\":\"- $\{\{TITLE}}\\n - PR: #$\{\{NUMBER}}\",\"empty_template\":\"- no magic changes\",\"categories\":[{\"title\":\"## 🚀 Features\",\"labels\":[\"feature\"]},{\"title\":\"## 🐛 Fixes\",\"labels\":[\"fix\"]},{\"title\":\"## 🧪 Tests\",\"labels\":[\"test\"]}],\"ignore_labels\":[\"ignore\"],\"label_extractor\":[],\"transformers\":[],\"tag_resolver\":{\"method\":\"semver\"},\"base_branches\":[],\"custom_placeholders\":[],\"trim_values\":true}`
)
})
+71 -14
View File
@@ -16,10 +16,14 @@ it('Should match generated changelog (unspecified fromTag)', async () => {
false,
false,
false,
true, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration
)
@@ -46,10 +50,14 @@ it('Should match generated changelog (unspecified tags)', async () => {
false,
false,
false,
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration
)
@@ -71,10 +79,14 @@ it('Should use empty placeholder', async () => {
false,
false,
false,
true, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/rcba_0.0.2-0.0.3_cache.json", // path to the cache
configuration
)
@@ -96,10 +108,14 @@ it('Should fill empty placeholders', async () => {
false,
false,
false,
true, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/rcba_0.0.2-0.0.3_cache.json", // path to the cache
configuration
)
@@ -123,10 +139,14 @@ it('Should fill `template` placeholders', async () => {
false,
false,
false,
true, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/rcba_0.0.1-0.0.3_cache.json", // path to the cache
configuration
)
@@ -139,6 +159,7 @@ it('Should fill `template` placeholders', async () => {
it('Should fill `template` placeholders, ignore', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_empty_all_placeholders.json'))
configuration.categories.pop() // drop `uncategorized` category
const releaseNotesBuilder = new ReleaseNotesBuilder(
null,
null,
@@ -150,10 +171,14 @@ it('Should fill `template` placeholders, ignore', async () => {
false,
false,
false,
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/rcba_0.9.1-0.9.5_cache.json", // path to the cache
configuration
)
@@ -177,10 +202,14 @@ it('Uncategorized category', async () => {
false,
false,
false,
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false,
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/rcba_0.9.1-0.9.5_cache.json", // path to the cache
configuration
)
@@ -204,10 +233,14 @@ it('Verify commit based changelog', async () => {
false,
false,
false,
true, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
true,
true, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/rcba_0.0.1-0.0.3_commit_cache.json", // path to the cache
configuration
)
@@ -231,10 +264,14 @@ it('Verify commit based changelog, with emoji categorisation', async () => {
false,
false,
false,
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
true,
true, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
"caches/stackzy_bd3242-17a9e4_cache.json", // path to the cache
configuration
)
@@ -258,10 +295,14 @@ it('Verify default inclusion of open PRs', async () => {
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false, // commitMode
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration // configuration
)
@@ -285,10 +326,14 @@ it('Verify custom categorisation of open PRs', async () => {
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch via commits
false, // enable to fetch reviewers
false, // enable to fetch tag release information
false, // enable to fetch reviews
false, // commitMode
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration // configuration
)
@@ -312,10 +357,14 @@ it('Verify reviewers who approved are fetched and also release information', asy
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch via commits
true, // enable to fetch reviewers
true, // enable to fetch tag release information
false, // enable to fetch reviews
false, // commitMode
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration // configuration
)
@@ -340,10 +389,14 @@ it('Fetch release information', async () => {
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch via commits
false, // enable to fetch reviewers
true, // enable to fetch tag release information
false, // enable to fetch reviews
false, // commitMode
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration // configuration
)
@@ -366,10 +419,14 @@ it('Fetch release information for non existing tag / release', async () => {
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch via commits
false, // enable to fetch reviewers
true, // enable to fetch tag release information
false, // enable to fetch reviews
false, // commitMode
false, // enable commitMode
false, // enable exportCache
false, // enable exportOnly
null, // path to the cache
configuration // configuration
)
@@ -1,52 +1,72 @@
import {ReleaseNotes} from '../src/releaseNotes'
import {mergeConfiguration, resolveConfiguration} from '../src/utils'
import {checkExportedData, mergeConfiguration, resolveConfiguration} from '../src/utils'
import {Octokit} from '@octokit/rest'
import {buildChangelog} from '../src/transform'
import {pullData} from '../src/pr-collector/prCollector'
import fetch from 'node-fetch'
import { Data } from '../src/releaseNotesBuilder'
jest.setTimeout(180000)
// load octokit instance
const enablePullData = false // if false -> use cache for data
const octokit = new Octokit({
auth: `token ${process.env.GITHUB_TOKEN}`
auth: `token ${process.env.GITHUB_TOKEN}`,
request: {
fetch: fetch
}
})
it('Should have empty changelog (tags)', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs/configuration.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v0.0.1'},
toTag: {name: 'v0.0.2'},
fromTag: {name: 'v0.0.2'},
toTag: {name: 'v0.0.3'},
includeOpen: false,
failOnError: false,
fetchViaCommits: true,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_0.0.2-0.0.3_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual('- no changes')
})
it('Should match generated changelog (tags)', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs/configuration.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v0.0.1'},
toTag: {name: 'v0.0.3'},
includeOpen: false,
failOnError: false,
fetchViaCommits: true,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_0.0.1-0.0.3_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🧪 Tests
@@ -58,21 +78,28 @@ it('Should match generated changelog (tags)', async () => {
it('Should match generated changelog (refs)', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_all_placeholders.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3'},
toTag: {name: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa'},
includeOpen: false,
failOnError: false,
fetchViaCommits: true,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_5ec7a2-fa3788_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🧪 Tests
@@ -92,21 +119,27 @@ nhoelzl
it('Should match generated changelog and replace all occurrences (refs)', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_replace_all_placeholders.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3'},
toTag: {name: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa'},
includeOpen: false,
failOnError: false,
fetchViaCommits: true,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_5ec7a2-fa3788_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🧪 Tests
@@ -128,63 +161,83 @@ nhoelzl
it('Should match ordered ASC', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_asc.json'))
const releaseNotes = new ReleaseNotes(octokit, {
configuration.categories.pop() // drop `uncategorized` category
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v0.3.0'},
toTag: {name: 'v0.5.0'},
includeOpen: false,
failOnError: false,
fetchViaCommits: false,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_0.3.0-0.5.0_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🚀 Features\n\n22\n24\n25\n26\n28\n\n## 🐛 Fixes\n\n23\n\n`)
})
it('Should match ordered DESC', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_desc.json'))
const releaseNotes = new ReleaseNotes(octokit, {
configuration.categories.pop() // drop `uncategorized` category
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v0.3.0'},
toTag: {name: 'v0.5.0'},
includeOpen: false,
failOnError: false,
fetchViaCommits: false,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_0.3.0-0.5.0_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🚀 Features\n\n28\n26\n25\n24\n22\n\n## 🐛 Fixes\n\n23\n\n`)
})
it('Should match ordered by title ASC', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_sort_title_asc.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v0.3.0'},
toTag: {name: 'v0.5.0'},
includeOpen: false,
failOnError: false,
fetchViaCommits: false,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_0.3.0-0.5.0_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(
`## 🚀 Features\n\nEnhanced action logs\nImprove README\nImproved configuration failure handling\nImproved defaults if no configuration is provided\nIntroduce additional placeholders [milestone, labels, assignees, reviewers]\n\n## 🐛 Fixes\n\nImproved handling for non existing tags\n\n`
@@ -193,21 +246,27 @@ it('Should match ordered by title ASC', async () => {
it('Should match ordered by title DESC', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_sort_title_desc.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v0.3.0'},
toTag: {name: 'v0.5.0'},
includeOpen: false,
failOnError: false,
fetchViaCommits: false,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_0.3.0-0.5.0_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(
`## 🚀 Features\n\nIntroduce additional placeholders [milestone, labels, assignees, reviewers]\nImproved defaults if no configuration is provided\nImproved configuration failure handling\nImprove README\nEnhanced action logs\n\n## 🐛 Fixes\n\nImproved handling for non existing tags\n\n`
@@ -216,42 +275,54 @@ it('Should match ordered by title DESC', async () => {
it('Should ignore PRs not merged into develop branch', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_base_branches_develop.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v1.3.1'},
toTag: {name: 'v1.4.0'},
includeOpen: false,
failOnError: false,
fetchViaCommits: true,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_1.3.1-1.4.0_base_develop_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`150\n\n`)
})
it('Should ignore PRs not merged into main branch', async () => {
const configuration = mergeConfiguration(undefined, resolveConfiguration('', 'configs_test/configuration_base_branches_main.json'))
const releaseNotes = new ReleaseNotes(octokit, {
const options = {
owner: 'mikepenz',
repo: 'release-changelog-builder-action',
fromTag: {name: 'v1.3.1'},
toTag: {name: 'v1.4.0'},
includeOpen: false,
failOnError: false,
fetchViaCommits: true,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration
})
const changeLog = await releaseNotes.pull()
}
let data: any
if (enablePullData) {
data = await pullData(octokit, options)
} else {
data = checkExportedData(false, "caches/rcba_1.3.1-1.4.0_base_main_cache.json")
}
const changeLog = buildChangelog(data!.diffInfo, data!.mergedPullRequests, options)
console.log(changeLog)
expect(changeLog).toStrictEqual(`153\n\n`)
})
+7 -13
View File
@@ -1,4 +1,4 @@
import {TagInfo, sortTags, filterTags} from '../src/tags'
import {TagInfo, filterTags, prepareAndSortTags} from '../src/pr-collector/tags'
jest.setTimeout(180000)
@@ -17,15 +17,13 @@ it('Should order tags correctly using semver', async () => {
const tagResolver = {
method: 'semver'
}
const sorted = sortTags(tags, tagResolver)
const sorted = prepareAndSortTags(tags, tagResolver)
.map(function (tag) {
return tag.name
})
.join(',')
expect(sorted).toStrictEqual(
`2020.4.0,2020.4.0-rc02,2020.3.2,v2020.3.1,2020.3.1-rc03,2020.3.1-rc01,2020.3.1-b01,v2020.3.0`
)
expect(sorted).toStrictEqual(`2020.4.0,2020.4.0-rc02,2020.3.2,v2020.3.1,2020.3.1-rc03,2020.3.1-rc01,2020.3.1-b01,v2020.3.0`)
})
it('Should order tags correctly using semver', async () => {
@@ -48,15 +46,13 @@ it('Should order tags correctly using semver', async () => {
const tagResolver = {
method: 'non-existing-method'
}
const sorted = sortTags(tags, tagResolver)
const sorted = prepareAndSortTags(tags, tagResolver)
.map(function (tag) {
return tag.name
})
.join(',')
expect(sorted).toStrictEqual(
`1000.0.0,100.0.0,20.0.2,10.1.0,10.1.0-2,10.0.0,2.0.0,1.0.0,1.0.0-a01,0.1.0,0.1.0-b01,0.0.1,0.0.1-rc01`
)
expect(sorted).toStrictEqual(`1000.0.0,100.0.0,20.0.2,10.1.0,10.1.0-2,10.0.0,2.0.0,1.0.0,1.0.0-a01,0.1.0,0.1.0-b01,0.0.1,0.0.1-rc01`)
})
it('Should order tags alphabetical', async () => {
@@ -79,15 +75,13 @@ it('Should order tags alphabetical', async () => {
const tagResolver = {
method: 'sort'
}
const sorted = sortTags(tags, tagResolver)
const sorted = prepareAndSortTags(tags, tagResolver)
.map(function (tag) {
return tag.name
})
.join(',')
expect(sorted).toStrictEqual(
`a,20.0.2,2.0.0,1000.0.0,10.1.0,10.1.0-2,10.0.0,1.0.0,1.0.0-a01,v1,0.1.0-b01,0.0.1,0.0.1-rc01`
)
expect(sorted).toStrictEqual(`a,20.0.2,2.0.0,1000.0.0,10.1.0,10.1.0-2,10.0.0,1.0.0,1.0.0-a01,v1,0.1.0-b01,0.0.1,0.0.1-rc01`)
})
it('Should filter tags correctly using the regex', async () => {
+52 -36
View File
@@ -1,8 +1,8 @@
import {buildChangelog} from '../src/transform'
import {PullRequestInfo} from '../src/pullRequests'
import moment from 'moment'
import {Configuration, DefaultConfiguration} from '../src/configuration'
import {DefaultDiffInfo} from '../src/commits'
import {PullRequestInfo} from '../src/pr-collector/pullRequests'
import {DefaultDiffInfo} from '../src/pr-collector/commits'
jest.setTimeout(180000)
@@ -39,7 +39,7 @@ mergedPullRequests.push(
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>(),
labels: [],
milestone: '',
body: 'no magic body1 for this matter',
assignees: [],
@@ -57,7 +57,7 @@ mergedPullRequests.push(
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>(),
labels: [],
milestone: '',
body: 'no magic body2 for this matter',
assignees: [],
@@ -75,7 +75,7 @@ mergedPullRequests.push(
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>(),
labels: [],
milestone: '',
body: 'no magic body3 for this matter',
assignees: [],
@@ -93,7 +93,7 @@ mergedPullRequests.push(
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>(),
labels: [],
milestone: '',
body: 'no magic body4 for this matter',
assignees: [],
@@ -113,7 +113,7 @@ const pullRequestWithLabelInBody: PullRequestInfo = {
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>(),
labels: [],
milestone: '',
body: '[Issue][Feature][AB-1234321] - no magic body for this matter',
assignees: [],
@@ -132,7 +132,7 @@ const openPullRequest: PullRequestInfo = {
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>(),
labels: [],
milestone: '',
body: 'Some fancy body message',
assignees: [],
@@ -246,7 +246,7 @@ pullRequestsWithLabels.push(
mergeCommitSha: 'sha1-1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>().add('feature'),
labels: ['feature'],
milestone: '',
body: 'no magic body for this matter',
assignees: [],
@@ -264,9 +264,9 @@ pullRequestsWithLabels.push(
mergeCommitSha: 'sha1-2',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>().add('issue').add('fix'),
labels: ['issue', 'fix'],
milestone: '',
body: 'no magic body for this matter',
body: 'no magic body for this matter - #1',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
@@ -282,7 +282,7 @@ pullRequestsWithLabels.push(
mergeCommitSha: 'sha1-3',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>().add('issue').add('feature').add('fix'),
labels: ['issue', 'feature', 'fix'],
milestone: '',
body: 'no magic body for this matter',
assignees: [],
@@ -300,7 +300,7 @@ pullRequestsWithLabels.push(
mergeCommitSha: 'sha1-4',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>().add(''),
labels: [''],
milestone: '',
body: 'no magic body for this matter',
assignees: [],
@@ -322,15 +322,15 @@ openPullRequestsWithLabels.push(
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>().add('feature'),
labels: ['feature'],
milestone: '',
body: 'Some fancy body message',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'open'
},
{
},
{
number: 7,
title: 'Still pending open pull request',
htmlURL: '',
@@ -340,14 +340,14 @@ openPullRequestsWithLabels.push(
mergeCommitSha: 'sha1',
author: 'Mike',
repoName: 'test-repo',
labels: new Set<string>().add('feature'),
labels: [],
milestone: '',
body: 'Some fancy body message',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'open'
}
}
)
it('Match multiple labels exhaustive for category', async () => {
@@ -376,6 +376,7 @@ it('Match multiple labels exhaustive for category', async () => {
it('Deduplicate duplicated PRs', async () => {
const customConfig = Object.assign({}, DefaultConfiguration)
customConfig.categories.pop() // drop `uncategorized` category
customConfig.duplicate_filter = {
pattern: '\\[ABC-....\\]',
on_property: 'title',
@@ -388,6 +389,7 @@ it('Deduplicate duplicated PRs', async () => {
it('Deduplicate duplicated PRs DESC', async () => {
const customConfig = Object.assign({}, DefaultConfiguration)
customConfig.categories.pop() // drop `uncategorized` category
customConfig.sort = 'DESC'
customConfig.duplicate_filter = {
pattern: '\\[ABC-....\\]',
@@ -399,6 +401,24 @@ it('Deduplicate duplicated PRs DESC', async () => {
)
})
it('Reference PRs', async () => {
const customConfig = Object.assign({}, DefaultConfiguration)
customConfig.categories = [
{
title: '',
labels: []
}
]
customConfig.pr_template = '${{NUMBER}} -- ${{REFERENCED[*].number}}'
customConfig.reference = {
pattern: '.* #(.).*', // matches the 1 from "abcdefg #1 adfasdf"
on_property: 'body',
method: 'replace',
target: '$1'
}
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(`1 -- 2\n4 -- \n3 -- \n\n`)
})
it('Use empty_content for empty category', async () => {
const customConfig = Object.assign({}, DefaultConfiguration)
customConfig.categories = [
@@ -457,9 +477,7 @@ it('Release Diff', async () => {
configuration: customConfig
})
expect(resultChangelog).toStrictEqual(
`https://github.com/mikepenz/release-changelog-builder-action/compare/v2.8.0...v2.8.1\n`
)
expect(resultChangelog).toStrictEqual(`https://github.com/mikepenz/release-changelog-builder-action/compare/v2.8.0...v2.8.1\n`)
})
it('Use exclude labels to not include a PR within a category.', async () => {
@@ -532,7 +550,6 @@ it('Extract custom placeholder from PR body and replace in global template', asy
)
})
it('Use Rules to include a PR within a Category.', async () => {
const customConfig = Object.assign({}, DefaultConfiguration)
customConfig.categories = [
@@ -542,12 +559,12 @@ it('Use Rules to include a PR within a Category.', async () => {
exclude_labels: ['Fix'],
rules: [
{
pattern: "\[ABC-1234\]",
on_property: "title"
pattern: '\\[ABC-1234\\]',
on_property: 'title'
},
{
pattern: "merged",
on_property: "status"
pattern: 'merged',
on_property: 'status'
}
],
exhaustive: true
@@ -568,8 +585,8 @@ it('Use Rules to get all open PRs in a Category.', async () => {
title: '## Open PRs only',
rules: [
{
pattern: "open",
on_property: "status"
pattern: 'open',
on_property: 'status'
}
]
}
@@ -577,7 +594,6 @@ it('Use Rules to get all open PRs in a Category.', async () => {
expect(buildChangelogTest(customConfig, prs)).toStrictEqual(`## Open PRs only\n\n- Still pending open pull request\n - PR: #6\n\n`)
})
it('Use Rules to get current open PR and merged categorised.', async () => {
let prs = Array.from(pullRequestsWithLabels)
prs = prs.concat(Array.from(openPullRequestsWithLabels))
@@ -599,7 +615,8 @@ it('Use Rules to get current open PR and merged categorised.', async () => {
],
exhaustive: true,
exhaustive_rules: false
},{
},
{
title: '## 🐛 Issues',
labels: ['Issue'],
rules: [
@@ -627,8 +644,8 @@ it('Use Rules to get all open PRs in one Category and merged categorised.', asyn
title: '## Open PRs only',
rules: [
{
pattern: "open",
on_property: "status"
pattern: 'open',
on_property: 'status'
}
]
},
@@ -637,11 +654,11 @@ it('Use Rules to get all open PRs in one Category and merged categorised.', asyn
labels: ['Feature', 'Issue'],
rules: [
{
pattern: "merged",
on_property: "status"
pattern: 'merged',
on_property: 'status'
}
],
exhaustive: true,
exhaustive: true
}
]
expect(buildChangelogTest(customConfig, prs)).toStrictEqual(
@@ -649,7 +666,6 @@ it('Use Rules to get all open PRs in one Category and merged categorised.', asyn
)
})
function buildChangelogTest(config: Configuration, prs: PullRequestInfo[]): string {
return buildChangelog(DefaultDiffInfo, prs, {
owner: 'mikepenz',
+13
View File
@@ -28,6 +28,9 @@ inputs:
failOnError:
description: 'Defines if the action should result in a build failure, if an error was discovered'
default: "false"
fetchViaCommits:
description: 'Defines if PRs are fetched via the commits identified. This will do 1 API request per commit -> Best for scenarios with squash merges | Or shorter from-to diffs (< 10 commits) | Also effective for shorters diffs for very old PRs'
default: "false"
fetchReviewers:
description: 'Will enable fetching the users/reviewers who approved the PR'
default: "false"
@@ -47,6 +50,14 @@ inputs:
default: ${{ github.token }}
baseUrl:
description: 'Defines the base url for GitHub Enterprise authentication, uses `https://api.github.com` by default'
exportCache:
description: 'If enabled, the action will export the collected data to the cache. This is disabled by default. Can be passed to a follow up run via `cache`.'
default: "false"
exportOnly:
description: 'If enabled, the action will only collect the data and terminate afterwards. Data can then be consumed by steps afterwards. This requires `exportCache` to be enabled'
default: "false"
cache:
description: 'Provide the cache of a previous run. Allows to re-use collected information multiple times to generate different release notes. Requires `exportCache` to be enabled for the previous run.'
outputs:
changelog:
description: The built release changelog built from the merged pull requests
@@ -68,6 +79,8 @@ outputs:
description: Count of uncategorized pull requests
open_prs:
description: Count of open pull requests. Only fetched if `includeOpen` is enabled.
cache:
description: 'Cache containing this runs data. Allows to re-use collected information multiple times to generate different release notes.'
runs:
using: 'node16'
main: 'dist/index.js'
+133
View File
@@ -0,0 +1,133 @@
{
"mergedPullRequests": [
{
"number": 10,
"title": "[CI] Specify Test Case",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/10",
"baseBranch": "develop",
"branch": "feature/specify_test",
"createdAt": "2020-10-16T13:58:49.000Z",
"mergedAt": "2020-10-16T13:59:36.000Z",
"mergeCommitSha": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"test",
"--rcba-merged"
],
"milestone": "1.0.0",
"body": "- specify test case",
"assignees": [
"mikepenz",
"nhoelzl"
],
"requestedReviewers": [
"nhoelzl"
],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 19,
"additions": 14827,
"deletions": 444,
"changes": 15271,
"commits": 3,
"commitInfo": [
{
"sha": "0a66008df0b0a89c4bcfd447c5457e223f4b9947",
"summary": "- introduce proper approach to retrieve tag before a given tag",
"message": "- introduce proper approach to retrieve tag before a given tag\n- add configuration options for\n - path\n - configuration\n - fromTag, toTag\n - token\n- allow to specify transformers to adjust information to a specific form\n- allow to specify different templates\n- speed up by limiting information to pull\n- add logic to automatically resolve current\n- use github actions logger",
"author": "mikepenz",
"authorDate": "2020-10-16T13:52:24.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-16T13:52:24.000Z"
},
{
"sha": "92577cd8be4b0ff97648fcf6db98ba38dcba1f25",
"summary": "- configure test case",
"message": "- configure test case",
"author": "mikepenz",
"authorDate": "2020-10-16T13:56:40.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-16T13:56:40.000Z"
},
{
"sha": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"summary": "Merge pull request #10 from mikepenz/feature/specify_test",
"message": "Merge pull request #10 from mikepenz/feature/specify_test\n\n[CI] Specify Test Case",
"author": "mikepenz",
"authorDate": "2020-10-16T13:59:35.000Z",
"committer": "web-flow",
"commitDate": "2020-10-16T13:59:35.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v0.0.1",
"commit": "v0.0.1"
},
"toTag": {
"name": "v0.0.3",
"commit": "v0.0.3"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"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}}",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{RELEASE_DIFF}}",
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"feature"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"fix"
]
},
{
"title": "## 🧪 Tests",
"labels": [
"test"
]
},
{
"title": "## 📦 Uncategorized",
"labels": []
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
+142
View File
@@ -0,0 +1,142 @@
{
"mergedPullRequests": [
{
"number": 0,
"title": "- introduce proper approach to retrieve tag before a given tag",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2020-10-16T13:52:24.000Z",
"mergedAt": "2020-10-16T13:52:24.000Z",
"mergeCommitSha": "0a66008df0b0a89c4bcfd447c5457e223f4b9947",
"author": "mikepenz",
"repoName": "",
"labels": [],
"milestone": "",
"body": "- introduce proper approach to retrieve tag before a given tag\n- add configuration options for\n - path\n - configuration\n - fromTag, toTag\n - token\n- allow to specify transformers to adjust information to a specific form\n- allow to specify different templates\n- speed up by limiting information to pull\n- add logic to automatically resolve current\n- use github actions logger",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "- configure test case",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2020-10-16T13:56:40.000Z",
"mergedAt": "2020-10-16T13:56:40.000Z",
"mergeCommitSha": "92577cd8be4b0ff97648fcf6db98ba38dcba1f25",
"author": "mikepenz",
"repoName": "",
"labels": [],
"milestone": "",
"body": "- configure test case",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "Merge pull request #10 from mikepenz/feature/specify_test",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2020-10-16T13:59:35.000Z",
"mergedAt": "2020-10-16T13:59:35.000Z",
"mergeCommitSha": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"author": "mikepenz",
"repoName": "",
"labels": [],
"milestone": "",
"body": "Merge pull request #10 from mikepenz/feature/specify_test\n\n[CI] Specify Test Case",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 19,
"additions": 14827,
"deletions": 444,
"changes": 15271,
"commits": 3,
"commitInfo": [
{
"sha": "0a66008df0b0a89c4bcfd447c5457e223f4b9947",
"summary": "- introduce proper approach to retrieve tag before a given tag",
"message": "- introduce proper approach to retrieve tag before a given tag\n- add configuration options for\n - path\n - configuration\n - fromTag, toTag\n - token\n- allow to specify transformers to adjust information to a specific form\n- allow to specify different templates\n- speed up by limiting information to pull\n- add logic to automatically resolve current\n- use github actions logger",
"author": "mikepenz",
"authorDate": "2020-10-16T13:52:24.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-16T13:52:24.000Z"
},
{
"sha": "92577cd8be4b0ff97648fcf6db98ba38dcba1f25",
"summary": "- configure test case",
"message": "- configure test case",
"author": "mikepenz",
"authorDate": "2020-10-16T13:56:40.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-16T13:56:40.000Z"
},
{
"sha": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"summary": "Merge pull request #10 from mikepenz/feature/specify_test",
"message": "Merge pull request #10 from mikepenz/feature/specify_test\n\n[CI] Specify Test Case",
"author": "mikepenz",
"authorDate": "2020-10-16T13:59:35.000Z",
"committer": "web-flow",
"commitDate": "2020-10-16T13:59:35.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v0.0.1",
"commit": "v0.0.1"
},
"toTag": {
"name": "v0.0.3",
"commit": "v0.0.3"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": true,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"template": "${{CHANGELOG}}\n\nUncategorized:\n${{UNCATEGORIZED}}\n\nIgnored:\n${{IGNORED}}\n\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}",
"pr_template": "- ${{TITLE}}\n",
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}",
"categories": [
{
"title": "## 📦 Uncategorized",
"labels": []
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
+70
View File
@@ -0,0 +1,70 @@
{
"mergedPullRequests": [],
"diffInfo": {
"changedFiles": 0,
"additions": 0,
"deletions": 0,
"changes": 0,
"commits": 0,
"commitInfo": []
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v0.0.2",
"commit": "v0.0.2"
},
"toTag": {
"name": "v0.0.3",
"commit": "v0.0.3"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": "ASC",
"template": "${{CHANGELOG}}",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"feature"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"fix"
]
},
{
"title": "## 🧪 Tests",
"labels": [
"test"
]
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
+618
View File
@@ -0,0 +1,618 @@
{
"mergedPullRequests": [
{
"number": 22,
"title": "Improve README",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/22",
"baseBranch": "develop",
"branch": "feature/improve_readme",
"createdAt": "2020-10-17T08:35:33.000Z",
"mergedAt": "2020-10-17T08:40:04.000Z",
"mergeCommitSha": "5ce9cb035198f91472ff44b0c99b94b89e332469",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"feature",
"--rcba-merged"
],
"milestone": "",
"body": "- update readme, with more details, more emojis, more everything",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 23,
"title": "Improved handling for non existing tags",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/23",
"baseBranch": "develop",
"branch": "feature/improve_missing_tag_handling",
"createdAt": "2020-10-17T15:38:35.000Z",
"mergedAt": "2020-10-17T15:57:00.000Z",
"mergeCommitSha": "c7eec1d5a6002d84d45559594ef15eee9e2ff443",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"fix",
"--rcba-merged"
],
"milestone": "",
"body": "- introduce better handling of cases in which invalid references are provided, return an empty changelog and send out error",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 24,
"title": "Improved configuration failure handling",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/24",
"baseBranch": "develop",
"branch": "feature/improved_configuration_issue_handling",
"createdAt": "2020-10-17T16:02:41.000Z",
"mergedAt": "2020-10-17T16:07:02.000Z",
"mergeCommitSha": "911126dfc76b9e4030aab0564a318133a96454e0",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"feature",
"--rcba-merged"
],
"milestone": "",
"body": "- introduce better more stable fallbacks in case the configuration is missing\r\n- move configurations into subfolder for easier discovery\r\n- simplify missing value fallback specification",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 25,
"title": "Improved defaults if no configuration is provided",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/25",
"baseBranch": "develop",
"branch": "feature/improved_defaults",
"createdAt": "2020-10-17T16:12:36.000Z",
"mergedAt": "2020-10-17T16:17:05.000Z",
"mergeCommitSha": "519f09e8915a63c3c666f1d19c7014e61048754e",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"feature",
"--rcba-merged"
],
"milestone": "",
"body": "- adjust defaults to already provide a great base set of categories\r\n- define categories\r\n```json\r\ncategories: [\r\n {\r\n title: '## 🚀 Features',\r\n labels: ['feature']\r\n },\r\n {\r\n title: '## 🐛 Fixes',\r\n labels: ['fix']\r\n },\r\n {\r\n title: '## 🧪 Tests',\r\n labels: ['test']\r\n }\r\n ]\r\n```",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 26,
"title": "Introduce additional placeholders [milestone, labels, assignees, reviewers]",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/26",
"baseBranch": "develop",
"branch": "feature/introduce_additional_placeholders",
"createdAt": "2020-10-17T16:18:42.000Z",
"mergedAt": "2020-10-17T16:21:08.000Z",
"mergeCommitSha": "d88fa22107021326ed5ee36b8ecf3e87b633c5d5",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"feature",
"--rcba-merged"
],
"milestone": "",
"body": "- introduce more placeholders (milestone, labels, assignees, reviewers)\r\n- update testcase to check new placeholders",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 27,
"title": "Fix typos in Readme",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/27",
"baseBranch": "develop",
"branch": "feature/proofread-readme",
"createdAt": "2020-10-17T16:54:36.000Z",
"mergedAt": "2020-10-17T17:00:35.000Z",
"mergeCommitSha": "c8090bcb0dc99210e766f5c0d1330e0dd3372dd1",
"author": "nhoelzl",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"other",
"--rcba-merged"
],
"milestone": "",
"body": "- fix misspelled words and comma issues",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 28,
"title": "Enhanced action logs",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/28",
"baseBranch": "develop",
"branch": "feature/enhance_logging_outputs",
"createdAt": "2020-10-17T17:04:44.000Z",
"mergedAt": "2020-10-17T17:57:36.000Z",
"mergeCommitSha": "809b20a9dee4179ee02c55f0a06f7213876784e5",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"feature",
"--rcba-merged"
],
"milestone": "",
"body": "- group logs together to have a better visualisation of what's going on\r\n- add emojis to all sorts of logs",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 29,
"title": "Improve changelog generation of project",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/29",
"baseBranch": "develop",
"branch": "feature/improved_changelog",
"createdAt": "2020-10-17T17:58:08.000Z",
"mergedAt": "2020-10-17T18:16:30.000Z",
"mergeCommitSha": "116d28a3234d04b7b5cb528ed730a5fe7ec6acbf",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"other",
"--rcba-merged"
],
"milestone": "",
"body": "- introduce `other` category for library changelog",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 30,
"title": "develop -> main",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/30",
"baseBranch": "main",
"branch": "develop",
"createdAt": "2020-10-17T18:16:59.000Z",
"mergedAt": "2020-10-17T18:18:23.000Z",
"mergeCommitSha": "4cecfac83e8e47adbb32cb97931cea6ee44e0d36",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"--rcba-merged"
],
"milestone": "",
"body": "Merge develop -> main",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 31,
"title": "Adjust release github action",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/31",
"baseBranch": "develop",
"branch": "feature/adjust_release_github_action",
"createdAt": "2020-10-18T07:16:35.000Z",
"mergedAt": "2020-10-18T07:16:41.000Z",
"mergeCommitSha": "d1f245b0eb35536da5dd38cae16d110ea3918eb4",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"other",
"--rcba-merged"
],
"milestone": "",
"body": "- add back checkout to have configuration available",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 32,
"title": "dev -> main",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/32",
"baseBranch": "main",
"branch": "develop",
"createdAt": "2020-10-18T07:16:58.000Z",
"mergedAt": "2020-10-18T07:17:04.000Z",
"mergeCommitSha": "ca3a814f05a7b2df3bd89c94b14e52b81107780c",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"--rcba-merged"
],
"milestone": "",
"body": "merge dev into main",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 19,
"additions": 603,
"deletions": 319,
"changes": 922,
"commits": 34,
"commitInfo": [
{
"sha": "4ee65b5cf02ccbac40a99236c012d01c46243965",
"summary": "- update readme, with more details, more emojis, more everything",
"message": "- update readme, with more details, more emojis, more everything",
"author": "mikepenz",
"authorDate": "2020-10-17T08:35:05.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T08:35:05.000Z"
},
{
"sha": "876d5042a33329ef419db306a8b8e814f4464167",
"summary": "- change header sizes",
"message": "- change header sizes",
"author": "mikepenz",
"authorDate": "2020-10-17T08:38:40.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T08:38:40.000Z"
},
{
"sha": "5ce9cb035198f91472ff44b0c99b94b89e332469",
"summary": "Merge pull request #22 from mikepenz/feature/improve_readme",
"message": "Merge pull request #22 from mikepenz/feature/improve_readme\n\nImprove README",
"author": "mikepenz",
"authorDate": "2020-10-17T08:40:03.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T08:40:03.000Z"
},
{
"sha": "619d3f460eb467222f275494158e1da89a4f43e9",
"summary": "- introduce better handling of cases in which invalid references are provided, return an empty changelog and send out error",
"message": "- introduce better handling of cases in which invalid references are provided, return an empty changelog and send out error",
"author": "mikepenz",
"authorDate": "2020-10-17T15:38:08.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T15:38:08.000Z"
},
{
"sha": "c7eec1d5a6002d84d45559594ef15eee9e2ff443",
"summary": "Merge pull request #23 from mikepenz/feature/improve_missing_tag_handling",
"message": "Merge pull request #23 from mikepenz/feature/improve_missing_tag_handling\n\nImproved handling for non existing tags",
"author": "mikepenz",
"authorDate": "2020-10-17T15:56:59.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T15:56:59.000Z"
},
{
"sha": "b464ff088a0407e8c66150e125f5dfef707caa2d",
"summary": "- introduce better more stable fallbacks in case the configuration is missing",
"message": "- introduce better more stable fallbacks in case the configuration is missing\n- move configurations into subfolder for easier discovery\n- simplify missing value fallback specification",
"author": "mikepenz",
"authorDate": "2020-10-17T16:02:08.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T16:02:08.000Z"
},
{
"sha": "fbc3c7370b2f7bbf3c9450fabea17d17c8997a53",
"summary": "- fix test case",
"message": "- fix test case",
"author": "mikepenz",
"authorDate": "2020-10-17T16:05:35.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T16:05:35.000Z"
},
{
"sha": "911126dfc76b9e4030aab0564a318133a96454e0",
"summary": "Merge pull request #24 from mikepenz/feature/improved_configuration_issue_handling",
"message": "Merge pull request #24 from mikepenz/feature/improved_configuration_issue_handling\n\nImproved configuration failure handling",
"author": "mikepenz",
"authorDate": "2020-10-17T16:07:01.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T16:07:01.000Z"
},
{
"sha": "8058353346f53b12ad17db2a72dd1a318b48e541",
"summary": "- adjust defaults to already provide a great base set of categories",
"message": "- adjust defaults to already provide a great base set of categories",
"author": "mikepenz",
"authorDate": "2020-10-17T16:03:46.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T16:07:31.000Z"
},
{
"sha": "da897391639b0c24efb71f47ba755811b2ae06ea",
"summary": "- introduce more placeholders (milestone, labels, asignees, reviewers)",
"message": "- introduce more placeholders (milestone, labels, asignees, reviewers)\n- update testcase to check new placeholders",
"author": "mikepenz",
"authorDate": "2020-10-17T16:11:22.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T16:11:22.000Z"
},
{
"sha": "17acfb397f365d1ffe28eac561125dd31d95361a",
"summary": "- update table with additional placeholders",
"message": "- update table with additional placeholders",
"author": "mikepenz",
"authorDate": "2020-10-17T16:17:01.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T16:17:01.000Z"
},
{
"sha": "519f09e8915a63c3c666f1d19c7014e61048754e",
"summary": "Merge pull request #25 from mikepenz/feature/improved_defaults",
"message": "Merge pull request #25 from mikepenz/feature/improved_defaults\n\nImproved defaults if no configuration is provided",
"author": "mikepenz",
"authorDate": "2020-10-17T16:17:05.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T16:17:05.000Z"
},
{
"sha": "6cce2a6c0f0368f8e4380d333937a76b46ef3da2",
"summary": "- write assignee correct",
"message": "- write assignee correct",
"author": "mikepenz",
"authorDate": "2020-10-17T16:19:41.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T16:19:41.000Z"
},
{
"sha": "d88fa22107021326ed5ee36b8ecf3e87b633c5d5",
"summary": "Merge pull request #26 from mikepenz/feature/introduce_additional_placeholders",
"message": "Merge pull request #26 from mikepenz/feature/introduce_additional_placeholders\n\nIntroduce additional placeholders [milestone, labels, assignees, reviewers]",
"author": "mikepenz",
"authorDate": "2020-10-17T16:21:07.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T16:21:07.000Z"
},
{
"sha": "44272b156eb889a1b7012017b0bfa680fbef4892",
"summary": "fix typos in readme",
"message": "fix typos in readme",
"author": "nhoelzl",
"authorDate": "2020-10-17T16:47:04.000Z",
"committer": "nhoelzl",
"commitDate": "2020-10-17T16:47:04.000Z"
},
{
"sha": "c8090bcb0dc99210e766f5c0d1330e0dd3372dd1",
"summary": "Merge pull request #27 from nhoelzl/feature/proofread-readme",
"message": "Merge pull request #27 from nhoelzl/feature/proofread-readme\n\nFix typos in Readme",
"author": "mikepenz",
"authorDate": "2020-10-17T17:00:35.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T17:00:35.000Z"
},
{
"sha": "f675789732276657e158284fdf0dc4f51bacc82f",
"summary": "- group logs together to have a better visualisation of what's going on",
"message": "- group logs together to have a better visualisation of what's going on\n- add emojis to all sorts of logs",
"author": "mikepenz",
"authorDate": "2020-10-17T17:00:04.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:37:11.000Z"
},
{
"sha": "1e0f6ab49e7327d0c806ec8fcc74fee6151d3e0c",
"summary": "- add more log messages to action",
"message": "- add more log messages to action",
"author": "mikepenz",
"authorDate": "2020-10-17T17:20:12.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:37:11.000Z"
},
{
"sha": "bd49950417115e662bda6a26bbc4fe8cec29ea4f",
"summary": "- use different pen for write logs",
"message": "- use different pen for write logs\n- remove default value for configuration, to cleanly fallback to defaults\n- rename gitHelper, move dir exists helper\n- add reading input values group\n- improve warning for configuration",
"author": "mikepenz",
"authorDate": "2020-10-17T17:35:26.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:37:11.000Z"
},
{
"sha": "f63fa1dabb0cdf1453d103436723e7f7a685c252",
"summary": "- fix formatting, and unused import",
"message": "- fix formatting, and unused import",
"author": "mikepenz",
"authorDate": "2020-10-17T17:42:26.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:42:26.000Z"
},
{
"sha": "f9222d8d7735fc23a6b3e1b586a1e557b9c9573b",
"summary": "- adjust README to reflect the no longer used default configuration lookup",
"message": "- adjust README to reflect the no longer used default configuration lookup",
"author": "mikepenz",
"authorDate": "2020-10-17T17:44:13.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:44:13.000Z"
},
{
"sha": "0452303d4c8efe16300568e38200d5d023506fd4",
"summary": "- improve action specification",
"message": "- improve action specification\n- clean up imports for tests",
"author": "mikepenz",
"authorDate": "2020-10-17T17:53:23.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:53:23.000Z"
},
{
"sha": "35c73a53787022efe9453b8a9bd6e256eb5cc7dd",
"summary": "- recompile",
"message": "- recompile",
"author": "mikepenz",
"authorDate": "2020-10-17T17:56:06.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:56:06.000Z"
},
{
"sha": "8044ea441ae9433d7ac82befecefb9a55439f9a6",
"summary": "- introduce `other` category for library changelog",
"message": "- introduce `other` category for library changelog",
"author": "mikepenz",
"authorDate": "2020-10-17T17:56:31.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T17:56:31.000Z"
},
{
"sha": "809b20a9dee4179ee02c55f0a06f7213876784e5",
"summary": "Merge pull request #28 from mikepenz/feature/enhance_logging_outputs",
"message": "Merge pull request #28 from mikepenz/feature/enhance_logging_outputs\n\nEnhanced action logs",
"author": "mikepenz",
"authorDate": "2020-10-17T17:57:36.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T17:57:36.000Z"
},
{
"sha": "9a9cd269402e105cb4d6472109f01d4d49a95e19",
"summary": "- improve build to add sample, without having a prior checkout",
"message": "- improve build to add sample, without having a prior checkout",
"author": "mikepenz",
"authorDate": "2020-10-17T18:04:44.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T18:04:44.000Z"
},
{
"sha": "bfabe29961086e383c17254f50a0cd7a93251a62",
"summary": "- use develop state for action",
"message": "- use develop state for action",
"author": "mikepenz",
"authorDate": "2020-10-17T18:08:53.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T18:08:53.000Z"
},
{
"sha": "d970a0bc9a36ba9216ab8c76181adbfa707515e9",
"summary": "- improve messages for test output",
"message": "- improve messages for test output\n- include complete sample in README",
"author": "mikepenz",
"authorDate": "2020-10-17T18:13:31.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T18:13:31.000Z"
},
{
"sha": "fde922d7852a24fd5e24597af6878ee5a2543bc6",
"summary": "- fix link",
"message": "- fix link",
"author": "mikepenz",
"authorDate": "2020-10-17T18:15:05.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-17T18:15:05.000Z"
},
{
"sha": "116d28a3234d04b7b5cb528ed730a5fe7ec6acbf",
"summary": "Merge pull request #29 from mikepenz/feature/improved_changelog",
"message": "Merge pull request #29 from mikepenz/feature/improved_changelog\n\nImprove changelog generation of project",
"author": "mikepenz",
"authorDate": "2020-10-17T18:16:30.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T18:16:30.000Z"
},
{
"sha": "4cecfac83e8e47adbb32cb97931cea6ee44e0d36",
"summary": "Merge pull request #30 from mikepenz/develop",
"message": "Merge pull request #30 from mikepenz/develop\n\ndevelop -> main",
"author": "mikepenz",
"authorDate": "2020-10-17T18:18:23.000Z",
"committer": "web-flow",
"commitDate": "2020-10-17T18:18:23.000Z"
},
{
"sha": "c03b55984d6c4dd9617cebcc8858209d2451def5",
"summary": "- add back checkout to have configuration available",
"message": "- add back checkout to have configuration available",
"author": "mikepenz",
"authorDate": "2020-10-18T07:16:18.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-18T07:16:18.000Z"
},
{
"sha": "d1f245b0eb35536da5dd38cae16d110ea3918eb4",
"summary": "Merge pull request #31 from mikepenz/feature/adjust_release_github_action",
"message": "Merge pull request #31 from mikepenz/feature/adjust_release_github_action\n\nAdjust release github action",
"author": "mikepenz",
"authorDate": "2020-10-18T07:16:40.000Z",
"committer": "web-flow",
"commitDate": "2020-10-18T07:16:40.000Z"
},
{
"sha": "ca3a814f05a7b2df3bd89c94b14e52b81107780c",
"summary": "Merge pull request #32 from mikepenz/develop",
"message": "Merge pull request #32 from mikepenz/develop\n\ndev -> main",
"author": "mikepenz",
"authorDate": "2020-10-18T07:17:04.000Z",
"committer": "web-flow",
"commitDate": "2020-10-18T07:17:04.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v0.3.0",
"commit": "v0.3.0"
},
"toTag": {
"name": "v0.5.0",
"commit": "v0.5.0"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": "ASC",
"template": "${{CHANGELOG}}",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"feature"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"fix"
]
},
{
"title": "## 🧪 Tests",
"labels": [
"test"
]
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
+482
View File
@@ -0,0 +1,482 @@
{
"mergedPullRequests": [
{
"number": 47,
"title": "Bump @types/node from 14.11.8 to 14.11.10",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/47",
"baseBranch": "develop",
"branch": "dependabot/npm_and_yarn/types/node-14.11.10",
"createdAt": "2020-10-19T07:14:58.000Z",
"mergedAt": "2020-10-19T07:28:55.000Z",
"mergeCommitSha": "2fb7019ca5820d18d6d53fb3926bb68d61323a9f",
"author": "dependabot[bot]",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"dependencies",
"--rcba-merged"
],
"milestone": "",
"body": "Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.11.8 to 14.11.10.\n<details>\n<summary>Commits</summary>\n<ul>\n<li>See full diff in <a href=\"https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node\">compare view</a></li>\n</ul>\n</details>\n<br />\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/node&package-manager=npm_and_yarn&previous-version=14.11.8&new-version=14.11.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/configuring-github-dependabot-security-updates)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n<details>\n<summary>Dependabot commands and options</summary>\n<br />\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n</details>",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 48,
"title": "Adjust code to move fromTag resolving to main.ts",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/48",
"baseBranch": "develop",
"branch": "feature/move_from_tag_resolval",
"createdAt": "2020-10-19T14:34:03.000Z",
"mergedAt": "2020-10-19T14:39:43.000Z",
"mergeCommitSha": "0ceacbaa6a79aa63ea2821acb59978eae2bab896",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"--rcba-merged"
],
"milestone": "",
"body": "- move fromTag resolving to main.ts and remove dependency on checks from ReleaseNotes.ts\r\n - require fromTag for ReleaseNotes\r\n- adjust tests, split into according test classes\r\n- simplify transform.ts",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 49,
"title": "Improve test cases",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/49",
"baseBranch": "develop",
"branch": "feature/split_logic",
"createdAt": "2020-10-19T15:30:05.000Z",
"mergedAt": "2020-10-19T15:44:18.000Z",
"mergeCommitSha": "470822c9f815deba5ba07dce30c164dc190b844f",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"test",
"--rcba-merged"
],
"milestone": "",
"body": "Add additional test cases to also verify action runner specifically",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 50,
"title": "New additional placeholders for `template` and `empty_template`",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/50",
"baseBranch": "develop",
"branch": "feature/dynamic_placeholders",
"createdAt": "2020-10-19T16:05:52.000Z",
"mergedAt": "2020-10-19T16:13:13.000Z",
"mergeCommitSha": "a774c0328fdcf13e96fa60bcc273a24ff9558ac6",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"ignore",
"--rcba-merged"
],
"milestone": "",
"body": "- introduce additional placeholders supported by the `template` \r\n- introduce placeholder support into `empty_template`\r\n- introduce new placeholders for templates, update README with new placeholders\r\n- recompile dist files\r\n- properly count categorized PRs\r\n- introduce tests to verify new placeholders used for `template` and `empty_template`",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 51,
"title": "Enhance sorting by using proper semver",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/51",
"baseBranch": "develop",
"branch": "feature/enhance_tags_sorting",
"createdAt": "2020-10-19T16:57:29.000Z",
"mergedAt": "2020-10-19T18:27:12.000Z",
"mergeCommitSha": "a5629a3f6e6711ed08871d10e64e9435848d6554",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"feature",
"--rcba-merged"
],
"milestone": "",
"body": "- make sortTags method to be accessible for test …\r\n- add test to verify ordering of tags\r\n- upgrade sorting logic to use semver to ensure we support all cases properly\r\n- highlight versioning resolving automation\r\n- formatting adjustment",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 52,
"title": "dev -> main",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/52",
"baseBranch": "main",
"branch": "develop",
"createdAt": "2020-10-19T18:34:23.000Z",
"mergedAt": "2020-10-19T18:36:20.000Z",
"mergeCommitSha": "0f9cd813de2e9738922ca580e690787d98f21579",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"--rcba-merged"
],
"milestone": "",
"body": "merge dev into main",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 53,
"title": "Update package.json to updated description",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/53",
"baseBranch": "develop",
"branch": "feature/improve_package.json",
"createdAt": "2020-10-19T18:40:40.000Z",
"mergedAt": "2020-10-19T18:43:21.000Z",
"mergeCommitSha": "7e8a518561a061def732618b66bd375323ac997a",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"other",
"--rcba-merged"
],
"milestone": "",
"body": "- add more keywords and update description",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 54,
"title": "dev -> main",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/54",
"baseBranch": "main",
"branch": "develop",
"createdAt": "2020-10-19T18:43:53.000Z",
"mergedAt": "2020-10-19T18:45:15.000Z",
"mergeCommitSha": "7d955b5f8d222f336a064e2dbe15662917fbf79c",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"--rcba-merged"
],
"milestone": "",
"body": "merge dev into main",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 16,
"additions": 2931,
"deletions": 450,
"changes": 3381,
"commits": 26,
"commitInfo": [
{
"sha": "6e2c5b3a6e382170a0241ad87414b70bf93dc0c9",
"summary": "Bump @types/node from 14.11.8 to 14.11.10",
"message": "Bump @types/node from 14.11.8 to 14.11.10\n\nBumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.11.8 to 14.11.10.\n- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)\n- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)\n\nSigned-off-by: dependabot[bot] <support@github.com>",
"author": "dependabot[bot]",
"authorDate": "2020-10-19T07:14:57.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T07:14:57.000Z"
},
{
"sha": "2fb7019ca5820d18d6d53fb3926bb68d61323a9f",
"summary": "Merge pull request #47 from mikepenz/dependabot/npm_and_yarn/types/node-14.11.10",
"message": "Merge pull request #47 from mikepenz/dependabot/npm_and_yarn/types/node-14.11.10\n\nBump @types/node from 14.11.8 to 14.11.10",
"author": "mikepenz",
"authorDate": "2020-10-19T07:28:54.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T07:28:54.000Z"
},
{
"sha": "d9c1239d34cc7cd9ae0cdc203740674b91541233",
"summary": "- move fromTag resolving to main.ts and remove dependency on checks from ReleaseNotes.ts",
"message": "- move fromTag resolving to main.ts and remove dependency on checks from ReleaseNotes.ts\n - require fromTag for ReleaseNotes\n- adjust tests, split into according test classes\n- simplify transform.ts",
"author": "mikepenz",
"authorDate": "2020-10-19T14:33:00.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T14:33:00.000Z"
},
{
"sha": "d61ec6c06cf142943a6be76f8f2795ea4c405c1b",
"summary": "- rebuild dist files",
"message": "- rebuild dist files",
"author": "mikepenz",
"authorDate": "2020-10-19T14:35:11.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T14:35:11.000Z"
},
{
"sha": "9258366eafaff9a4345468dd2cdd08d8f4f6896a",
"summary": "- tmp remove test class",
"message": "- tmp remove test class",
"author": "mikepenz",
"authorDate": "2020-10-19T14:37:11.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T14:37:11.000Z"
},
{
"sha": "0ceacbaa6a79aa63ea2821acb59978eae2bab896",
"summary": "Merge pull request #48 from mikepenz/feature/move_from_tag_resolval",
"message": "Merge pull request #48 from mikepenz/feature/move_from_tag_resolval\n\nAdjust code to move fromTag resolving to main.ts",
"author": "mikepenz",
"authorDate": "2020-10-19T14:39:42.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T14:39:42.000Z"
},
{
"sha": "8b6119add8ae9aa85e5bf9dde99340bae7b3c210",
"summary": "- split logic to validate and read in additional details for changelog generation into new `releaseNotesBuilder`",
"message": "- split logic to validate and read in additional details for changelog generation into new `releaseNotesBuilder`\n- construct main class to be as simple as possible",
"author": "mikepenz",
"authorDate": "2020-10-19T15:11:13.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T15:28:54.000Z"
},
{
"sha": "49d12f5b1e6adadcb303e1f0609034e09d4e7d90",
"summary": "- introduce tests covering the action process itself",
"message": "- introduce tests covering the action process itself",
"author": "mikepenz",
"authorDate": "2020-10-19T15:28:28.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T15:28:54.000Z"
},
{
"sha": "470822c9f815deba5ba07dce30c164dc190b844f",
"summary": "Merge pull request #49 from mikepenz/feature/split_logic",
"message": "Merge pull request #49 from mikepenz/feature/split_logic\n\nImprove test cases",
"author": "mikepenz",
"authorDate": "2020-10-19T15:44:17.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T15:44:17.000Z"
},
{
"sha": "c6ed215bc27914551f484a20b14943c073d52ee8",
"summary": "- introduce additional placeholders supported by the `template`",
"message": "- introduce additional placeholders supported by the `template`\n- introduce placeholder support into `empty_template`\n- introduce new placeholders for templates, update README with new placeholders",
"author": "mikepenz",
"authorDate": "2020-10-19T15:53:04.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T15:53:39.000Z"
},
{
"sha": "4eaa60b4d55c63f43b70df90aa29936b04fb9c46",
"summary": "- recompile dist files",
"message": "- recompile dist files",
"author": "mikepenz",
"authorDate": "2020-10-19T15:54:18.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T15:54:18.000Z"
},
{
"sha": "26cab8c692c791ec20e3e921b45553c8f764b7ee",
"summary": "- properly count categorized PRs",
"message": "- properly count categorized PRs",
"author": "mikepenz",
"authorDate": "2020-10-19T16:03:50.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T16:03:50.000Z"
},
{
"sha": "bdb790ac5eef1d39537c7833afdcf1e00939c8a6",
"summary": "- introduce tests to verify new placeholders used for `template` and `empty_template`",
"message": "- introduce tests to verify new placeholders used for `template` and `empty_template`",
"author": "mikepenz",
"authorDate": "2020-10-19T16:04:56.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T16:04:56.000Z"
},
{
"sha": "a774c0328fdcf13e96fa60bcc273a24ff9558ac6",
"summary": "Merge pull request #50 from mikepenz/feature/dynamic_placeholders",
"message": "Merge pull request #50 from mikepenz/feature/dynamic_placeholders\n\nNew additional placeholders for `template` and `empty_template`",
"author": "mikepenz",
"authorDate": "2020-10-19T16:13:13.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T16:13:13.000Z"
},
{
"sha": "c309b839db3f3af9e92d5fa1484682202db4ade9",
"summary": "- make sortTags method to be accessible for test",
"message": "- make sortTags method to be accessible for test\n- add test to verify ordering of tags",
"author": "mikepenz",
"authorDate": "2020-10-19T16:14:10.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T16:56:26.000Z"
},
{
"sha": "83ad299b7efd80b3d1fc59859aa196578e8e4887",
"summary": "- upgrade sorting logic to use semver to ensure we support all cases properly",
"message": "- upgrade sorting logic to use semver to ensure we support all cases properly",
"author": "mikepenz",
"authorDate": "2020-10-19T16:49:22.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T16:56:26.000Z"
},
{
"sha": "a048bfac80a9681ea279a49df647c169470ac54b",
"summary": "- highlight versioning resolving automation",
"message": "- highlight versioning resolving automation",
"author": "mikepenz",
"authorDate": "2020-10-19T16:55:00.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T16:56:26.000Z"
},
{
"sha": "4ad1d585c9c700617812b12d137ee95711c3d5da",
"summary": "- formatting adjustment",
"message": "- formatting adjustment",
"author": "mikepenz",
"authorDate": "2020-10-19T16:55:59.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T16:56:26.000Z"
},
{
"sha": "2a95fba312329f7a9d039a9a67dabd3baf05e28b",
"summary": "- verify versions match semver versioning",
"message": "- verify versions match semver versioning",
"author": "mikepenz",
"authorDate": "2020-10-19T17:58:36.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T17:58:36.000Z"
},
{
"sha": "01db48f0528c9d498fbdc15e6e88b86caf1fac34",
"summary": "- rebuild dist",
"message": "- rebuild dist",
"author": "mikepenz",
"authorDate": "2020-10-19T18:25:24.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T18:25:24.000Z"
},
{
"sha": "a5629a3f6e6711ed08871d10e64e9435848d6554",
"summary": "Merge pull request #51 from mikepenz/feature/enhance_tags_sorting",
"message": "Merge pull request #51 from mikepenz/feature/enhance_tags_sorting\n\nEnhance sorting by using proper semver",
"author": "mikepenz",
"authorDate": "2020-10-19T18:27:12.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T18:27:12.000Z"
},
{
"sha": "0f9cd813de2e9738922ca580e690787d98f21579",
"summary": "Merge pull request #52 from mikepenz/develop",
"message": "Merge pull request #52 from mikepenz/develop\n\ndev -> main",
"author": "mikepenz",
"authorDate": "2020-10-19T18:36:19.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T18:36:19.000Z"
},
{
"sha": "0648f8a89720680fca0e690f188a764087a50b0b",
"summary": "- add more keywords and update description",
"message": "- add more keywords and update description",
"author": "mikepenz",
"authorDate": "2020-10-19T18:40:13.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T18:40:13.000Z"
},
{
"sha": "b0227ab71a91effef6774342e435a4807dfb004c",
"summary": "- add changelog to headline",
"message": "- add changelog to headline",
"author": "mikepenz",
"authorDate": "2020-10-19T18:41:44.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-19T18:41:44.000Z"
},
{
"sha": "7e8a518561a061def732618b66bd375323ac997a",
"summary": "Merge pull request #53 from mikepenz/feature/improve_package.json",
"message": "Merge pull request #53 from mikepenz/feature/improve_package.json\n\nUpdate package.json to updated description",
"author": "mikepenz",
"authorDate": "2020-10-19T18:43:21.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T18:43:21.000Z"
},
{
"sha": "7d955b5f8d222f336a064e2dbe15662917fbf79c",
"summary": "Merge pull request #54 from mikepenz/develop",
"message": "Merge pull request #54 from mikepenz/develop\n\ndev -> main",
"author": "mikepenz",
"authorDate": "2020-10-19T18:45:15.000Z",
"committer": "web-flow",
"commitDate": "2020-10-19T18:45:15.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v0.9.1",
"commit": "v0.9.1"
},
"toTag": {
"name": "v0.9.5",
"commit": "v0.9.5"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"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}}",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{RELEASE_DIFF}}",
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"feature"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"fix"
]
},
{
"title": "## 🧪 Tests",
"labels": [
"test"
]
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
@@ -0,0 +1,205 @@
{
"mergedPullRequests": [
{
"number": 150,
"title": "Bump @vercel/ncc from 0.26.1 to 0.26.2",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/150",
"baseBranch": "develop",
"branch": "dependabot/npm_and_yarn/vercel/ncc-0.26.2",
"createdAt": "2021-01-07T06:32:59.000Z",
"mergedAt": "2021-01-07T07:24:43.000Z",
"mergeCommitSha": "cb75836b8da89f4e7d6bfabc985a5715e4e41826",
"author": "dependabot[bot]",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"dependencies",
"--rcba-merged"
],
"milestone": "",
"body": "Bumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.26.1 to 0.26.2.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/vercel/ncc/releases\">@vercel/ncc's releases</a>.</em></p>\n<blockquote>\n<h2>0.26.2</h2>\n<h3>Patches</h3>\n<ul>\n<li>Enable minification for sourcemap-register.js: <a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/631\">#631</a></li>\n<li>Avoid <strong>webpack_require</strong> conflicts: <a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/633\">#633</a></li>\n<li>Bump axios from 0.18.1 to 0.21.1: <a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/636\">#636</a></li>\n<li>Fix: skip typechecking on sub-builds: <a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/637\">#637</a></li>\n</ul>\n<h3>Credits</h3>\n<p>Huge thanks to <a href=\"https://github.com/xom9ikk\">@xom9ikk</a> and <a href=\"https://github.com/guybedford\">@guybedford</a> for helping!</p>\n</blockquote>\n</details>\n<details>\n<summary>Commits</summary>\n<ul>\n<li><a href=\"https://github.com/vercel/ncc/commit/da9b3816d3958e96c92152914d0f74903a91bbb2\"><code>da9b381</code></a> 0.26.2</li>\n<li><a href=\"https://github.com/vercel/ncc/commit/e2910fb638d261755d2b1c185a0572026069d14d\"><code>e2910fb</code></a> fix: skip typechecking on sub-builds (<a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/637\">#637</a>)</li>\n<li><a href=\"https://github.com/vercel/ncc/commit/7ed861074111f459f8e86088876feeb06f870261\"><code>7ed8610</code></a> Bump axios from 0.18.1 to 0.21.1 (<a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/636\">#636</a>)</li>\n<li><a href=\"https://github.com/vercel/ncc/commit/fd3961bde76e2218452a909f601b74ae0633881e\"><code>fd3961b</code></a> Avoid <strong>webpack_require</strong> conflicts (<a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/633\">#633</a>)</li>\n<li><a href=\"https://github.com/vercel/ncc/commit/26222e3fef477749eca57941133a6600472040db\"><code>26222e3</code></a> Enable minification for sourcemap-register.js (<a href=\"https://github-redirect.dependabot.com/vercel/ncc/issues/631\">#631</a>)</li>\n<li>See full diff in <a href=\"https://github.com/vercel/ncc/compare/0.26.1...0.26.2\">compare view</a></li>\n</ul>\n</details>\n<details>\n<summary>Maintainer changes</summary>\n<p>This version was pushed to npm by <a href=\"https://www.npmjs.com/~timer\">timer</a>, a new releaser for @vercel/ncc since your current version.</p>\n</details>\n<br />\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@vercel/ncc&package-manager=npm_and_yarn&previous-version=0.26.1&new-version=0.26.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n<details>\n<summary>Dependabot commands and options</summary>\n<br />\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n</details>",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 151,
"title": "Experimental commit based changelog generation mode",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/151",
"baseBranch": "develop",
"branch": "feature/141",
"createdAt": "2021-01-07T14:32:30.000Z",
"mergedAt": "2021-01-07T14:38:58.000Z",
"mergeCommitSha": "626951a1000cda5638a736820fa191a12b4b8fb6",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"other",
"--rcba-merged"
],
"milestone": "",
"body": "- introduce experimental (light) commit based changelog generation mode\r\n - FIX https://github.com/mikepenz/release-changelog-builder-action/issues/141\r\n - this is not fully supported and not documented as it lacks big amounts of the features we know and love\r\n- npm install\r\n- recompile dist",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 152,
"title": "Update jest",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/152",
"baseBranch": "develop",
"branch": "feature/update_jest",
"createdAt": "2021-01-07T14:42:07.000Z",
"mergedAt": "2021-01-07T14:43:46.000Z",
"mergeCommitSha": "eb374ed818dfb7d29b1a17daf831ddd7611ec6a1",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"dependencies",
"--rcba-merged"
],
"milestone": "",
"body": "- update jest and recompile dist",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 12,
"additions": 10148,
"deletions": 21465,
"changes": 31613,
"commits": 8,
"commitInfo": [
{
"sha": "59903d2471fb3ddbc12e68b5d77d03509038703b",
"summary": "Bump @vercel/ncc from 0.26.1 to 0.26.2",
"message": "Bump @vercel/ncc from 0.26.1 to 0.26.2\n\nBumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.26.1 to 0.26.2.\n- [Release notes](https://github.com/vercel/ncc/releases)\n- [Commits](https://github.com/vercel/ncc/compare/0.26.1...0.26.2)\n\nSigned-off-by: dependabot[bot] <support@github.com>",
"author": "dependabot[bot]",
"authorDate": "2021-01-07T06:32:58.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T06:32:58.000Z"
},
{
"sha": "cb75836b8da89f4e7d6bfabc985a5715e4e41826",
"summary": "Merge pull request #150 from mikepenz/dependabot/npm_and_yarn/vercel/ncc-0.26.2",
"message": "Merge pull request #150 from mikepenz/dependabot/npm_and_yarn/vercel/ncc-0.26.2\n\nBump @vercel/ncc from 0.26.1 to 0.26.2",
"author": "mikepenz",
"authorDate": "2021-01-07T07:24:43.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T07:24:43.000Z"
},
{
"sha": "d66aa0a4e5aa2037387d4ae13ccde6a106442d9b",
"summary": "- introduce experimental (light) commit based changelog generation mode",
"message": "- introduce experimental (light) commit based changelog generation mode\n - FIX https://github.com/mikepenz/release-changelog-builder-action/issues/141\n - this is not fully supported and not documented as it lacks big amounts of the features we know and love\n- npm install\n- recompile dist",
"author": "mikepenz",
"authorDate": "2021-01-07T14:31:18.000Z",
"committer": "mikepenz",
"commitDate": "2021-01-07T14:31:18.000Z"
},
{
"sha": "937f979dcbce7b629455279dbb09da67743a4aee",
"summary": "- add new param also to other test set",
"message": "- add new param also to other test set",
"author": "mikepenz",
"authorDate": "2021-01-07T14:36:26.000Z",
"committer": "mikepenz",
"commitDate": "2021-01-07T14:36:26.000Z"
},
{
"sha": "626951a1000cda5638a736820fa191a12b4b8fb6",
"summary": "Merge pull request #151 from mikepenz/feature/141",
"message": "Merge pull request #151 from mikepenz/feature/141\n\nExperimental commit based changelog generation mode",
"author": "mikepenz",
"authorDate": "2021-01-07T14:38:58.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T14:38:58.000Z"
},
{
"sha": "6f1faacf001681108f3a5677febf2abdc5261d33",
"summary": "- update jest and recompile dist",
"message": "- update jest and recompile dist",
"author": "mikepenz",
"authorDate": "2021-01-07T14:41:18.000Z",
"committer": "mikepenz",
"commitDate": "2021-01-07T14:41:18.000Z"
},
{
"sha": "eb374ed818dfb7d29b1a17daf831ddd7611ec6a1",
"summary": "Merge pull request #152 from mikepenz/feature/update_jest",
"message": "Merge pull request #152 from mikepenz/feature/update_jest\n\nUpdate jest",
"author": "mikepenz",
"authorDate": "2021-01-07T14:43:46.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T14:43:46.000Z"
},
{
"sha": "12ab81c9e9e730283fecbe3b6c85356952fc5ccb",
"summary": "Merge pull request #153 from mikepenz/develop",
"message": "Merge pull request #153 from mikepenz/develop\n\ndev -> main",
"author": "mikepenz",
"authorDate": "2021-01-07T14:48:32.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T14:48:32.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v1.3.1",
"commit": "v1.3.1"
},
"toTag": {
"name": "v1.4.0",
"commit": "v1.4.0"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": "DESC",
"template": "${{CHANGELOG}}",
"pr_template": "${{NUMBER}}",
"empty_template": "- no changes",
"categories": [
{
"title": "",
"labels": [
"dev",
"Bump"
]
}
],
"ignore_labels": [],
"label_extractor": [
{
"pattern": ".*(dev|Bump).*",
"target": "$1",
"on_property": "title"
}
],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [
"develop"
],
"custom_placeholders": [],
"trim_values": false
}
}
}
@@ -0,0 +1,161 @@
{
"mergedPullRequests": [
{
"number": 153,
"title": "dev -> main",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/153",
"baseBranch": "main",
"branch": "develop",
"createdAt": "2021-01-07T14:44:21.000Z",
"mergedAt": "2021-01-07T14:48:33.000Z",
"mergeCommitSha": "12ab81c9e9e730283fecbe3b6c85356952fc5ccb",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"ignore",
"--rcba-merged"
],
"milestone": "",
"body": "merge dev into main",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 12,
"additions": 10148,
"deletions": 21465,
"changes": 31613,
"commits": 8,
"commitInfo": [
{
"sha": "59903d2471fb3ddbc12e68b5d77d03509038703b",
"summary": "Bump @vercel/ncc from 0.26.1 to 0.26.2",
"message": "Bump @vercel/ncc from 0.26.1 to 0.26.2\n\nBumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.26.1 to 0.26.2.\n- [Release notes](https://github.com/vercel/ncc/releases)\n- [Commits](https://github.com/vercel/ncc/compare/0.26.1...0.26.2)\n\nSigned-off-by: dependabot[bot] <support@github.com>",
"author": "dependabot[bot]",
"authorDate": "2021-01-07T06:32:58.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T06:32:58.000Z"
},
{
"sha": "cb75836b8da89f4e7d6bfabc985a5715e4e41826",
"summary": "Merge pull request #150 from mikepenz/dependabot/npm_and_yarn/vercel/ncc-0.26.2",
"message": "Merge pull request #150 from mikepenz/dependabot/npm_and_yarn/vercel/ncc-0.26.2\n\nBump @vercel/ncc from 0.26.1 to 0.26.2",
"author": "mikepenz",
"authorDate": "2021-01-07T07:24:43.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T07:24:43.000Z"
},
{
"sha": "d66aa0a4e5aa2037387d4ae13ccde6a106442d9b",
"summary": "- introduce experimental (light) commit based changelog generation mode",
"message": "- introduce experimental (light) commit based changelog generation mode\n - FIX https://github.com/mikepenz/release-changelog-builder-action/issues/141\n - this is not fully supported and not documented as it lacks big amounts of the features we know and love\n- npm install\n- recompile dist",
"author": "mikepenz",
"authorDate": "2021-01-07T14:31:18.000Z",
"committer": "mikepenz",
"commitDate": "2021-01-07T14:31:18.000Z"
},
{
"sha": "937f979dcbce7b629455279dbb09da67743a4aee",
"summary": "- add new param also to other test set",
"message": "- add new param also to other test set",
"author": "mikepenz",
"authorDate": "2021-01-07T14:36:26.000Z",
"committer": "mikepenz",
"commitDate": "2021-01-07T14:36:26.000Z"
},
{
"sha": "626951a1000cda5638a736820fa191a12b4b8fb6",
"summary": "Merge pull request #151 from mikepenz/feature/141",
"message": "Merge pull request #151 from mikepenz/feature/141\n\nExperimental commit based changelog generation mode",
"author": "mikepenz",
"authorDate": "2021-01-07T14:38:58.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T14:38:58.000Z"
},
{
"sha": "6f1faacf001681108f3a5677febf2abdc5261d33",
"summary": "- update jest and recompile dist",
"message": "- update jest and recompile dist",
"author": "mikepenz",
"authorDate": "2021-01-07T14:41:18.000Z",
"committer": "mikepenz",
"commitDate": "2021-01-07T14:41:18.000Z"
},
{
"sha": "eb374ed818dfb7d29b1a17daf831ddd7611ec6a1",
"summary": "Merge pull request #152 from mikepenz/feature/update_jest",
"message": "Merge pull request #152 from mikepenz/feature/update_jest\n\nUpdate jest",
"author": "mikepenz",
"authorDate": "2021-01-07T14:43:46.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T14:43:46.000Z"
},
{
"sha": "12ab81c9e9e730283fecbe3b6c85356952fc5ccb",
"summary": "Merge pull request #153 from mikepenz/develop",
"message": "Merge pull request #153 from mikepenz/develop\n\ndev -> main",
"author": "mikepenz",
"authorDate": "2021-01-07T14:48:32.000Z",
"committer": "web-flow",
"commitDate": "2021-01-07T14:48:32.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "v1.3.1",
"commit": "v1.3.1"
},
"toTag": {
"name": "v1.4.0",
"commit": "v1.4.0"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": "DESC",
"template": "${{CHANGELOG}}",
"pr_template": "${{NUMBER}}",
"empty_template": "- no changes",
"categories": [
{
"title": "",
"labels": [
"dev",
"Bump"
]
}
],
"ignore_labels": [],
"label_extractor": [
{
"pattern": ".*(dev|Bump).*",
"target": "$1",
"on_property": "title"
}
],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [
"main"
],
"custom_placeholders": [],
"trim_values": false
}
}
}
+126
View File
@@ -0,0 +1,126 @@
{
"mergedPullRequests": [
{
"number": 10,
"title": "[CI] Specify Test Case",
"htmlURL": "https://github.com/mikepenz/release-changelog-builder-action/pull/10",
"baseBranch": "develop",
"branch": "feature/specify_test",
"createdAt": "2020-10-16T13:58:49.000Z",
"mergedAt": "2020-10-16T13:59:36.000Z",
"mergeCommitSha": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"author": "mikepenz",
"repoName": "mikepenz/release-changelog-builder-action",
"labels": [
"test",
"--rcba-merged"
],
"milestone": "1.0.0",
"body": "- specify test case",
"assignees": [
"mikepenz",
"nhoelzl"
],
"requestedReviewers": [
"nhoelzl"
],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 19,
"additions": 14827,
"deletions": 444,
"changes": 15271,
"commits": 3,
"commitInfo": [
{
"sha": "0a66008df0b0a89c4bcfd447c5457e223f4b9947",
"summary": "- introduce proper approach to retrieve tag before a given tag",
"message": "- introduce proper approach to retrieve tag before a given tag\n- add configuration options for\n - path\n - configuration\n - fromTag, toTag\n - token\n- allow to specify transformers to adjust information to a specific form\n- allow to specify different templates\n- speed up by limiting information to pull\n- add logic to automatically resolve current\n- use github actions logger",
"author": "mikepenz",
"authorDate": "2020-10-16T13:52:24.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-16T13:52:24.000Z"
},
{
"sha": "92577cd8be4b0ff97648fcf6db98ba38dcba1f25",
"summary": "- configure test case",
"message": "- configure test case",
"author": "mikepenz",
"authorDate": "2020-10-16T13:56:40.000Z",
"committer": "mikepenz",
"commitDate": "2020-10-16T13:56:40.000Z"
},
{
"sha": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"summary": "Merge pull request #10 from mikepenz/feature/specify_test",
"message": "Merge pull request #10 from mikepenz/feature/specify_test\n\n[CI] Specify Test Case",
"author": "mikepenz",
"authorDate": "2020-10-16T13:59:35.000Z",
"committer": "web-flow",
"commitDate": "2020-10-16T13:59:35.000Z"
}
]
},
"options": {
"owner": "mikepenz",
"repo": "release-changelog-builder-action",
"fromTag": {
"name": "5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3",
"commit": "5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3"
},
"toTag": {
"name": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa",
"commit": "fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": false,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": "ASC",
"template": "${{CHANGELOG}}",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"feature"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"fix"
]
},
{
"title": "## 🧪 Tests",
"labels": [
"test"
]
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [],
"transformers": [],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
+532
View File
@@ -0,0 +1,532 @@
{
"mergedPullRequests": [
{
"number": 0,
"title": "💚 fix tests",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T02:21:29.000Z",
"mergedAt": "2021-02-17T02:21:29.000Z",
"mergeCommitSha": "2fac84de45bb39cc954f89c11905ac832dd2202b",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "💚 fix tests",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "◀️ improve lib merging",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T02:43:31.000Z",
"mergedAt": "2021-02-17T02:43:31.000Z",
"mergeCommitSha": "9d75b1716ddb729827c5d2383c30a90edf015fd8",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "◀️ improve lib merging",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🌟 add dynamic merging",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T02:51:15.000Z",
"mergedAt": "2021-02-17T02:51:15.000Z",
"mergeCommitSha": "77d6ee9f51a3f5bab5b59fcd807380c6bb050ed2",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🌟 add dynamic merging",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "◀️ disable lib tracking",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T02:52:00.000Z",
"mergedAt": "2021-02-17T02:52:00.000Z",
"mergeCommitSha": "78a1f31a8bee4827ede57a4a442a1540d5bc06ba",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "◀️ disable lib tracking",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🐛 fix dynamic lib replacement",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T02:55:19.000Z",
"mergedAt": "2021-02-17T02:55:19.000Z",
"mergeCommitSha": "65bec59b224d71ab57f2e4030d58f796a0aefbfb",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🐛 fix dynamic lib replacement",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🌟 add auto-cleaning",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T03:09:37.000Z",
"mergedAt": "2021-02-17T03:09:37.000Z",
"mergeCommitSha": "75322fd674ad75db961d7fdffe2dddbb827465e4",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🌟 add auto-cleaning",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "👕 code refactor",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T03:10:21.000Z",
"mergedAt": "2021-02-17T03:10:21.000Z",
"mergeCommitSha": "05e47270d5965bf44509b1524fadcd1f9af4dcef",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "👕 code refactor",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🌟 add built-in adb support",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T09:02:00.000Z",
"mergedAt": "2021-02-17T09:02:00.000Z",
"mergeCommitSha": "822348a5f2f7fc7ae4c2e87ea3e420e40e1fb393",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🌟 add built-in adb support",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🌟 add adb fallback (thanks to @mikepenz ;))",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T10:54:03.000Z",
"mergedAt": "2021-02-17T10:54:03.000Z",
"mergeCommitSha": "b2431355a870956ac36d22345552ec1ed74ecd7c",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🌟 add adb fallback (thanks to @mikepenz ;))",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🐛 fix apostrophe issue with app name",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-17T11:55:49.000Z",
"mergedAt": "2021-02-17T11:55:49.000Z",
"mergeCommitSha": "bdea54101b5198abcebbcc9b55b027e52717ce99",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🐛 fix apostrophe issue with app name",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🌟 add install note",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-18T15:02:11.000Z",
"mergedAt": "2021-02-18T15:02:11.000Z",
"mergeCommitSha": "4da2f341279548c1386a4d5879dfcf88530a1667",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🌟 add install note",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🌟 add @mikepenz to credits",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-18T19:34:57.000Z",
"mergedAt": "2021-02-18T19:34:57.000Z",
"mergeCommitSha": "8060a9ffd2f07f9e4c69e68ff999a6f430628b7b",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🌟 add @mikepenz to credits",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "🐛 fix java.util.logger error",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-18T21:47:18.000Z",
"mergedAt": "2021-02-18T21:47:18.000Z",
"mergeCommitSha": "7f33fb2ba1537f1056137d281f55aeefc5a046a7",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "🐛 fix java.util.logger error",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "👕 move merging logic to report class and apply sort by category",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-19T05:37:51.000Z",
"mergedAt": "2021-02-19T05:37:51.000Z",
"mergeCommitSha": "8cb2762a9d7b6c1f934200294a235fd729e6f7ca",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "👕 move merging logic to report class and apply sort by category",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "📖 update screenshot with truecaller stack",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-19T05:40:07.000Z",
"mergedAt": "2021-02-19T05:40:07.000Z",
"mergeCommitSha": "14248286122a2c683307dd303fa1306dbfeab2a0",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "📖 update screenshot with truecaller stack",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
},
{
"number": 0,
"title": "◀️ remove map categorizing since we're not using that any more. also add some method docs",
"htmlURL": "",
"baseBranch": "",
"createdAt": "2021-02-19T06:02:25.000Z",
"mergedAt": "2021-02-19T06:02:25.000Z",
"mergeCommitSha": "17a9e4dfaedcabe6a6eff2754bebb715e1c58ec4",
"author": "theapache64",
"repoName": "",
"labels": [],
"milestone": "",
"body": "◀️ remove map categorizing since we're not using that any more. also add some method docs",
"assignees": [],
"requestedReviewers": [],
"approvedReviewers": [],
"status": "merged"
}
],
"diffInfo": {
"changedFiles": 20,
"additions": 235,
"deletions": 75,
"changes": 310,
"commits": 16,
"commitInfo": [
{
"sha": "2fac84de45bb39cc954f89c11905ac832dd2202b",
"summary": "💚 fix tests",
"message": "💚 fix tests",
"author": "theapache64",
"authorDate": "2021-02-17T02:21:29.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T02:21:29.000Z"
},
{
"sha": "9d75b1716ddb729827c5d2383c30a90edf015fd8",
"summary": "◀️ improve lib merging",
"message": "◀️ improve lib merging",
"author": "theapache64",
"authorDate": "2021-02-17T02:43:31.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T02:43:31.000Z"
},
{
"sha": "77d6ee9f51a3f5bab5b59fcd807380c6bb050ed2",
"summary": "🌟 add dynamic merging",
"message": "🌟 add dynamic merging",
"author": "theapache64",
"authorDate": "2021-02-17T02:51:15.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T02:51:15.000Z"
},
{
"sha": "78a1f31a8bee4827ede57a4a442a1540d5bc06ba",
"summary": "◀️ disable lib tracking",
"message": "◀️ disable lib tracking",
"author": "theapache64",
"authorDate": "2021-02-17T02:52:00.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T02:52:00.000Z"
},
{
"sha": "65bec59b224d71ab57f2e4030d58f796a0aefbfb",
"summary": "🐛 fix dynamic lib replacement",
"message": "🐛 fix dynamic lib replacement",
"author": "theapache64",
"authorDate": "2021-02-17T02:55:19.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T02:55:19.000Z"
},
{
"sha": "75322fd674ad75db961d7fdffe2dddbb827465e4",
"summary": "🌟 add auto-cleaning",
"message": "🌟 add auto-cleaning",
"author": "theapache64",
"authorDate": "2021-02-17T03:09:37.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T03:09:37.000Z"
},
{
"sha": "05e47270d5965bf44509b1524fadcd1f9af4dcef",
"summary": "👕 code refactor",
"message": "👕 code refactor",
"author": "theapache64",
"authorDate": "2021-02-17T03:10:21.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T03:10:21.000Z"
},
{
"sha": "822348a5f2f7fc7ae4c2e87ea3e420e40e1fb393",
"summary": "🌟 add built-in adb support",
"message": "🌟 add built-in adb support",
"author": "theapache64",
"authorDate": "2021-02-17T09:02:00.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T09:02:00.000Z"
},
{
"sha": "b2431355a870956ac36d22345552ec1ed74ecd7c",
"summary": "🌟 add adb fallback (thanks to @mikepenz ;))",
"message": "🌟 add adb fallback (thanks to @mikepenz ;))",
"author": "theapache64",
"authorDate": "2021-02-17T10:54:03.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T10:54:03.000Z"
},
{
"sha": "bdea54101b5198abcebbcc9b55b027e52717ce99",
"summary": "🐛 fix apostrophe issue with app name",
"message": "🐛 fix apostrophe issue with app name",
"author": "theapache64",
"authorDate": "2021-02-17T11:55:49.000Z",
"committer": "theapache64",
"commitDate": "2021-02-17T11:55:49.000Z"
},
{
"sha": "4da2f341279548c1386a4d5879dfcf88530a1667",
"summary": "🌟 add install note",
"message": "🌟 add install note",
"author": "theapache64",
"authorDate": "2021-02-18T15:02:11.000Z",
"committer": "theapache64",
"commitDate": "2021-02-18T15:02:11.000Z"
},
{
"sha": "8060a9ffd2f07f9e4c69e68ff999a6f430628b7b",
"summary": "🌟 add @mikepenz to credits",
"message": "🌟 add @mikepenz to credits",
"author": "theapache64",
"authorDate": "2021-02-18T19:34:57.000Z",
"committer": "theapache64",
"commitDate": "2021-02-18T19:34:57.000Z"
},
{
"sha": "7f33fb2ba1537f1056137d281f55aeefc5a046a7",
"summary": "🐛 fix java.util.logger error",
"message": "🐛 fix java.util.logger error",
"author": "theapache64",
"authorDate": "2021-02-18T21:47:18.000Z",
"committer": "theapache64",
"commitDate": "2021-02-18T21:47:18.000Z"
},
{
"sha": "8cb2762a9d7b6c1f934200294a235fd729e6f7ca",
"summary": "👕 move merging logic to report class and apply sort by category",
"message": "👕 move merging logic to report class and apply sort by category",
"author": "theapache64",
"authorDate": "2021-02-19T05:37:51.000Z",
"committer": "theapache64",
"commitDate": "2021-02-19T05:37:51.000Z"
},
{
"sha": "14248286122a2c683307dd303fa1306dbfeab2a0",
"summary": "📖 update screenshot with truecaller stack",
"message": "📖 update screenshot with truecaller stack",
"author": "theapache64",
"authorDate": "2021-02-19T05:40:07.000Z",
"committer": "theapache64",
"commitDate": "2021-02-19T05:40:07.000Z"
},
{
"sha": "17a9e4dfaedcabe6a6eff2754bebb715e1c58ec4",
"summary": "◀️ remove map categorizing since we're not using that any more. also add some method docs",
"message": "◀️ remove map categorizing since we're not using that any more. also add some method docs",
"author": "theapache64",
"authorDate": "2021-02-19T06:02:25.000Z",
"committer": "theapache64",
"commitDate": "2021-02-19T06:02:25.000Z"
}
]
},
"options": {
"owner": "theapache64",
"repo": "stackzy",
"fromTag": {
"name": "bd3242a6b6eadb24744c478e112c4628e89609c2",
"commit": "bd3242a6b6eadb24744c478e112c4628e89609c2"
},
"toTag": {
"name": "17a9e4dfaedcabe6a6eff2754bebb715e1c58ec4",
"commit": "17a9e4dfaedcabe6a6eff2754bebb715e1c58ec4"
},
"includeOpen": false,
"failOnError": false,
"fetchReviewers": false,
"fetchReleaseInformation": false,
"fetchReviews": false,
"commitMode": true,
"configuration": {
"max_tags_to_fetch": 200,
"max_pull_requests": 1000,
"max_back_track_time_days": 1000,
"exclude_merge_branches": [],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"template": "${{CHANGELOG}}",
"pr_template": "${{TITLE}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"🚀",
"🌟"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"🐛"
]
},
{
"title": "## 🧪 Tests",
"labels": [
"🧪"
]
},
{
"title": "## 💬 Other",
"labels": [
"💬",
"📖",
"🚨"
]
},
{
"title": "## 📦 Dependencies",
"labels": [
"dependencies"
]
}
],
"ignore_labels": [
"ignore"
],
"label_extractor": [
{
"pattern": "(.) (.+)",
"target": "$1"
}
],
"transformers": [
{
"pattern": "(.) (.+)",
"target": "- $2"
}
],
"tag_resolver": {
"method": "semver"
},
"base_branches": [],
"custom_placeholders": [],
"trim_values": false
}
}
}
Generated Vendored
+4911 -2951
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+1950 -7126
View File
File diff suppressed because it is too large Load Diff
+20 -21
View File
@@ -1,6 +1,6 @@
{
"name": "release-changelog-builder-action",
"version": "v3.0.0",
"version": "v4.0.0",
"private": true,
"description": "A GitHub action that builds your release notes / changelog fast, easy and exactly the way you want.",
"main": "lib/main.js",
@@ -35,30 +35,29 @@
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@octokit/rest": "^19.0.7",
"https-proxy-agent": "^5.0.1",
"@octokit/rest": "^20.0.1",
"https-proxy-agent": "^7.0.1",
"moment": "^2.29.4",
"semver": "^7.5.0",
"tunnel": "^0.0.6",
"webpack": "^5.81.0"
"node-fetch": "2.6.12",
"semver": "^7.5.4"
},
"devDependencies": {
"@types/jest": "^29.5.1",
"@types/node": "^18.16.3",
"@types/semver": "^7.3.13",
"@typescript-eslint/parser": "^5.59.2",
"@types/jest": "^29.5.4",
"@types/node": "^20.5.6",
"@types/node-fetch": "^2.6.4",
"@types/semver": "^7.5.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"@vercel/ncc": "^0.36.1",
"eslint": "^8.39.0",
"eslint-plugin-github": "^4.7.0",
"eslint-plugin-jest": "^27.2.1",
"jest": "^29.5.0",
"jest-circus": "^29.5.0",
"eslint": "^8.47.0",
"eslint-plugin-github": "^4.9.2",
"eslint-plugin-jest": "^27.2.3",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.6.4",
"jest-circus": "^29.6.4",
"js-yaml": "^4.1.0",
"prettier": "2.8.8",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4"
},
"overrides": {
"json5": "^2.2.3"
"prettier": "3.0.2",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
}
}
+2629
View File
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
{
"name": "pr-collector",
"version": "v1.2.0",
"description": "Library to fetch GitHub pull request between 2 tags/sha1 hashes.",
"main": "lib/prCollector.js",
"types": "lib/prCollector.d.ts",
"scripts": {
"build": "tsc",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"lint": "eslint src/**/*.ts",
"package": "ncc build --source-map --license licenses.txt",
"test": "jest --passWithNoTests",
"all": "npm run build && npm run format && npm run lint && npm run package && npm test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mikepenz/release-changelog-builder.git"
},
"keywords": [
"github",
"release",
"notes",
"change",
"pull-requests"
],
"author": "Mike Penz",
"license": "Apache 2.0",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@octokit/rest": "^20.0.1",
"https-proxy-agent": "^7.0.1",
"moment": "^2.29.4",
"node-fetch": "2.6.12",
"semver": "^7.5.4"
},
"devDependencies": {
"@types/node": "^20.5.6",
"@types/node-fetch": "^2.6.4",
"@types/semver": "^7.5.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@vercel/ncc": "^0.36.1",
"eslint-plugin-prettier": "^5.0.0",
"js-yaml": "^4.1.0",
"prettier": "3.0.2",
"typescript": "^5.2.2"
}
}
+68 -5
View File
@@ -1,6 +1,9 @@
import * as core from '@actions/core'
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
import moment from 'moment'
import {failOrError} from './utils'
import {PullRequestInfo} from './pullRequests'
import {Options} from './prCollector'
export interface DiffInfo {
changedFiles: number
@@ -25,7 +28,9 @@ export interface CommitInfo {
summary: string
message: string
author: string
date: moment.Moment
authorDate: moment.Moment
committer: string
commitDate: moment.Moment
}
export class Commits {
@@ -87,8 +92,10 @@ export class Commits {
sha: commit.sha || '',
summary: commit.commit.message.split('\n')[0],
message: commit.commit.message,
date: moment(commit.commit.committer?.date),
author: commit.commit.author?.name || '',
author: commit.author?.login || '',
authorDate: moment(commit.commit.author?.date),
committer: commit.committer?.login || '',
commitDate: moment(commit.commit.committer?.date),
prNumber: undefined
}))
}
@@ -107,9 +114,9 @@ export class Commits {
}
commitsResult.sort((a, b) => {
if (a.date.isBefore(b.date)) {
if (a.commitDate.isBefore(b.commitDate)) {
return -1
} else if (b.date.isBefore(a.date)) {
} else if (b.commitDate.isBefore(a.commitDate)) {
return 1
}
return 0
@@ -117,6 +124,62 @@ export class Commits {
return commitsResult
}
async getCommitHistory(options: Options): Promise<DiffInfo> {
const {owner, repo, fromTag, toTag, failOnError} = options
core.info(`️ Comparing ${owner}/${repo} - '${fromTag.name}...${toTag.name}'`)
const commitsApi = new Commits(this.octokit)
let diffInfo: DiffInfo
try {
diffInfo = await commitsApi.getDiff(owner, repo, fromTag.name, toTag.name)
} catch (error) {
failOrError(`💥 Failed to retrieve - Invalid tag? - Because of: ${error}`, failOnError)
return DefaultDiffInfo
}
if (diffInfo.commitInfo.length === 0) {
core.warning(`⚠️ No commits found between - ${fromTag.name}...${toTag.name}`)
return DefaultDiffInfo
}
return diffInfo
}
async generateCommitPRs(options: Options): Promise<[DiffInfo, PullRequestInfo[]]> {
const {owner, repo, configuration} = options
const diffInfo = await this.getCommitHistory(options)
const commits = diffInfo.commitInfo
if (commits.length === 0) {
return [diffInfo, []]
}
const prCommits = filterCommits(commits, configuration.exclude_merge_branches)
core.info(`️ Retrieved ${prCommits.length} commits for ${owner}/${repo}`)
const prs = prCommits.map(function (commit): PullRequestInfo {
return {
number: 0,
title: commit.summary,
htmlURL: '',
baseBranch: '',
createdAt: commit.commitDate,
mergedAt: commit.commitDate,
mergeCommitSha: commit.sha,
author: commit.author || '',
repoName: '',
labels: [],
milestone: '',
body: commit.message || '',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'merged'
}
})
return [diffInfo, prs]
}
}
/**
+164
View File
@@ -0,0 +1,164 @@
import * as core from '@actions/core'
import {PullConfiguration} from './types'
import {Octokit} from '@octokit/rest'
import {TagInfo, Tags} from './tags'
import {failOrError} from './utils'
import {HttpsProxyAgent} from 'https-proxy-agent'
import {PullRequestInfo, PullRequests} from './pullRequests'
import {Commits, DiffInfo} from './commits'
import fetch from 'node-fetch'
export interface Options {
owner: string // the owner of the repository
repo: string // the repository
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
fetchViaCommits: boolean // defines if PRs are fetched via the commits identified. This will do 1 API request per commit -> Best for scenarios with squash merges | Or shorter from-to diffs (< 10 commits) | Also effective for shorters diffs for very old PRs
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
fetchReviews: boolean // defines if the action should fetch the reviews for the PR.
commitMode: boolean // defines if we use the alternative commit based mode. note: this is only partially supported
configuration: PullConfiguration // the configuration as defined in `configuration.ts`
}
export interface Data {
diffInfo: DiffInfo
mergedPullRequests: PullRequestInfo[]
fromTag: TagInfo
toTag: TagInfo
}
export class PullRequestCollector {
constructor(
private baseUrl: string | null,
private token: string | null,
private repositoryPath: string,
private owner: string,
private repo: string,
private fromTag: string | null,
private toTag: string | null,
private includeOpen = false,
private failOnError: boolean,
private ignorePreReleases: boolean,
private fetchViaCommits = false,
private fetchReviewers = false,
private fetchReleaseInformation = false,
private fetchReviews = false,
private commitMode = false,
private configuration: PullConfiguration
) {}
async build(): Promise<Data | null> {
// check proxy setup for GHES environments
const proxy = process.env.https_proxy || process.env.HTTPS_PROXY
const noProxy = process.env.no_proxy || process.env.NO_PROXY
let noProxyArray: string[] = []
if (noProxy) {
noProxyArray = noProxy.split(',')
}
// load octokit instance
const octokit = new Octokit({
auth: `token ${this.token || process.env.GITHUB_TOKEN}`,
baseUrl: `${this.baseUrl || 'https://api.github.com'}`,
request: {
fetch
}
})
if (proxy) {
const agent = new HttpsProxyAgent(proxy)
octokit.hook.before('request', options => {
if (noProxyArray.includes(options.request.hostname)) {
return
}
options.request.agent = agent
})
}
// ensure proper from <-> to tag range
core.startGroup(`🔖 Resolve tags`)
const tagsApi = new Tags(octokit)
const tagRange = await tagsApi.retrieveRange(
this.repositoryPath,
this.owner,
this.repo,
this.fromTag,
this.toTag,
this.ignorePreReleases,
this.configuration.max_tags_to_fetch,
this.configuration.tag_resolver
)
let thisTag = tagRange.to
if (!thisTag) {
failOrError(`💥 Missing or couldn't resolve 'toTag'`, this.failOnError)
return null
} else {
core.debug(`Resolved 'toTag' as ${thisTag.name}`)
}
let previousTag = tagRange.from
if (previousTag == null) {
failOrError(`💥 Unable to retrieve previous tag given ${this.toTag}`, this.failOnError)
return null
}
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()
return await pullData(octokit, {
owner: this.owner,
repo: this.repo,
fromTag: previousTag,
toTag: thisTag,
includeOpen: this.includeOpen,
failOnError: this.failOnError,
fetchViaCommits: this.fetchViaCommits,
fetchReviewers: this.fetchReviewers,
fetchReleaseInformation: this.fetchReleaseInformation,
fetchReviews: this.fetchReviews,
commitMode: this.commitMode,
configuration: this.configuration
})
}
}
export async function pullData(octokit: Octokit, options: Options): Promise<Data | null> {
let mergedPullRequests: PullRequestInfo[]
let diffInfo: DiffInfo
const commitsApi = new Commits(octokit)
if (!options.commitMode) {
core.startGroup(`🚀 Load pull requests`)
const pullRequestsApi = new PullRequests(octokit, commitsApi)
const [info, prs] = await pullRequestsApi.getMergedPullRequests(options)
mergedPullRequests = prs
diffInfo = info
} else {
core.startGroup(`🚀 Load commit history`)
core.info(`⚠️ Executing experimental commit mode`)
const [info, prs] = await commitsApi.generateCommitPRs(options)
mergedPullRequests = prs
diffInfo = info
}
core.endGroup()
return {
diffInfo,
mergedPullRequests,
fromTag: options.fromTag,
toTag: options.toTag
}
}
+439
View File
@@ -0,0 +1,439 @@
import * as core from '@actions/core'
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
import {Unpacked} from './utils'
import moment from 'moment'
import {Property, Sort} from './types'
import {Commits, DiffInfo, filterCommits} from './commits'
import {Options} from './prCollector'
export interface PullRequestInfo {
number: number
title: string
htmlURL: string
baseBranch: string
branch?: string
createdAt: moment.Moment
mergedAt: moment.Moment | undefined
mergeCommitSha: string
author: string
repoName: string
labels: string[]
milestone: string
body: string
assignees: string[]
requestedReviewers: string[]
approvedReviewers: string[]
reviews?: CommentInfo[]
status: 'open' | 'merged'
}
export interface CommentInfo {
id: number
htmlURL: string
submittedAt: moment.Moment | undefined
author: string
body: string
state: string | undefined
}
export const EMPTY_PULL_REQUEST_INFO: PullRequestInfo = {
number: 0,
title: '',
htmlURL: '',
baseBranch: '',
mergedAt: undefined,
createdAt: moment(),
mergeCommitSha: '',
author: '',
repoName: '',
labels: [],
milestone: '',
body: '',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'open'
}
export const EMPTY_COMMENT_INFO: CommentInfo = {
id: 0,
htmlURL: '',
submittedAt: undefined,
author: '',
body: '',
state: undefined
}
type PullData = RestEndpointMethodTypes['pulls']['get']['response']['data']
type PullsListData = RestEndpointMethodTypes['pulls']['list']['response']['data']
type PullReviewsData = RestEndpointMethodTypes['pulls']['listReviews']['response']['data']
export class PullRequests {
constructor(
private octokit: Octokit,
private commits: Commits
) {}
async getSingle(owner: string, repo: string, prNumber: number): Promise<PullRequestInfo | null> {
try {
const {data} = await this.octokit.pulls.get({
owner,
repo,
pull_number: prNumber
})
return mapPullRequest(data)
} catch (e: any /* eslint-disable-line @typescript-eslint/no-explicit-any */) {
core.warning(`⚠️ Cannot find PR ${owner}/${repo}#${prNumber} - ${e.message}`)
return null
}
}
async getForCommitHash(owner: string, repo: string, commit_sha: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = []
const options = this.octokit.repos.listPullRequestsAssociatedWithCommit.endpoint.merge({
owner,
repo,
commit_sha,
per_page: `${Math.min(10, maxPullRequests)}`,
direction: 'desc'
})
for await (const response of this.octokit.paginate.iterator(options)) {
const prs: PullsListData = response.data as PullsListData
for (const pr of prs) {
mergedPRs.push(mapPullRequest(pr, pr.merged_at ? 'merged' : 'open'))
}
}
return sortPrs(mergedPRs)
}
async getBetweenDates(
owner: string,
repo: string,
fromDate: moment.Moment,
toDate: moment.Moment,
maxPullRequests: number
): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = []
const options = this.octokit.pulls.list.endpoint.merge({
owner,
repo,
state: 'closed',
sort: 'merged',
per_page: `${Math.min(100, maxPullRequests)}`,
direction: 'desc'
})
for await (const response of this.octokit.paginate.iterator(options)) {
const prs: PullsListData = response.data as PullsListData
for (const pr of prs.filter(p => !!p.merged_at)) {
mergedPRs.push(mapPullRequest(pr, 'merged'))
}
if (mergedPRs.length >= maxPullRequests) {
core.warning(`⚠️ Reached 'maxPullRequests' count ${maxPullRequests} (1)`)
break // bail out early to not keep iterating forever
} else if (prs.length > 0) {
if (fetchedEnough(prs, fromDate)) {
return sortPrs(mergedPRs) // bail out early to not keep iterating on PRs super old
}
} else {
core.debug(`⚠️ No more PRs retrieved from API. Fetched so far: ${mergedPRs.length}`)
break
}
}
return sortPrs(mergedPRs)
}
async getOpen(owner: string, repo: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const openPrs: PullRequestInfo[] = []
const options = this.octokit.pulls.list.endpoint.merge({
owner,
repo,
state: 'open',
sort: 'created',
per_page: '100',
direction: 'desc'
})
for await (const response of this.octokit.paginate.iterator(options)) {
const prs: PullsListData = response.data as PullsListData
for (const pr of prs) {
openPrs.push(mapPullRequest(pr, 'open'))
}
const firstPR = prs[0]
if (firstPR === undefined || openPrs.length >= maxPullRequests) {
if (openPrs.length >= maxPullRequests) {
core.warning(`⚠️ Reached 'maxPullRequests' count ${maxPullRequests} (2)`)
}
break // bail out early to not keep iterating forever
}
}
return sortPrs(openPrs)
}
async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
const options = this.octokit.pulls.listReviews.endpoint.merge({
owner,
repo,
pull_number: pr.number,
sort: 'created',
direction: 'desc'
})
const prReviews: CommentInfo[] = []
for await (const response of this.octokit.paginate.iterator(options)) {
const comments: PullReviewsData = response.data as PullReviewsData
for (const comment of comments) {
prReviews.push(mapComment(comment))
}
}
pr.reviews = prReviews
}
async getMergedPullRequests(options: Options): Promise<[DiffInfo, PullRequestInfo[]]> {
const {owner, repo, includeOpen, fetchReviewers, fetchReviews, configuration} = options
const diffInfo = await this.commits.getCommitHistory(options)
const commits = diffInfo.commitInfo
if (commits.length === 0) {
return [diffInfo, []]
}
const firstCommit = commits[0]
const lastCommit = commits[commits.length - 1]
let fromDate = moment.min(firstCommit.authorDate, firstCommit.commitDate) // get the lower date (e.g. if commits are modified)
const toDate = moment.max(lastCommit.authorDate, lastCommit.commitDate) // ensure we get the higher date (e.g. in case of rebases)
const maxDays = configuration.max_back_track_time_days
const maxFromDate = toDate.clone().subtract(maxDays, 'days')
if (maxFromDate.isAfter(fromDate)) {
core.info(`⚠️ Adjusted 'fromDate' to go max ${maxDays} back`)
fromDate = maxFromDate
}
core.info(`️ Fetching PRs between dates ${fromDate.toISOString()} to ${toDate.toISOString()} for ${owner}/${repo}`)
const prCommits = filterCommits(commits, configuration.exclude_merge_branches)
core.info(`️ Retrieved ${prCommits.length} release commits for ${owner}/${repo}`)
// create array of commits for this release
const releaseCommitHashes = prCommits.map(commit => {
return commit.sha
})
let pullRequests: PullRequestInfo[]
if (options.fetchViaCommits) {
// fetch PRs based on commits instead (will get associated PRs per commit found)
const prsForReleaseCommits: Map<number, PullRequestInfo> = new Map()
for (const commit of prCommits) {
const result = await this.getForCommitHash(owner, repo, commit.sha, configuration.max_pull_requests)
for (const pr of result) {
prsForReleaseCommits.set(pr.number, pr)
}
}
const dedupedPrsForReleaseCommits = Array.from(prsForReleaseCommits.values())
if (!includeOpen) {
pullRequests = dedupedPrsForReleaseCommits.filter(pr => pr.status !== 'open')
core.info(`️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} based on the release commit hashes`)
} else {
pullRequests = dedupedPrsForReleaseCommits
core.info(`️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} based on the release commit hashes (including open)`)
}
} else {
// fetch PRs based on the date range identified
const pullRequestsBetweenDate = await this.getBetweenDates(owner, repo, fromDate, toDate, configuration.max_pull_requests)
core.info(`️ Retrieved ${pullRequestsBetweenDate.length} PRs for ${owner}/${repo} in date range from API`)
// filter out pull requests not associated with this release
const mergedPullRequests = pullRequestsBetweenDate.filter(pr => {
return releaseCommitHashes.includes(pr.mergeCommitSha)
})
core.info(`️ Retrieved ${mergedPullRequests.length} merged PRs for ${owner}/${repo}`)
let allPullRequests = mergedPullRequests
if (includeOpen) {
// retrieve all open pull requests
const openPullRequests = await this.getOpen(owner, repo, configuration.max_pull_requests)
core.info(`️ Retrieved ${openPullRequests.length} open PRs for ${owner}/${repo}`)
// all pull requests
allPullRequests = allPullRequests.concat(openPullRequests)
core.info(`️ Retrieved ${allPullRequests.length} total PRs for ${owner}/${repo}`)
}
pullRequests = allPullRequests
}
// retrieve base branches we allow
const baseBranches = configuration.base_branches
const baseBranchPatterns = baseBranches.map(baseBranch => {
return new RegExp(baseBranch.replace('\\\\', '\\'), 'gu')
})
// return only prs if the baseBranch is matching the configuration
const finalPrs = pullRequests.filter(pr => {
if (baseBranches.length !== 0) {
return baseBranchPatterns.some(pattern => {
return pr.baseBranch.match(pattern) !== null
})
}
return true
})
if (baseBranches.length !== 0) {
core.info(`️ Retrieved ${finalPrs.length} PRs for ${owner}/${repo} filtered by the 'base_branches' configuration.`)
}
// fetch reviewers only if enabled (requires an additional API request per PR)
if (fetchReviews || fetchReviewers) {
core.info(`️ Fetching reviews (or reviewers) was enabled`)
// update PR information with reviewers who approved
for (const pr of finalPrs) {
await this.getReviews(owner, repo, pr)
const reviews = pr.reviews
if (reviews && (reviews?.length || 0) > 0) {
core.info(`️ Retrieved ${reviews.length || 0} review(s) for PR ${owner}/${repo}/#${pr.number}`)
// backwards compatiblity
pr.approvedReviewers = reviews.filter(r => r.state === 'APPROVED').map(r => r.author)
} else {
core.debug(`No reviewer(s) for PR ${owner}/${repo}/#${pr.number}`)
}
}
} else {
core.debug(`️ Fetching reviews (or reviewers) was disabled`)
}
return [diffInfo, finalPrs]
}
}
function fetchedEnough(pullRequests: PullsListData, fromDate: moment.Moment): boolean {
for (let i = 0; i < Math.min(pullRequests.length, 3); i++) {
const firstPR = pullRequests[i]
if (!firstPR.merged_at) {
continue // no merged_at timestamp -> look for the next
} else if (fromDate.isAfter(moment(firstPR.merged_at))) {
return true
} else {
break // not enough PRs yet, go further
}
}
return false
}
function sortPrs(pullRequests: PullRequestInfo[]): PullRequestInfo[] {
return sortPullRequests(pullRequests, {
order: 'ASC',
on_property: 'mergedAt'
})
}
export function sortPullRequests(pullRequests: PullRequestInfo[], sort: Sort | string): PullRequestInfo[] {
let sortConfig: Sort
// legacy handling to support string sort config
if (typeof sort === 'string') {
let order: 'ASC' | 'DESC' = 'ASC'
if (sort.toUpperCase() === 'DESC') order = 'DESC'
sortConfig = {order, on_property: 'mergedAt'}
} else {
sortConfig = sort
}
if (sortConfig.order === 'ASC') {
pullRequests.sort((a, b) => {
return compare(a, b, sortConfig)
})
} else {
pullRequests.sort((b, a) => {
return compare(a, b, sortConfig)
})
}
return pullRequests
}
export function compare(a: PullRequestInfo, b: PullRequestInfo, sort: Sort): number {
if (sort.on_property === 'mergedAt') {
const aa = a.mergedAt || a.createdAt
const bb = b.mergedAt || b.createdAt
if (aa.isBefore(bb)) {
return -1
} else if (bb.isBefore(aa)) {
return 1
}
return 0
} else {
// only else for now `label`
return a.title.localeCompare(b.title)
}
}
/**
* Helper function to retrieve a property from the PullRequestInfo
*/
export function retrieveProperty(pr: PullRequestInfo, property: Property, useCase: string): string {
let value: string | number | Set<string> | string[] | undefined = pr[property]
if (value === undefined) {
core.warning(`⚠️ the provided property '${property}' for \`${useCase}\` is not valid. Fallback to 'body'`)
value = pr['body']
} else if (value instanceof Set) {
value = Array.from(value).join(',') // join into single string
} else if (Array.isArray(value)) {
value = value.join(',') // join into single string
} else {
value = value.toString()
}
return value
}
// helper function to add a special open label to prs not merged.
function attachSpeciaLabels(status: 'open' | 'merged', labels: string[]): string[] {
labels.push(`--rcba-${status}`)
return labels
}
const mapPullRequest = (pr: PullData | Unpacked<PullsListData>, status: 'open' | 'merged' = 'open'): PullRequestInfo => ({
number: pr.number,
title: pr.title,
htmlURL: pr.html_url,
baseBranch: pr.base.ref,
branch: pr.head.ref,
createdAt: moment(pr.created_at),
mergedAt: pr.merged_at ? moment(pr.merged_at) : undefined,
mergeCommitSha: pr.merge_commit_sha || '',
author: pr.user?.login || '',
repoName: pr.base.repo.full_name,
labels: attachSpeciaLabels(status, pr.labels?.map(lbl => lbl.name?.toLocaleLowerCase('en') || '') || []),
milestone: pr.milestone?.title || '',
body: pr.body || '',
assignees: pr.assignees?.map(asignee => asignee?.login || '') || [],
requestedReviewers: pr.requested_reviewers?.map(reviewer => reviewer?.login || '') || [],
approvedReviewers: [],
reviews: undefined,
status
})
const mapComment = (comment: Unpacked<PullReviewsData>): CommentInfo => ({
id: comment.id,
htmlURL: comment.html_url,
submittedAt: comment.submitted_at ? moment(comment.submitted_at) : undefined,
author: comment.user?.login || '',
body: comment.body,
state: comment.state
})
+60
View File
@@ -0,0 +1,60 @@
import * as core from '@actions/core'
import {Extractor, Property, Regex, RegexTransformer, Transformer} from './types'
export function validateTransformer(transformer?: Regex): RegexTransformer | null {
if (transformer === undefined) {
return null
}
try {
let target = undefined
if (transformer.hasOwnProperty('target')) {
target = (transformer as Transformer).target
}
let onProperty = undefined
let method = undefined
let onEmpty = undefined
if (transformer.hasOwnProperty('method')) {
method = (transformer as Extractor).method
onEmpty = (transformer as Extractor).on_empty
onProperty = (transformer as Extractor).on_property
} else if (transformer.hasOwnProperty('on_property')) {
onProperty = (transformer as Extractor).on_property
}
// legacy handling, transform single value input to array
if (!Array.isArray(onProperty)) {
if (onProperty !== undefined) {
onProperty = [onProperty]
}
}
return buildRegex(transformer, target, onProperty, method, onEmpty)
} catch (e) {
core.warning(`⚠️ Failed to validate transformer: ${transformer.pattern}`)
return null
}
}
/**
* Constructs the RegExp, providing the configured Regex and additional values
*/
export function buildRegex(
regex: Regex,
target: string | undefined,
onProperty?: Property[] | undefined,
method?: 'replace' | 'match' | undefined,
onEmpty?: string | undefined
): RegexTransformer | null {
try {
return {
pattern: new RegExp(regex.pattern.replace('\\\\', '\\'), regex.flags ?? 'gu'),
target: target || '',
onProperty,
method,
onEmpty
}
} catch (e) {
core.warning(`⚠️ Bad regex: ${regex.pattern} (${e})`)
return null
}
}
+46 -18
View File
@@ -3,10 +3,10 @@ import * as github from '@actions/github'
import * as semver from 'semver'
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
import {SemVer} from 'semver'
import {TagResolver} from './configuration'
import {RegexTransformer, TagResolver, Transformer} from './types'
import {createCommandManager} from './gitHelper'
import moment from 'moment'
import {RegexTransformer, validateTransformer} from './regexUtils'
import {validateTransformer} from './regexUtils'
export interface TagResult {
from: TagInfo | null
@@ -16,6 +16,7 @@ export interface TagResult {
export interface TagInfo {
name: string
commit?: string
preRelease?: boolean
date?: moment.Moment
}
@@ -104,7 +105,7 @@ export class Tags {
if (ignorePreReleases) {
core.info(`️ Enabled 'ignorePreReleases', searching for the closest release`)
for (let ii = i + 1; ii < length; ii++) {
if (!tags[ii].name.includes('-')) {
if (!tags[ii].preRelease) {
return tags[ii]
}
}
@@ -139,6 +140,9 @@ export class Tags {
maxTagsToFetch: number,
tagResolver: TagResolver
): Promise<TagResult> {
let tags: TagInfo[] = []
if (!toTag || !fromTag) {
// filter out tags not matching the specified filter
const filteredTags = filterTags(
// retrieve the tags from the API
@@ -146,20 +150,33 @@ export class Tags {
tagResolver
)
// check if a transformer was defined
const tagTransformer = validateTransformer(tagResolver.transformer)
let transformedTags: TagInfo[]
if (tagTransformer != null) {
core.debug(`️ Using configured tagTransformer`)
transformedTags = transformTags(filteredTags, tagTransformer)
// check if a transformer, legacy handling, transform single value input to array
let tagTransfomers: Transformer[] | undefined = undefined
if (tagResolver.transformer !== undefined) {
if (!Array.isArray(tagResolver.transformer)) {
tagTransfomers = [tagResolver.transformer]
} else {
transformedTags = filteredTags
tagTransfomers = tagResolver.transformer
}
}
let tags = sortTags(transformedTags, tagResolver)
let transformed = false
let transformedTags: TagInfo[] = filteredTags
if (tagTransfomers !== undefined && tagTransfomers.length > 0) {
for (const transformer of tagTransfomers) {
const tagTransformer = validateTransformer(transformer)
if (tagTransformer != null) {
core.debug(`️ Using configured tagTransformer (${transformer.pattern})`)
transformedTags = transformTags(transformedTags, tagTransformer)
transformed = true
}
}
}
// sort tags, apply additional information (e.g. if tag is a pre release)
tags = prepareAndSortTags(transformedTags, tagResolver)
if (transformed) {
// restore the original name, after sorting
tags = filteredTags.map(function (tag) {
if (tag.hasOwnProperty('tmp')) {
@@ -169,6 +186,7 @@ export class Tags {
}
})
}
}
let resultToTag: TagInfo | null
let resultFromTag: TagInfo | null
@@ -278,15 +296,16 @@ function transformTags(tags: TagInfo[], transformer: RegexTransformer): TagInfo[
2020.3.1-a01
2020.3.0
*/
export function sortTags(tags: TagInfo[], tagResolver: TagResolver): TagInfo[] {
export function prepareAndSortTags(tags: TagInfo[], tagResolver: TagResolver): TagInfo[] {
if (tagResolver.method === 'sort') {
return stringSorting(tags)
return stringTags(tags)
} else {
return semVerSorting(tags)
// semver is default
return semVerTags(tags)
}
}
function semVerSorting(tags: TagInfo[]): TagInfo[] {
function semVerTags(tags: TagInfo[]): TagInfo[] {
// filter out tags which do not follow semver
const validatedTags = tags.filter(tag => {
const isValid =
@@ -295,6 +314,11 @@ function semVerSorting(tags: TagInfo[]): TagInfo[] {
}) !== null
if (!isValid) {
core.debug(`⚠️ dropped tag ${tag.name} because it is not a valid semver tag`)
} else {
tag.preRelease =
semver.prerelease(tag.name, {
loose: true
}) != null
}
return isValid
})
@@ -309,7 +333,11 @@ function semVerSorting(tags: TagInfo[]): TagInfo[] {
return validatedTags
}
function stringSorting(tags: TagInfo[]): TagInfo[] {
function stringTags(tags: TagInfo[]): TagInfo[] {
for (const tag of tags) {
tag.preRelease = tag.name.includes('-')
}
return tags.sort((b, a) => {
const partsA = a.name.replace(/^v/, '').split('-')
const partsB = b.name.replace(/^v/, '').split('-')
+63
View File
@@ -0,0 +1,63 @@
export interface PullConfiguration {
max_tags_to_fetch: number
max_pull_requests: number
max_back_track_time_days: number
exclude_merge_branches: string[]
sort: Sort | string // "ASC" or "DESC"
tag_resolver: TagResolver
base_branches: string[]
}
/**
* Defines the properties of the PullRequestInfo useable in different configurations
*/
export type Property =
| 'number'
| 'title'
| 'branch'
| 'author'
| 'labels'
| 'milestone'
| 'body'
| 'assignees'
| 'requestedReviewers'
| 'approvedReviewers'
| 'status'
export interface Rule extends Regex {
on_property?: Property // retrieve the property to apply the rule on
}
export interface Sort {
order: 'ASC' | 'DESC' // the sorting order
on_property: 'mergedAt' | 'title' // the property to sort on. (mergedAt falls back to createdAt)
}
export interface TagResolver {
method: string // semver, sort
filter?: Regex // the regex to filter the tags, prior to sorting
transformer?: Transformer | Transformer[] // transforms the tag name using the regex, run after the filter
}
export interface Regex {
pattern: string // the regex pattern to match
flags?: string // the regex flag to use for RegExp
}
export interface Transformer extends Regex {
target?: string // the target string to transform the source string using the regex to
}
export interface Extractor extends Transformer {
on_property?: Property[] | Property | undefined // retrieve the property to extract the value from
method?: 'replace' | 'match' | undefined // the method to use to extract the value, `match` will not use the `target` property
on_empty?: string | undefined // in case the regex results in an empty string, this value is gonna be used instead (only for label_extractor currently)
}
export interface RegexTransformer {
pattern: RegExp | null
target: string
onProperty?: Property[]
method?: 'replace' | 'match'
onEmpty?: string
}
+49
View File
@@ -0,0 +1,49 @@
import * as core from '@actions/core'
import * as fs from 'fs'
/**
* Will automatically either report the message to the log, or mark the action as failed. Additionally defining the output failed, allowing it to be read in by other actions
*/
export function failOrError(message: string | Error, failOnError: boolean): void {
// if we report any failure, consider the action to have failed, may not make the build fail
core.setOutput('failed', true)
if (failOnError) {
core.setFailed(message)
} else {
core.error(message)
}
}
/**
* Checks if a given directory exists
*/
export function directoryExistsSync(inputPath: string, required?: boolean): boolean {
if (!inputPath) {
throw new Error("Arg 'path' must not be empty")
}
let stats: fs.Stats
try {
stats = fs.statSync(inputPath)
} catch (error: any /* eslint-disable-line @typescript-eslint/no-explicit-any */) {
if (error.code === 'ENOENT') {
if (!required) {
return false
}
throw new Error(`Directory '${inputPath}' does not exist`)
}
throw new Error(`Encountered an error when checking whether path '${inputPath}' exists: ${error.message}`)
}
if (stats.isDirectory()) {
return true
} else if (!required) {
return false
}
throw new Error(`Directory '${inputPath}' does not exist`)
}
export type Unpacked<T> = T extends (infer U)[] ? U : T
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"outDir": "./lib", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"lib": [ "ES2021.String" ], /* Enable custom `ES2021.String` extension in typescript for `replaceAll` */
"declaration": true
},
"exclude": ["node_modules", "**/*.test.ts", "lib"]
}
+9 -25
View File
@@ -1,4 +1,6 @@
export interface Configuration {
import {Rule, Extractor, Regex, Transformer, Sort, PullConfiguration} from './pr-collector/types'
export interface Configuration extends PullConfiguration {
max_tags_to_fetch: number
max_pull_requests: number
max_back_track_time_days: number
@@ -11,6 +13,7 @@ export interface Configuration {
ignore_labels: string[]
label_extractor: Extractor[]
duplicate_filter?: Extractor // extract an identifier from a PR used to detect duplicates, will keep the last match (depends on `sort`)
reference?: Extractor // extracts a reference from a PR, used to establish parent child relations. This will remove the child from the main PR list.
transformers: Transformer[]
tag_resolver: TagResolver
base_branches: string[]
@@ -19,6 +22,7 @@ export interface Configuration {
}
export interface Category {
key?: string // a key for this category. This is currently only used for the json output
title: string // the title of this category
labels?: string[] // labels to associate PRs to this category
exclude_labels?: string[] // if an exclude label is detected, the PR will be excluded from this category
@@ -44,30 +48,6 @@ export type Property =
| 'approvedReviewers'
| 'status'
export interface Rule extends Regex {
on_property?: Property // retrieve the property to apply the rule on
}
export interface Sort {
order: 'ASC' | 'DESC' // the sorting order
on_property: 'mergedAt' | 'title' // the property to sort on. (mergedAt falls back to createdAt)
}
export interface Regex {
pattern: string // the regex pattern to match
flags?: string // the regex flag to use for RegExp
}
export interface Transformer extends Regex {
target?: string // the target string to transform the source string using the regex to
}
export interface Extractor extends Transformer {
on_property?: Property[] | Property | undefined // retrieve the property to extract the value from
method?: 'replace' | 'match' | undefined // the method to use to extract the value, `match` will not use the `target` property
on_empty?: string | undefined // in case the regex results in an empty string, this value is gonna be used instead (only for label_extractor currently)
}
export interface TagResolver {
method: string // semver, sort
filter?: Regex // the regex to filter the tags, prior to sorting
@@ -105,6 +85,10 @@ export const DefaultConfiguration: Configuration = {
{
title: '## 🧪 Tests',
labels: ['test']
},
{
title: '## 📦 Uncategorized',
labels: []
}
], // the categories to support for the ordering
ignore_labels: ['ignore'], // list of lables being ignored from the changelog
+9 -1
View File
@@ -31,7 +31,7 @@ async function run(): Promise<void> {
core.info(`️ Retreived configuration via 'configuration' (via file).`)
}
if (!configurationFile && !configFile) {
if (!configJson && !configFile) {
core.info(`️ No configuration provided. Using Defaults.`)
}
@@ -50,10 +50,14 @@ async function run(): Promise<void> {
const includeOpen = core.getInput('includeOpen') === 'true'
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true'
const failOnError = core.getInput('failOnError') === 'true'
const fetchViaCommits = core.getInput('fetchViaCommits') === 'true'
const fetchReviewers = core.getInput('fetchReviewers') === 'true'
const fetchReleaseInformation = core.getInput('fetchReleaseInformation') === 'true'
const fetchReviews = core.getInput('fetchReviews') === 'true'
const commitMode = core.getInput('commitMode') === 'true'
const exportCache = core.getInput('exportCache') === 'true'
const exportOnly = core.getInput('exportOnly') === 'true'
const cache = core.getInput('cache')
const result = await new ReleaseNotesBuilder(
baseUrl,
@@ -66,10 +70,14 @@ async function run(): Promise<void> {
includeOpen,
failOnError,
ignorePreReleases,
fetchViaCommits,
fetchReviewers,
fetchReleaseInformation,
fetchReviews,
commitMode,
exportCache,
exportOnly,
cache,
configuration
).build()
+1
View File
@@ -0,0 +1 @@
../pr-collector/src/
-263
View File
@@ -1,263 +0,0 @@
import * as core from '@actions/core'
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
import {Unpacked} from './utils'
import moment from 'moment'
import {Property, Sort} from './configuration'
export interface PullRequestInfo {
number: number
title: string
htmlURL: string
baseBranch: string
branch?: string
createdAt: moment.Moment
mergedAt: moment.Moment | undefined
mergeCommitSha: string
author: string
repoName: string
labels: Set<string>
milestone: string
body: string
assignees: string[]
requestedReviewers: string[]
approvedReviewers: string[]
reviews?: CommentInfo[]
status: 'open' | 'merged'
}
export interface CommentInfo {
id: number
htmlURL: string
submittedAt: moment.Moment | undefined
author: string
body: string
state: string | undefined
}
export const EMPTY_COMMENT_INFO: CommentInfo = {
id: 0,
htmlURL: '',
submittedAt: undefined,
author: '',
body: '',
state: undefined
}
type PullData = RestEndpointMethodTypes['pulls']['get']['response']['data']
type PullsListData = RestEndpointMethodTypes['pulls']['list']['response']['data']
type PullReviewsData = RestEndpointMethodTypes['pulls']['listReviews']['response']['data']
export class PullRequests {
constructor(private octokit: Octokit) {}
async getSingle(owner: string, repo: string, prNumber: number): Promise<PullRequestInfo | null> {
try {
const {data} = await this.octokit.pulls.get({
owner,
repo,
pull_number: prNumber
})
return mapPullRequest(data)
} catch (e: any /* eslint-disable-line @typescript-eslint/no-explicit-any */) {
core.warning(`⚠️ Cannot find PR ${owner}/${repo}#${prNumber} - ${e.message}`)
return null
}
}
async getBetweenDates(
owner: string,
repo: string,
fromDate: moment.Moment,
toDate: moment.Moment,
maxPullRequests: number
): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = []
const options = this.octokit.pulls.list.endpoint.merge({
owner,
repo,
state: 'closed',
sort: 'merged',
per_page: `${Math.min(100, maxPullRequests)}`,
direction: 'desc'
})
for await (const response of this.octokit.paginate.iterator(options)) {
const prs: PullsListData = response.data as PullsListData
for (const pr of prs.filter(p => !!p.merged_at)) {
mergedPRs.push(mapPullRequest(pr, 'merged'))
}
const firstPR = prs[0]
if (
firstPR === undefined ||
(firstPR.merged_at && fromDate.isAfter(moment(firstPR.merged_at))) ||
mergedPRs.length >= maxPullRequests
) {
if (mergedPRs.length >= maxPullRequests) {
core.warning(`⚠️ Reached 'maxPullRequests' count ${maxPullRequests}`)
}
// bail out early to not keep iterating on PRs super old
return sortPrs(mergedPRs)
}
}
return sortPrs(mergedPRs)
}
async getOpen(owner: string, repo: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const openPrs: PullRequestInfo[] = []
const options = this.octokit.pulls.list.endpoint.merge({
owner,
repo,
state: 'open',
sort: 'created',
per_page: '100',
direction: 'desc'
})
for await (const response of this.octokit.paginate.iterator(options)) {
const prs: PullsListData = response.data as PullsListData
for (const pr of prs) {
openPrs.push(mapPullRequest(pr, 'open'))
}
const firstPR = prs[0]
if (firstPR === undefined || openPrs.length >= maxPullRequests) {
if (openPrs.length >= maxPullRequests) {
core.warning(`⚠️ Reached 'maxPullRequests' count ${maxPullRequests}`)
}
// bail out early to not keep iterating on PRs super old
return sortPrs(openPrs)
}
}
return sortPrs(openPrs)
}
async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
const options = this.octokit.pulls.listReviews.endpoint.merge({
owner,
repo,
pull_number: pr.number,
sort: 'created',
direction: 'desc'
})
const prReviews: CommentInfo[] = []
for await (const response of this.octokit.paginate.iterator(options)) {
const comments: PullReviewsData = response.data as PullReviewsData
for (const comment of comments) {
prReviews.push(mapComment(comment))
}
}
pr.reviews = prReviews
}
}
function sortPrs(pullRequests: PullRequestInfo[]): PullRequestInfo[] {
return sortPullRequests(pullRequests, {
order: 'ASC',
on_property: 'mergedAt'
})
}
export function sortPullRequests(pullRequests: PullRequestInfo[], sort: Sort | string): PullRequestInfo[] {
let sortConfig: Sort
// legacy handling to support string sort config
if (typeof sort === 'string') {
let order: 'ASC' | 'DESC' = 'ASC'
if (sort.toUpperCase() === 'DESC') order = 'DESC'
sortConfig = {order, on_property: 'mergedAt'}
} else {
sortConfig = sort
}
if (sortConfig.order === 'ASC') {
pullRequests.sort((a, b) => {
return compare(a, b, sortConfig)
})
} else {
pullRequests.sort((b, a) => {
return compare(a, b, sortConfig)
})
}
return pullRequests
}
export function compare(a: PullRequestInfo, b: PullRequestInfo, sort: Sort): number {
if (sort.on_property === 'mergedAt') {
const aa = a.mergedAt || a.createdAt
const bb = b.mergedAt || b.createdAt
if (aa.isBefore(bb)) {
return -1
} else if (bb.isBefore(aa)) {
return 1
}
return 0
} else {
// only else for now `label`
return a.title.localeCompare(b.title)
}
}
/**
* Helper function to retrieve a property from the PullRequestInfo
*/
export function retrieveProperty(pr: PullRequestInfo, property: Property, useCase: string): string {
let value: string | number | Set<string> | string[] | undefined = pr[property]
if (value === undefined) {
core.warning(`⚠️ the provided property '${property}' for \`${useCase}\` is not valid. Fallback to 'body'`)
value = pr['body']
} else if (value instanceof Set) {
value = Array.from(value).join(',') // join into single string
} else if (Array.isArray(value)) {
value = value.join(',') // join into single string
} else {
value = value.toString()
}
return value
}
// helper function to add a special open label to prs not merged.
function attachSpeciaLabels(status: 'open' | 'merged', labels: Set<string>): Set<string> {
labels.add(`--rcba-${status}`)
return labels
}
const mapPullRequest = (pr: PullData | Unpacked<PullsListData>, status: 'open' | 'merged' = 'open'): PullRequestInfo => ({
number: pr.number,
title: pr.title,
htmlURL: pr.html_url,
baseBranch: pr.base.ref,
branch: pr.head.ref,
createdAt: moment(pr.created_at),
mergedAt: pr.merged_at ? moment(pr.merged_at) : undefined,
mergeCommitSha: pr.merge_commit_sha || '',
author: pr.user?.login || '',
repoName: pr.base.repo.full_name,
labels: attachSpeciaLabels(status, new Set(pr.labels?.map(lbl => lbl.name?.toLocaleLowerCase('en') || '') || [])),
milestone: pr.milestone?.title || '',
body: pr.body || '',
assignees: pr.assignees?.map(asignee => asignee?.login || '') || [],
requestedReviewers: pr.requested_reviewers?.map(reviewer => reviewer?.login || '') || [],
approvedReviewers: [],
reviews: undefined,
status
})
const mapComment = (comment: Unpacked<PullReviewsData>): CommentInfo => ({
id: comment.id,
htmlURL: comment.html_url,
submittedAt: comment.submitted_at ? moment(comment.submitted_at) : undefined,
author: comment.user?.login || '',
body: comment.body,
state: comment.state
})
+3 -68
View File
@@ -1,6 +1,7 @@
import * as core from '@actions/core'
import {Extractor, Property, Regex, Rule, Transformer} from './configuration'
import {PullRequestInfo, retrieveProperty} from './pullRequests'
import {Rule, RegexTransformer} from './pr-collector/types'
import {PullRequestInfo, retrieveProperty} from './pr-collector/pullRequests'
import {validateTransformer} from './pr-collector/regexUtils'
/**
* Checks if any of the rules match the given PR
@@ -37,69 +38,3 @@ function matches(pr: PullRequestInfo, extractor: RegexTransformer, extractor_use
}
return false
}
export function validateTransformer(transformer?: Regex): RegexTransformer | null {
if (transformer === undefined) {
return null
}
try {
let target = undefined
if (transformer.hasOwnProperty('target')) {
target = (transformer as Transformer).target
}
let onProperty = undefined
let method = undefined
let onEmpty = undefined
if (transformer.hasOwnProperty('method')) {
method = (transformer as Extractor).method
onEmpty = (transformer as Extractor).on_empty
onProperty = (transformer as Extractor).on_property
} else if (transformer.hasOwnProperty('on_property')) {
onProperty = (transformer as Extractor).on_property
}
// legacy handling, transform single value input to array
if (!Array.isArray(onProperty)) {
if (onProperty !== undefined) {
onProperty = [onProperty]
}
}
return buildRegex(transformer, target, onProperty, method, onEmpty)
} catch (e) {
core.warning(`⚠️ Failed to validate transformer: ${transformer.pattern}`)
return null
}
}
/**
* Constructs the RegExp, providing the configured Regex and additional values
*/
export function buildRegex(
regex: Regex,
target: string | undefined,
onProperty?: Property[] | undefined,
method?: 'replace' | 'match' | undefined,
onEmpty?: string | undefined
): RegexTransformer | null {
try {
return {
pattern: new RegExp(regex.pattern.replace('\\\\', '\\'), regex.flags ?? 'gu'),
target: target || '',
onProperty,
method,
onEmpty
}
} catch (e) {
core.warning(`⚠️ Bad replacer regex: ${regex.pattern}`)
return null
}
}
export interface RegexTransformer {
pattern: RegExp | null
target: string
onProperty?: Property[]
method?: 'replace' | 'match'
onEmpty?: string
}
-230
View File
@@ -1,230 +0,0 @@
import * as core from '@actions/core'
import {Commits, filterCommits, DiffInfo, DefaultDiffInfo} from './commits'
import {Configuration} from './configuration'
import {PullRequestInfo, PullRequests} from './pullRequests'
import {Octokit} from '@octokit/rest'
import {buildChangelog, replaceEmptyTemplate} 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: 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
fetchReviews: boolean // defines if the action should fetch the reviews for the PR.
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`
}
export class ReleaseNotes {
constructor(private octokit: Octokit, private options: ReleaseNotesOptions) {}
async pull(): Promise<string> {
let mergedPullRequests: PullRequestInfo[]
let diffInfo: DiffInfo
if (!this.options.commitMode) {
core.startGroup(`🚀 Load pull requests`)
const [info, prs] = await this.getMergedPullRequests(this.octokit)
mergedPullRequests = prs
diffInfo = info
// define the included PRs within this release as output
core.setOutput(
'pull_requests',
mergedPullRequests
.map(pr => {
return pr.number
})
.join(',')
)
core.endGroup()
} else {
core.startGroup(`🚀 Load commit history`)
core.info(`⚠️ Executing experimental commit mode`)
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 replaceEmptyTemplate(this.options.configuration.empty_template, this.options)
}
core.startGroup('📦 Build changelog')
const resultChangelog = buildChangelog(diffInfo, mergedPullRequests, this.options)
core.endGroup()
return resultChangelog
}
private async getCommitHistory(octokit: Octokit): Promise<DiffInfo> {
const {owner, repo, fromTag, toTag, failOnError} = this.options
core.info(`️ Comparing ${owner}/${repo} - '${fromTag.name}...${toTag.name}'`)
const commitsApi = new Commits(octokit)
let diffInfo: DiffInfo
try {
diffInfo = await commitsApi.getDiff(owner, repo, fromTag.name, toTag.name)
} catch (error) {
failOrError(`💥 Failed to retrieve - Invalid tag? - Because of: ${error}`, failOnError)
return DefaultDiffInfo
}
if (diffInfo.commitInfo.length === 0) {
core.warning(`⚠️ No commits found between - ${fromTag.name}...${toTag.name}`)
return DefaultDiffInfo
}
return diffInfo
}
private async getMergedPullRequests(octokit: Octokit): Promise<[DiffInfo, PullRequestInfo[]]> {
const {owner, repo, includeOpen, fetchReviewers, fetchReviews, configuration} = this.options
const diffInfo = await this.getCommitHistory(octokit)
const commits = diffInfo.commitInfo
if (commits.length === 0) {
return [diffInfo, []]
}
const firstCommit = commits[0]
const lastCommit = commits[commits.length - 1]
let fromDate = firstCommit.date
const toDate = lastCommit.date
const maxDays = configuration.max_back_track_time_days
const maxFromDate = toDate.clone().subtract(maxDays, 'days')
if (maxFromDate.isAfter(fromDate)) {
core.info(`⚠️ Adjusted 'fromDate' to go max ${maxDays} back`)
fromDate = maxFromDate
}
core.info(`️ Fetching PRs between dates ${fromDate.toISOString()} to ${toDate.toISOString()} for ${owner}/${repo}`)
const pullRequestsApi = new PullRequests(octokit)
const pullRequests = await pullRequestsApi.getBetweenDates(owner, repo, fromDate, toDate, configuration.max_pull_requests)
core.info(`️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} in date range from API`)
const prCommits = filterCommits(commits, configuration.exclude_merge_branches)
core.info(`️ Retrieved ${prCommits.length} release commits for ${owner}/${repo}`)
// create array of commits for this release
const releaseCommitHashes = prCommits.map(commmit => {
return commmit.sha
})
// filter out pull requests not associated with this release
const mergedPullRequests = pullRequests.filter(pr => {
return releaseCommitHashes.includes(pr.mergeCommitSha)
})
core.info(`️ Retrieved ${mergedPullRequests.length} merged PRs for ${owner}/${repo}`)
let allPullRequests = mergedPullRequests
if (includeOpen) {
// retrieve all open pull requests
const openPullRequests = await pullRequestsApi.getOpen(owner, repo, configuration.max_pull_requests)
core.info(`️ Retrieved ${openPullRequests.length} open PRs for ${owner}/${repo}`)
// all pull requests
allPullRequests = allPullRequests.concat(openPullRequests)
core.info(`️ Retrieved ${allPullRequests.length} total PRs for ${owner}/${repo}`)
}
// retrieve base branches we allow
const baseBranches = configuration.base_branches
const baseBranchPatterns = baseBranches.map(baseBranch => {
return new RegExp(baseBranch.replace('\\\\', '\\'), 'gu')
})
// return only prs if the baseBranch is matching the configuration
const finalPrs = allPullRequests.filter(pr => {
if (baseBranches.length !== 0) {
return baseBranchPatterns.some(pattern => {
return pr.baseBranch.match(pattern) !== null
})
}
return true
})
if (baseBranches.length !== 0) {
core.info(`️ Retrieved ${finalPrs.length} PRs for ${owner}/${repo} filtered by the 'base_branches' configuration.`)
}
// fetch reviewers only if enabled (requires an additional API request per PR)
if (fetchReviews || fetchReviewers) {
core.info(`️ Fetching reviews (or reviewers) was enabled`)
// update PR information with reviewers who approved
for (const pr of finalPrs) {
await pullRequestsApi.getReviews(owner, repo, pr)
const reviews = pr.reviews
if (reviews && (reviews?.length || 0) > 0) {
core.info(`️ Retrieved ${reviews.length || 0} review(s) for PR ${owner}/${repo}/#${pr.number}`)
// backwards compatiblity
pr.approvedReviewers = reviews.filter(r => r.state === 'APPROVED').map(r => r.author)
} else {
core.debug(`No reviewer(s) for PR ${owner}/${repo}/#${pr.number}`)
}
}
} else {
core.debug(`️ Fetching reviews (or reviewers) was disabled`)
}
return [diffInfo, finalPrs]
}
private async generateCommitPRs(octokit: Octokit): Promise<[DiffInfo, PullRequestInfo[]]> {
const {owner, repo, configuration} = this.options
const diffInfo = await this.getCommitHistory(octokit)
const commits = diffInfo.commitInfo
if (commits.length === 0) {
return [diffInfo, []]
}
const prCommits = filterCommits(commits, configuration.exclude_merge_branches)
core.info(`️ Retrieved ${prCommits.length} commits for ${owner}/${repo}`)
const prs = prCommits.map(function (commit): PullRequestInfo {
return {
number: 0,
title: commit.summary,
htmlURL: '',
baseBranch: '',
createdAt: commit.date,
mergedAt: commit.date,
mergeCommitSha: commit.sha,
author: commit.author || '',
repoName: '',
labels: new Set(),
milestone: '',
body: commit.message || '',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'merged'
}
})
return [diffInfo, prs]
}
}
+139 -73
View File
@@ -1,10 +1,33 @@
import * as core from '@actions/core'
import {Configuration} from './configuration'
import {Octokit} from '@octokit/rest'
import {ReleaseNotes} from './releaseNotes'
import {Tags} from './tags'
import {failOrError} from './utils'
import {HttpsProxyAgent} from 'https-proxy-agent'
import {checkExportedData, writeCacheData} from './utils'
import {PullRequestData, buildChangelog} from './transform'
import {PullRequestCollector} from './pr-collector/prCollector'
import {failOrError} from './pr-collector/utils'
import {TagInfo} from './pr-collector/tags'
import {DiffInfo} from './pr-collector/commits'
import {PullRequestInfo} from './pr-collector/pullRequests'
import * as fs from 'fs'
export interface ReleaseNotesOptions {
owner: string // the owner of the repository
repo: string // the repository
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
fetchReviews: boolean // defines if the action should fetch the reviews for the PR.
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`
}
export interface Data {
diffInfo: DiffInfo
mergedPullRequests: PullRequestInfo[]
options: ReleaseNotesOptions
}
export class ReleaseNotesBuilder {
constructor(
@@ -15,22 +38,33 @@ export class ReleaseNotesBuilder {
private repo: string | null,
private fromTag: string | null,
private toTag: string | null,
private includeOpen: boolean = false,
private includeOpen = false,
private failOnError: boolean,
private ignorePreReleases: boolean,
private fetchReviewers: boolean = false,
private fetchReleaseInformation: boolean = false,
private fetchReviews: boolean = false,
private commitMode: boolean,
private fetchViaCommits = false,
private fetchReviewers = false,
private fetchReleaseInformation = false,
private fetchReviews = false,
private commitMode = false,
private exportCache = false,
private exportOnly = false,
private cache: string | null = null,
private configuration: Configuration
) {}
async build(): Promise<string | null> {
let releaseNotesData: Data | null
try {
releaseNotesData = checkExportedData(this.exportCache, this.cache)
} catch (error) {
failOrError(`${error}`, this.failOnError)
return null
}
if (releaseNotesData == null) {
if (!this.owner) {
failOrError(`💥 Missing or couldn't resolve 'owner'`, this.failOnError)
return null
} else {
core.setOutput('owner', this.owner)
core.debug(`Resolved 'owner' as ${this.owner}`)
}
@@ -38,82 +72,38 @@ export class ReleaseNotesBuilder {
failOrError(`💥 Missing or couldn't resolve 'owner'`, this.failOnError)
return null
} else {
core.setOutput('repo', this.repo)
core.debug(`Resolved 'repo' as ${this.repo}`)
}
core.endGroup()
// check proxy setup for GHES environments
const proxy = process.env.https_proxy || process.env.HTTPS_PROXY
const noProxy = process.env.no_proxy || process.env.NO_PROXY
let noProxyArray: string[] = []
if (noProxy) {
noProxyArray = noProxy.split(',')
}
// load octokit instance
const octokit = new Octokit({
auth: `token ${this.token || process.env.GITHUB_TOKEN}`,
baseUrl: `${this.baseUrl || 'https://api.github.com'}`
})
if (proxy) {
const agent = new HttpsProxyAgent(proxy)
octokit.hook.before('request', options => {
if (noProxyArray.includes(options.request.hostname)) {
return
}
options.request.agent = agent
})
}
// ensure proper from <-> to tag range
core.startGroup(`🔖 Resolve tags`)
const tagsApi = new Tags(octokit)
const tagRange = await tagsApi.retrieveRange(
const prData = await new PullRequestCollector(
this.baseUrl,
this.token,
this.repositoryPath,
this.owner,
this.repo,
this.fromTag,
this.toTag,
this.includeOpen,
this.failOnError,
this.ignorePreReleases,
this.configuration.max_tags_to_fetch,
this.configuration.tag_resolver
)
this.fetchViaCommits,
this.fetchReviewers,
this.fetchReleaseInformation,
this.fetchReviews,
this.commitMode,
this.configuration
).build()
let thisTag = tagRange.to
if (!thisTag) {
failOrError(`💥 Missing or couldn't resolve 'toTag'`, this.failOnError)
return null
} else {
core.setOutput('toTag', thisTag.name)
core.debug(`Resolved 'toTag' as ${thisTag.name}`)
}
let previousTag = tagRange.from
if (previousTag == null) {
failOrError(`💥 Unable to retrieve previous tag given ${this.toTag}`, this.failOnError)
if (prData == null) {
return null
}
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 = {
const options: ReleaseNotesOptions = {
owner: this.owner,
repo: this.repo,
fromTag: previousTag,
toTag: thisTag,
fromTag: prData.fromTag,
toTag: prData.toTag,
includeOpen: this.includeOpen,
failOnError: this.failOnError,
fetchReviewers: this.fetchReviewers,
@@ -122,8 +112,84 @@ export class ReleaseNotesBuilder {
commitMode: this.commitMode,
configuration: this.configuration
}
const releaseNotes = new ReleaseNotes(octokit, options)
const mergedPullRequests = prData.mergedPullRequests
const diffInfo = prData.diffInfo
this.setOutputs(options, diffInfo, mergedPullRequests)
return await releaseNotes.pull()
if (this.exportCache) {
const cacheData = {
mergedPullRequests,
diffInfo,
options
}
writeCacheData(cacheData, this.cache)
if (this.exportOnly) {
core.info(`️ Enabled 'exportOnly' will not generate changelog`)
core.endGroup()
return null
}
}
return buildChangelog(diffInfo, mergedPullRequests, options)
} else {
core.info(`️ Retrieved previously cache data`)
// merge input with options (in case some data was updated)
const diffInfo = releaseNotesData.diffInfo
const mergedPullRequests = releaseNotesData.mergedPullRequests
const orgOptions = releaseNotesData.options
// merge fromTag info with provided info || otherwise use cached info
const fromTag: TagInfo = orgOptions.fromTag
if (this.fromTag) {
fromTag.name = this.fromTag
}
const toTag: TagInfo = orgOptions.toTag
if (this.toTag) {
toTag.name = this.toTag
}
// merge provided values with previous options (prefer provided)
const options: ReleaseNotesOptions = {
owner: this.owner || orgOptions.owner,
repo: this.repo || orgOptions.repo,
fromTag,
toTag,
includeOpen: this.includeOpen || orgOptions.includeOpen,
failOnError: this.failOnError || orgOptions.failOnError,
fetchReviewers: this.fetchReviewers || orgOptions.fetchReviewers,
fetchReleaseInformation: this.fetchReleaseInformation || orgOptions.fetchReleaseInformation,
fetchReviews: this.fetchReviews || orgOptions.fetchReviews,
commitMode: this.commitMode || orgOptions.commitMode,
configuration: this.configuration || orgOptions.configuration
}
this.setOutputs(options, diffInfo, mergedPullRequests)
return buildChangelog(diffInfo, mergedPullRequests, options)
}
}
setOutputs(options: ReleaseNotesOptions, diffInfo: DiffInfo, mergedPullRequests: PullRequestData[]): void {
core.setOutput('owner', options.owner)
core.setOutput('repo', options.repo)
core.setOutput('toTag', options.toTag.name)
core.setOutput('fromTag', options.fromTag.name)
// define the included PRs within this release as output
core.setOutput(
'pull_requests',
mergedPullRequests
.map(pr => {
return pr.number
})
.join(',')
)
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)
}
}
+133 -15
View File
@@ -1,24 +1,84 @@
import * as core from '@actions/core'
import {Category, Configuration, Placeholder, Property, Transformer} from './configuration'
import {CommentInfo, EMPTY_COMMENT_INFO, PullRequestInfo, retrieveProperty, sortPullRequests} from './pullRequests'
import {ReleaseNotesOptions} from './releaseNotes'
import {DiffInfo} from './commits'
import {createOrSet, haveCommonElements, haveEveryElements} from './utils'
import {matchesRules, RegexTransformer, validateTransformer} from './regexUtils'
import {Category, Configuration, Placeholder, Property} from './configuration'
import {createOrSet, haveCommonElementsArr, haveEveryElementsArr} from './utils'
import {
CommentInfo,
EMPTY_COMMENT_INFO,
EMPTY_PULL_REQUEST_INFO,
PullRequestInfo,
retrieveProperty,
sortPullRequests
} from './pr-collector/pullRequests'
import {DiffInfo} from './pr-collector/commits'
import {validateTransformer} from './pr-collector/regexUtils'
import {Transformer, RegexTransformer} from './pr-collector/types'
import {ReleaseNotesOptions} from './releaseNotesBuilder'
import {matchesRules} from './regexUtils'
const EMPTY_MAP = new Map<string, string>()
export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], options: ReleaseNotesOptions): string {
export interface PullRequestData extends PullRequestInfo {
childPrs?: PullRequestInfo[]
}
export function buildChangelog(diffInfo: DiffInfo, origPrs: PullRequestInfo[], options: ReleaseNotesOptions): string {
core.startGroup('📦 Build changelog')
let prs: PullRequestData[] = origPrs
if (prs.length === 0) {
core.warning(`⚠️ No pull requests found`)
const result = replaceEmptyTemplate(options.configuration.empty_template, options)
core.endGroup()
return result
}
// sort to target order
const config = options.configuration
const sort = config.sort
prs = sortPullRequests(prs, sort)
core.info(`️ Sorted all pull requests ascending: ${JSON.stringify(sort)}`)
// establish parent child PR relations
if (config.reference !== undefined) {
const reference = validateTransformer(config.reference)
if (reference !== null) {
core.info(`️ Identifying PR references using \`reference\``)
const mapped = new Map<number, PullRequestData>()
for (const pr of prs) {
mapped.set(pr.number, pr)
}
const remappedPrs: PullRequestData[] = []
for (const pr of prs) {
const extracted = extractValues(pr, reference, 'reference')
if (extracted !== null && extracted.length > 0) {
const foundNumber = parseInt(extracted[0])
const valid = !isNaN(foundNumber)
const parent = mapped.get(foundNumber)
if (valid && parent !== undefined) {
if (parent.childPrs === undefined) {
parent.childPrs = []
}
parent.childPrs.push(pr)
} else {
if (!valid) core.debug(`⚠️ Extracted reference 'isNaN': ${extracted}`)
remappedPrs.push(pr)
}
} else {
remappedPrs.push(pr)
}
}
prs = remappedPrs
} else {
core.warning(`⚠️ Configured \`reference\` invalid.`)
}
}
// drop duplicate pull requests
if (config.duplicate_filter !== undefined) {
const extractor = validateTransformer(config.duplicate_filter)
if (extractor != null) {
if (extractor !== null) {
core.info(`️ Remove duplicated pull requests using \`duplicate_filter\``)
const deduplicatedMap = new Map<string, PullRequestInfo>()
@@ -49,7 +109,7 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
const extracted = extractValues(pr, extractor, 'label_extractor')
if (extracted !== null) {
for (const label of extracted) {
pr.labels.add(label)
pr.labels.push(label)
}
if (core.isDebug()) {
@@ -92,7 +152,7 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
// bring elements in order
for (const [pr, body] of transformedMap) {
if (
haveCommonElements(
haveCommonElementsArr(
ignoredLabels.map(lbl => lbl.toLocaleLowerCase('en')),
pr.labels
)
@@ -111,7 +171,7 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
// check if any exclude label matches
if (category.exclude_labels !== undefined) {
if (
haveCommonElements(
haveCommonElementsArr(
category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')),
pr.labels
)
@@ -128,7 +188,7 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
// validate for an exhaustive match (e.g. every provided rule applies)
if (category.exhaustive === true && (category.labels !== undefined || category.rules !== undefined)) {
if (category.labels !== undefined) {
matched = haveEveryElements(
matched = haveEveryElementsArr(
category.labels.map(lbl => lbl.toLocaleLowerCase('en')),
pr.labels
)
@@ -137,14 +197,14 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
if (category.exhaustive_rules !== undefined) {
exhaustive_rules = category.exhaustive_rules
}
if (matched && category.rules !== undefined) {
if ((matched || category.labels === undefined) && category.rules !== undefined) {
matched = matchesRules(category.rules, pr, exhaustive_rules)
}
} else {
// if not exhaustive, do individual matches
if (category.labels !== undefined) {
// check if either any of the labels applies
matched = haveCommonElements(
matched = haveCommonElementsArr(
category.labels.map(lbl => lbl.toLocaleLowerCase('en')),
pr.labels
)
@@ -168,10 +228,30 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
// we allow to have pull requests included in an "uncategorized" category
for (const [category, pullRequests] of categorized) {
if ((category.labels === undefined || category.labels.length === 0) && category.rules === undefined) {
// check if any exclude label matches for the "uncategorized" category
if (category.exclude_labels !== undefined) {
if (
!haveCommonElementsArr(
category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')),
pr.labels
)
) {
pullRequests.push(body)
} else if (core.isDebug()) {
const excludeLabels = JSON.stringify(category.exclude_labels)
core.debug(
` PR ${pr.number} with labels: ${pr.labels} excluded from uncategorized category via exclude label: ${excludeLabels}`
)
}
} else {
pullRequests.push(body)
}
break
}
}
// note the `exclude label` configuration of categories will not apply to the legacy "UNCATEGORIZED" placeholder
uncategorizedPrs.push(body)
} else {
categorizedPrs.push(body)
@@ -179,6 +259,13 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
}
core.info(`️ Ordered all pull requests into ${categories.length} categories`)
// serialize and provide the categorized content as json
const transformedCategorized = Array.from(categorized).reduce(
(obj, [key, value]) => Object.assign(obj, {[key.key || key.title]: value}),
{}
)
core.setOutput('categorized', JSON.stringify(transformedCategorized))
// construct final changelog
let changelog = ''
for (const [category, pullRequests] of categorized) {
@@ -266,7 +353,9 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
transformedChangelog = replacePlaceholders(transformedChangelog, EMPTY_MAP, placeholderMap, placeholders, placeholderPrMap, config)
transformedChangelog = replacePrPlaceholders(transformedChangelog, placeholderPrMap, config)
transformedChangelog = cleanupPrPlaceholders(transformedChangelog, placeholders)
transformedChangelog = cleanupPlaceholders(transformedChangelog)
core.info(`️ Filled template`)
core.endGroup()
return transformedChangelog
}
@@ -304,7 +393,7 @@ function fillAdditionalPlaceholders(
}
function fillPrTemplate(
pr: PullRequestInfo,
pr: PullRequestData,
template: string,
placeholders: Map<string, Placeholder[]> /* placeholders to apply */,
placeholderPrMap: Map<string, string[]> /* map to keep replaced placeholder values with their key */,
@@ -312,6 +401,7 @@ function fillPrTemplate(
): string {
const arrayPlaceholderMap = new Map<string, string>()
fillReviewPlaceholders(arrayPlaceholderMap, 'REVIEWS', pr.reviews || [])
fillChildPrPlaceholders(arrayPlaceholderMap, 'REFERENCED', pr.childPrs || [])
const placeholderMap = new Map<string, string>()
placeholderMap.set('NUMBER', pr.number.toString())
placeholderMap.set('TITLE', pr.title)
@@ -401,6 +491,7 @@ function fillArrayPlaceholders(
key: string,
values: string[]
): void {
if (values.length === 0) return
for (let i = 0; i < values.length; i++) {
placeholderMap.set(`${key}[${i}]`, values[i])
}
@@ -412,6 +503,7 @@ function fillReviewPlaceholders(
parentKey: string,
values: CommentInfo[]
): void {
if (values.length === 0) return
// retrieve the keys from the CommentInfo object
for (const childKey of Object.keys(EMPTY_COMMENT_INFO)) {
for (let i = 0; i < values.length; i++) {
@@ -424,6 +516,24 @@ function fillReviewPlaceholders(
}
}
function fillChildPrPlaceholders(
placeholderMap: Map<string, string> /* placeholderKey and original value */,
parentKey: string,
values: PullRequestInfo[]
): void {
if (values.length === 0) return
// retrieve the keys from the PullRequestInfo object
for (const childKey of Object.keys(EMPTY_PULL_REQUEST_INFO)) {
for (let i = 0; i < values.length; i++) {
placeholderMap.set(`${parentKey}[${i}].${childKey}`, values[i][childKey as keyof PullRequestInfo]?.toLocaleString('en') || '')
}
placeholderMap.set(
`${parentKey}[*].${childKey}`,
values.map(value => value[childKey as keyof PullRequestInfo]?.toLocaleString('en') || '').join(', ')
)
}
}
function replacePrPlaceholders(
template: string,
placeholderPrMap: Map<string, string[]> /* map with all pr related custom placeholder values */,
@@ -449,6 +559,14 @@ function cleanupPrPlaceholders(template: string, placeholders: Map<string, Place
return transformed
}
function cleanupPlaceholders(template: string): string {
let transformed = template
for (const phs of ['REVIEWS', 'REFERENCED', 'ASSIGNEES', 'REVIEWERS', 'APPROVERS']) {
transformed = transformed.replaceAll(new RegExp(`\\$\\{\\{${phs}\\[.+?\\]\\..*?\\}\\}`, 'gu'), '')
}
return transformed
}
function transform(filled: string, transformers: RegexTransformer[]): string {
if (transformers.length === 0) {
return filled
+93 -43
View File
@@ -2,6 +2,11 @@ import * as core from '@actions/core'
import * as fs from 'fs'
import * as path from 'path'
import {Configuration, DefaultConfiguration} from './configuration'
import moment from 'moment'
import {DiffInfo} from './pr-collector/commits'
import {PullRequestInfo} from './pr-collector/pullRequests'
import {Data, ReleaseNotesOptions} from './releaseNotesBuilder'
import {env} from 'process'
/**
* Resolves the repository path, relatively to the GITHUB_WORKSPACE
*/
@@ -19,16 +24,87 @@ export function retrieveRepositoryPath(providedPath: string): string {
return repositoryPath
}
/**
* Will automatically either report the message to the log, or mark the action as failed. Additionally defining the output failed, allowing it to be read in by other actions
*/
export function failOrError(message: string | Error, failOnError: boolean): void {
// if we report any failure, consider the action to have failed, may not make the build fail
core.setOutput('failed', true)
if (failOnError) {
core.setFailed(message)
export function writeCacheData(data: Data, cacheOutput: string | null): void {
let cacheFile: string
if (cacheOutput && !cacheOutput.startsWith('{')) {
// legacy handling, originally we allowed cache as direct string.
// However, this can result in a "Argument list too long" exception for very long caches
cacheFile = cacheOutput
} else {
core.error(message)
if (env.RUNNER_TEMP && !fs.existsSync(env.RUNNER_TEMP)) {
fs.mkdirSync(env.RUNNER_TEMP)
}
cacheFile = `${env.RUNNER_TEMP}/rcba-cache.json`
core.debug(`Defined cacheFile as ${cacheFile}`)
}
try {
fs.writeFileSync(cacheFile, JSON.stringify(data))
core.setOutput(`cache`, cacheFile)
} catch (error) {
core.warning(`Failed to write cache file. (${error})`)
}
}
/**
* Retrieves the exported information from a previous run of the `release-changelog-builder-action`.
* If available, return a [ReleaseNotesData].
*/
export function checkExportedData(exportCache: boolean, cacheInput: string | null): Data | null {
if (exportCache) {
return null
}
if (cacheInput) {
// legacy handling, originally we allowed cache as direct string.
// However, this can result in a "Argument list too long" exception for very long caches
const legacyJsonCache = cacheInput.startsWith('{')
let cache: Data
if (legacyJsonCache) {
cache = JSON.parse(cacheInput)
} else {
if (!fs.existsSync(cacheInput)) {
throw new Error(`💥 The provided cache file does not exist`)
} else {
cache = JSON.parse(fs.readFileSync(cacheInput, 'utf8'))
}
}
const diffInfo: DiffInfo = cache.diffInfo
const mergedPullRequests: PullRequestInfo[] = cache.mergedPullRequests
for (const pr of mergedPullRequests) {
pr.createdAt = moment(pr.createdAt)
if (pr.mergedAt) {
pr.mergedAt = moment(pr.mergedAt)
}
if (pr.reviews) {
for (const review of pr.reviews) {
if (review.submittedAt) {
review.submittedAt = moment(review.submittedAt)
}
}
}
}
const options: ReleaseNotesOptions = cache.options
if (options.fromTag.date) {
options.fromTag.date = moment(options.fromTag.date)
}
if (options.toTag.date) {
options.toTag.date = moment(options.toTag.date)
}
return {
diffInfo,
mergedPullRequests,
options
}
} else {
return null
}
}
@@ -110,38 +186,6 @@ export function mergeConfiguration(jc?: Configuration, fc?: Configuration): Conf
}
}
/**
* Checks if a given directory exists
*/
export function directoryExistsSync(inputPath: string, required?: boolean): boolean {
if (!inputPath) {
throw new Error("Arg 'path' must not be empty")
}
let stats: fs.Stats
try {
stats = fs.statSync(inputPath)
} catch (error: any /* eslint-disable-line @typescript-eslint/no-explicit-any */) {
if (error.code === 'ENOENT') {
if (!required) {
return false
}
throw new Error(`Directory '${inputPath}' does not exist`)
}
throw new Error(`Encountered an error when checking whether path '${inputPath}' exists: ${error.message}`)
}
if (stats.isDirectory()) {
return true
} else if (!required) {
return false
}
throw new Error(`Directory '${inputPath}' does not exist`)
}
/**
* Writes the changelog to the given the file
*/
@@ -157,8 +201,6 @@ export function writeOutput(githubWorkspacePath: string, outputFile: string, cha
}
}
export type Unpacked<T> = T extends (infer U)[] ? U : T
export function createOrSet<T>(map: Map<string, T[]>, key: string, value: T): void {
const entry = map.get(key)
if (!entry) {
@@ -172,6 +214,14 @@ export function haveCommonElements(arr1: string[], arr2: Set<string>): boolean {
return arr1.some(item => arr2.has(item))
}
export function haveCommonElementsArr(arr1: string[], arr2: string[]): boolean {
return haveCommonElements(arr1, new Set(arr2))
}
export function haveEveryElements(arr1: string[], arr2: Set<string>): boolean {
return arr1.every(item => arr2.has(item))
}
export function haveEveryElementsArr(arr1: string[], arr2: string[]): boolean {
return haveEveryElements(arr1, new Set(arr2))
}
+1 -1
View File
@@ -9,5 +9,5 @@
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"lib": [ "ES2021.String" ] /* Enable custom `ES2021.String` extension in typescript for `replaceAll` */
},
"exclude": ["node_modules", "**/*.test.ts"]
"exclude": ["node_modules", "**/*.test.ts", "pr-collector"]
}