Skip to content

Commit e7a73be

Browse files
committed
Merge pull request #1 from nomi9995/feat/changelog
feat: add changelog template
2 parents f5988bd + 1b235ba commit e7a73be

11 files changed

+156
-8
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
Generate release notes from git commit history either **commit range** or **tag range**.
1414

15-
![](media/appstore.png)
15+
| ![](media/appstore.png) | ![](media/changeLog.png) |
16+
| :---------------------: | :----------------------: |
17+
| App Store Template | Changelog Template |
1618

1719
### Installation
1820

@@ -43,6 +45,7 @@ Where
4345
Three sample templates are included as a reference in the `templates` folder
4446

4547
- `appstore` [(sample)](https://github.com/nomi9995/release-notes-cli/blob/master/samples/output-appstore.txt)
48+
- `changelog` [(sample)](https://github.com/nomi9995/release-notes-cli/blob/master/samples/output-changelog.md)
4649
- `markdown` [(sample)](https://github.com/nomi9995/release-notes-cli/blob/master/samples/output-markdown.md)
4750
- `html` [(sample)](http://htmlpreview.github.io/?https://github.com/nomi9995/release-notes-cli/blob/master/samples/output-html.html)
4851
- `html-bootstrap` [(sample)](http://htmlpreview.github.io/?https://github.com/nomi9995/release-notes-cli/blob/master/samples/output-html-bootstrap.html)
@@ -69,6 +72,23 @@ fix(server): send cors headers
6972
feat(blog): add comment section
7073
```
7174

75+
#### Changelog Template
76+
77+
You need to get **GitHub personal** access token from github for setting committer username like this: [@nomi9995](https://github.com/nomi9995)
78+
79+
Since `release-notes-cli` interacts with the GitHub API you may run into rate
80+
limiting issues which can be resolved by supplying a "personal access token":
81+
82+
```
83+
export GITHUB_AUTH="..."
84+
```
85+
86+
You'll need a [personal access token](https://github.com/settings/tokens)
87+
for the GitHub API with the `repo` scope for private repositories or just
88+
`public_repo` scope for public repositories.
89+
90+
**Note:** if you dont set `GITHUB_AUTH` then it will not print committer username for all commits, it will print email instead of github username
91+
7292
#### Custom template
7393

7494
The second parameter of `release-notes-cli` can be any path to a valid ejs template files.

media/appstore.png

15.6 KB
Loading

media/bootstrap.png

38.9 KB
Loading

media/changeLog.png

53.7 KB
Loading

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
},
1212
"keywords": [
1313
"git",
14+
"markdown",
15+
"changelog",
16+
"changelog-generator",
17+
"commitlint",
1418
"log",
1519
"release notes",
1620
"compare",
@@ -39,11 +43,13 @@
3943
"watch": "yarn build -- --watch"
4044
},
4145
"dependencies": {
46+
"@octokit/rest": "^19.0.4",
4247
"chalk": "4.1.2",
4348
"clipboardy": "2.3.0",
4449
"date-fns": "^2.29.2",
4550
"debug": "^4.3.4",
4651
"ejs": "^3.1.8",
52+
"gitconfiglocal": "^2.1.0",
4753
"yargs": "^17.1.0"
4854
},
4955
"devDependencies": {

samples/output-changelog.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
###Others
2+
3+
- release 1.5.2 ([bccb6f28fd](https://github.com/Shobbak/react-native-compressor/commit/bccb6f28fdeecd0915f12fbe990b9b170217ff90) by [@nomi9995](https://github.com/nomi9995))
4+
- release 1.5.1 ([f58a268b0b](https://github.com/Shobbak/react-native-compressor/commit/f58a268b0bfb940a34b1643080b28e6339417169) by [@nomi9995](https://github.com/nomi9995))
5+
- release 1.5.0 ([e696968913](https://github.com/Shobbak/react-native-compressor/commit/e696968913cf0aa1a309345b0e75e38695be1516) by [@nomi9995](https://github.com/nomi9995))
6+
- release 1.4.0 ([30b7bedd78](https://github.com/Shobbak/react-native-compressor/commit/30b7bedd78d22ab6096dfed04895fcc5e94bbf49) by [@nomi9995](https://github.com/nomi9995))
7+
8+
###docs
9+
10+
- update table of content ([b77bdb2105](https://github.com/Shobbak/react-native-compressor/commit/b77bdb21058187c13eef7ad9942b870e815538e7) by [@nomi9995](https://github.com/nomi9995))
11+
- update docs ([8321e362d3](https://github.com/Shobbak/react-native-compressor/commit/8321e362d3adc1cd341130e1bf7b5039109330ac) by [@nomi9995](https://github.com/nomi9995))
12+
13+
###Features
14+
15+
- add getVideoMetaData function for video metadata ([490c8cb884](https://github.com/Shobbak/react-native-compressor/commit/490c8cb88489dc7201a57ba213642a3121c1b203) by [@nomi9995](https://github.com/nomi9995))

src/index.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ let dateFnsFormat = require("date-fns/format");
77
import type { OPTIONS, ICommit } from "./types";
88
import * as clipboard from "clipboardy";
99
import chalk = require("chalk");
10+
const githubUsername = require("./utils/github-username");
1011

1112
export default (cliOptions: OPTIONS, positionalRange: string, positionalTemplate: string = "appstore") => {
1213
return fileSystem.resolveTemplate(positionalTemplate).then((template: string) => {
@@ -33,7 +34,7 @@ export default (cliOptions: OPTIONS, positionalRange: string, positionalTemplate
3334
});
3435
};
3536

36-
const render = (
37+
const render = async (
3738
range: string,
3839
templateContent: string,
3940
data: any,
@@ -42,16 +43,45 @@ const render = (
4243
) => {
4344
debug("Rendering template");
4445
let renderedContent = "";
45-
if (type === "appstore") {
46+
if (type === "appstore" || type === "changelog") {
47+
let gitRemote = "";
48+
let isError = false;
4649
const allCommits: { [key: string]: ICommit } = commitFormateForAppstore(data.commits);
47-
for (let [key, value] of Object.entries(allCommits)) {
48-
renderedContent += ejs.render(templateContent, { title: key, commits: value }) + "\n";
50+
if (type === "changelog") {
51+
gitRemote = await git.gitRemoteOriginUrl();
52+
for (let [key, value] of Object.entries(allCommits)) {
53+
//@ts-ignore
54+
const valueCommits: ICommit[] = value;
55+
const x = valueCommits.map(async commit => {
56+
try {
57+
const username = await githubUsername(commit.committerEmail, { token: process.env.GITHUB_AUTH });
58+
//@ts-ignore
59+
commit.username = username;
60+
} catch (error) {
61+
isError = true;
62+
}
63+
});
64+
await Promise.all(x);
65+
66+
renderedContent += ejs.render(templateContent, { title: key, gitRemote, commits: valueCommits }) + "\n";
67+
}
68+
} else {
69+
for (let [key, value] of Object.entries(allCommits)) {
70+
renderedContent += ejs.render(templateContent, { title: key, commits: value }) + "\n";
71+
}
4972
}
5073
console.log(chalk.magentaBright(renderedContent));
5174
if (copy) {
5275
clipboard.writeSync(renderedContent);
5376
console.log(chalk.green("Copied to clipboard successfully\n"));
5477
}
78+
if (isError) {
79+
console.log(
80+
chalk.red(
81+
'You need to get personal access token from github for setting committer username like this:\n\nexport GITHUB_AUTH="..."'
82+
)
83+
);
84+
}
5585
return;
5686
}
5787

@@ -94,7 +124,7 @@ const commitLintTypesMapper: string[] = [
94124
"Features",
95125
"Fixes",
96126
"perf",
97-
"Fixes",
127+
"Changed",
98128
"revert",
99129
"style",
100130
"test",

src/utils/git.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
//@ts-ignore
22
let debug = require("debug")("release-notes:git");
33
let parser = require("debug")("release-notes:parser");
4+
const gitconfig = require("gitconfiglocal");
5+
const { promisify } = require("util");
6+
const pGitconfig = promisify(gitconfig);
47

58
exports.log = function (options: any) {
69
return new Promise(function (resolve, reject) {
@@ -156,3 +159,10 @@ function parseTag(line: string) {
156159
function normalizeNewlines(message: string) {
157160
return message.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, "");
158161
}
162+
163+
export async function gitRemoteOriginUrl({ cwd = process.cwd(), remoteName = "origin" } = {}) {
164+
const config = await pGitconfig(cwd);
165+
const url: string = (config.remote && config.remote[remoteName] && config.remote[remoteName].url) || "";
166+
167+
return url.replace(/\.git$/, "");
168+
}

src/utils/github-username.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const { Octokit } = require("@octokit/rest");
2+
3+
async function searchCommits(octokit: any, email: string) {
4+
const { data } = await octokit.search.commits({
5+
q: `author-email:${email}`,
6+
sort: "author-date",
7+
// eslint-disable-next-line camelcase
8+
per_page: 1,
9+
});
10+
11+
if (data.total_count === 0) {
12+
throw new Error(`Couldn't find username for \`${email}\``);
13+
}
14+
15+
return data.items[0].author.login;
16+
}
17+
18+
//@ts-ignore
19+
module.exports = async function githubUsername(email: string, { token } = {}) {
20+
if (!(typeof email === "string" && email.includes("@"))) {
21+
throw new Error("Email required");
22+
}
23+
24+
const octokit = new Octokit({
25+
auth: token,
26+
userAgent: "https://github.com/nomi9995/github-username",
27+
});
28+
29+
const { data } = await octokit.search.users({
30+
q: `${email} in:email`,
31+
});
32+
33+
if (data.total_count === 0) {
34+
return searchCommits(octokit, email);
35+
}
36+
37+
return data.items[0].login;
38+
};

templates/changelog.ejs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
###<%= title -%>
2+
3+
<% commits.forEach(function (commit) { -%>
4+
-<%= commit.title -%> ([<%= commit.sha1.slice(0,10) -%>](<%= gitRemote -%>/commit/<%= commit.sha1 -%>) by [@<%= commit.username?commit.username:commit.committerEmail-%>](https://github.com/<%= commit.username?commit.username:commit.committerEmail-%>))
5+
<% }) -%>

yarn.lock

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,13 @@
687687
dependencies:
688688
"@octokit/types" "^6.41.0"
689689

690+
"@octokit/plugin-paginate-rest@^4.0.0":
691+
version "4.1.0"
692+
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-4.1.0.tgz#670ac9ac369448c69a2371bfcd7e2b37d95534f2"
693+
integrity sha512-2O5K5fpajYG5g62wjzHR7/cWYaCA88CextAW3vFP+yoIHD0KEdlVMHfM5/i5LyV+JMmqiYW7w5qfg46FR+McNw==
694+
dependencies:
695+
"@octokit/types" "^7.1.1"
696+
690697
"@octokit/plugin-request-log@^1.0.4":
691698
version "1.0.4"
692699
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
@@ -731,14 +738,24 @@
731738
"@octokit/plugin-request-log" "^1.0.4"
732739
"@octokit/plugin-rest-endpoint-methods" "^6.0.0"
733740

741+
"@octokit/rest@^19.0.4":
742+
version "19.0.4"
743+
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.4.tgz#fd8bed1cefffa486e9ae46a9dc608ce81bcfcbdd"
744+
integrity sha512-LwG668+6lE8zlSYOfwPj4FxWdv/qFXYBpv79TWIQEpBLKA9D/IMcWsF/U9RGpA3YqMVDiTxpgVpEW3zTFfPFTA==
745+
dependencies:
746+
"@octokit/core" "^4.0.0"
747+
"@octokit/plugin-paginate-rest" "^4.0.0"
748+
"@octokit/plugin-request-log" "^1.0.4"
749+
"@octokit/plugin-rest-endpoint-methods" "^6.0.0"
750+
734751
"@octokit/types@^6.41.0":
735752
version "6.41.0"
736753
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04"
737754
integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==
738755
dependencies:
739756
"@octokit/openapi-types" "^12.11.0"
740757

741-
"@octokit/types@^7.0.0":
758+
"@octokit/types@^7.0.0", "@octokit/types@^7.1.1":
742759
version "7.1.1"
743760
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-7.1.1.tgz#a30fd6ca3279d59d532fa75583d65d93b7588e6d"
744761
integrity sha512-Dx6cNTORyVaKY0Yeb9MbHksk79L8GXsihbG6PtWqTpkyA2TY1qBWE26EQXVG3dHwY9Femdd/WEeRUEiD0+H3TQ==
@@ -2399,6 +2416,13 @@ git-url-parse@12.0.0:
23992416
dependencies:
24002417
git-up "^6.0.0"
24012418

2419+
gitconfiglocal@^2.1.0:
2420+
version "2.1.0"
2421+
resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-2.1.0.tgz#07c28685c55cc5338b27b5acbcfe34aeb92e43d1"
2422+
integrity sha512-qoerOEliJn3z+Zyn1HW2F6eoYJqKwS6MgC9cztTLUB/xLWX8gD/6T60pKn4+t/d6tP7JlybI7Z3z+I572CR/Vg==
2423+
dependencies:
2424+
ini "^1.3.2"
2425+
24022426
glob-parent@^5.1.2:
24032427
version "5.1.2"
24042428
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
@@ -2659,7 +2683,7 @@ ini@2.0.0:
26592683
resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
26602684
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
26612685

2662-
ini@^1.3.4, ini@~1.3.0:
2686+
ini@^1.3.2, ini@^1.3.4, ini@~1.3.0:
26632687
version "1.3.8"
26642688
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
26652689
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==

0 commit comments

Comments
 (0)