feat:add gitea platform resolver

This commit is contained in:
Ankio
2023-10-31 22:46:26 +08:00
parent 476af24df0
commit 549ee31eaa
6 changed files with 279 additions and 35 deletions
+10 -14
View File
@@ -3,31 +3,28 @@ import * as github from '@actions/github'
import {mergeConfiguration, parseConfiguration, resolveConfiguration, retrieveRepositoryPath, writeOutput} from './utils'
import {ReleaseNotesBuilder} from './releaseNotesBuilder'
import {Configuration} from './configuration'
import {GithubRepository} from "./repositories/GithubRepository";
import {GiteaRepository} from "./repositories/GiteaRepository";
import {GithubRepository} from './repositories/GithubRepository'
import {GiteaRepository} from './repositories/GiteaRepository'
async function run(): Promise<void> {
const supportedPlatform = {
github: GithubRepository,
gitea: GiteaRepository,
};
gitea: GiteaRepository
}
function isSupportedPlatform(type: string): type is keyof typeof supportedPlatform {
return type in supportedPlatform;
return type in supportedPlatform
}
core.setOutput('failed', false) // mark the action not failed by default
core.startGroup(`📘 Reading input values`)
try {
// read in path specification, resolve github workspace, and repo path
const platform = core.getInput('platform') || "github"
if(!isSupportedPlatform(platform)){
const platform = core.getInput('platform') || 'github'
if (!isSupportedPlatform(platform)) {
core.setFailed(`The ${platform} platform is not supported. `)
return
}
const inputPath = core.getInput('path')
const repositoryPath = retrieveRepositoryPath(inputPath)
@@ -58,7 +55,7 @@ async function run(): Promise<void> {
// read in repository inputs
const baseUrl = core.getInput('baseUrl')
const token = core.getInput('token') || process.env.GITHUB_TOKEN || ""
const token = core.getInput('token') || process.env.GITHUB_TOKEN || ''
const owner = core.getInput('owner') || github.context.repo.owner
const repo = core.getInput('repo') || github.context.repo.repo
// read in from, to tag inputs
@@ -77,11 +74,10 @@ async function run(): Promise<void> {
const exportOnly = core.getInput('exportOnly') === 'true'
const cache = core.getInput('cache')
const repositoryUtils = new supportedPlatform[platform](token,baseUrl);
const repositoryUtils = new supportedPlatform[platform](token, baseUrl, repositoryPath)
const result = await new ReleaseNotesBuilder(
baseUrl,
repositoryUtils,
repositoryUtils,
repositoryPath,
owner,
repo,
+1 -1
View File
@@ -39,7 +39,7 @@ class GitCommandManager {
return result
}
private async execGit(args: string[], allowAllExitCodes = false, silent = false): Promise<GitOutput> {
async execGit(args: string[], allowAllExitCodes = false, silent = false): Promise<GitOutput> {
directoryExistsSync(this.workingDirectory, true)
const result = new GitOutput()
+1 -1
View File
@@ -8,7 +8,7 @@ import {TagInfo} from './pr-collector/tags'
import {DiffInfo} from './pr-collector/commits'
import {PullRequestInfo} from './pr-collector/pullRequests'
import * as fs from 'fs'
import {BaseRepository} from "./repositories/BaseRepository";
import {BaseRepository} from './repositories/BaseRepository'
export interface ReleaseNotesOptions {
owner: string // the owner of the repository
+212 -19
View File
@@ -1,43 +1,236 @@
import {BaseRepository} from "./BaseRepository";
import {TagInfo} from "../pr-collector/tags";
import {PullRequestInfo} from "../pr-collector/pullRequests";
import {
CommentInfo,
PullRequestInfo,
} from "../pr-collector/pullRequests";
import {DiffInfo} from "../pr-collector/commits";
import {Api, PullRequest, PullReview} from "gitea-js";
import moment from "moment";
import * as core from "@actions/core";
import {createCommandManager} from "../pr-collector/gitHelper";
export class GiteaRepository extends BaseRepository {
private api: Api<unknown>
export class GiteaRepository extends BaseRepository{
get defaultUrl(): string {
return "https://gitea.com/api/v1";
return "https://gitea.com";
}
constructor(token: string, url?: string) {
super(token, url);
constructor(token: string, url: string | undefined, repositoryPath: string) {
super(token, url, repositoryPath);
this.url = url || this.defaultUrl
const fetch = require('cross-fetch');
const {giteaApi} = require('gitea-js');
this.api = new giteaApi('https://gitea.com/', {
token: token, // generate one at https://gitea.example.com/user/settings/applications
customFetch: fetch,
});
}
fillTagInformation(repositoryPath: string, owner: string, repo: string, tagInfo: TagInfo): Promise<TagInfo> {
return Promise.resolve(undefined);
async fillTagInformation(repositoryPath: string, owner: string, repo: string, tagInfo: TagInfo): Promise<TagInfo> {
const response = await this.api.repos.repoGetTag(owner, repo, tagInfo.name)
if (response.error === null) {
if (response.data.commit) {
tagInfo.date = moment(response.data.commit.created)
core.info(`️ Retrieved information about the release associated with ${tagInfo.name} from the Gitea API`)
return tagInfo
}
}
return await this.getTagByCreateTime(repositoryPath, tagInfo)
}
getBetweenDates(owner: string, repo: string, fromDate: moment.Moment, toDate: moment.Moment, maxPullRequests: number): Promise<PullRequestInfo[]> {
return Promise.resolve([]);
async getBetweenDates(owner: string, repo: string, fromDate: moment.Moment, toDate: moment.Moment, maxPullRequests: number): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = []
const response = await this.api.repos.repoListPullRequests(owner, repo, {
sort: 'recentupdate',
state: 'closed',
limit: Math.min(100, maxPullRequests),
})
if (response.error === null) {
for (const pr of response.data.filter(p => !!p.merged_at)) {
mergedPRs.push(this.mapPullRequest(pr, 'merged'))
}
}
return mergedPRs;
}
getDiffRemote(owner: string, repo: string, base: string, head: string): Promise<DiffInfo> {
return Promise.resolve(undefined);
private mapPullRequest(pr: PullRequest, status: 'open' | 'merged' = 'open'): PullRequestInfo {
return {
number: pr.number || 0,
title: pr.title || "",
htmlURL: pr.html_url || "",
baseBranch: pr.base?.repo?.default_branch || "",
branch: pr.merge_base || "",
mergedAt: pr.merged_at ? moment(pr.merged_at) : undefined,
mergeCommitSha: pr.merge_commit_sha || "",
author: pr.user?.login || "",
repoName: pr.base?.repo?.full_name || "",
labels: pr.labels?.map((label) => label.name) as string[],
milestone: pr.milestone?.title || "",
body: pr.body || "",
assignees: pr.assignees?.map((user) => user.full_name) as string[],
requestedReviewers: pr.requested_reviewers?.map((user) => user.full_name) as string[],
approvedReviewers: [],
createdAt: moment(pr.created_at),
status: status,
reviews: undefined
}
}
getForCommitHash(owner: string, repo: string, commit_sha: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
return Promise.resolve([]);
async getDiffRemote(owner: string, repo: string, base: string, head: string): Promise<DiffInfo> {
let changedFilesCount = 0;
let additionCount = 0;
let deletionCount = 0;
let changeCount = 0;
let commitCount = 0;
const gitHelper = await createCommandManager(this.repositoryPath)
// Get the diff stats between the two branches/commits
const diffStat = await gitHelper.execGit(['diff', '--stat', `${base}...${head}`]);
const diffStatLines = diffStat.stdout.split('\n');
for (const line of diffStatLines) {
// Extract the addition and deletion counts from each line of the git diff output
const match = line.match(/(\d+) insertions?\(\+\), (\d+) deletions?\(\-\)/);
if (match) {
additionCount += parseInt(match[1], 10);
deletionCount += parseInt(match[2], 10);
}
}
// Get the list of changed files
const diffNameOnly = await gitHelper.execGit(['diff', '--name-only', `${base}...${head}`]);
const changedFiles = diffNameOnly.stdout.split('\n');
changedFilesCount = changedFiles.length - 1; // Subtract one for the empty line at the end
// Get the commit count between the two branches/commits
const logCount = await gitHelper.execGit(['rev-list', '--count', `${base}...${head}`]);
commitCount = parseInt(logCount.stdout.trim(), 10);
// Now let's get the commit logs between the two branches/commits
const log = await gitHelper.execGit(['log', '--pretty=format:%H||||%an||||%ae||||%ad||||%cn||||%ce||||%cd||||%s', `${base}...${head}`]);
const commitLogs = log.stdout.trim().split('\n');
// Process commit logs
const commitInfo = commitLogs.map(log => {
const [sha, authorName, authorEmail, authorDate, committerName, committerEmail, committerDate, subject] = log.split('||||');
return {
sha,
summary: subject,
message: '', // This would require another git command to get the full message if needed
author: authorName,
authorDate: moment(authorDate, "ddd MMM DD HH:mm:ss YYYY ZZ", false),
committer: committerName,
commitDate: moment(committerDate, "ddd MMM DD HH:mm:ss YYYY ZZ", false),
prNumber: undefined // This is not available directly from git, would require additional logic to associate commits with PRs
};
});
return {
changedFiles: changedFilesCount,
additions: additionCount,
deletions: deletionCount,
changes: changeCount,
commits: commitCount,
commitInfo: commitInfo
};
}
getOpen(owner: string, repo: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
return Promise.resolve([]);
async getForCommitHash(owner: string, repo: string, commit_sha: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = []
const response = await this.api.repos.repoListPullRequests(owner, repo, {
sort: 'recentupdate',
state: 'closed',
limit: 1000,
})
if (response.error === null) {
for (const pr of response.data) {
if (pr.merge_commit_sha === commit_sha) {
mergedPRs.push(this.mapPullRequest(pr, pr.merged_at ? 'merged' : 'open'))
}
}
}
return mergedPRs
}
getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
return Promise.resolve(undefined);
async getOpen(owner: string, repo: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const openPrs: PullRequestInfo[] = []
const response = await this.api.repos.repoListPullRequests(owner, repo, {
sort: 'recentupdate',
state: 'open',
limit: Math.min(100, maxPullRequests),
})
if (response.error === null) {
for (const pr of response.data) {
openPrs.push(this.mapPullRequest(pr, 'open'))
}
}
return openPrs
}
getTags(owner: string, repo: string, maxTagsToFetch: number): Promise<TagInfo[]> {
return Promise.resolve([]);
async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
const prReviews: CommentInfo[] = []
const response = await this.api.repos.repoListPullReviews(owner, repo, pr.number, {})
if (response.error === null) {
for (const comment of response.data) {
prReviews.push(this.mapComment(comment))
}
}
pr.reviews = prReviews
}
private mapComment = (comment: PullReview): CommentInfo => ({
id: comment.id || 0,
htmlURL: comment.html_url || "",
submittedAt: comment.submitted_at ? moment(comment.submitted_at) : undefined,
author: comment.user?.login || '',
body: comment.body || "",
state: comment.state
})
async getTags(owner: string, repo: string, maxTagsToFetch: number): Promise<TagInfo[]> {
const response = await this.api.repos.repoListTags(owner, repo, {
limit: maxTagsToFetch
})
const tagsInfo: TagInfo[] = []
if (response.error === null) {
for (const tag of response.data) {
tagsInfo.push({
name: tag.name || "",
commit: tag.commit?.sha
})
}
}
core.info(`️ Found ${tagsInfo.length} (fetching max: ${maxTagsToFetch}) tags from the GitHub API for ${owner}/${repo}`)
return tagsInfo
}
}