mirror of
https://gitea.com/Lydanne/issues-helper.git
synced 2025-08-19 10:15:59 +08:00
wip: add helper & base
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
|
export const baseInfo = (mess: string) => {
|
||||||
|
core.info(mess);
|
||||||
|
}
|
||||||
|
|
||||||
export const info = (mess: string) => {
|
export const info = (mess: string) => {
|
||||||
core.info(`[📝 AC] ${mess}`);
|
core.info(`[📝 AC] ${mess}`);
|
||||||
}
|
}
|
||||||
@@ -16,8 +20,8 @@ export const warning = (mess: string) => {
|
|||||||
core.warning(`[🎃 AC] ${mess}`);
|
core.warning(`[🎃 AC] ${mess}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getInput = (key: string): string | void => {
|
export const getInput = (key: string, options?: core.InputOptions): string | void => {
|
||||||
core.getInput(key);
|
core.getInput(key, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setOutput = (key: string, value: string | number | object | void ) => {
|
export const setOutput = (key: string, value: string | number | object | void ) => {
|
||||||
|
15
src/helper/advanced.ts
Normal file
15
src/helper/advanced.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { dealStringToArr } from 'actions-util';
|
||||||
|
import * as core from '../core';
|
||||||
|
import { TIssueState, TUpdateMode, TEmoji, TLockReasons } from '../types';
|
||||||
|
import { ELockReasons } from '../shared';
|
||||||
|
import { IIssueCoreEngine } from '../issue';
|
||||||
|
|
||||||
|
let ICE: IIssueCoreEngine;
|
||||||
|
|
||||||
|
export function initAdvancedICE(_ICE: IIssueCoreEngine) {
|
||||||
|
ICE = _ICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doCheckInactive() {
|
||||||
|
|
||||||
|
}
|
138
src/helper/base.ts
Normal file
138
src/helper/base.ts
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import { dealStringToArr } from 'actions-util';
|
||||||
|
import * as core from '../core';
|
||||||
|
import { TIssueState, TUpdateMode, TEmoji, TLockReasons } from '../types';
|
||||||
|
import { ELockReasons } from '../shared';
|
||||||
|
import { IIssueCoreEngine } from '../issue';
|
||||||
|
|
||||||
|
let ICE: IIssueCoreEngine;
|
||||||
|
|
||||||
|
export function initBaseICE(_ICE: IIssueCoreEngine) {
|
||||||
|
ICE = _ICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doAddAssignees(assignees: string[]) {
|
||||||
|
await ICE.addAssignees(assignees);
|
||||||
|
core.info(`[doAddAssignees] [${assignees}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doAddLabels(labels: string[]) {
|
||||||
|
await ICE.addLabels(labels);
|
||||||
|
core.info(`[doAddLabels] [${labels}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doCloseIssue(issueNumber: number) {
|
||||||
|
await ICE.closeIssue();
|
||||||
|
core.info(`[doCloseIssue] [${issueNumber}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doCreateComment(body: string, emoji?: string) {
|
||||||
|
if (body) {
|
||||||
|
const commentId = await ICE.createComment(body);
|
||||||
|
core.info(`[doCreateComment] [${body}] success!`);
|
||||||
|
core.setOutput('comment-id', commentId);
|
||||||
|
if (emoji) {
|
||||||
|
await doCreateCommentEmoji(commentId, emoji);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
core.warning(`[doCreateComment] body is empty!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doCreateCommentEmoji(_commentId: number | void, emoji: string) {
|
||||||
|
const commentId = _commentId || core.getInput('comment-id');
|
||||||
|
if (emoji && commentId) {
|
||||||
|
await ICE.createCommentEmoji(+commentId, dealStringToArr(emoji) as TEmoji[]);
|
||||||
|
core.info(`[doCreateCommentEmoji] [${emoji}] success!`);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doCreateCommentEmoji] emoji or commentId is empty!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doCreateIssue(title: string, body: string, labels: string[] | void, assignees: string[] | void, emoji: string | void) {
|
||||||
|
if (title) {
|
||||||
|
const issueNumber = await ICE.createIssue(title, body, labels, assignees);
|
||||||
|
core.info(`[doCreateIssue] [${title}] success!`);
|
||||||
|
core.setOutput('issue-number', issueNumber);
|
||||||
|
if (emoji) {
|
||||||
|
ICE.setIssueNumber(issueNumber);
|
||||||
|
await ICE.createIssueEmoji(dealStringToArr(emoji) as TEmoji[]);
|
||||||
|
core.info(`[createIssueEmoji] [${emoji}] success!`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
core.warning(`[doCreateIssue] title is empty!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doCreateLabel() {
|
||||||
|
const name = core.getInput('label-name');
|
||||||
|
const color = core.getInput('label-color') || 'ededed';
|
||||||
|
const description = core.getInput('label-desc') || '';
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
await ICE.createLabel(name, color, description);
|
||||||
|
core.info(`[doCreateLabel] [${name}] success!`);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doCreateLabel] label-name is empty!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doDeleteComment(_commentId: number | void) {
|
||||||
|
const commentId = _commentId || core.getInput('comment-id');
|
||||||
|
if (commentId) {
|
||||||
|
await ICE.deleteComment(+commentId);
|
||||||
|
core.info(`[doDeleteComment] [${commentId}] success!`);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doDeleteComment] commentId is empty!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doLockIssue(issueNumber: number) {
|
||||||
|
const lockReason = core.getInput('lock-reason') || '';
|
||||||
|
// @ts-ignore
|
||||||
|
if (lockReason && !ELockReasons[lockReason]) {
|
||||||
|
core.warning(`[doLockIssue] lock-reason is illegal!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await ICE.lockIssue(lockReason as TLockReasons);
|
||||||
|
core.info(`[doLockIssue] ${issueNumber} success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doOpenIssue(issueNumber: number) {
|
||||||
|
await ICE.openIssue();
|
||||||
|
core.info(`[doOpenIssue] [${issueNumber}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doRemoveAssignees(assignees: string[]) {
|
||||||
|
await ICE.removeAssignees(assignees);
|
||||||
|
core.info(`[doRemoveAssignees] [${assignees}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doRemoveLabels(labels: string[]) {
|
||||||
|
await ICE.removeLabels(labels);
|
||||||
|
core.info(`[doRemoveLabels] [${labels}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doSetLabels(labels: string[]) {
|
||||||
|
await ICE.setLabels(labels);
|
||||||
|
core.info(`[doSetLabels] [${labels}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doUnlockIssue(issueNumber: number) {
|
||||||
|
await ICE.unlockIssue();
|
||||||
|
core.info(`[doUnlockIssue] [${issueNumber}] success!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doUpdateComment(_commentId: number | void, body: string, updateMode: TUpdateMode, emoji: string | void) {
|
||||||
|
const commentId = _commentId || core.getInput('comment-id');
|
||||||
|
if (commentId) {
|
||||||
|
await ICE.updateComment(+commentId, body, updateMode);
|
||||||
|
core.info(`[doUpdateComment] [${commentId}] success!`);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doUpdateComment] commentId is empty!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function doUpdateIssue(issueNumber: number, state: TIssueState, title: string | void, body: string | void, updateMode: TUpdateMode, labels?: string[] | void, assignees?: string[] | void) {
|
||||||
|
await ICE.updateIssue(state, title, body, updateMode, labels, assignees);
|
||||||
|
core.info(`[doUpdateIssue] [${issueNumber}] success!`);
|
||||||
|
}
|
201
src/helper/helper.ts
Normal file
201
src/helper/helper.ts
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
// import * as github from '@actions/github';
|
||||||
|
import { dealStringToArr } from 'actions-util';
|
||||||
|
import * as core from '../core';
|
||||||
|
import { Context, TIssueState, TUpdateMode, TAction, TEmoji } from '../types';
|
||||||
|
import {
|
||||||
|
IssueCoreEngine,
|
||||||
|
IIssueCoreEngine,
|
||||||
|
} from '../issue';
|
||||||
|
import { dealRandomAssignees } from '../util';
|
||||||
|
import { IIssueHelperEngine } from './types';
|
||||||
|
|
||||||
|
import {
|
||||||
|
initBaseICE,
|
||||||
|
doAddAssignees,
|
||||||
|
doAddLabels,
|
||||||
|
doCloseIssue,
|
||||||
|
doCreateComment,
|
||||||
|
doCreateCommentEmoji,
|
||||||
|
doCreateIssue,
|
||||||
|
doCreateLabel,
|
||||||
|
doDeleteComment,
|
||||||
|
doLockIssue,
|
||||||
|
doOpenIssue,
|
||||||
|
doRemoveAssignees,
|
||||||
|
doRemoveLabels,
|
||||||
|
doSetLabels,
|
||||||
|
doUnlockIssue,
|
||||||
|
doUpdateComment,
|
||||||
|
doUpdateIssue,
|
||||||
|
} from './base';
|
||||||
|
|
||||||
|
import {
|
||||||
|
initAdvancedICE,
|
||||||
|
doCheckInactive,
|
||||||
|
} from './advanced';
|
||||||
|
|
||||||
|
export class IssueHelperEngine implements IIssueHelperEngine {
|
||||||
|
private ICE!: IIssueCoreEngine;
|
||||||
|
|
||||||
|
private owner!: string;
|
||||||
|
private repo!: string;
|
||||||
|
private issueNumber!: number;
|
||||||
|
private githubToken!: string;
|
||||||
|
|
||||||
|
private emoji?: string;
|
||||||
|
private labels?: string[] | void;
|
||||||
|
private assignees?: string[] | void;
|
||||||
|
private title: string = '';
|
||||||
|
private body: string = '';
|
||||||
|
private state: TIssueState = 'open';
|
||||||
|
private updateMode: TUpdateMode = 'replace';
|
||||||
|
|
||||||
|
public constructor(readonly ctx: Context) {
|
||||||
|
this.initInput(ctx);
|
||||||
|
this.initIssueCore();
|
||||||
|
initBaseICE(this.ICE);
|
||||||
|
initAdvancedICE(this.ICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private initInput(ctx: Context) {
|
||||||
|
// No display to outside
|
||||||
|
const repoInput = core.getInput('repo');
|
||||||
|
if (repoInput) {
|
||||||
|
this.owner = repoInput.split('/')[0];
|
||||||
|
this.repo = repoInput.split('/')[1];
|
||||||
|
} else {
|
||||||
|
this.owner = ctx.repo.owner;
|
||||||
|
this.repo = ctx.repo.repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
let defaultCtxNumber: number | undefined;
|
||||||
|
if (ctx.eventName === 'issues' || ctx.eventName === 'issue_comment') {
|
||||||
|
defaultCtxNumber = ctx.payload.issue?.number;
|
||||||
|
}
|
||||||
|
const issueNumber = core.getInput('issue-number') || defaultCtxNumber;
|
||||||
|
if (issueNumber) {
|
||||||
|
this.issueNumber = +issueNumber;
|
||||||
|
} else {
|
||||||
|
core.setFailed(`issue-number is missing!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.githubToken = core.getInput('token', { required: true }) as string;
|
||||||
|
this.emoji = core.getInput('emoji') || '';
|
||||||
|
this.labels = dealStringToArr(core.getInput('labels') || '');
|
||||||
|
|
||||||
|
const assigneesInput = core.getInput('assignees') || '';
|
||||||
|
const randomTo = core.getInput('random-to');
|
||||||
|
this.assignees = dealRandomAssignees(assigneesInput, randomTo);
|
||||||
|
|
||||||
|
this.title = core.getInput('title') || '';
|
||||||
|
this.body = core.getInput('body') || '';
|
||||||
|
this.state = core.getInput('state') === 'closed' ? 'closed' : 'open';
|
||||||
|
this.updateMode = core.getInput('update-mode') === 'append' ? 'append' : 'replace';
|
||||||
|
}
|
||||||
|
|
||||||
|
private initIssueCore() {
|
||||||
|
const { owner, repo, issueNumber, githubToken } = this;
|
||||||
|
this.ICE = new IssueCoreEngine({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issueNumber,
|
||||||
|
githubToken,
|
||||||
|
});
|
||||||
|
core.info(`[Init] [${owner}/${repo}] [${issueNumber}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async doExeAction(action: TAction) {
|
||||||
|
const { owner, repo, issueNumber, emoji, labels, assignees, title, body, updateMode, state } = this;
|
||||||
|
switch (action) {
|
||||||
|
// ---[ Base Begin ]--->>>
|
||||||
|
case 'add-assignees': {
|
||||||
|
if (assignees && assignees.length) {
|
||||||
|
await doAddAssignees(assignees);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doAddAssignees] assignees is empty!`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'add-labels': {
|
||||||
|
if (labels && labels.length) {
|
||||||
|
await doAddLabels(labels);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doAddLabels] labels is empty!`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'close-issue': {
|
||||||
|
await doCloseIssue(issueNumber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'create-comment': {
|
||||||
|
await doCreateComment(body, emoji);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'create-issue': {
|
||||||
|
await doCreateIssue(title, body, labels, assignees, emoji);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'create-label': {
|
||||||
|
await doCreateLabel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'delete-comment': {
|
||||||
|
await doDeleteComment();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'lock-issue': {
|
||||||
|
await doLockIssue(issueNumber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'open-issue': {
|
||||||
|
await doOpenIssue(issueNumber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'remove-assignees': {
|
||||||
|
if (assignees && assignees.length) {
|
||||||
|
await doRemoveAssignees(assignees);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doRemoveAssignees] assignees is empty!`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'remove-labels': {
|
||||||
|
if (labels && labels.length) {
|
||||||
|
await doRemoveLabels(labels);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doRemoveLabels] labels is empty!`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'set-labels': {
|
||||||
|
if (labels && labels.length) {
|
||||||
|
await doSetLabels(labels);
|
||||||
|
} else {
|
||||||
|
core.warning(`[doSetLabels] labels is empty!`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'unlock-issue': {
|
||||||
|
await doUnlockIssue(issueNumber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'update-comment': {
|
||||||
|
await doUpdateComment(0, body, updateMode, emoji);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'update-issue': {
|
||||||
|
await doUpdateIssue(issueNumber, state, title, body, updateMode, labels, assignees);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// ---[ Base End ]--->>>
|
||||||
|
// ^_^ ============= ^_^
|
||||||
|
// -[ Advanced Begin ]->
|
||||||
|
case 'check-inactive': {
|
||||||
|
await doCheckInactive();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
src/helper/index.ts
Normal file
2
src/helper/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './helper';
|
||||||
|
export * from './types';
|
5
src/helper/types.ts
Normal file
5
src/helper/types.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { TAction } from '../types';
|
||||||
|
|
||||||
|
export interface IIssueHelperEngine {
|
||||||
|
doExeAction(action: TAction): Promise<void>;
|
||||||
|
}
|
@@ -1,9 +1,7 @@
|
|||||||
import { Octokit } from '@octokit/rest';
|
import { Octokit } from '@octokit/rest';
|
||||||
|
|
||||||
import * as core from '../core';
|
import { TEmoji, TLockReasons, TUpdateMode, TIssueState } from '../types';
|
||||||
|
import { IIssueBaseInfo, IIssueCoreEngine } from './types';
|
||||||
import { TEmoji, TLockReasons } from '../types';
|
|
||||||
import { IIssueBaseInfo, IIssueCoreEngine, TUpdateMode } from './types';
|
|
||||||
|
|
||||||
export class IssueCoreEngine implements IIssueCoreEngine {
|
export class IssueCoreEngine implements IIssueCoreEngine {
|
||||||
private owner!: string;
|
private owner!: string;
|
||||||
@@ -13,13 +11,13 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
|
|
||||||
private octokit!: Octokit;
|
private octokit!: Octokit;
|
||||||
|
|
||||||
public constructor(private _info: IIssueBaseInfo) {
|
public constructor(_info: IIssueBaseInfo) {
|
||||||
if (_info.owner && _info.repo && _info.githubToken) {
|
if (_info.owner && _info.repo && _info.githubToken) {
|
||||||
Object.assign(this, _info);
|
Object.assign(this, _info);
|
||||||
const octokit = new Octokit({ auth: `token ${this.githubToken}` });
|
const octokit = new Octokit({ auth: `token ${this.githubToken}` });
|
||||||
this.octokit = octokit;
|
this.octokit = octokit;
|
||||||
} else {
|
} else {
|
||||||
core.error(`Init failed, need owner、repo and token!`);
|
console && console.error && console.error(`Init failed, need owner、repo and token!`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +27,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async addAssignees(assignees: string[]) {
|
public async addAssignees(assignees: string[]) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.addAssignees({
|
await octokit.issues.addAssignees({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -39,17 +37,17 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async addLabels(labels: string[]) {
|
public async addLabels(labels: string[]) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.addLabels({
|
await octokit.issues.addLabels({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
labels: labels,
|
labels,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async closeIssue() {
|
public async closeIssue() {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.update({
|
await octokit.issues.update({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -59,19 +57,18 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async createComment(body: string): Promise<number> {
|
public async createComment(body: string): Promise<number> {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
const { data } = await octokit.issues.createComment({
|
const { data } = await octokit.issues.createComment({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
core.setOutput('comment-id', data.id);
|
|
||||||
return data.id;
|
return data.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createCommentEmoji(commentId: number, emoji: TEmoji[]) {
|
public async createCommentEmoji(commentId: number, emoji: TEmoji[]) {
|
||||||
const {owner, repo, octokit } = this;
|
const { owner, repo, octokit } = this;
|
||||||
for (const content of emoji) {
|
for (const content of emoji) {
|
||||||
await octokit.reactions.createForIssueComment({
|
await octokit.reactions.createForIssueComment({
|
||||||
owner,
|
owner,
|
||||||
@@ -79,12 +76,11 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
comment_id: commentId,
|
comment_id: commentId,
|
||||||
content,
|
content,
|
||||||
});
|
});
|
||||||
core.info(`[create-comment-emoji] [${content}] success!`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createIssue(title: string, body: string | undefined, labels: string[], assignees: string[]): Promise<number> {
|
public async createIssue(title: string, body: string, labels?: string[], assignees?: string[]): Promise<number> {
|
||||||
const {owner, repo, octokit } = this;
|
const { owner, repo, octokit } = this;
|
||||||
const { data } = await octokit.issues.create({
|
const { data } = await octokit.issues.create({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -93,12 +89,11 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
labels,
|
labels,
|
||||||
assignees,
|
assignees,
|
||||||
});
|
});
|
||||||
core.setOutput('issue-number', data.number);
|
|
||||||
return data.number;
|
return data.number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createIssueEmoji(emoji: TEmoji[]) {
|
public async createIssueEmoji(emoji: TEmoji[]) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
for (const content of emoji) {
|
for (const content of emoji) {
|
||||||
await octokit.reactions.createForIssue({
|
await octokit.reactions.createForIssue({
|
||||||
owner,
|
owner,
|
||||||
@@ -106,12 +101,11 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
content,
|
content,
|
||||||
});
|
});
|
||||||
core.info(`[create-issue-emoji] [${content}] success!`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createLabel(labelName: string, labelColor: string, labelDescription: string | undefined) {
|
public async createLabel(labelName: string, labelColor: string, labelDescription: string | undefined) {
|
||||||
const {owner, repo, octokit } = this;
|
const { owner, repo, octokit } = this;
|
||||||
await octokit.issues.createLabel({
|
await octokit.issues.createLabel({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -122,7 +116,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async deleteComment(commentId: number) {
|
public async deleteComment(commentId: number) {
|
||||||
const {owner, repo, octokit } = this;
|
const { owner, repo, octokit } = this;
|
||||||
await octokit.issues.deleteComment({
|
await octokit.issues.deleteComment({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -131,17 +125,20 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async lockIssue(lockReason: TLockReasons) {
|
public async lockIssue(lockReason: TLockReasons) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.lock({
|
const params: any = {
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
lockReason,
|
}
|
||||||
});
|
if (lockReason) {
|
||||||
|
params.lock_reason = lockReason;
|
||||||
|
}
|
||||||
|
await octokit.issues.lock(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async openIssue() {
|
public async openIssue() {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.update({
|
await octokit.issues.update({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -151,7 +148,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async removeAssignees(assignees: string[]) {
|
public async removeAssignees(assignees: string[]) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.removeAssignees({
|
await octokit.issues.removeAssignees({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -161,7 +158,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async removeLabels(labels: string[]) {
|
public async removeLabels(labels: string[]) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
const issue = await octokit.issues.get({
|
const issue = await octokit.issues.get({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -171,8 +168,6 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
const baseLabels = issue.data.labels.map(({ name }: any) => name);
|
const baseLabels = issue.data.labels.map(({ name }: any) => name);
|
||||||
const removeLabels = baseLabels.filter(name => labels.includes(name));
|
const removeLabels = baseLabels.filter(name => labels.includes(name));
|
||||||
|
|
||||||
core.info(`[filter-labels] [${removeLabels.join(',')}]!`);
|
|
||||||
|
|
||||||
for (const label of removeLabels) {
|
for (const label of removeLabels) {
|
||||||
await octokit.issues.removeLabel({
|
await octokit.issues.removeLabel({
|
||||||
owner,
|
owner,
|
||||||
@@ -180,7 +175,6 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
name: label,
|
name: label,
|
||||||
});
|
});
|
||||||
core.info(`[remove-label] [${label}] success!`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +182,7 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
// https://github.com/octokit/rest.js/issues/34
|
// https://github.com/octokit/rest.js/issues/34
|
||||||
// - Probability to appear
|
// - Probability to appear
|
||||||
// - avoid use setLabels
|
// - avoid use setLabels
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
|
|
||||||
const issue = await octokit.issues.get({
|
const issue = await octokit.issues.get({
|
||||||
owner,
|
owner,
|
||||||
@@ -201,18 +195,16 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
const addLabels = labels.filter(name => !baseLabels.includes(name));
|
const addLabels = labels.filter(name => !baseLabels.includes(name));
|
||||||
|
|
||||||
if (removeLabels.length) {
|
if (removeLabels.length) {
|
||||||
core.info(`[filter-remove-labels] [${removeLabels.join(',')}]!`);
|
|
||||||
await this.removeLabels(removeLabels);
|
await this.removeLabels(removeLabels);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addLabels.length) {
|
if (addLabels.length) {
|
||||||
core.info(`[filter-add-labels] [${addLabels.join(',')}]!`);
|
|
||||||
await this.addLabels(addLabels);
|
await this.addLabels(addLabels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async unlockIssue() {
|
public async unlockIssue() {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
await octokit.issues.unlock({
|
await octokit.issues.unlock({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -221,31 +213,25 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async updateComment(commentId: number, body: string, mode: TUpdateMode) {
|
public async updateComment(commentId: number, body: string, mode: TUpdateMode) {
|
||||||
const {owner, repo, octokit } = this;
|
const { owner, repo, octokit } = this;
|
||||||
const comment = await octokit.issues.getComment({
|
const comment = await octokit.issues.getComment({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
comment_id: commentId,
|
comment_id: commentId,
|
||||||
});
|
});
|
||||||
const baseBody = comment.data.body;
|
const baseBody = comment.data.body;
|
||||||
|
const newBody = body ? (mode === 'append' ? `${baseBody}\n${body}` : body) : baseBody;
|
||||||
let newBody: string;
|
|
||||||
if (mode === 'append') {
|
|
||||||
newBody = `${baseBody}\n${body}`;
|
|
||||||
} else {
|
|
||||||
newBody = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
await octokit.issues.updateComment({
|
await octokit.issues.updateComment({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
comment_id: commentId,
|
comment_id: commentId,
|
||||||
body: newBody,
|
body: newBody || '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateIssue(state: 'open' | 'closed', title: string | undefined, body: string | undefined, mode: TUpdateMode, labels: string[], assignees: string[]) {
|
public async updateIssue(state: TIssueState, title: string | void, body: string | void, mode: TUpdateMode, labels?: string[] | void, assignees?: string[] | void) {
|
||||||
const {owner, repo, octokit, issueNumber } = this;
|
const { owner, repo, octokit, issueNumber } = this;
|
||||||
|
|
||||||
const issue = await octokit.issues.get({
|
const issue = await octokit.issues.get({
|
||||||
owner,
|
owner,
|
||||||
@@ -255,8 +241,8 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
|
|
||||||
const { body: baseBody, title: baseTitle, labels: baseLabels, assignees: baseAssigness, state: baseState } = issue.data;
|
const { body: baseBody, title: baseTitle, labels: baseLabels, assignees: baseAssigness, state: baseState } = issue.data;
|
||||||
|
|
||||||
const baseLabelsName = baseLabels.map(({name}: any) => name);
|
const baseLabelsName = baseLabels.map(({ name }: any) => name);
|
||||||
const baseAssignessName = baseLabels.map(({login}: any) => login);
|
const baseAssignessName = baseAssigness?.map(({ login }: any) => login);
|
||||||
|
|
||||||
const newBody = body ? (mode === 'append' ? `${baseBody}\n${body}` : body) : baseBody;
|
const newBody = body ? (mode === 'append' ? `${baseBody}\n${body}` : body) : baseBody;
|
||||||
|
|
||||||
@@ -267,8 +253,16 @@ export class IssueCoreEngine implements IIssueCoreEngine {
|
|||||||
state: state || baseState,
|
state: state || baseState,
|
||||||
title: title || baseTitle,
|
title: title || baseTitle,
|
||||||
body: newBody,
|
body: newBody,
|
||||||
labels: labels.length ? labels : baseLabelsName,
|
labels: labels?.length ? labels : baseLabelsName,
|
||||||
assignees: assignees.length ? assignees : baseAssignessName,
|
assignees: assignees?.length ? assignees : baseAssignessName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async queryIssues() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async listIssues(params, page = 1) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +1,32 @@
|
|||||||
import { TEmoji, TLockReasons } from '../types';
|
import { TEmoji, TLockReasons, TIssueState, TUpdateMode } from '../types';
|
||||||
|
|
||||||
export interface IIssueBaseInfo {
|
export interface IIssueBaseInfo {
|
||||||
owner: string;
|
owner: string;
|
||||||
repo: string;
|
repo: string;
|
||||||
issueNunber: string;
|
issueNumber: number;
|
||||||
githubToken: string;
|
githubToken: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TUpdateMode = 'append' | string | undefined;
|
export interface IListIssuesParams {
|
||||||
|
owner: string;
|
||||||
|
repo: string;
|
||||||
|
state: 'all' | 'open' | 'closed';
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export interface IIssueCoreEngine {
|
export interface IIssueCoreEngine {
|
||||||
addAssignees(assignees: string[]): void;
|
setIssueNumber(newIssueNumber: number): void;
|
||||||
addLabels(labels: string[]): void;
|
addAssignees(assignees: string[]): Promise<void>;
|
||||||
|
addLabels(labels: string[]): Promise<void>;
|
||||||
|
|
||||||
closeIssue(): void;
|
closeIssue(): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* @param body The comment body.
|
* @param body The comment body.
|
||||||
* @returns The create new comment id.
|
* @returns The create new comment id.
|
||||||
*/
|
*/
|
||||||
createComment(body: string): Promise<number>;
|
createComment(body: string): Promise<number>;
|
||||||
createCommentEmoji(commentId: number, emoji: TEmoji[]): void;
|
createCommentEmoji(commentId: number, emoji: TEmoji[]): Promise<void>;
|
||||||
/**
|
/**
|
||||||
* @param title
|
* @param title
|
||||||
* @param body
|
* @param body
|
||||||
@@ -27,23 +34,23 @@ export interface IIssueCoreEngine {
|
|||||||
* @param assignees
|
* @param assignees
|
||||||
* @returns The create new issue number.
|
* @returns The create new issue number.
|
||||||
*/
|
*/
|
||||||
createIssue(title: string, body: string | undefined, labels: string[], assignees: string[]): Promise<number>;
|
createIssue(title: string, body: string, labels: string[] | void, assignees: string[] | void): Promise<number>;
|
||||||
createIssueEmoji(emoji: TEmoji[]): void;
|
createIssueEmoji(emoji: TEmoji[]): Promise<void>;
|
||||||
createLabel(labelName: string, labelColor: string, labelDescription: string | undefined): void;
|
createLabel(labelName: string, labelColor: string, labelDescription: string | undefined): Promise<void>;
|
||||||
|
|
||||||
deleteComment(commentId: number): void;
|
deleteComment(commentId: number): Promise<void>;
|
||||||
|
|
||||||
lockIssue(lockReason: TLockReasons): void;
|
lockIssue(lockReason: TLockReasons): Promise<void>;
|
||||||
|
|
||||||
openIssue(): void;
|
openIssue(): Promise<void>;
|
||||||
|
|
||||||
removeAssignees(assignees: string[]): void;
|
removeAssignees(assignees: string[]): Promise<void>;
|
||||||
removeLabels(labels: string[]): void;
|
removeLabels(labels: string[]): Promise<void>;
|
||||||
|
|
||||||
setLabels(labels: string[]): void;
|
setLabels(labels: string[]): Promise<void>;
|
||||||
|
|
||||||
unlockIssue(): void;
|
unlockIssue(): Promise<void>;
|
||||||
|
|
||||||
updateComment(commentId: number, body: string, mode: TUpdateMode): void;
|
updateComment(commentId: number, body: string, mode: TUpdateMode): Promise<void>;
|
||||||
updateIssue(state: 'open' | 'closed', title: string | undefined, body: string | undefined, mode: TUpdateMode, labels: string[], assignees: string[]): void;
|
updateIssue(state: TIssueState, title: string | void, body: string | void, mode: TUpdateMode, labels?: string[] | void, assignees?: string[] | void): Promise<void>;
|
||||||
}
|
}
|
||||||
|
21
src/main.ts
21
src/main.ts
@@ -0,0 +1,21 @@
|
|||||||
|
import * as github from '@actions/github';
|
||||||
|
import { dealStringToArr, THANKS } from 'actions-util';
|
||||||
|
|
||||||
|
import * as core from './core';
|
||||||
|
import { TAction } from './types';
|
||||||
|
import { IssueHelperEngine } from './helper';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
try {
|
||||||
|
const actions = core.getInput('actions', { required: true }) as string;
|
||||||
|
const IHE = new IssueHelperEngine(github.context);
|
||||||
|
for (const action of dealStringToArr(actions)) {
|
||||||
|
await IHE.doExeAction(action as TAction);
|
||||||
|
}
|
||||||
|
core.baseInfo(`\n${THANKS}`);
|
||||||
|
} catch (err: any) {
|
||||||
|
core.setFailed(err.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
||||||
|
38
src/types.ts
38
src/types.ts
@@ -1,3 +1,41 @@
|
|||||||
|
export { Context } from '@actions/github/lib/context';
|
||||||
|
|
||||||
export type TEmoji = '+1' | '-1' | 'laugh' | 'confused' | 'heart' | 'hooray' | 'rocket' | 'eyes';
|
export type TEmoji = '+1' | '-1' | 'laugh' | 'confused' | 'heart' | 'hooray' | 'rocket' | 'eyes';
|
||||||
|
|
||||||
export type TLockReasons = 'off-topic' | 'too heated' | 'resolved' | 'spam' | undefined;
|
export type TLockReasons = 'off-topic' | 'too heated' | 'resolved' | 'spam' | undefined;
|
||||||
|
|
||||||
|
export type TIssueState = 'open' | 'closed';
|
||||||
|
|
||||||
|
export type TUpdateMode = 'append' | 'replace';
|
||||||
|
|
||||||
|
export type TAction =
|
||||||
|
// [ Base Begin ]
|
||||||
|
'add-assignees'
|
||||||
|
| 'add-labels'
|
||||||
|
| 'close-issue'
|
||||||
|
| 'create-comment'
|
||||||
|
| 'create-issue'
|
||||||
|
| 'create-label'
|
||||||
|
| 'delete-comment'
|
||||||
|
| 'lock-issue'
|
||||||
|
| 'open-issue'
|
||||||
|
| 'remove-assignees'
|
||||||
|
| 'remove-labels'
|
||||||
|
| 'set-labels'
|
||||||
|
| 'unlock-issue'
|
||||||
|
| 'update-comment'
|
||||||
|
| 'update-issue'
|
||||||
|
// [ Base End ]
|
||||||
|
// ^_^ ========== ^_^
|
||||||
|
// [ Advanced Begin ]
|
||||||
|
| 'check-inactive'
|
||||||
|
| 'check-issue'
|
||||||
|
| 'close-issues'
|
||||||
|
| 'find-comments'
|
||||||
|
| 'find-issues'
|
||||||
|
| 'lock-issues'
|
||||||
|
| 'mark-assignees'
|
||||||
|
| 'mark-duplicate'
|
||||||
|
| 'month-statistics'
|
||||||
|
| 'welcome';
|
||||||
|
// [ Advanced End ]
|
||||||
|
@@ -2,14 +2,6 @@ import sampleSize from 'lodash/sampleSize';
|
|||||||
import { dealStringToArr } from 'actions-util';
|
import { dealStringToArr } from 'actions-util';
|
||||||
export { dealStringToArr };
|
export { dealStringToArr };
|
||||||
|
|
||||||
export const dealRandomAssignees = (assignees: string, randomTo: number): string[] => {
|
|
||||||
let arr = dealStringToArr(assignees);
|
|
||||||
if (randomTo && Number(randomTo) > 0 && Number(randomTo) < arr.length) {
|
|
||||||
arr = sampleSize(arr, randomTo);
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const matchKeyword = (content: string, keywords: string[]): string | undefined => {
|
export const matchKeyword = (content: string, keywords: string[]): string | undefined => {
|
||||||
return keywords.find(item => content.toLowerCase().includes(item));
|
return keywords.find(item => content.toLowerCase().includes(item));
|
||||||
}
|
}
|
10
src/util/deal.ts
Normal file
10
src/util/deal.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import sampleSize from 'lodash/sampleSize';
|
||||||
|
import { dealStringToArr } from 'actions-util';
|
||||||
|
|
||||||
|
export const dealRandomAssignees = (assignees: string, randomTo: string | void): string[] => {
|
||||||
|
let arr = dealStringToArr(assignees);
|
||||||
|
if (randomTo && Number(randomTo) > 0 && Number(randomTo) < arr.length) {
|
||||||
|
arr = sampleSize(arr, Number(randomTo));
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
import { dealStringToArr } from 'actions-util';
|
||||||
|
export { dealStringToArr };
|
||||||
|
|
||||||
|
export * from './data';
|
||||||
|
export * from './deal';
|
||||||
|
@@ -69,6 +69,9 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"lib",
|
"lib",
|
||||||
|
"dist",
|
||||||
|
"docs-dist",
|
||||||
|
"web",
|
||||||
"**/*.test.ts"
|
"**/*.test.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user