diff --git a/src/class/issuesClose.ts b/src/class/issuesClose.ts new file mode 100644 index 0000000..fe02758 --- /dev/null +++ b/src/class/issuesClose.ts @@ -0,0 +1,75 @@ +import Context from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class IssuesClose { + + /** + * @private + * @type Context<"issues.closed"> + */ + private context: Context<"issues.closed">; + + /** + * @constructor + * @param {Context<"issues.closed">} context + */ + constructor(context: Context<"issues.closed">) { + this.context = context; + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async closed(): Promise { + const issueClosed = this.context.issue({ + body: `Issue closed by @${this.context.payload.sender.login}.` + }); + console.log("Issues closed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Closed"] + }) + ); + await this.context.octokit.issues.createComment(issueClosed); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async invalid(): Promise { + const issueClosed = this.context.issue({ + body: `Issue closed as invalid by @${this.context.payload.sender.login}.` + }); + console.log("Issues closed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Closed", "Invalid"] + }) + ); + await this.context.octokit.issues.createComment(issueClosed); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + await this.context.octokit.issues.lock({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.issue.number, + lock_reason: "spam" + }); + } +} diff --git a/src/class/issuesComment.ts b/src/class/issuesComment.ts new file mode 100644 index 0000000..4ee2d59 --- /dev/null +++ b/src/class/issuesComment.ts @@ -0,0 +1,192 @@ +import Context from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class IssuesComment { + + /** + * @private + * @type Context<"issue_comment.created"> + */ + private context: Context<"issue_comment.created">; + + /** + * @constructor + * @param {Context<"issue_comment.created">} context + */ + constructor(context: Context<"issue_comment.created">) { + this.context = context; + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async userPRsComment(): Promise { + if (this.context.payload.comment.body.toLowerCase() == "ready to merge") { + await this.context.octokit.pulls.get({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.issue.number + }).then(async (res) => { + if (res.data.mergeable_state.toLowerCase() == "clean" || res.data.mergeable == true) { + if (this.context.payload.issue.user.login == this.context.payload.comment.user.login) { + let i: number; + for (i = 0; i < this.context.payload.issue.labels.length; i++) { + if (this.context.payload.issue.labels[i].name == "Approved") { + console.log("Merging"); + await this.context.octokit.pulls.merge({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.issue.number, + commit_title: `Merge PR #${this.context.payload.issue.number} ${this.context.payload.issue.title}`, + commit_message: this.context.payload.issue.title + }); + console.log("Merged!"); + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merged by ${this.context.payload.comment.user.login}!` + }) + ); + break; + } else if (this.context.payload.issue.labels[i].name == "Requested Changes") { + console.log("PRs Blocked"); + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merging blocked because PRs has requested changes! @${this.context.payload.comment.user.login}` + }) + ); + break; + } else { + continue; + } + } + } else { + return; + } + } else if (res.data.mergeable_state.toLowerCase() == "dirty" || res.data.mergeable == false) { + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merging blocked because PRs has merge conflict! @${this.context.payload.comment.user.login}` + }) + ); + } else { + await this.context.octokit.issues.createComment( + this.context.issue({ + body: "We apologize for the inconvenience, but it seems that Automaton processes are currently unable to proceed with merging your commit. Please wait for a moment and try merging it again." + }) + ); + } + }); + } + + if (this.context.payload.comment.body.toLowerCase() == "merge") { + if (this.context.payload.sender.login == this.context.payload.repository.owner.login) { + await this.context.octokit.pulls.merge({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.issue.number, + commit_title: `Merge PR #${this.context.payload.issue.number} ${this.context.payload.issue.title}`, + commit_message: this.context.payload.issue.title + }); + console.log("Merged!"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merged by \`[OWNER]\`${this.context.payload.comment.user.login}!` + }) + ); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Owner Merge"] + }) + ); + } else if (this.context.payload.issue.author_association === "MEMBER" || this.context.payload.issue.author_association === "COLLABORATOR") { + await this.context.octokit.pulls.merge({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.issue.number, + commit_title: `Merge PR #${this.context.payload.issue.number} ${this.context.payload.issue.title}`, + commit_message: this.context.payload.issue.title + }); + console.log("Merged!"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merged by \`[MAINTAINER]\`${this.context.payload.comment.user.login}!` + }) + ); + } else { + return; + } + } + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async botPRsComment(): Promise { + if (this.context.payload.comment.body.toLowerCase() == "merge") { + if (this.context.payload.sender.login == this.context.payload.repository.owner.login) { + await this.context.octokit.pulls.merge({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.issue.number, + commit_title: `Merge PR #${this.context.payload.issue.number} ${this.context.payload.issue.title}`, + commit_message: this.context.payload.issue.title + }); + console.log("Merged!"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merged by \`[OWNER]\`${this.context.payload.comment.user.login}!` + }) + ); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Owner Merge"] + }) + ); + } else if (this.context.payload.issue.author_association === "MEMBER" || this.context.payload.issue.author_association === "COLLABORATOR") { + await this.context.octokit.pulls.merge({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.issue.number, + commit_title: `Merge PR #${this.context.payload.issue.number} ${this.context.payload.issue.title}`, + commit_message: this.context.payload.issue.title + }); + console.log("Merged!"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + await this.context.octokit.issues.createComment( + this.context.issue({ + body: `Merged by \`[MAINTAINER]\`${this.context.payload.comment.user.login}!` + }) + ); + } else { + return; + } + } + } +} diff --git a/src/class/issuesOpen.ts b/src/class/issuesOpen.ts new file mode 100644 index 0000000..e63c425 --- /dev/null +++ b/src/class/issuesOpen.ts @@ -0,0 +1,42 @@ +import Context from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class IssuesOpen { + + /** + * @private + * @type Context<"issues.opened"> + */ + private context: Context<"issues.opened">; + + /** + * @constructor + * @param {Context<"issues.opened">} context + */ + constructor(context: Context<"issues.opened">) { + this.context = context; + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async open(): Promise { + if (this.context.payload.sender.login === "Muunatic") return; + const issueComment = this.context.issue({ + body: `Hello @${this.context.payload.sender.login} Thank you for submitting Issue, please wait for next notification after we review your Issue.` + }); + console.log("Issues created"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Pending"] + }) + ); + await this.context.octokit.issues.createComment(issueComment); + } +} diff --git a/src/class/prsOpen.ts b/src/class/prsOpen.ts new file mode 100644 index 0000000..3e2656c --- /dev/null +++ b/src/class/prsOpen.ts @@ -0,0 +1,184 @@ +import Context, { octokit } from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class PullRequestOpen { + + /** + * @private + * @type Context<"pull_request.opened"> + */ + private context: Context<"pull_request.opened">; + + /** + * @constructor + * @param {Context<"pull_request.opened">} context + */ + constructor(context: Context<"pull_request.opened">) { + this.context = context; + } + + /** + * @private + * @async + * @returns {Promise} + */ + private async checkChanges(): Promise { + let totalChanges: number = 0; + await this.context.octokit.pulls.listFiles({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + pull_number: this.context.payload.number + }).then(async (res) => { + const filterFiles = res.data.filter((a) => a.filename !== "package.json" && a.filename !== "package-lock.json"); + for (let i = 0; i < filterFiles.length; i++) { + totalChanges += filterFiles[i].additions; + } + + if (totalChanges > 1000) { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Huge Changes"] + }) + ); + } + }); + } + + /** + * @private + * @async + * @returns {Promise} + */ + private async giveLabels(): Promise { + const fileLabels: string[] = []; + const filteredlabels: string[] = []; + await this.context.octokit.pulls.listFiles({ + owner: "Typeslint", + repo: "github-AutoResponse", + pull_number: this.context.payload.number + }).then(async (res) => { + const listFiles = res.data.map(a => a.filename); + for (let i = 0; i < listFiles.length; i++) { + if (/src\/index/i.test(listFiles[i])) { + fileLabels.push("Core"); + } else if (/src\/class\/prs/i.test(listFiles[i])) { + fileLabels.push("lib: Pull Request"); + } else if (/src\/class\/issues/i.test(listFiles[i])) { + fileLabels.push("lib: Issues"); + } else if (/src\/class\/push/i.test(listFiles[i])) { + fileLabels.push("lib: Push"); + } else if (/src\/class\/workflow/i.test(listFiles[i])) { + fileLabels.push("lib: Workflow"); + } else { + continue; + } + } + + console.log(fileLabels); + console.log(filteredlabels); + + if (fileLabels.length > 0) { + new Set(fileLabels).forEach(a => filteredlabels.push(a)); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: filteredlabels + }) + ); + } else { + return; + } + }); + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async open(): Promise { + + if (this.context.payload.sender.login != this.context.payload.repository.owner.login) { + const propened = this.context.issue({ + body: `Hello @${this.context.payload.sender.login} Thank you for submitting Pull Request, please wait for next notification after we review your Pull Request` + }); + console.log("Pull request opened"); + await this.context.octokit.issues.createComment(propened); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Pending"] + }) + ); + await this.checkChanges(); + } else { + const propened = this.context.issue({ + body: `PRs by \`[OWNER]\`${this.context.payload.pull_request.user.login}!` + }); + console.log("Pull request opened"); + await this.context.octokit.issues.createComment(propened); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Pending"] + }) + ); + await this.checkChanges(); + } + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async openCore(): Promise { + const propened = this.context.issue({ + body: `Hello @${this.context.payload.sender.login} Thank you for submitting Pull Request, please wait for next notification after we review your Pull Request` + }); + console.log("Pull request opened"); + await this.context.octokit.issues.createComment(propened); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Pending"] + }) + ); + await this.giveLabels(); + await this.checkChanges(); + let shaRef: string; + await octokit.rest.pulls.get({ + owner: "Typeslint", + repo: "github-AutoResponse", + pull_number: this.context.payload.number + }).then(async (res) => { + shaRef = res.data.head.sha; + await octokit.rest.repos.getContent({ + owner: "Typeslint", + repo: "github-AutoResponse", + ref: shaRef, + path: "tsconfig.json" + }).then(async (res) => { + if ("content" in res.data) { + const textContent:string = res.data.content; + const decodeContent:string = Buffer.from(textContent, "base64").toString("utf-8"); + if (decodeContent.includes("\"noImplicitAny\": true") && decodeContent.includes("\"noImplicitThis\": true") && decodeContent.includes("\"strictFunctionTypes\": true") && decodeContent.includes("\"strictNullChecks\": true")) { + return; + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Config Invalid"] + }) + ); + const configInvalid = this.context.issue({ + body: `[tsconfig](${res.data.html_url}) need [*noImplicitAny*, *noImplicitThis*, *strictFunctionTypes*, *strictNullChecks*] to true value` + }); + await this.context.octokit.issues.createComment(configInvalid); + } + } else { + return; + } + }); + }); + } +} diff --git a/src/class/prsReview.ts b/src/class/prsReview.ts new file mode 100644 index 0000000..364f9ff --- /dev/null +++ b/src/class/prsReview.ts @@ -0,0 +1,485 @@ +import Context from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class PullRequestReview { + + /** + * @private + * @type Context<"pull_request_review.submitted"> + */ + private context: Context<"pull_request_review.submitted">; + + /** + * @constructor + * @param {Context<"pull_request_review.submitted">} context + */ + constructor(context: Context<"pull_request_review.submitted">) { + this.context = context; + } + + /** + * @private + * @async + * @returns {Promise} + */ + public async userPRs(): Promise { + if (this.context.payload.sender.login == this.context.payload.repository.owner.login) { + // Owner + if (this.context.payload.review.state == "approved") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} your pull request has been approved by @${this.context.payload.review.user.login}, please type \`Ready to merge\` for merging`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Requested Changes" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } else if (this.context.payload.review.state == "changes_requested") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `Pull request has requested changes by @${this.context.payload.review.user.login}. PING! @${this.context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Approved")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Approved" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } + } else if (this.context.payload.pull_request.author_association == "MEMBER" || this.context.payload.pull_request.author_association == "COLLABORATOR") { + if (this.context.payload.review.state == "approved") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} your pull request has been approved by \`[MAINTAINER]\`@${this.context.payload.review.user.login}, please type \`Ready to merge\` for merging`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Requested Changes" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } else if (this.context.payload.review.state == "changes_requested") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `Pull request has requested changes by @${this.context.payload.review.user.login}. PING! @${this.context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Approved")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Approved" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } + } else { + // Others Approved + if (this.context.payload.review.state == "approved") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} your pull request has been approved by @${this.context.payload.review.user.login}, even though please wait for the \`MAINTAINERS\`/\`CODEOWNERS\` to review`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Requested Changes" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Others Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Others Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } else if (this.context.payload.review.state == "changes_requested") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `Pull request has requested changes by @${this.context.payload.review.user.login}. PING! @${this.context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, + event: "COMMENT" + }); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } + } + + /** + * @private + * @async + * @returns {Promise} + */ + public async botPRs(): Promise { + if (this.context.payload.sender.login == this.context.payload.repository.owner.login) { + // Owner + if (this.context.payload.review.state == "approved") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} Pull request has been approved by \`[OWNER]\`@${this.context.payload.review.user.login}, please type \`Merge\` for merging @${this.context.payload.review.user.login}`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Requested Changes" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } else if (this.context.payload.review.state == "changes_requested") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} your pull request has requested changes by \`[OWNER]\`@${this.context.payload.review.user.login}. Please address their comments before I'm merging this PR, thanks!`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Approved")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Approved" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } + } else if (this.context.payload.pull_request.author_association == "MEMBER" || this.context.payload.pull_request.author_association == "COLLABORATOR") { + if (this.context.payload.review.state == "approved") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} Pull request has been approved by \`[MAINTAINER]\`@${this.context.payload.review.user.login}, please type \`Merge\` for merging @${this.context.payload.review.user.login}`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Requested Changes" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } else if (this.context.payload.review.state == "changes_requested") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `Pull request has requested changes by \`[MAINTAINER]\`@${this.context.payload.review.user.login}. PING! @${this.context.payload.pull_request.user.login} Please address their comments before I"m merging this PR, thanks!`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Approved")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Approved" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } + } else { + // Others Approved + if (this.context.payload.review.state == "approved") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `@${this.context.payload.pull_request.user.login} your pull request has been approved by @${this.context.payload.review.user.login}, even though please wait for the \`MAINTAINERS\`/\`CODEOWNERS\` to review`, + event: "COMMENT" + }); + if (this.context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Requested Changes" + }) + ); + console.log("Label removed"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Others Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } else { + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Others Approved"] + }) + ); + console.log("PRs Approved"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } else if (this.context.payload.review.state == "changes_requested") { + await this.context.octokit.pulls.createReview({ + repo: this.context.payload.repository.name, + owner: this.context.payload.repository.owner.login, + pull_number: this.context.payload.pull_request.number, + body: `Pull request has requested changes by @${this.context.payload.review.user.login}. PING! @${this.context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, + event: "COMMENT" + }); + await this.context.octokit.issues.addLabels( + this.context.issue({ + labels: ["Requested Changes"] + }) + ); + console.log("PRs Requested Changes"); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Pending" + }) + ); + } + } + } +} diff --git a/src/class/prsStale.ts b/src/class/prsStale.ts new file mode 100644 index 0000000..6713699 --- /dev/null +++ b/src/class/prsStale.ts @@ -0,0 +1,140 @@ +import { octokit } from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class PRsStale { + /** + * @constructor + */ + constructor() { + + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async checkStale(): Promise { + await octokit.rest.repos.listForUser({ + username: "Muunatic", + type: "owner" + }).then(async (res) => { + for (let i = 0; i < res.data.length; i++) { + if (res.data[i].fork === false) { + await octokit.rest.pulls.list({ + owner: res.data[i].owner.login, + repo: res.data[i].name + }).then(async (res) => { + for (let i = 0; i < res.data.length; i++) { + const currentRepo = res.data[i].base.repo.name; + const currentOwner = res.data[i].base.repo.owner.login; + const currentPRs = res.data[i].number; + if (res.data[i].state.toLowerCase() == "open" && res.data[i].draft == false) { + if (res.data[i].user?.type.toLowerCase() == "user") { + await octokit.rest.pulls.listCommits({ + owner: currentOwner, + repo: currentRepo, + pull_number: currentPRs + }).then(async (res) => { + const currentDate = new Date(); + const createdAt = new Date(res.data[res.data.length - 1].commit.author?.date as string); + const staleDate = new Date(createdAt.getTime() + 7 * 24 * 60 * 60 * 1000); + const closeDate = new Date(createdAt.getTime() + 30 * 24 * 60 * 60 * 1000); + if (currentDate > staleDate) { + if (currentDate > closeDate) { + await octokit.rest.pulls.update({ + owner: currentOwner, + repo: currentRepo, + pull_number: currentPRs, + state: "closed" + }).then(async (res) => { + if (res.data.labels.find((a) => a.name == "Stale")) { + await octokit.rest.issues.addLabels({ + owner: res.data.base.repo.owner.login, + repo: res.data.base.repo.name, + issue_number: res.data.number, + labels: ["Closed"] + }); + await octokit.rest.issues.removeLabel({ + owner: res.data.base.repo.owner.login, + repo: res.data.base.repo.name, + issue_number: res.data.number, + name: "Pending" + }); + await octokit.rest.issues.createComment({ + owner: res.data.base.repo.owner.login, + repo: res.data.base.repo.name, + issue_number: res.data.number, + body: `Hello @${res.data.user.login}! We've observed that your pull requests have remained inactive for the last 30 days. Due to this prolonged inactivity, we've had to close these PRs. If you still intend to pursue these changes, please feel free to create new PRs.` + }); + await octokit.rest.issues.lock({ + owner: currentOwner, + repo: currentRepo, + issue_number: currentPRs, + lock_reason: "resolved" + }); + } else { + return; + } + }); + } else { + await octokit.rest.pulls.get({ + owner: currentOwner, + repo: currentRepo, + pull_number: currentPRs + }).then(async (res) => { + if (res.data.labels.find((a) => a.name == "Stale")) { + return; + } else { + const prsReviewers: string[] = []; + await octokit.rest.pulls.listReviewComments({ + owner: res.data.base.repo.owner.login, + repo: res.data.base.repo.name, + pull_number: res.data.number + }).then((res) => { + if (res.data.length !== 0) { + for (let i = 0; i < res.data.length; i++) { + prsReviewers.push("@" + res.data[i].user.login); + } + } else { + prsReviewers.push("@Muunatic"); + } + }); + await octokit.rest.issues.addLabels({ + owner: res.data.base.repo.owner.login, + repo: res.data.base.repo.name, + issue_number: res.data.number, + labels: ["Stale"] + }); + await octokit.rest.issues.createComment({ + owner: res.data.base.repo.owner.login, + repo: res.data.base.repo.name, + issue_number: res.data.number, + body: `Hello @${res.data.user.login}! We noticed that your pull request has been inactive for the past 7 days. If you've already received a response from the maintainer, please ensure that you review and address the feedback provided. If not, please reach out to the maintainer to seek clarification or assistance if needed.\n\n Additionally, we'd appreciate it if ${prsReviewers.join(", ")} could also take a moment to review the pull request and provide feedback.` + }); + } + }); + } + } else { + return; + } + }); + } else { + continue; + } + } else { + continue; + } + } + }); + } else { + continue; + } + } + }); + } +} diff --git a/src/class/prsSynchronize.ts b/src/class/prsSynchronize.ts new file mode 100644 index 0000000..ecf6233 --- /dev/null +++ b/src/class/prsSynchronize.ts @@ -0,0 +1,149 @@ +import Context, { octokit } from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class PullRequestSynchronize { + + /** + * @private + * @type Context<"pull_request.synchronize"> + */ + private context: Context<"pull_request.synchronize">; + + /** + * @constructor + * @param {Context<"pull_request.synchronize">} context + */ + constructor(context: Context<"pull_request.synchronize">) { + this.context = context; + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async sync(): Promise { + await this.context.octokit.issues.listLabelsOnIssue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.pull_request.number + }).then(async (res) => { + let i: number; + const prsLabels = res.data.find(a => a.name == "Requested Changes" || a.name == "Approved")?.name; + if (prsLabels) { + await this.context.octokit.pulls.listReviews({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + pull_number: this.context.payload.pull_request.number + }).then(async (res) => { + const reviewersArray: string[] = []; + const tagReviewers: string[] = []; + for (i = 0; i < res.data.length; i++) { + if (res.data[i].user?.type == "User") { + const datastate: string[] = [ + "CHANGES_REQUESTED", + "APPROVED" + ]; + if (res.data[i].state == datastate.find(a => a == res.data[i].state)) { + if (res.data[i].user?.login != reviewersArray.find(a => a == res.data[i].user?.login)) { + const username: string = res.data[i].user?.login || ""; + reviewersArray.push(username); + tagReviewers.push("@" + username); + await this.context.octokit.pulls.dismissReview({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + pull_number: this.context.payload.pull_request.number, + review_id: res.data[i].id, + message: "This review is stale and has been dismissed." + }); + await this.context.octokit.pulls.requestReviewers({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + pull_number: this.context.payload.pull_request.number, + reviewers: [username] + }); + } else { + continue; + } + } else { + continue; + } + } else { + continue; + } + } + await this.context.octokit.issues.createComment( + this.context.issue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.pull_request.number, + body: `PING! ${tagReviewers.join(", ")}. The author has pushed new commits since your last review. please review @${this.context.payload.sender.login} new commit before merge, thanks!` + }) + ); + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: prsLabels + }) + ); + }); + } else { + return; + } + }); + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async synchronizeCore(): Promise { + let shaRef: string; + await octokit.rest.pulls.get({ + owner: "Typeslint", + repo: "github-AutoResponse", + pull_number: this.context.payload.number + }).then(async (res) => { + shaRef = res.data.head.sha; + await octokit.rest.repos.getContent({ + owner: "Typeslint", + repo: "github-AutoResponse", + ref: shaRef, + path: "tsconfig.json" + }).then(async (res) => { + if ("content" in res.data) { + const textContent:string = res.data.content; + const decodeContent:string = Buffer.from(textContent, "base64").toString("utf-8"); + if (decodeContent.includes("\"noImplicitAny\": true") && decodeContent.includes("\"noImplicitThis\": true") && decodeContent.includes("\"strictFunctionTypes\": true") && decodeContent.includes("\"strictNullChecks\": true")) { + await this.context.octokit.issues.listLabelsOnIssue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.pull_request.number + }).then(async (res) => { + if (res.data.find(a => a.name == "Config Invalid")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + name: "Config Invalid" + }) + ); + } else { + return; + } + }); + } else { + const configInvalid = this.context.issue({ + body: `[tsconfig](${res.data.html_url}) need [*noImplicitAny*, *noImplicitThis*, *strictFunctionTypes*, *strictNullChecks*] to true value` + }); + await this.context.octokit.issues.createComment(configInvalid); + } + } else { + return; + } + }); + }); + } +} diff --git a/src/class/push.ts b/src/class/push.ts new file mode 100644 index 0000000..f6336ff --- /dev/null +++ b/src/class/push.ts @@ -0,0 +1,143 @@ +import Context, { getEvent, getUserData, octokit, token } from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class Push { + + /** + * @private + * @type Context<"push"> + */ + private context: Context<"push">; + + /** + * @constructor + * @param {Context<"push">} context + */ + constructor(context: Context<"push">) { + this.context = context; + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async push(): Promise { + let event1: string, event2: string, event3: string, event4: string, event5: string; + /** + * @function + * @async + * @returns {Promise} + */ + async function userActivity(): Promise { + const arrayActivity: getUserData = { "userData": [] }; + await fetch("https://api.github.com/users/Muunatic/events/public", { + method: "GET", + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer " + token + } + }).then((res: Response) => { + return res.json(); + }).then((res: [getEvent]) => { + let i: number; + for (i = 0; i < res.length; i++) { + if (res[i].type == "PushEvent") { + if (arrayActivity.userData.length < 5) { + let commitsI: number; + for (commitsI = 0; commitsI < res[i].payload.commits.length; commitsI++) { + if (res[i].payload.commits[commitsI].author.name == "Muunatic") { + if (arrayActivity.userData.length < 5) { + arrayActivity.userData.push({ event: `Commit on [${res[i].payload.commits[commitsI].sha.slice(0, 7)}](https://github.com/${res[i].repo.name}/commit/${res[i].payload.commits[commitsI].sha}) in [${res[i].repo.name}](https://github.com/${res[i].repo.name})` }); + } else { + break; + } + } else { + continue; + } + } + } else { + break; + } + } else if (res[i].type == "PullRequestEvent") { + if (arrayActivity.userData.length < 5) { + if (res[i].payload.pull_request.user.login == "Muunatic") { + arrayActivity.userData.push({ event: `Pull Request on [\#${res[i].payload.pull_request.number.toString()}](https://github.com/${res[i].repo.name}/pull/${res[i].payload.pull_request.number}) in [${res[i].repo.name}](https://github.com/${res[i].repo.name})` }); + } else { + continue; + } + } else { + break; + } + } else { + continue; + } + } + event1 = arrayActivity.userData[0].event; + event2 = arrayActivity.userData[1].event; + event3 = arrayActivity.userData[2].event; + event4 = arrayActivity.userData[3].event; + event5 = arrayActivity.userData[4].event; + return; + }); + } + if (this.context.payload.repository.owner.login == "Muunatic") { + if (this.context.payload.sender.login == "Muunatic") { + await userActivity(); + await this.context.octokit.repos.getContent({ + owner: "Muunatic", + repo: "Muunatic", + path: "README.md", + ref: "main" + }).then(async (res) => { + if ("sha" in res.data) { + const textcontent = `# ɢɪᴛʜᴜʙ sᴛᴀᴛs

\nUpdated ${new Date().toUTCString()} \n\n1. ${event1}\n2. ${event2}\n3. ${event3}\n4. ${event4}\n5. ${event5}`; + await this.context.octokit.repos.createOrUpdateFileContents({ + content: Buffer.from(textcontent, "utf-8").toString("base64"), + path: "README.md", + message: "Update Readme.md", + owner: "Muunatic", + repo: "Muunatic", + branch: "main", + sha: res.data.sha + }); + } else { + return; + } + }); + } else if (this.context.payload.sender.login == "typeslint-cli[bot]") { + if (this.context.payload.repository.name == "Muunatic") { + await octokit.rest.checks.create({ + owner: "Muunatic", + repo: "Muunatic", + name: "typeslint/ci", + head_sha: this.context.payload.head_commit?.id, + status: "in_progress" + }).then(async (resId) => { + await octokit.rest.checks.update({ + owner: "Muunatic", + repo: "Muunatic", + name: "typeslint/ci", + check_run_id: resId.data.id, + status: "completed", + conclusion: "success", + output: { + title: "Update Activities ✔️", + summary: "@" + this.context.payload.sender.login + " README Update" + } + }); + }); + } else { + return; + } + } else { + return; + } + } + } +} diff --git a/src/class/workflowCheck.ts b/src/class/workflowCheck.ts new file mode 100644 index 0000000..16ff5e6 --- /dev/null +++ b/src/class/workflowCheck.ts @@ -0,0 +1,100 @@ +import Context from "../index"; + +/** + * @class + * @default + * @exports + */ +export default class WorkflowCheck { + + /** + * @private + * @type Context<"issues.closed"> + */ + private context: Context<"workflow_run.completed">; + + /** + * @constructor + * @param {Context<"issues.closed">} context + */ + constructor(context: Context<"workflow_run.completed">) { + this.context = context; + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async checkCI(): Promise { + if (this.context.payload.workflow_run.conclusion == "failure") { + await this.context.octokit.issues.addLabels( + this.context.issue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.workflow_run.pull_requests[0].number, + labels: ["CI Failed"] + }) + ); + await this.context.octokit.issues.createComment( + this.context.issue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.workflow_run.pull_requests[0].number, + body: `CI build failed! for more information please review the [logs](${this.context.payload.workflow_run.html_url}).` + }) + ); + } else { + return; + } + } + + /** + * @public + * @async + * @returns {Promise} + */ + public async CheckUserCI(): Promise { + if (this.context.payload.workflow_run.conclusion == "success") { + await this.context.octokit.pulls.get({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + pull_number: this.context.payload.workflow_run.pull_requests[0].number + }).then(async (res) => { + if (res.data.labels.find(a => a.name == "CI Failed")) { + await this.context.octokit.issues.removeLabel( + this.context.issue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.workflow_run.pull_requests[0].number, + name: "CI Failed" + }) + ); + console.log("CI Passed!"); + } else { + return; + } + }); + } else if (this.context.payload.workflow_run.conclusion == "failure") { + console.log("CI Failure!"); + await this.context.octokit.issues.addLabels( + this.context.issue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.workflow_run.pull_requests[0].number, + labels: ["CI Failed"] + }) + ); + await this.context.octokit.issues.createComment( + this.context.issue({ + owner: this.context.payload.repository.owner.login, + repo: this.context.payload.repository.name, + issue_number: this.context.payload.workflow_run.pull_requests[0].number, + body: `CI build failed! for more information please review the [logs](${this.context.payload.workflow_run.html_url}).` + }) + ); + } else { + return; + } + } +} diff --git a/src/index.ts b/src/index.ts index 1027306..8d6dada 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,9 @@ -import { Probot } from "probot"; +import { Context, Probot } from "probot"; import { Octokit } from "octokit"; import { createAppAuth } from "@octokit/auth-app"; import { token } from "./data/config"; -import { getUserData, getEvent } from "./structures/interface"; +import { IssuesClose, IssuesComment, IssuesOpen, PRsStale, PullRequestOpen, PullRequestReview, PullRequestSynchronize, Push, WorkflowCheck } from "./structures/constant"; +import { getEvent, getUserData } from "./structures/type"; import "./structures/listener"; import dotenv from "dotenv"; dotenv.config(); @@ -14,1226 +15,99 @@ const octokit = new Octokit({ privateKey: process.env.PRIVATE_KEY, clientId: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, - installationId: 12345678 // env not working + installationId: 21573969 } }); module.exports = (app: Probot) => { + app.on("push", async (context): Promise => { + await new Push(context).push(); + }); - app.on("push", async (context) => { - let event1: string, event2: string, event3: string, event4: string, event5: string; - async function userActivity() { - const arrayActivity: getUserData = {"userData": []}; - await fetch("https://api.github.com/users/Muunatic/events/public", { - method: "GET", - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - "Authorization": "Bearer " + token - } - }).then((res: Response) => { - return res.json(); - }).then((res: [getEvent]) => { - let i: number; - for (i = 0; i < res.length; i++) { - if (res[i].type == "PushEvent") { - if (arrayActivity.userData.length < 5) { - let commitsI: number; - for (commitsI = 0; commitsI < res[i].payload.commits.length; commitsI++) { - if (res[i].payload.commits[commitsI].author.name == "Muunatic") { - if (arrayActivity.userData.length < 5) { - arrayActivity.userData.push({event: `Commit on [${res[i].payload.commits[commitsI].sha.slice(0, 7)}](https://github.com/${res[i].repo.name}/commit/${res[i].payload.commits[commitsI].sha}) in [${res[i].repo.name}](https://github.com/${res[i].repo.name})`}); - } else { - break; - } - } else { - continue; - } - } - } else { - break; - } - } else if (res[i].type == "PullRequestEvent") { - if (arrayActivity.userData.length < 5) { - if (res[i].payload.pull_request.user.login == "Muunatic") { - arrayActivity.userData.push({event: `Pull Request on [\#${res[i].payload.pull_request.number.toString()}](https://github.com/${res[i].repo.name}/pull/${res[i].payload.pull_request.number}) in [${res[i].repo.name}](https://github.com/${res[i].repo.name})`}); - } else { - continue; - } - } else { - break; - } - } else { - continue; - } - } - event1 = arrayActivity.userData[0].event; - event2 = arrayActivity.userData[1].event; - event3 = arrayActivity.userData[2].event; - event4 = arrayActivity.userData[3].event; - event5 = arrayActivity.userData[4].event; - return; - }); - } - if (context.payload.repository.owner.login == "Muunatic") { - if (context.payload.sender.login == "Muunatic") { - await userActivity(); - await context.octokit.repos.getContent({ - owner: "Muunatic", - repo: "Muunatic", - path: "README.md", - ref: "main" - }).then(async (res) => { - if ("sha" in res.data) { - const textcontent = `# ɢɪᴛʜᴜʙ sᴛᴀᴛs

\nUpdated ${new Date().toUTCString()} \n\n1. ${event1}\n2. ${event2}\n3. ${event3}\n4. ${event4}\n5. ${event5}`; - await context.octokit.repos.createOrUpdateFileContents({ - content: Buffer.from(textcontent, "utf-8").toString("base64"), - path: "README.md", - message: "Update Readme.md", - owner: "Muunatic", - repo: "Muunatic", - branch: "main", - sha: res.data.sha - }); - } else { - return; - } - }); - } else if (context.payload.sender.login == "typeslint-cli[bot]") { - if (context.payload.repository.name == "Muunatic") { - await octokit.rest.checks.create({ - owner: "Muunatic", - repo: "Muunatic", - name: "typeslint/ci", - head_sha: context.payload.head_commit?.id, - status: "in_progress" - }).then(async (resId) => { - await octokit.rest.checks.update({ - owner: "Muunatic", - repo: "Muunatic", - name: "typeslint/ci", - check_run_id: resId.data.id, - status: "completed", - conclusion: "success", - output: { - title: "Update Activities ✔️", - summary: "@" + context.payload.sender.login + " README Update" - } - }); - }); - } else { - return; - } - } else { - return; - } - } + app.on("issues.opened", async (context): Promise => { + await new IssuesOpen(context).open(); }); - // Issues opened - app.on("issues.opened", async (context) => { - if (context.payload.sender.login === "Muunatic") return; - const username = context.payload.sender.login; - const issueComment = context.issue({ - body: `Hello @${username} Thank you for submitting Issue, please wait for next notification after we review your Issue.` - }); - console.log("Issues created"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Pending"] - }) - ); - await context.octokit.issues.createComment(issueComment); + app.on("issue_comment.created", async (context): Promise => { + if (context.payload.comment.user.type == "User") { + switch (context.payload.issue.user.type) { + case "User": + await new IssuesComment(context).userPRsComment(); + break; + case "Bot": + await new IssuesComment(context).botPRsComment(); + break; + default: + break; + } + } }); - // Issues closed - app.on("issues.closed", async (context) => { - const username = context.payload.sender.login; + app.on("issues.closed", async (context): Promise => { if (context.payload.issue.state_reason == "not_planned") { - const issueClosed = context.issue({ - body: `Issue closed as invalid by @${username}.` - }); - console.log("Issues closed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Closed", "Invalid"] - }) - ); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - await context.octokit.issues.createComment(issueClosed); + await new IssuesClose(context).invalid(); } else { - const issueClosed = context.issue({ - body: `Issue closed by @${username}.` - }); - console.log("Issues closed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Closed"] - }) - ); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - await context.octokit.issues.createComment(issueClosed); + await new IssuesClose(context).closed(); } }); - // Pull request openened - app.on("pull_request.opened", async (context) => { + app.on("pull_request.opened", async (context): Promise => { if (context.payload.sender.type == "User") { - if (context.payload.sender.login != context.payload.repository.owner.login) { - if (context.payload.repository.html_url == "https://github.com/Typeslint/github-AutoResponse") { - await context.octokit.pulls.listFiles({ - owner: "Typeslint", - repo: "github-AutoResponse", - pull_number: context.payload.number - }).then((res) => { - return res.data; - }).then(async (data) => { - if (data.find(a => a.filename == "src/index.ts")) { - const username = context.payload.sender.login; - const propened = context.issue({ - body: `Hello @${username} Thank you for submitting Pull Request, please wait for next notification after we review your Pull Request` - }); - console.log("Pull request opened"); - await context.octokit.issues.createComment(propened); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Pending", "Core"] - }) - ); - let shaRef: string; - await octokit.rest.pulls.get({ - owner: "Typeslint", - repo: "github-AutoResponse", - pull_number: context.payload.number - }).then(async (res) => { - shaRef = res.data.head.sha; - await octokit.rest.repos.getContent({ - owner: "Typeslint", - repo: "github-AutoResponse", - ref: shaRef, - path: "tsconfig.json" - }).then(async (res) => { - if ("content" in res.data) { - const textContent:string = res.data.content; - const decodeContent:string = Buffer.from(textContent, "base64").toString("utf-8"); - if (decodeContent.includes("\"noImplicitAny\": true") && decodeContent.includes("\"noImplicitThis\": true") && decodeContent.includes("\"strictFunctionTypes\": true") && decodeContent.includes("\"strictNullChecks\": true")) { - return; - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Config Invalid"] - }) - ); - const configInvalid = context.issue({ - body: `[tsconfig](${res.data.html_url}) need [*noImplicitAny*, *noImplicitThis*, *strictFunctionTypes*, *strictNullChecks*] to true value` - }); - await context.octokit.issues.createComment(configInvalid); - } - } else { - return; - } - }); - }); - } else { - const username = context.payload.sender.login; - const propened = context.issue({ - body: `Hello @${username} Thank you for submitting Pull Request, please wait for next notification after we review your Pull Request` - }); - console.log("Pull request opened"); - await context.octokit.issues.createComment(propened); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Pending"] - }) - ); - } - }); - } else { - const username = context.payload.sender.login; - const propened = context.issue({ - body: `Hello @${username} Thank you for submitting Pull Request, please wait for next notification after we review your Pull Request` - }); - console.log("Pull request opened"); - await context.octokit.issues.createComment(propened); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Pending"] - }) - ); - } + if (context.payload.repository.html_url == "https://github.com/Typeslint/github-AutoResponse") { + await new PullRequestOpen(context).openCore(); } else { - const propened = context.issue({ - body: `PRs by \`[OWNER]\`${context.payload.pull_request.user.login}!` - }); - console.log("Pull request opened"); - await context.octokit.issues.createComment(propened); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Pending"] - }) - ); + await new PullRequestOpen(context).open(); } } else { return; } }); - // Pull request comment - app.on("pull_request_review.submitted", async (context) => { + app.on("pull_request_review.submitted", async (context): Promise => { if (context.payload.sender.type == "User") { switch (context.payload.pull_request.user.type) { case "User": - if (context.payload.sender.login == context.payload.repository.owner.login) { - // Owner - if (context.payload.review.state == "approved") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} your pull request has been approved by @${context.payload.review.user.login}, please type \`Ready to merge\` for merging`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } else if (context.payload.review.state == "changes_requested") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `Pull request has requested changes by @${context.payload.review.user.login}. PING! @${context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Approved")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Approved" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } - } else if (context.payload.pull_request.author_association == "MEMBER" || context.payload.pull_request.author_association == "COLLABORATOR") { - if (context.payload.review.state == "approved") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} your pull request has been approved by \`[MAINTAINER]\`@${context.payload.review.user.login}, please type \`Ready to merge\` for merging`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } else if (context.payload.review.state == "changes_requested") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `Pull request has requested changes by @${context.payload.review.user.login}. PING! @${context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Approved")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Approved" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } - } else { - // Others Approved - if (context.payload.review.state == "approved") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} your pull request has been approved by @${context.payload.review.user.login}, even though please wait for the \`MAINTAINERS\`/\`CODEOWNERS\` to review`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Others Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Others Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } else if (context.payload.review.state == "changes_requested") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `Pull request has requested changes by @${context.payload.review.user.login}. PING! @${context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, - event: "COMMENT" - }); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } + await new PullRequestReview(context).userPRs(); break; case "Bot": - if (context.payload.sender.login == context.payload.repository.owner.login) { - // Owner - if (context.payload.review.state == "approved") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} Pull request has been approved by \`[OWNER]\`@${context.payload.review.user.login}, please type \`Merge\` for merging @${context.payload.review.user.login}`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } else if (context.payload.review.state == "changes_requested") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} your pull request has requested changes by \`[OWNER]\`@${context.payload.review.user.login}. Please address their comments before I'm merging this PR, thanks!`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Approved")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Approved" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } - } else if (context.payload.pull_request.author_association == "MEMBER" || context.payload.pull_request.author_association == "COLLABORATOR") { - if (context.payload.review.state == "approved") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} Pull request has been approved by \`[MAINTAINER]\`@${context.payload.review.user.login}, please type \`Merge\` for merging @${context.payload.review.user.login}`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } else if (context.payload.review.state == "changes_requested") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `Pull request has requested changes by \`[MAINTAINER]\`@${context.payload.review.user.login}. PING! @${context.payload.pull_request.user.login} Please address their comments before I"m merging this PR, thanks!`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Approved")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Approved" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } - } else { - // Others Approved - if (context.payload.review.state == "approved") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `@${context.payload.pull_request.user.login} your pull request has been approved by @${context.payload.review.user.login}, even though please wait for the \`MAINTAINERS\`/\`CODEOWNERS\` to review`, - event: "COMMENT" - }); - if (context.payload.pull_request.labels.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - console.log("Label removed"); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Others Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } else { - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Others Approved"] - }) - ); - console.log("PRs Approved"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } else if (context.payload.review.state == "changes_requested") { - await context.octokit.pulls.createReview({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.pull_request.number, - body: `Pull request has requested changes by @${context.payload.review.user.login}. PING! @${context.payload.pull_request.user.login} Please address their comments before I'm merging this PR, thanks!`, - event: "COMMENT" - }); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Requested Changes"] - }) - ); - console.log("PRs Requested Changes"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - } - } + await new PullRequestReview(context).botPRs(); break; default: - return; + break; } - } else { - return; } }); - // re-requested reviewer - app.on("pull_request.synchronize", async (context) => { + app.on("pull_request.synchronize", async (context): Promise => { if (context.payload.pull_request.user.type == "User") { if (context.payload.repository.homepage == "https://github.com/Typeslint/github-AutoResponse") { - let shaRef: string; - await octokit.rest.pulls.get({ - owner: "Typeslint", - repo: "github-AutoResponse", - pull_number: context.payload.number - }).then(async (res) => { - shaRef = res.data.head.sha; - await octokit.rest.repos.getContent({ - owner: "Typeslint", - repo: "github-AutoResponse", - ref: shaRef, - path: "tsconfig.json" - }).then(async (res) => { - if ("content" in res.data) { - const textContent:string = res.data.content; - const decodeContent:string = Buffer.from(textContent, "base64").toString("utf-8"); - if (decodeContent.includes("\"noImplicitAny\": true") && decodeContent.includes("\"noImplicitThis\": true") && decodeContent.includes("\"strictFunctionTypes\": true") && decodeContent.includes("\"strictNullChecks\": true")) { - await context.octokit.issues.listLabelsOnIssue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.pull_request.number - }).then(async (res) => { - if (res.data.find(a => a.name == "Config Invalid")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Config Invalid" - }) - ); - } else { - return; - } - }); - } else { - const configInvalid = context.issue({ - body: `[tsconfig](${res.data.html_url}) need [*noImplicitAny*, *noImplicitThis*, *strictFunctionTypes*, *strictNullChecks*] to true value` - }); - await context.octokit.issues.createComment(configInvalid); - } - } else { - return; - } - }); - }); + await new PullRequestSynchronize(context).synchronizeCore(); } - await context.octokit.issues.listLabelsOnIssue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.pull_request.number - }).then(async (res) => { - let i: number; - if (res.data.find(a => a.name == "Requested Changes")) { - await context.octokit.pulls.listReviews({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - pull_number: context.payload.pull_request.number - }).then(async (res) => { - const reviewersArray: string[] = []; - const tagReviewers: string[] = []; - for (i = 0; i < res.data.length; i++) { - if (res.data[i].user?.type == "User") { - const datastate: string[] = [ - "CHANGES_REQUESTED", - "APPROVED" - ]; - if (res.data[i].state == datastate.find(a => a == res.data[i].state)) { - if (res.data[i].user?.login != reviewersArray.find(a => a == res.data[i].user?.login)) { - const username: string = res.data[i].user?.login || ""; - reviewersArray.push(username); - tagReviewers.push("@" + username); - await context.octokit.pulls.requestReviewers({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - pull_number: context.payload.pull_request.number, - reviewers: [username] - }); - } else { - continue; - } - } else { - continue; - } - } else { - continue; - } - } - await context.octokit.issues.createComment( - context.issue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.pull_request.number, - body: `PING! ${tagReviewers.join(", ")}. The author has pushed new commits since your last review. please review @${context.payload.sender.login} new commit before merge, thanks!` - }) - ); - await context.octokit.issues.listLabelsOnIssue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.pull_request.number - }).then(async (res) => { - if (res.data.find(a => a.name == "Requested Changes")) { - await context.octokit.issues.removeLabel( - context.issue({ - name: "Requested Changes" - }) - ); - } else { - return; - } - }); - }); - } else if (res.data.find(a => a.name == "Approved")) { - return; - } - }); + await new PullRequestSynchronize(context).sync(); } else { return; } }); - // Check CI - app.on("workflow_run.completed", async (context) => { + app.on("workflow_run.completed", async (context): Promise => { if (context.payload.workflow_run.event == "pull_request") { if (context.payload.sender.type == "User") { - if (context.payload.workflow_run.conclusion == "success") { - await context.octokit.pulls.get({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - pull_number: context.payload.workflow_run.pull_requests[0].number - }).then(async (res) => { - if (res.data.labels.find(a => a.name == "CI Failed")) { - await context.octokit.issues.removeLabel( - context.issue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.workflow_run.pull_requests[0].number, - name: "CI Failed" - }) - ); - console.log("CI Passed!"); - } else { - return; - } - }); - } else if (context.payload.workflow_run.conclusion == "failure") { - console.log("CI Failure!"); - await context.octokit.issues.addLabels( - context.issue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.workflow_run.pull_requests[0].number, - labels: ["CI Failed"] - }) - ); - await context.octokit.issues.createComment( - context.issue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.workflow_run.pull_requests[0].number, - body: `CI build failed! for more information please review the [logs](${context.payload.workflow_run.html_url}).` - }) - ); - } else { - return; - } + await new WorkflowCheck(context).CheckUserCI(); } else { - if (context.payload.workflow_run.conclusion == "failure") { - await context.octokit.issues.addLabels( - context.issue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.workflow_run.pull_requests[0].number, - labels: ["CI Failed"] - }) - ); - await context.octokit.issues.createComment( - context.issue({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: context.payload.workflow_run.pull_requests[0].number, - body: `CI build failed! for more information please review the [logs](${context.payload.workflow_run.html_url}).` - }) - ); - } else { - return; - } + await new WorkflowCheck(context).checkCI(); } } else { return; } }); +}; - // Comment created - app.on("issue_comment.created", async (context) => { - if (context.payload.comment.user.type == "User") { - switch (context.payload.issue.user.type) { - case "User": - // Merge pull request - if (context.payload.comment.body.toLowerCase() == "ready to merge") { - await context.octokit.pulls.get({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.issue.number - }).then(async (res) => { - if (res.data.mergeable_state.toLowerCase() == "clean" || res.data.mergeable == true) { - if (context.payload.issue.user.login == context.payload.comment.user.login) { - let i: number; - for (i = 0; i < context.payload.issue.labels.length; i++) { - if (context.payload.issue.labels[i].name == "Approved") { - console.log("Merging"); - await context.octokit.pulls.merge({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.issue.number, - commit_title: `Merge PR #${context.payload.issue.number} ${context.payload.issue.title}`, - commit_message: context.payload.issue.title - }); - console.log("Merged!"); - await context.octokit.issues.createComment( - context.issue({ - body: `Merged by ${context.payload.comment.user.login}!` - }) - ); - break; - } else if (context.payload.issue.labels[i].name == "Requested Changes") { - console.log("PRs Blocked"); - await context.octokit.issues.createComment( - context.issue({ - body: `Merging blocked because PRs has requested changes! @${context.payload.comment.user.login}` - }) - ); - break; - } else { - continue; - } - } - } else { - return; - } - } else if (res.data.mergeable_state.toLowerCase() == "dirty" || res.data.mergeable == false) { - await context.octokit.issues.createComment( - context.issue({ - body: `Merging blocked because PRs has merge conflict! @${context.payload.comment.user.login}` - }) - ); - } else if (res.data.mergeable == null) { - await context.octokit.issues.createComment( - context.issue({ - body: "We apologize for the inconvenience, but it seems that Automaton processes are currently unable to proceed with merging your commit. Please wait for a moment and try merging it again." - }) - ); - } - }); - } - - if (context.payload.comment.body.toLowerCase() == "merge") { - if (context.payload.sender.login == context.payload.repository.owner.login) { - await context.octokit.pulls.merge({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.issue.number, - commit_title: `Merge PR #${context.payload.issue.number} ${context.payload.issue.title}`, - commit_message: context.payload.issue.title - }); - console.log("Merged!"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - await context.octokit.issues.createComment( - context.issue({ - body: `Merged by \`[OWNER]\`${context.payload.comment.user.login}!` - }) - ); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Owner Merge"] - }) - ); - } else if (context.payload.issue.author_association === "MEMBER" || context.payload.issue.author_association === "COLLABORATOR") { - await context.octokit.pulls.merge({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.issue.number, - commit_title: `Merge PR #${context.payload.issue.number} ${context.payload.issue.title}`, - commit_message: context.payload.issue.title - }); - console.log("Merged!"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - await context.octokit.issues.createComment( - context.issue({ - body: `Merged by \`[MAINTAINER]\`${context.payload.comment.user.login}!` - }) - ); - } else { - return; - } - } - break; - case "Bot": - // Merge pull request - if (context.payload.comment.body.toLowerCase() == "merge") { - if (context.payload.sender.login == context.payload.repository.owner.login) { - await context.octokit.pulls.merge({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.issue.number, - commit_title: `Merge PR #${context.payload.issue.number} ${context.payload.issue.title}`, - commit_message: context.payload.issue.title - }); - console.log("Merged!"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - await context.octokit.issues.createComment( - context.issue({ - body: `Merged by \`[OWNER]\`${context.payload.comment.user.login}!` - }) - ); - await context.octokit.issues.addLabels( - context.issue({ - labels: ["Owner Merge"] - }) - ); - } else if (context.payload.issue.author_association === "MEMBER" || context.payload.issue.author_association === "COLLABORATOR") { - await context.octokit.pulls.merge({ - repo: context.payload.repository.name, - owner: context.payload.repository.owner.login, - pull_number: context.payload.issue.number, - commit_title: `Merge PR #${context.payload.issue.number} ${context.payload.issue.title}`, - commit_message: context.payload.issue.title - }); - console.log("Merged!"); - await context.octokit.issues.removeLabel( - context.issue({ - name: "Pending" - }) - ); - await context.octokit.issues.createComment( - context.issue({ - body: `Merged by \`[MAINTAINER]\`${context.payload.comment.user.login}!` - }) - ); - } else { - return; - } - } - break; - default: - break; - } - } else { - return; - } +setInterval(() => { + (async () => { + await new PRsStale().checkStale(); }); +}, 3600000); - // Stale PRs - setInterval(() => { - (async () => { - await octokit.rest.repos.listForUser({ - username: "Muunatic", - type: "owner" - }).then(async (res) => { - for (let i = 0; i < res.data.length; i++) { - if (res.data[i].fork === false) { - await octokit.rest.pulls.list({ - owner: res.data[i].owner.login, - repo: res.data[i].name - }).then(async (res) => { - for (let i = 0; i < res.data.length; i++) { - const currentRepo = res.data[i].base.repo.name; - const currentOwner = res.data[i].base.repo.owner.login; - const currentPRs = res.data[i].number; - if (res.data[i].state.toLowerCase() == "open" && res.data[i].draft == false) { - if (res.data[i].user?.type.toLowerCase() == "user") { - await octokit.rest.pulls.listCommits({ - owner: currentOwner, - repo: currentRepo, - pull_number: currentPRs - }).then(async (res) => { - const currentDate = new Date(); - const createdAt = new Date(res.data[res.data.length - 1].commit.author?.date as string); - const staleDate = new Date(createdAt.getTime() + 7 * 24 * 60 * 60 * 1000); - const closeDate = new Date(createdAt.getTime() + 30 * 24 * 60 * 60 * 1000); - if (currentDate > staleDate) { - if (currentDate > closeDate) { - await octokit.rest.pulls.update({ - owner: currentOwner, - repo: currentRepo, - pull_number: currentPRs, - state: "closed" - }).then(async (res) => { - if (res.data.labels.find((a) => a.name == "Stale")) { - await octokit.rest.issues.addLabels({ - owner: res.data.base.repo.owner.login, - repo: res.data.base.repo.name, - issue_number: res.data.number, - labels: ["Closed"] - }); - await octokit.rest.issues.removeLabel({ - owner: res.data.base.repo.owner.login, - repo: res.data.base.repo.name, - issue_number: res.data.number, - name: "Pending" - }); - await octokit.rest.issues.createComment({ - owner: res.data.base.repo.owner.login, - repo: res.data.base.repo.name, - issue_number: res.data.number, - body: `Hello @${res.data.user?.login}! We've observed that your pull requests have remained inactive for the last 30 days. Due to this prolonged inactivity, we've had to close these PRs. If you still intend to pursue these changes, please feel free to create new PRs.` - }); - await octokit.rest.issues.lock({ - owner: currentOwner, - repo: currentRepo, - issue_number: currentPRs, - lock_reason: "resolved" - }); - } else { - return; - } - }); - } else { - await octokit.rest.pulls.get({ - owner: currentOwner, - repo: currentRepo, - pull_number: currentPRs - }).then(async (res) => { - if (res.data.labels.find((a) => a.name == "Stale")) { - return; - } else { - const prsReviewers: string[] = []; - await octokit.rest.pulls.listReviewComments({ - owner: res.data.base.repo.owner.login, - repo: res.data.base.repo.name, - pull_number: res.data.number - }).then((res) => { - if (res.data.length !== 0) { - for (let i = 0; i < res.data.length; i++) { - prsReviewers.push("@" + res.data[i].user?.login); - } - } else { - prsReviewers.push("@Muunatic"); - } - }); - await octokit.rest.issues.addLabels({ - owner: res.data.base.repo.owner.login, - repo: res.data.base.repo.name, - issue_number: res.data.number, - labels: ["Stale"] - }); - await octokit.rest.issues.createComment({ - owner: res.data.base.repo.owner.login, - repo: res.data.base.repo.name, - issue_number: res.data.number, - body: `Hello @${res.data.user?.login}! We noticed that your pull request has been inactive for the past 7 days. If you've already received a response from the maintainer, please ensure that you review and address the feedback provided. If not, please reach out to the maintainer to seek clarification or assistance if needed.\n\n Additionally, we'd appreciate it if ${prsReviewers.join(", ")} could also take a moment to review the pull request and provide feedback.` - }); - } - }); - } - } else { - return; - } - }); - } else { - continue; - } - } else { - continue; - } - } - }); - } else { - continue; - } - } - }); - }); - }, 3600000); - -}; +export default Context; +export { octokit, token }; +export type { getEvent, getUserData }; diff --git a/src/structures/constant.ts b/src/structures/constant.ts new file mode 100644 index 0000000..54a2b8a --- /dev/null +++ b/src/structures/constant.ts @@ -0,0 +1,21 @@ +import IssuesClose from "../class/issuesClose"; +import IssuesComment from "../class/issuesComment"; +import IssuesOpen from "../class/issuesOpen"; +import PullRequestOpen from "../class/prsOpen"; +import PullRequestReview from "../class/prsReview"; +import PullRequestSynchronize from "../class/prsSynchronize"; +import Push from "../class/push"; +import WorkflowCheck from "../class/workflowCheck"; +import PRsStale from "../class/prsStale"; + +export { + IssuesClose, + IssuesComment, + IssuesOpen, + PullRequestOpen, + PullRequestReview, + PullRequestSynchronize, + Push, + WorkflowCheck, + PRsStale +}; diff --git a/src/structures/interface.ts b/src/structures/type.ts similarity index 92% rename from src/structures/interface.ts rename to src/structures/type.ts index f0e42a5..457634c 100644 --- a/src/structures/interface.ts +++ b/src/structures/type.ts @@ -1,12 +1,13 @@ -export interface getUserData { +export type getUserData = { userData: userDataInterface[]; } -interface userDataInterface { +type userDataInterface = { event: string; } -export interface getEvent { + +export type getEvent = { id: string; type: string;