feat:extra pulls variable

This commit is contained in:
Ankio
2023-11-01 11:04:21 +08:00
parent 5ac643aaac
commit 08cf89bc11
+93 -110
View File
@@ -1,146 +1,140 @@
import {BaseRepository} from "./BaseRepository"; import {BaseRepository} from './BaseRepository'
import {TagInfo} from "../pr-collector/tags"; import {TagInfo} from '../pr-collector/tags'
import { import {CommentInfo, PullRequestInfo} from '../pr-collector/pullRequests'
CommentInfo, import {DiffInfo} from '../pr-collector/commits'
PullRequestInfo, import {Api, PullRequest, PullReview} from 'gitea-js'
} from "../pr-collector/pullRequests"; import moment from 'moment'
import {DiffInfo} from "../pr-collector/commits"; import * as core from '@actions/core'
import {Api, PullRequest, PullReview} from "gitea-js"; import {createCommandManager} from '../pr-collector/gitHelper'
import moment, {min} from "moment"; interface Pulls {
import * as core from "@actions/core"; closed: PullRequest[]
import {createCommandManager} from "../pr-collector/gitHelper"; open: PullRequest[]
import {match} from "assert"; }
import {log} from "util";
export class GiteaRepository extends BaseRepository { export class GiteaRepository extends BaseRepository {
private api: Api<unknown> private api: Api<unknown>
get defaultUrl(): string { get defaultUrl(): string {
return "https://gitea.com"; return 'https://gitea.com'
} }
constructor(token: string, url: string | undefined, repositoryPath: string) { constructor(token: string, url: string | undefined, repositoryPath: string) {
super(token, url, repositoryPath); super(token, url, repositoryPath)
this.url = url || this.defaultUrl this.url = url || this.defaultUrl
const fetch = require('cross-fetch'); const fetch = require('cross-fetch')
const {giteaApi} = require('gitea-js'); const {giteaApi} = require('gitea-js')
// @ts-ignore
this.api = new giteaApi('https://gitea.com/', { this.api = new giteaApi('https://gitea.com/', {
token: token, // generate one at https://gitea.example.com/user/settings/applications token, // generate one at https://gitea.example.com/user/settings/applications
customFetch: fetch, customFetch: fetch
}); })
} }
async fillTagInformation(repositoryPath: string, owner: string, repo: string, tagInfo: TagInfo): Promise<TagInfo> { async fillTagInformation(repositoryPath: string, owner: string, repo: string, tagInfo: TagInfo): Promise<TagInfo> {
const response = await this.api.repos.repoGetTag(owner, repo, tagInfo.name) const response = await this.api.repos.repoGetTag(owner, repo, tagInfo.name)
if (response.error === null) { if (response.error === null) {
if (response.data.commit) { if (response.data.commit) {
tagInfo.date = moment(response.data.commit.created) tagInfo.date = moment(response.data.commit.created)
core.info(`️ Retrieved information about the release associated with ${tagInfo.name} from the Gitea API`) core.info(`️ Retrieved information about the release associated with ${tagInfo.name} from the Gitea API`)
return tagInfo return tagInfo
} }
} }
return await this.getTagByCreateTime(repositoryPath, tagInfo) return await this.getTagByCreateTime(repositoryPath, tagInfo)
} }
async getBetweenDates(owner: string, repo: string, fromDate: moment.Moment, toDate: moment.Moment, maxPullRequests: number): Promise<PullRequestInfo[]> { async getBetweenDates(
owner: string,
repo: string,
fromDate: moment.Moment,
toDate: moment.Moment,
maxPullRequests: number
): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = [] const mergedPRs: PullRequestInfo[] = []
await this.getAllPullRequest(owner, repo, 'closed', maxPullRequests)
const response = await this.api.repos.repoListPullRequests(owner, repo, { for (const pr of GiteaRepository.pulls.closed.filter(p => !!p.merged_at)) {
sort: 'recentupdate', if (moment(pr.closed_at) > fromDate && moment(pr.closed_at) < toDate) {
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')) mergedPRs.push(this.mapPullRequest(pr, 'merged'))
} }
} }
return mergedPRs
return mergedPRs;
} }
private mapPullRequest(pr: PullRequest, status: 'open' | 'merged' = 'open'): PullRequestInfo { private mapPullRequest(pr: PullRequest, status: 'open' | 'merged' = 'open'): PullRequestInfo {
return { return {
number: pr.number || 0, number: pr.number || 0,
title: pr.title || "", title: pr.title || '',
htmlURL: pr.html_url || "", htmlURL: pr.html_url || '',
baseBranch: pr.base?.repo?.default_branch || "", baseBranch: pr.base?.repo?.default_branch || '',
branch: pr.merge_base || "", branch: pr.merge_base || '',
mergedAt: pr.merged_at ? moment(pr.merged_at) : undefined, mergedAt: pr.merged_at ? moment(pr.merged_at) : undefined,
mergeCommitSha: pr.merge_commit_sha || "", mergeCommitSha: pr.merge_commit_sha || '',
author: pr.user?.login || "", author: pr.user?.login || '',
repoName: pr.base?.repo?.full_name || "", repoName: pr.base?.repo?.full_name || '',
labels: pr.labels?.map((label) => label.name) as string[], labels: pr.labels?.map(label => label.name) as string[],
milestone: pr.milestone?.title || "", milestone: pr.milestone?.title || '',
body: pr.body || "", body: pr.body || '',
assignees: pr.assignees?.map((user) => user.full_name) as string[], assignees: pr.assignees?.map(user => user.full_name) as string[],
requestedReviewers: pr.requested_reviewers?.map((user) => user.full_name) as string[], requestedReviewers: pr.requested_reviewers?.map(user => user.full_name) as string[],
approvedReviewers: [], approvedReviewers: [],
createdAt: moment(pr.created_at), createdAt: moment(pr.created_at),
status: status, status,
reviews: undefined reviews: undefined
} }
} }
async getDiffRemote(owner: string, repo: string, base: string, head: string): Promise<DiffInfo> { async getDiffRemote(owner: string, repo: string, base: string, head: string): Promise<DiffInfo> {
let changedFilesCount = 0; let changedFilesCount = 0
let additionCount = 0; let additionCount = 0
let deletionCount = 0; let deletionCount = 0
let changeCount = 0; const changeCount = 0
let commitCount = 0; let commitCount = 0
const gitHelper = await createCommandManager(this.repositoryPath) const gitHelper = await createCommandManager(this.repositoryPath)
// Get the diff stats between the two branches/commits // Get the diff stats between the two branches/commits
const diffStat = await gitHelper.execGit(['diff', '--stat', `${base}...${head}`]); const diffStat = await gitHelper.execGit(['diff', '--stat', `${base}...${head}`])
const diffStatLines = diffStat.stdout.split('\n'); const diffStatLines = diffStat.stdout.split('\n')
for (const line of diffStatLines) { for (const line of diffStatLines) {
// Extract the addition and deletion counts from each line of the git diff output // Extract the addition and deletion counts from each line of the git diff output
const match = line.match(/(\d+) insertions?\(\+\), (\d+) deletions?\(\-\)/); const match = line.match(/(\d+) insertions?\(\+\), (\d+) deletions?\(\-\)/)
if (match) { if (match) {
additionCount += parseInt(match[1], 10); additionCount += parseInt(match[1], 10)
deletionCount += parseInt(match[2], 10); deletionCount += parseInt(match[2], 10)
} }
} }
// Get the list of changed files // Get the list of changed files
const diffNameOnly = await gitHelper.execGit(['diff', '--name-only', `${base}...${head}`]); const diffNameOnly = await gitHelper.execGit(['diff', '--name-only', `${base}...${head}`])
const changedFiles = diffNameOnly.stdout.split('\n'); const changedFiles = diffNameOnly.stdout.split('\n')
changedFilesCount = changedFiles.length - 1; // Subtract one for the empty line at the end changedFilesCount = changedFiles.length - 1 // Subtract one for the empty line at the end
// Get the commit count between the two branches/commits // Get the commit count between the two branches/commits
const logCount = await gitHelper.execGit(['rev-list', '--count', `${base}...${head}`]); const logCount = await gitHelper.execGit(['rev-list', '--count', `${base}...${head}`])
commitCount = parseInt(logCount.stdout.trim(), 10); commitCount = parseInt(logCount.stdout.trim(), 10)
// Now let's get the commit logs between the two branches/commits // 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 log = await gitHelper.execGit(['log', '--pretty=format:%H||||%an||||%ae||||%ad||||%cn||||%ce||||%cd||||%s', `${base}...${head}`])
const commitLogs = log.stdout.trim().split('\n'); const commitLogs = log.stdout.trim().split('\n')
// Process commit logs // Process commit logs
const commitInfo = commitLogs.map(log => { const commitInfo = commitLogs.map(log => {
const [sha, authorName, authorEmail, authorDate, committerName, committerEmail, committerDate, subject] = log.split('||||'); const [sha, authorName, authorEmail, authorDate, committerName, committerEmail, committerDate, subject] = log.split('||||')
return { return {
sha, sha,
summary: subject, summary: subject,
message: '', // This would require another git command to get the full message if needed message: '', // This would require another git command to get the full message if needed
author: authorName, author: authorName,
authorDate: moment(authorDate, "ddd MMM DD HH:mm:ss YYYY ZZ", false), authorDate: moment(authorDate, 'ddd MMM DD HH:mm:ss YYYY ZZ', false),
committer: committerName, committer: committerName,
commitDate: moment(committerDate, "ddd MMM DD HH:mm:ss YYYY ZZ", false), 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 prNumber: undefined // This is not available directly from git, would require additional logic to associate commits with PRs
}; }
}); })
return { return {
changedFiles: changedFilesCount, changedFiles: changedFilesCount,
@@ -148,75 +142,66 @@ export class GiteaRepository extends BaseRepository {
deletions: deletionCount, deletions: deletionCount,
changes: changeCount, changes: changeCount,
commits: commitCount, commits: commitCount,
commitInfo: commitInfo commitInfo
}; }
} }
static pulls:PullRequest[] = []; static pulls: Pulls = {
closed: [],
open: []
}
async getForCommitHash(owner: string, repo: string, commit_sha: string, maxPullRequests: number): Promise<PullRequestInfo[]> { private async getAllPullRequest(owner: string, repo: string, state: 'closed' | 'open', maxPullRequests: number) {
const mergedPRs: PullRequestInfo[] = [] if (GiteaRepository.pulls[state].length === 0) {
if(GiteaRepository.pulls.length===0){
let page = 1 let page = 1
let count = 0 let count = 0
while (count < maxPullRequests) { while (count < maxPullRequests) {
let limit = Math.min(50, maxPullRequests) const limit = Math.min(50, maxPullRequests)
const response = await this.api.repos.repoListPullRequests(owner, repo, { const response = await this.api.repos.repoListPullRequests(owner, repo, {
sort: 'recentupdate', sort: 'recentupdate',
state: 'closed', state,
limit: limit, limit,
page page
}) })
if (response.error === null) { if (response.error === null) {
GiteaRepository.pulls.push(...response.data) GiteaRepository.pulls[state].push(...response.data)
} }
page++; page++
count += response.data.length count += response.data.length
if(response.data.length===0)break; if (response.data.length === 0) break
}
}
} }
} async getForCommitHash(owner: string, repo: string, commit_sha: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const mergedPRs: PullRequestInfo[] = []
await this.getAllPullRequest(owner, repo, 'closed', maxPullRequests)
for (const pr of GiteaRepository.pulls) { for (const pr of GiteaRepository.pulls.closed) {
if (pr.merge_commit_sha === commit_sha) { if (pr.merge_commit_sha === commit_sha) {
mergedPRs.push(this.mapPullRequest(pr, pr.merged_at ? 'merged' : 'open')) mergedPRs.push(this.mapPullRequest(pr, pr.merged_at ? 'merged' : 'open'))
} }
} }
core.debug(`⚠️ No more PRs retrieved from API. Fetched so far: ${mergedPRs.length}`) core.debug(`⚠️ No more PRs retrieved from API. Fetched so far: ${mergedPRs.length}`)
return mergedPRs return mergedPRs
} }
async getOpen(owner: string, repo: string, maxPullRequests: number): Promise<PullRequestInfo[]> { async getOpen(owner: string, repo: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
const openPrs: PullRequestInfo[] = [] await this.getAllPullRequest(owner, repo, 'open', maxPullRequests)
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) { const openPrs: PullRequestInfo[] = []
for (const pr of GiteaRepository.pulls.open) {
openPrs.push(this.mapPullRequest(pr, 'open')) openPrs.push(this.mapPullRequest(pr, 'open'))
} }
}
return openPrs return openPrs
} }
async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> { async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
const prReviews: CommentInfo[] = [] const prReviews: CommentInfo[] = []
const response = await this.api.repos.repoListPullReviews(owner, repo, pr.number, {}) const response = await this.api.repos.repoListPullReviews(owner, repo, pr.number, {})
if (response.error === null) { if (response.error === null) {
for (const comment of response.data) { for (const comment of response.data) {
prReviews.push(this.mapComment(comment)) prReviews.push(this.mapComment(comment))
} }
@@ -226,10 +211,10 @@ export class GiteaRepository extends BaseRepository {
private mapComment = (comment: PullReview): CommentInfo => ({ private mapComment = (comment: PullReview): CommentInfo => ({
id: comment.id || 0, id: comment.id || 0,
htmlURL: comment.html_url || "", htmlURL: comment.html_url || '',
submittedAt: comment.submitted_at ? moment(comment.submitted_at) : undefined, submittedAt: comment.submitted_at ? moment(comment.submitted_at) : undefined,
author: comment.user?.login || '', author: comment.user?.login || '',
body: comment.body || "", body: comment.body || '',
state: comment.state state: comment.state
}) })
@@ -241,18 +226,16 @@ export class GiteaRepository extends BaseRepository {
if (response.error === null) { if (response.error === null) {
for (const tag of response.data) { for (const tag of response.data) {
tagsInfo.push({ tagsInfo.push({
name: tag.name || "", name: tag.name || '',
commit: tag.commit?.sha commit: tag.commit?.sha
}) })
} }
} }
core.info(`️ Found ${tagsInfo.length} (fetching max: ${maxTagsToFetch}) tags from the GitHub API for ${owner}/${repo}`) core.info(`️ Found ${tagsInfo.length} (fetching max: ${maxTagsToFetch}) tags from the GitHub API for ${owner}/${repo}`)
return tagsInfo return tagsInfo
} }
get homeUrl(): string { get homeUrl(): string {
return "https://gitea.com"; return 'https://gitea.com'
} }
} }