Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: multiple prs handling #132

Merged
4 changes: 2 additions & 2 deletions src/data-collection/collect-linked-pulls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type IssueWithClosedByPRs = {
};
};

export async function collectLinkedMergedPull(issue: IssueParams) {
export async function collectLinkedMergedPulls(issue: IssueParams) {
const octokit = getOctokitInstance();
const { owner, repo, issue_number } = issue;

Expand All @@ -30,5 +30,5 @@ export async function collectLinkedMergedPull(issue: IssueParams) {
issue_number,
});

return result.repository.issue.closedByPullRequestsReferences.edges.map((edge) => edge.node).slice(-1);
return result.repository.issue.closedByPullRequestsReferences.edges.map((edge) => edge.node);
}
4 changes: 2 additions & 2 deletions src/issue-activity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CommentAssociation, CommentKind } from "./configuration/comment-types";
import configuration from "./configuration/config-reader";
import { DataCollectionConfiguration } from "./configuration/data-collection-config";
import { collectLinkedMergedPull } from "./data-collection/collect-linked-pulls";
import { collectLinkedMergedPulls } from "./data-collection/collect-linked-pulls";
import {
GitHubIssue,
GitHubIssueComment,
Expand Down Expand Up @@ -47,7 +47,7 @@ export class IssueActivity {

private async _getLinkedReviews(): Promise<Review[]> {
logger.debug("Trying to fetch linked pull-requests for", this._issueParams);
const pulls = await collectLinkedMergedPull(this._issueParams);
const pulls = (await collectLinkedMergedPulls(this._issueParams)).slice(-1);
logger.debug("Collected linked pull-requests", { pulls });
const promises = pulls
.map(async (pull) => {
Expand Down
28 changes: 28 additions & 0 deletions src/run.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import configuration from "./configuration/config-reader";
import { collectLinkedMergedPulls } from "./data-collection/collect-linked-pulls";
import githubCommentModuleInstance from "./helpers/github-comment-module-instance";
import { getSortedPrices } from "./helpers/label-price-extractor";
import logger from "./helpers/logger";
import { IssueActivity } from "./issue-activity";
import { getOctokitInstance } from "./octokit";
import program from "./parser/command-line";
import { Processor } from "./parser/processor";
import { parseGitHubUrl } from "./start";
Expand All @@ -13,6 +15,11 @@ export async function run() {
if (eventPayload.issue.state_reason !== "completed") {
return logger.info("Issue was not closed as completed. Skipping.").logMessage.raw;
}
if (!(await preCheck())) {
const result = logger.error("All linked pull requests must be closed to generate rewards.");
await githubCommentModuleInstance.postComment(result.logMessage.diff);
return result.logMessage.raw;
Comment on lines +19 to +21
Copy link
Member

@0x4007 0x4007 Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought our logger abstracts all this away. Why not just add a param postComment: boolean in the logger methods? I'm pretty sure I implemented that the first go around. It was the third parameter I believe.

(message: string, metadata: Record<key, value>, postComment: boolean)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we wanted to separate Supabase from the logger for a few reasons:

  • it would require every project to link to Octokit
  • that would force every project to include Octokit which differs in use between Actions and Workers
  • some do no need to log them (mostly actions) as the logs are saved within the Action run (and now within worker with the new Logs)

My suggestion was to have optional packages that you can add on init, like Octokit does if you want to use pagination for example, where we could link a package that would post comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can file a spec before it's forgotten about

Copy link
Member Author

@gentlementlegen gentlementlegen Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a task carried out about this I remember, let me find it.
ubiquity-os/ubiquity-os-logger#35

}
const issue = parseGitHubUrl(eventPayload.issue.html_url);
const activity = new IssueActivity(issue);
await activity.init();
Expand All @@ -28,3 +35,24 @@ export async function run() {
return logger.error(`${eventName} is not supported, skipping.`).logMessage.raw;
}
}

async function preCheck() {
const { eventPayload } = program;

const issue = parseGitHubUrl(eventPayload.issue.html_url);
const linkedPulls = await collectLinkedMergedPulls(issue);
logger.debug("Checking open linked pull-requests for", {
issue,
linkedPulls,
});
if (linkedPulls.some((linkedPull) => linkedPull.state === "OPEN")) {
await getOctokitInstance().rest.issues.update({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.issue_number,
state: "open",
});
return false;
}
return true;
}
1 change: 1 addition & 0 deletions src/types/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const LINKED_PULL_REQUESTS = /* GraphQL */ `
title
number
url
state
author {
login
... on User {
Expand Down
132 changes: 132 additions & 0 deletions tests/pre-check.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { drop } from "@mswjs/data";
import { http, HttpResponse } from "msw";
import "../src/parser/command-line";
import { db } from "./__mocks__/db";
import dbSeed from "./__mocks__/db-seed.json";
import { server } from "./__mocks__/node";

const issueUrl = "https://github.com/ubiquity/work.ubq.fi/issues/69";

jest.mock("@actions/github", () => ({
context: {
runId: "1",
payload: {
repository: {
html_url: "https://github.com/ubiquibot/conversation-rewards",
},
},
},
}));

jest.mock("@octokit/plugin-paginate-graphql", () => ({
paginateGraphQL() {
return {
graphql: {
paginate() {
return {
repository: {
issue: {
closedByPullRequestsReferences: {
edges: [
{
node: {
id: "PR_kwDOKzVPS85zXUoj",
title: "fix: add state to sorting manager for bottom and top",
number: 70,
url: "https://github.com/ubiquity/work.ubq.fi/pull/70",
state: "OPEN",
author: {
login: "0x4007",
id: 4975670,
},
repository: {
owner: {
login: "ubiquity",
},
name: "work.ubq.fi",
},
},
},
{
node: {
id: "PR_kwDOKzVPS85zXUok",
title: "fix: add state to sorting manager for bottom and top 2",
number: 71,
url: "https://github.com/ubiquity/work.ubq.fi/pull/71",
state: "MERGED",
author: {
login: "0x4007",
id: 4975670,
},
repository: {
owner: {
login: "ubiquity",
},
name: "work.ubq.fi",
},
},
},
],
},
},
},
};
},
},
};
},
}));

jest.mock("../src/parser/command-line", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const cfg = require("./__mocks__/results/valid-configuration.json");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const dotenv = require("dotenv");
dotenv.config();
return {
stateId: 1,
eventName: "issues.closed",
authToken: process.env.GITHUB_TOKEN,
ref: "",
eventPayload: {
issue: {
html_url: issueUrl,
number: 1,
state_reason: "completed",
},
repository: {
name: "conversation-rewards",
owner: {
login: "ubiquibot",
id: 76412717,
},
},
},
settings: JSON.stringify(cfg),
};
});

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

describe("Pre-check tests", () => {
beforeEach(async () => {
drop(db);
for (const table of Object.keys(dbSeed)) {
const tableName = table as keyof typeof dbSeed;
for (const row of dbSeed[tableName]) {
db[tableName].create(row);
}
}
});

it("Should reopen the issue and not generate rewards if linked pull-requests are still open", async () => {
const patchMock = jest.fn(() => HttpResponse.json({}));
server.use(http.patch("https://api.github.com/repos/ubiquity/work.ubq.fi/issues/69", patchMock, { once: true }));
const module = (await import("../src/index")) as unknown as { default: Promise<string> };
const result = await module.default;
expect(result).toEqual("All linked pull requests must be closed to generate rewards.");
expect(patchMock).toHaveBeenCalled();
});
});
Loading