2023-08-11 17:23:56 +02:00
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import yargs from 'yargs' ;
import githubToken from './github_token.json' ;
type GithubCommit = {
sha : string ;
html_url : string ;
commit : {
message : string ;
2023-12-13 23:48:35 +01:00
author : {
name : string ;
};
2023-08-11 17:23:56 +02:00
};
author : { login : string } | null ;
};
type Commit = {
repoUrl : string ;
revision : number ;
url : string ;
githubUser : string | undefined ;
author : string ;
title : string ;
};
const { sha } = yargs
. options ({
sha : {
description : 'The hash of the last commit of the previous release' ,
type : 'string' ,
demandOption : true ,
},
})
. parseSync ();
2023-12-13 23:48:35 +01:00
const getHeaderWithAuth = () => ({
headers : {
// token is optional, might be needed in case of getting rate-limited - to provide a token create a "github_token.json" (see "github_token.template.json") and add your token in there
Authorization : githubToken.token ? `token ${ githubToken . token } ` : '' ,
},
});
const fetchTotalCommitCount = async ( owner : string , repo : string , branch : string = 'master' ) => {
const response = await fetch (
`https://api.github.com/repos/ ${ owner } / ${ repo } /commits?sha= ${ branch } &per_page=1&page=1` ,
getHeaderWithAuth (),
);
const linkHeader = response . headers . get ( 'Link' );
const pageCountMatch = linkHeader ? . match ( /page=(\d+)>; rel="last"/ );
if ( ! pageCountMatch ) {
throw new Error ( 'Page count not found in Link header' );
}
return parseInt ( pageCountMatch [ 1 ], 10 );
};
2023-08-11 17:23:56 +02:00
/**
* Fetches and returns all commits after the provided commit hash
*/
const fetchCommits = async (
owner : string ,
repo : string ,
loadUntilSha : string ,
page : number = 1 ,
) : Promise < GithubCommit [] > => {
const commitList = ( await (
2023-12-13 23:48:35 +01:00
await fetch ( `https://api.github.com/repos/ ${ owner } / ${ repo } /commits?page= ${ page } ` , getHeaderWithAuth ())
2023-08-11 17:23:56 +02:00
). json ()) as GithubCommit [];
const indexOfOldestCommitToLoad = commitList . findIndex (( commit ) => commit . sha === loadUntilSha );
const loadedAllCommits = indexOfOldestCommitToLoad !== - 1 ;
if ( loadedAllCommits ) {
return commitList . slice ( 0 , indexOfOldestCommitToLoad );
}
return [... commitList , ...( await fetchCommits ( owner , repo , loadUntilSha , page + 1 ))];
};
const createChangelogCommitLine = ( commit : Commit ) : string => {
const author = commit . githubUser ?? commit . author ;
const credit = `by @ ${ author } ` ;
const revision = `([r ${ commit . revision } ]( ${ commit . url } ))` ;
const includesPrId = commit . title . match ( /.*\(#[0-9]+\)$/g );
if ( ! includesPrId ) {
return ` ${ revision } ${ commit . title } ( ${ credit } )` ;
}
const splitTitle = commit . title . split ( '#' );
const rawPrId = splitTitle [ splitTitle . length - 1 ]; // = <prId>) e.g. 420)
const prId = rawPrId . substring ( 0 , rawPrId . length - 1 );
const prUrl = ` ${ commit . repoUrl } /pull/ ${ prId } ` ;
const authorCredit = `[# ${ prId } ]( ${ prUrl } ) ${ credit } ` ;
return ` ${ revision } ${ splitTitle . slice ( 0 , splitTitle . length - 1 ). join ( '#' ) }${ authorCredit } )` ;
};
const createChangelog = async ( prevReleaseLastCommitSha : string ) => {
const owner = 'Suwayomi' ;
const repo = 'Tachidesk-WebUI' ;
2023-12-13 23:48:35 +01:00
const numberOfCommits = await fetchTotalCommitCount ( owner , repo );
2023-08-11 17:23:56 +02:00
const githubCommits = await fetchCommits ( owner , repo , prevReleaseLastCommitSha );
const commits : Commit [] = githubCommits . map (( githubCommit , index ) => ({
repoUrl : `https://github.com/ ${ owner } / ${ repo } ` ,
revision : numberOfCommits - index ,
url : githubCommit.html_url ,
githubUser : githubCommit.author?.login ,
2023-12-13 23:48:35 +01:00
author : githubCommit.commit.author.name ,
2023-08-11 17:23:56 +02:00
title : githubCommit.commit.message.split ( '\n' )[ 0 ],
}));
const commitChangelogLines = commits . map ( createChangelogCommitLine );
commitChangelogLines . forEach (( commit ) => console . log ( '-' , commit ));
};
createChangelog ( sha ). catch (( error ) => {
console . error ( 'Failed due to' , error );
process . exit ( 1 );
});