@twyr/announce
Version:
CLI Tool and NPM Library for announcing a release on Github / Gitlab / etc. and on NPM
230 lines (206 loc) • 6.21 kB
JavaScript
;
/**
* Module dependencies, required for ALL Twy'r modules
* @ignore
*/
/**
* Module dependencies, required for this module
* @ignore
*/
/**
* @class GitHubWrapper
* @classdesc The command class that wraps GitHub related functionality for Release and Publish.
*
* @param {string} token - The GitHub Personal Access Token to be used to access the repositories
*
* @description
* The wrapper class that provides an API interface for all GitHub related operations.
*
*/
class GitHubWrapper {
// #region Constructor
constructor(token) {
this.#client = require('octonode')?.client?.(token);
}
// #endregion
// #region Public API
/**
* @async
* @function
* @instance
* @memberof GitHubWrapper
* @name fetchCommitInformation
*
* @param {object} repository - the GitHub repository to query for the release
* @param {string} commitLog - the git commit object for which commit information needs to be fetched
*
* @return {object} The required information about the commit from GitHub.
*
* @summary Given a GitHub repository, returns information about the commit pointed to by the commitLog object.
*
*/
async fetchCommitInformation(repository, commitLog) {
const ghRepo = this.#client?.repo?.(`${repository?.user}/${repository?.project}`);
const commit = await ghRepo?.commitAsync?.(commitLog?.hash);
return commit?.[0];
}
/**
* @async
* @function
* @instance
* @memberof GitHubWrapper
* @name fetchCommitAuthorInformation
*
* @param {object} repository - the GitHub repository to query for the release
* @param {string} commitLog - the git commit object for which the author information needs to be fetched
*
* @return {object} The required information about the commit author from GitHub.
*
* @summary Given a GitHub repository, returns information about the commit author pointed to by the commitLog object.
*
*/
async fetchCommitAuthorInformation(repository, commitLog) {
const ghRepo = this.#client?.repo?.(`${repository?.user}/${repository?.project}`);
let commit = await ghRepo?.commitAsync?.(commitLog?.hash);
commit = commit?.[0];
return {
'name': commit?.commit?.author?.name,
'email': commit?.commit?.author?.email,
'profile': commit?.author?.html_url,
'avatar': commit?.author?.avatar_url
};
}
/**
* @async
* @function
* @instance
* @memberof GitHubWrapper
* @name fetchReleaseInformation
*
* @param {object} repository - the GitHub repository to query for the release
* @param {string} releaseName - the name of the release
*
* @return {object} The required information about the release from GitHub.
*
* @summary Given a GitHub repository, returns information about the release - either the latest, or the one matching the specified release name.
*
*/
async fetchReleaseInformation(repository, releaseName) {
const ghRepo = this.#client?.repo?.(`${repository?.user}/${repository?.project}`);
let allReleases = await ghRepo?.releasesAsync?.();
allReleases = allReleases?.[0];
if(releaseName?.trim?.()?.length) {
const releaseInfo = allReleases?.filter?.((release) => { return (release?.name === releaseName); })?.shift?.();
return {
'name': releaseInfo?.name,
'prerelease': releaseInfo?.prerelease,
'published': releaseInfo?.published_at,
'tarball_url': releaseInfo?.tarball_url,
'tag': releaseInfo?.tag_name
};
}
const releaseInfo = allReleases?.map?.((release) => {
return {
'name': release?.name,
'prerelease': release?.prerelease,
'published': release?.published_at,
'tarball_url': release?.tarball_url,
'tag': release?.tag_name
};
})
?.sort?.((left, right) => {
return (new Date(right?.published))?.valueOf() - (new Date(left?.published))?.valueOf();
})
?.shift?.();
return releaseInfo;
}
/**
* @async
* @function
* @instance
* @memberof GitHubWrapper
* @name createRelease
*
* @param {object} releaseData - The data required for creating a release on GitHub
*
* @return {null} Nothing.
*
* @summary Given the required data, creates a release on Github.
*
*/
async createRelease(releaseData) {
return new Promise((resolve, reject) => {
const repository = releaseData?.['REPO'];
this.#client?.post?.(`https://api.${repository.domain}/repos/${repository.user}/${repository.project}/releases`, {
'accept': 'application/vnd.github.v3+json',
'tag_name': releaseData?.['RELEASE_TAG'],
'name': releaseData?.['RELEASE_NAME'],
'body': releaseData?.['RELEASE_NOTES'],
'prerelease': !!(releaseData?.['RELEASE_TYPE'] === 'pre-release')
}, (err, status) => {
if(err) {
reject?.(err);
return;
}
if(status >= 300) {
reject?.(status);
return;
}
resolve?.(status);
});
});
}
/**
* @function
* @instance
* @memberof GitHubWrapper
* @name getCommitLink
*
* @param {object} repository - the GitHub repository to query for the release
* @param {object} commitLog - the commit information
*
* @return {object} The URL to access the commit on GitHub.
*
* @summary Given a GitHub repository, and a commit, returns the URL to access the commit directly.
*
*/
getCommitLink(repository, commitLog) {
return `https://${repository?.domain}/${repository?.user}/${repository?.project}/commit/${commitLog?.hash})`;
}
// #endregion
// #region Private Methods
/**
* @async
* @function
* @instance
* @memberof GitHubWrapper
* @name _fetchData
*
* @param {string} url - the url giving the information we seek
*
* @return {object} Hopefully, the required information from GitHub.
*
* @summary Given a GitHub REST API endpoint, call it and give back the information returned.
*
*/
async _fetchData(url) {
return new Promise((resolve, reject) => {
this.#client?.get?.(url, {}, (err, status, body) => {
if(err) {
reject?.(err);
return;
}
if(status >= 300) {
reject?.(status);
return;
}
resolve?.(body);
});
});
}
// #endregion
// #region Private Fields
#client = null;
// #endregion
}
exports.GitHostWrapper = GitHubWrapper;