Skip to content

Commit

Permalink
feat(projects): generate changelog by total tags
Browse files Browse the repository at this point in the history
  • Loading branch information
honghuangdc committed Jun 3, 2023
1 parent 4085eb7 commit 9ee85ff
Show file tree
Hide file tree
Showing 9 changed files with 490 additions and 94 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ module.exports = {
'no-unused-expressions': 'off'
}
}
]
],
rules: {
'no-await-in-loop': 'off'
}
};
427 changes: 362 additions & 65 deletions CHANGELOG.md

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@
"commit": "soy git-commit",
"cleanup": "soy cleanup",
"update-pkg": "soy update-pkg",
"update-version": "bumpp **/package.json !**/node_modules --execute=\"pnpm soy changelog\" --commit=\"chore(projects): release v%s\" --push --tag",
"version": "pnpm soy changelog",
"update-version": "bumpp **/package.json !**/node_modules --tag --commit=\"chore(projects): release v%s\"",
"publish-pkg": "pnpm -r publish --access public",
"typecheck": "tsc --noEmit",
"release": "pnpm update-version && pnpm build && pnpm publish-pkg"
},
"dependencies": {
"bumpp": "^9.1.0",
"bumpp": "9.1.0",
"cac": "6.7.14",
"convert-gitmoji": "^0.1.3",
"dayjs": "^1.11.8",
"convert-gitmoji": "0.1.3",
"dayjs": "1.11.8",
"enquirer": "2.3.6",
"execa": "7.1.1",
"kolorist": "1.8.0",
Expand Down
20 changes: 19 additions & 1 deletion src/changelog/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,29 @@ import { ofetch } from 'ofetch';
import { execCommand, notNullish } from '../shared';
import type { RawGitCommit, GitCommit, GitCommitAuthor, Reference, AuthorInfo } from '../types';

export async function getLastGitTag(delta = 0) {
export async function getTotalGitTags() {
const tagStr = await execCommand('git', ['--no-pager', 'tag', '-l', '--sort=creatordate']);

const tags = tagStr.split('\n');

return tags;
}

export function getFromToTags(tags: string[]) {
const result: { from: string; to: string }[] = [];

tags.forEach((tag, index) => {
if (index < tags.length - 1) {
result.push({ from: tag, to: tags[index + 1] });
}
});

return result;
}

export async function getLastGitTag(delta = 0) {
const tags = await getTotalGitTags();

return tags[tags.length + delta - 1];
}

Expand Down
73 changes: 60 additions & 13 deletions src/changelog/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { readFile } from 'fs/promises';
import {
getTotalGitTags,
getLastGitTag,
getFromToTags,
getCurrentGitBranch,
getGitHubRepo,
isPrerelease,
getFirstGitCommit,
getGitCommits,
getGitCommitsAndResolvedAuthors
} from './git';
import { generateMarkdown, writeMarkdown } from './markdown';
import { isVersionInMarkdown, generateMarkdown, writeMarkdown } from './markdown';
import type { ChangelogOption } from '../types';

function createDefaultOptions() {
Expand All @@ -35,13 +37,15 @@ function createDefaultOptions() {
githubToken: process.env.GITHUB_TOKEN || '',
from: '',
to: '',
tags: [],
prerelease: false,
capitalize: true,
emoji: true,
titles: {
breakingChanges: '🚨 Breaking Changes'
},
output: 'CHANGELOG1.md'
output: 'CHANGELOG.md',
overrideChangelog: false
};

return options;
Expand Down Expand Up @@ -73,32 +77,75 @@ export async function initOptions() {
if (!options.to) {
options.to = await getCurrentGitBranch();
}

options.github = await getGitHubRepo();

options.prerelease = isPrerelease(options.to);

if (options.to === options.from) {
const lastTag = await getLastGitTag(-1);
const firstCommit = await getFirstGitCommit();

options.from = lastTag || firstCommit;
}

options.tags = await getTotalGitTags();

options.github = await getGitHubRepo();

options.prerelease = isPrerelease(options.to);

return options;
}

/**
* 根据git commit message生成CHANGELOG.md
*/
export async function generateChangelog() {
const options = await initOptions();
async function generateChangelogByTag(options: ChangelogOption) {
const gitCommits = await getGitCommits(options.from, options.to, options.scopeMap);
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(
gitCommits,
options.github,
options.githubToken
);
const md = generateMarkdown({ commits, options, showTitle: true, contributors });
writeMarkdown(md, options.output);
return md;
}

async function generateChangelogByTags(options: ChangelogOption) {
const tags = getFromToTags(options.tags);

let md = '';

for (let i = 0; i < tags.length; i += 1) {
const { from, to } = tags[i];
const gitCommits = await getGitCommits(from, to, options.scopeMap);
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(
gitCommits,
options.github,
options.githubToken
);
const opts = { ...options, from, to };
const nextMd = generateMarkdown({ commits, options: opts, showTitle: true, contributors });

md = `${nextMd}\n\n${md}`;
}

return md;
}

/**
* 根据git commit message生成CHANGELOG.md
*/
export async function generateChangelog(total = false) {
const options = await initOptions();

let md = '';

if (total) {
md = await generateChangelogByTags(options);
writeMarkdown(md, options.output, true);
return;
}

const isIn = await isVersionInMarkdown(options.to, options.output);

if (!options.overrideChangelog && isIn) {
return;
}

md = await generateChangelogByTag(options);
writeMarkdown(md, options.output, false);
}
28 changes: 24 additions & 4 deletions src/changelog/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function formatSection(commits: GitCommit[], sectionName: string, options: Chang
return lines;
}

export function getGitUserAvatar(userName: string) {
function getGitUserAvatar(userName: string) {
const avatarUrl = `https://github.com/${userName}.png?size=48`;

return avatarUrl;
Expand Down Expand Up @@ -119,7 +119,7 @@ export function generateMarkdown(params: {
if (showTitle) {
const today = dayjs().format('YYYY-MM-DD');

const title = `## [${options.to}](${url})(${today}})`;
const title = `## [${options.to}](${url})(${today})`;

lines.push(title);
}
Expand Down Expand Up @@ -158,12 +158,32 @@ export function generateMarkdown(params: {
return markdown;
}

export async function writeMarkdown(md: string, mdPath: string) {
export async function isVersionInMarkdown(version: string, mdPath: string) {
let isIn = false;

const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+\]/g;

const md = await readFile(mdPath, 'utf8');

if (md) {
const matches = md.match(VERSION_REG_OF_MARKDOWN);

if (matches?.length) {
const versionInMarkdown = `## [${version}]`;

isIn = matches.includes(versionInMarkdown);
}
}

return isIn;
}

export async function writeMarkdown(md: string, mdPath: string, override = false) {
let changelogMD: string;

const changelogPrefix = '# Changelog';

if (existsSync(mdPath)) {
if (!override && existsSync(mdPath)) {
changelogMD = await readFile(mdPath, 'utf8');
if (!changelogMD.startsWith(changelogPrefix)) {
changelogMD = `${changelogPrefix}\n\n${changelogMD}`;
Expand Down
4 changes: 2 additions & 2 deletions src/command/changelog.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { generateChangelog } from '../changelog';

export async function genChangelog() {
await generateChangelog();
export async function genChangelog(total = false) {
await generateChangelog(total);
}
16 changes: 12 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {

const cli = cac('soybean');

cli.version(version).help();
cli.version(version).option('--total', 'Generate changelog by total tags').help();

type Command =
| 'git-commit'
Expand All @@ -28,9 +28,15 @@ type Command =
| 'lint-staged'
| 'changelog';

type CommandWithAction = Record<Command, { desc: string; action: () => Promise<void> | void }>;
type CommandAction<A extends object> = (args?: A) => Promise<void> | void;

const commands: CommandWithAction = {
type CommandWithAction<A extends object = object> = Record<Command, { desc: string; action: CommandAction<A> }>;

interface CommandArg {
total?: boolean;
}

const commands: CommandWithAction<CommandArg> = {
'git-commit': {
desc: '生成符合 Angular 规范的 git commit',
action: gitCommit
Expand Down Expand Up @@ -65,7 +71,9 @@ const commands: CommandWithAction = {
},
changelog: {
desc: '生成changelog',
action: genChangelog
action: args => {
genChangelog(args?.total);
}
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface ChangelogOption {
githubToken: string;
from: string;
to: string;
tags: string[];
prerelease: boolean;
capitalize: boolean;
/**
Expand All @@ -56,4 +57,5 @@ export interface ChangelogOption {
*/
group?: boolean | 'multiple';
output: string;
overrideChangelog: boolean;
}

0 comments on commit 9ee85ff

Please sign in to comment.