feat: add doCheckInactive

This commit is contained in:
元凛
2022-02-07 21:36:24 +08:00
parent f3ccc454b5
commit a83194ca41
5 changed files with 139 additions and 23 deletions

View File

@@ -1,15 +1,105 @@
import { dealStringToArr } from 'actions-util';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import * as core from '../core';
import { TIssueState, TUpdateMode, TEmoji, TLockReasons } from '../types';
import { ELockReasons } from '../shared';
import { IIssueCoreEngine } from '../issue';
import { IIssueCoreEngine, IListIssuesParams, TListIssuesResults } from '../issue';
import {
doAddLabels,
doCreateComment,
} from './base';
let ICE: IIssueCoreEngine;
export function initAdvancedICE(_ICE: IIssueCoreEngine) {
ICE = _ICE;
}
export async function doCheckInactive() {
export async function doQueryIssues(state: TIssueState | 'all', creator?: string): Promise<TListIssuesResults> {
const params = {
state,
} as IListIssuesParams;
const issueCreator = core.getInput('issue-creator');
const issueAssignee = core.getInput('issue-assignee');
const issueMentioned = core.getInput('issue-mentioned');
issueCreator ? (params.creator = issueCreator) : null;
issueAssignee ? (params.assignee = issueAssignee) : null;
issueMentioned ? (params.mentioned = issueMentioned) : null;
const labels = core.getInput('labels');
labels ? params.labels = labels : null;
creator? params.creator = creator : null;
const issuesList = await ICE.listIssues(params);
const issues: TListIssuesResults = [];
const issueNumbers: number[] = [];
if (issuesList.length) {
const excludeLabels = core.getInput('exclude-labels') || '';
const bodyIncludes = core.getInput('body-includes');
const titleIncludes = core.getInput('title-includes');
const excludeLabelsArr = dealStringToArr(excludeLabels);
issuesList.forEach(issue => {
const bodyCheck = bodyIncludes ? issue.body.includes(bodyIncludes) : true;
const titleCheck = titleIncludes ? issue.title.includes(titleIncludes) : true;
/**
* Note: GitHub's REST API v3 considers every pull request an issue, but not every issue is a pull request.
* For this reason, "Issues" endpoints may return both issues and pull requests in the response.
* You can identify pull requests by the pull_request key.
*/
if (bodyCheck && titleCheck && issue.pull_request === undefined) {
if (excludeLabelsArr.length) {
for (let i = 0; i < issue.labels.length; i += 1) {
if (excludeLabelsArr.includes(issue.labels[i].name)) return;
}
}
const inactiveDay = core.getInput('inactive-day');
if (inactiveDay) {
dayjs.extend(utc);
dayjs.extend(isSameOrBefore);
const lastTime = dayjs.utc().subtract(+inactiveDay, 'day');
const updateTime = dayjs.utc(issue.updated_at);
if (updateTime.isSameOrBefore(lastTime)) {
issues.push(issue);
issueNumbers.push(issue.number);
}
} else {
issues.push(issue);
issueNumbers.push(issue.number);
}
}
});
}
core.info(`[doQueryIssues] issueNumbers is [${JSON.stringify(issueNumbers)}]`);
return issues;
}
export async function doCheckInactive(body: string, emoji?: string) {
let issueState = core.getInput('issue-state');
if (issueState !== 'all' && issueState !== 'closed') {
issueState = 'open';
}
const issues = await doQueryIssues(issueState as TIssueState | 'all');
if (issues.length) {
const inactiveLabel = core.getInput('inactive-label') || 'inactive';
for (const issue of issues) {
const { labels, number } = issue;
const labelNames = labels.map(({name}) => name);
if (!labelNames.includes(inactiveLabel)) {
await doAddLabels([inactiveLabel], number);
if (body) await doCreateComment(body, emoji, number);
} else {
core.info(`[doCheckInactive] The issue ${number} already has ${inactiveLabel} label!`);
}
}
} else {
core.info(`[doCheckInactive] Query issues empty!`);
}
}

View File

@@ -5,7 +5,6 @@ import { ELockReasons } from '../shared';
import { IIssueCoreEngine } from '../issue';
let ICE: IIssueCoreEngine;
export function initBaseICE(_ICE: IIssueCoreEngine) {
ICE = _ICE;
}
@@ -15,7 +14,8 @@ export async function doAddAssignees(assignees: string[]) {
core.info(`[doAddAssignees] [${assignees}] success!`);
}
export async function doAddLabels(labels: string[]) {
export async function doAddLabels(labels: string[], issueNumber?: number) {
if (issueNumber) ICE.setIssueNumber(issueNumber);
await ICE.addLabels(labels);
core.info(`[doAddLabels] [${labels}] success!`);
}
@@ -25,8 +25,9 @@ export async function doCloseIssue(issueNumber: number) {
core.info(`[doCloseIssue] [${issueNumber}] success!`);
}
export async function doCreateComment(body: string, emoji?: string) {
export async function doCreateComment(body: string, emoji?: string, issueNumber?: number) {
if (body) {
if (issueNumber) ICE.setIssueNumber(issueNumber);
const commentId = await ICE.createComment(body);
core.info(`[doCreateComment] [${body}] success!`);
core.setOutput('comment-id', commentId);
@@ -127,6 +128,9 @@ export async function doUpdateComment(_commentId: number | void, body: string, u
if (commentId) {
await ICE.updateComment(+commentId, body, updateMode);
core.info(`[doUpdateComment] [${commentId}] success!`);
if (emoji) {
await doCreateCommentEmoji(+commentId, emoji);
}
} else {
core.warning(`[doUpdateComment] commentId is empty!`);
}

View File

@@ -193,7 +193,7 @@ export class IssueHelperEngine implements IIssueHelperEngine {
// ^_^ ============= ^_^
// -[ Advanced Begin ]->
case 'check-inactive': {
await doCheckInactive();
await doCheckInactive(body, emoji);
break;
}
}

View File

@@ -1,7 +1,7 @@
import { Octokit } from '@octokit/rest';
import { TEmoji, TLockReasons, TUpdateMode, TIssueState } from '../types';
import { IIssueBaseInfo, IIssueCoreEngine } from './types';
import { IIssueBaseInfo, IIssueCoreEngine, IListIssuesParams, TListIssuesResults } from './types';
export class IssueCoreEngine implements IIssueCoreEngine {
private owner!: string;
@@ -124,6 +124,22 @@ export class IssueCoreEngine implements IIssueCoreEngine {
});
}
public async listIssues(params: IListIssuesParams, page = 1) {
const { octokit, owner, repo } = this;
const { data } = await octokit.issues.listForRepo({
...params,
owner,
repo,
per_page: 100,
page,
});
let issues = [...data] as unknown as TListIssuesResults;
if (issues.length >= 100) {
issues = issues.concat(await this.listIssues(params, page + 1));
}
return issues;
}
public async lockIssue(lockReason: TLockReasons) {
const { owner, repo, octokit, issueNumber } = this;
const params: any = {
@@ -165,7 +181,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
issue_number: issueNumber,
});
const baseLabels = issue.data.labels.map(({ name }: any) => name);
const baseLabels: string[] = issue.data.labels.map(({ name }: any) => name);
const removeLabels = baseLabels.filter(name => labels.includes(name));
for (const label of removeLabels) {
@@ -190,7 +206,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
issue_number: issueNumber,
});
const baseLabels = issue.data.labels.map(({ name }: any) => name);
const baseLabels: string[] = issue.data.labels.map(({ name }: any) => name);
const removeLabels = baseLabels.filter(name => !labels.includes(name));
const addLabels = labels.filter(name => !baseLabels.includes(name));
@@ -257,12 +273,4 @@ export class IssueCoreEngine implements IIssueCoreEngine {
assignees: assignees?.length ? assignees : baseAssignessName,
});
}
public async queryIssues() {
}
private async listIssues(params, page = 1) {
}
}

View File

@@ -8,13 +8,26 @@ export interface IIssueBaseInfo {
}
export interface IListIssuesParams {
owner: string;
repo: string;
state: 'all' | 'open' | 'closed';
state: TIssueState | 'all';
creator?: string;
assignee?: string;
mentioned?: string;
labels?: string;
}
export type TListIssuesResult = {
number: number;
title: string;
body: string;
labels: {
name: string;
}[];
updated_at: string;
pull_request?: any;
}
export type TListIssuesResults = TListIssuesResult[];
export interface IIssueCoreEngine {
setIssueNumber(newIssueNumber: number): void;
addAssignees(assignees: string[]): Promise<void>;
@@ -40,6 +53,7 @@ export interface IIssueCoreEngine {
deleteComment(commentId: number): Promise<void>;
listIssues(params: IListIssuesParams): Promise<TListIssuesResults>;
lockIssue(lockReason: TLockReasons): Promise<void>;
openIssue(): Promise<void>;