Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #273 from seprintour/link-pr-to-issue
Browse files Browse the repository at this point in the history
Assign PR owner to linked issue
  • Loading branch information
0x4007 authored Apr 30, 2023
2 parents 1fdbc9c + dfae2ab commit 2399857
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 13 deletions.
26 changes: 13 additions & 13 deletions app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ default_events:
# - gollum
- issue_comment
- issues
# - label
# - milestone
# - member
# - membership
# - org_block
# - organization
# - page_build
# - project
# - project_card
# - project_column
# - public
# - pull_request
# - label
# - milestone
# - member
# - membership
# - org_block
# - organization
# - page_build
# - project
# - project_card
# - project_column
# - public
- pull_request
# - pull_request_review
# - pull_request_review_comment
# - push
Expand Down Expand Up @@ -82,7 +82,7 @@ default_permissions:

# Pull requests and related comments, assignees, labels, milestones, and merges.
# https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
# pull_requests: read
pull_requests: read

# Manage the post-receive hooks for a repository.
# https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
Expand Down
51 changes: 51 additions & 0 deletions src/handlers/assign/auto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { getBotContext, getLogger } from "../../bindings";
import { addAssignees, getIssueByNumber, getPullRequests } from "../../helpers";
import { gitLinkedIssueParser } from "../../helpers/parser";
import { Payload } from "../../types";

// Check for pull requests linked to their respective issues but not assigned to them
export const checkPullRequests = async () => {
const context = getBotContext();
const logger = getLogger();
const pulls = await getPullRequests(context);

if (pulls.length === 0) {
logger.debug(`No pull requests found at this time`);
return;
}

const payload = context.payload as Payload;

// Loop through the pull requests and assign them to their respective issues if needed
for (const pull of pulls) {
let pullRequestLinked = await gitLinkedIssueParser({
owner: payload.repository.owner.login,
repo: payload.repository.name,
issue_number: pull.number,
});

// if pullRequestLinked is empty, continue
if (pullRequestLinked == "") {
continue;
}

const linkedIssueNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1);

// Check if the pull request opener is assigned to the issue
const opener = pull!.user!.login;

let issue = await getIssueByNumber(context, +linkedIssueNumber);

// if issue is already assigned, continue
if (issue!.assignees!.length > 0) {
logger.debug(`Issue already assigned, ignoring...`);
continue;
}

const assignedUsernames = issue!.assignees!.map((assignee) => assignee.login);
if (!assignedUsernames.includes(opener)) {
await addAssignees(+linkedIssueNumber, [opener]);
logger.debug(`Assigned pull request #${pull.number} opener to issue ${linkedIssueNumber}.`);
}
}
};
6 changes: 6 additions & 0 deletions src/handlers/processors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { checkBountiesToUnassign, collectAnalytics, checkWeeklyUpdate } from "./
import { nullHandler } from "./shared";
import { handleComment } from "./comment";
import { handleIssueClosed } from "./payout";
import { checkPullRequests } from "./assign/auto";

export const processors: Record<string, Handler> = {
[GithubEvent.ISSUES_LABELED]: {
Expand Down Expand Up @@ -37,6 +38,11 @@ export const processors: Record<string, Handler> = {
action: [handleIssueClosed],
post: [nullHandler],
},
[GithubEvent.PULL_REQUEST_OPENED]: {
pre: [nullHandler],
action: [checkPullRequests],
post: [nullHandler],
},
};

/**
Expand Down
35 changes: 35 additions & 0 deletions src/helpers/issue.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Context } from "probot";
import { getBotContext, getLogger } from "../bindings";
import { Comment, Payload } from "../types";
import { checkRateLimitGit } from "../utils";
Expand Down Expand Up @@ -187,3 +188,37 @@ export const deleteLabel = async (label: string): Promise<void> => {
logger.debug(`Label deletion failed!, reason: ${e}`);
}
};

// Use `context.octokit.rest` to get the pull requests for the repository
export const getPullRequests = async (context: Context, state: "open" | "closed" | "all" = "open") => {
const logger = getLogger();
const payload = context.payload as Payload;
try {
const { data: pulls } = await context.octokit.rest.pulls.list({
owner: payload.repository.owner.login,
repo: payload.repository.name,
state,
});
return pulls;
} catch (e: unknown) {
logger.debug(`Fetching pull requests failed!, reason: ${e}`);
return [];
}
};

// Get issues by issue number
export const getIssueByNumber = async (context: Context, issue_number: number) => {
const logger = getLogger();
const payload = context.payload as Payload;
try {
const { data: issue } = await context.octokit.rest.issues.get({
owner: payload.repository.owner.login,
repo: payload.repository.name,
issue_number,
});
return issue;
} catch (e: unknown) {
logger.debug(`Fetching issue failed!, reason: ${e}`);
return;
}
};
18 changes: 18 additions & 0 deletions src/helpers/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,21 @@ export const gitIssueParser = async ({ owner, repo, issue_number }: GitParser):
return true;
}
};

export const gitLinkedIssueParser = async ({ owner, repo, issue_number }: GitParser): Promise<string> => {
try {
const { data } = await axios.get(`https://github.com/${owner}/${repo}/pull/${issue_number}`);
const dom = parse(data);
const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement;
const linkedPRs = devForm.querySelectorAll(".my-1");

if (linkedPRs.length === 0) {
return "";
}

const prUrl = linkedPRs[0].querySelector("a")?.attrs?.href || "";
return prUrl;
} catch (error) {
return "";
}
};
3 changes: 3 additions & 0 deletions src/types/payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export enum GithubEvent {
// issue_comment
ISSUE_COMMENT_CREATED = "issue_comment.created",
ISSUE_COMMENT_EDITED = "issue_comment.edited",

// pull_request
PULL_REQUEST_OPENED = "pull_request.opened",
}

export enum UserType {
Expand Down

0 comments on commit 2399857

Please sign in to comment.