Skip to content

Commit

Permalink
feat: add iterateCommits utility function
Browse files Browse the repository at this point in the history
Signed-off-by: Ardalan Amini <ardalanamini22@gmail.com>
  • Loading branch information
ardalanamini committed Feb 13, 2025
1 parent ac84952 commit 185fe61
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 68 deletions.
2 changes: 1 addition & 1 deletion action/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion action/index.js.map

Large diffs are not rendered by default.

119 changes: 53 additions & 66 deletions src/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
mentionAuthors,
useGithubAutolink,
} from "./inputs/index.js";
import { octokit, parseCommitMessage, repository, sha } from "./utils/index.js";
import { iterateCommits, parseCommitMessage, repository } from "./utils/index.js";

interface TypeGroupI {
scopes: ScopeGroupI[];
Expand Down Expand Up @@ -66,7 +66,6 @@ function sortBy<T>(array: T[], property: keyof T): T[] {
}

export async function generateChangelog(lastSha?: string): Promise<string> {
const { paginate, rest } = octokit();
const { owner, repo, url } = repository();
const defaultType = defaultCommitType();
const typeMap = commitTypes();
Expand All @@ -75,100 +74,88 @@ export async function generateChangelog(lastSha?: string): Promise<string> {
const shouldMentionAuthors = mentionAuthors();
const shouldUseGithubAutolink = useGithubAutolink();

const iterator = paginate.iterator(
rest.repos.listCommits,
{
per_page: 100,
sha : sha(),
owner,
repo,
},
);

const typeGroups: TypeGroupI[] = [];

paginator: for await (const { data } of iterator) {
for (const commit of data) {
if (commit.sha === lastSha) break paginator;
for await (const commit of iterateCommits(owner, repo)) {
if (commit.sha === lastSha) break;

const message = commit.commit.message.split("\n")[0];
const message = commit.commit.message.split("\n")[0];

debug(`commit message -> ${ message }`);
debug(`commit message -> ${ message }`);

let { type, scope, description, pr, flag, breaking } = parseCommitMessage(message);
let { type, scope, description, pr, flag, breaking } = parseCommitMessage(message);

if (!description) continue;
if (!description) continue;

description = trim(description);
description = trim(description);

flag = trim(flag);
flag = trim(flag);

if (flag === "ignore") continue;
if (flag === "ignore") continue;

// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
type = typeMap[trim(type ?? "")] ?? defaultType;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
type = typeMap[trim(type ?? "")] ?? defaultType;

let typeGroup = typeGroups.find(record => record.type === type);
let typeGroup = typeGroups.find(record => record.type === type);

if (typeGroup == null) {
typeGroup = {
type,
scopes: [],
};
if (typeGroup == null) {
typeGroup = {
type,
scopes: [],
};

typeGroups.push(typeGroup);
}
typeGroups.push(typeGroup);
}

scope = trim(scope ?? "");
scope = trim(scope ?? "");

let scopeGroup = typeGroup.scopes.find(record => record.scope === scope);
let scopeGroup = typeGroup.scopes.find(record => record.scope === scope);

if (scopeGroup == null) {
scopeGroup = {
scope,
logs: [],
};
if (scopeGroup == null) {
scopeGroup = {
scope,
logs: [],
};

typeGroup.scopes.push(scopeGroup);
}
typeGroup.scopes.push(scopeGroup);
}

let log = scopeGroup.logs.find(record => record.description === description);
let log = scopeGroup.logs.find(record => record.description === description);

if (log == null) {
log = {
breaking,
description,
references: [],
};
if (log == null) {
log = {
breaking,
description,
references: [],
};

scopeGroup.logs.push(log);
}
scopeGroup.logs.push(log);
}

const reference: string[] = [];
const reference: string[] = [];

if (pr && shouldIncludePRLinks) reference.push(shouldUseGithubAutolink ? `#${ pr }` : `[#${ pr }](${ url }/issues/${ pr })`);
else if (shouldIncludeCommitLinks) reference.push(shouldUseGithubAutolink ? commit.sha : `\`[${ commit.sha }](${ url }/commit/${ commit.sha })\``);
if (pr && shouldIncludePRLinks) reference.push(shouldUseGithubAutolink ? `#${ pr }` : `[#${ pr }](${ url }/issues/${ pr })`);
else if (shouldIncludeCommitLinks) reference.push(shouldUseGithubAutolink ? commit.sha : `\`[${ commit.sha }](${ url }/commit/${ commit.sha })\``);

const username = commit.author?.login;
const username = commit.author?.login;

if (username && shouldMentionAuthors) {
const mention = `by @${ username }`;
if (username && shouldMentionAuthors) {
const mention = `by @${ username }`;

reference.push(mention);
reference.push(mention);

const lastReference = log.references[log.references.length - 1];
const lastReference = log.references[log.references.length - 1];

// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (lastReference?.endsWith(mention)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
log.references.push(log.references.pop()!.replace(mention, `& ${ reference.join(" ") }`));
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (lastReference?.endsWith(mention)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
log.references.push(log.references.pop()!.replace(mention, `& ${ reference.join(" ") }`));

continue;
}
continue;
}

if (reference.length > 0) log.references.push(reference.join(" "));
}

if (reference.length > 0) log.references.push(reference.join(" "));
}

const types = unique(Object.values(typeMap).concat(defaultType));
Expand Down
45 changes: 45 additions & 0 deletions src/utils/github.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* MIT License
*
* Copyright (c) 2025 Ardalan Amini
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

import { octokit } from "./octokit.js";
import { sha } from "./sha.js";

// eslint-disable-next-line max-len
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types,@typescript-eslint/explicit-function-return-type
export async function *iterateCommits(owner: string, repo: string) {
const { paginate, rest } = octokit();

const iterator = paginate.iterator(
rest.repos.listCommits,
{
per_page: 100,
sha : sha(),
owner,
repo,
},
);

for await (const { data } of iterator) for (const commit of data) yield commit;
}
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
export * from "./boolean-input.js";
export * from "./cache.js";
export * from "./git.js";
export * from "./github.js";
export * from "./input.js";
export * from "./octokit.js";
export * from "./output.js";
Expand Down

0 comments on commit 185fe61

Please sign in to comment.