Skip to content

Commit

Permalink
Merge queue support (#87)
Browse files Browse the repository at this point in the history
* Add support for merge_queue events
* fix: merge-queue support (#85)
* Fix merge_group tests

---------

Co-authored-by: Victor Martinez <victormartinezrubio@gmail.com>
  • Loading branch information
mheap and v1v authored Dec 8, 2024
1 parent 4292bf2 commit a4fafed
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 11 deletions.
47 changes: 37 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async function action() {

let providedLabels = core.getInput("labels", { required: true });

core.debug(`gather labels: ${providedLabels}`);
if (labelsAreRegex) {
// If labels are regex they must be provided as new line delimited
providedLabels = providedLabels.split("\n");
Expand All @@ -43,6 +44,18 @@ async function action() {
// Remove any empty labels
providedLabels = providedLabels.filter((r) => r);

let issue_number = github.context.issue.number;

if (github.context.eventName === "merge_group" && !issue_number) {
// Parse out of the ref for merge queue
// e.g. refs/heads/gh-readonly-queue/main/pr-17-a3c310584587d4b97c2df0cb46fe050cc46a15d6
const lastPart = github.context.ref.split("/").pop();
issue_number = lastPart.match(/pr-(\d+)-/)[1];
core.info(
`merge_group event detected and issue_number parsed as ${issue_number}`,
);
}

const allowedModes = ["exactly", "minimum", "maximum"];
if (!allowedModes.includes(mode)) {
await exitWithError(
Expand All @@ -52,6 +65,7 @@ async function action() {
`Unknown mode input [${mode}]. Must be one of: ${allowedModes.join(
", ",
)}`,
issue_number,
);
return;
}
Expand All @@ -65,17 +79,18 @@ async function action() {
`Unknown exit_code input [${exitType}]. Must be one of: ${allowedExitCodes.join(
", ",
)}`,
issue_number,
);
return;
}

// Fetch the labels using the API
core.debug(`fetch the labels for ${issue_number} using the API`);
// We use the API rather than read event.json in case earlier steps
// added a label
const labels = (
await octokit.rest.issues.listLabelsOnIssue({
...github.context.repo,
issue_number: github.context.issue.number,
issue_number,
})
).data;

Expand All @@ -98,7 +113,7 @@ async function action() {
);
}

// Is there an error?
core.debug(`detect errors...`);
let errorMode;
if (mode === "exactly" && intersection.length !== count) {
errorMode = "exactly";
Expand All @@ -108,7 +123,7 @@ async function action() {
errorMode = "at most";
}

// If so, add a comment (if enabled) and fail the run
core.debug(`if so, add a comment (if enabled) and fail the run...`);
if (errorMode !== undefined) {
const comment = core.getInput("message");
const errorMessage = tmpl(comment, {
Expand All @@ -119,15 +134,21 @@ async function action() {
applied: appliedLabels.join(", "),
});

await exitWithError(exitType, octokit, shouldAddComment, errorMessage);
await exitWithError(
exitType,
octokit,
shouldAddComment,
errorMessage,
issue_number,
);
return;
}

// Remove the comment if it exists
core.debug(`remove the comment if it exists...`);
if (shouldAddComment) {
const { data: existing } = await octokit.rest.issues.listComments({
...github.context.repo,
issue_number: github.context.issue.number,
issue_number: issue_number,
});

const generatedComment = existing.find((c) =>
Expand All @@ -154,19 +175,25 @@ function tmpl(t, o) {
});
}

async function exitWithError(exitType, octokit, shouldAddComment, message) {
async function exitWithError(
exitType,
octokit,
shouldAddComment,
message,
issue_number,
) {
if (shouldAddComment) {
// Is there an existing comment?
const { data: existing } = await octokit.rest.issues.listComments({
...github.context.repo,
issue_number: github.context.issue.number,
issue_number: issue_number,
});

const generatedComment = existing.find((c) => c.body.includes(matchToken));

const params = {
...github.context.repo,
issue_number: github.context.issue.number,
issue_number: issue_number,
body: `${matchToken}${message}`,
};

Expand Down
66 changes: 65 additions & 1 deletion index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe("Required Labels", () => {
core.setOutput = jest.fn();
core.warning = jest.fn();
core.setFailed = jest.fn();
core.debug = jest.fn();
});

afterEach(() => {
Expand Down Expand Up @@ -645,6 +646,59 @@ describe("Required Labels", () => {
await action();
});
});

describe("merge_group", () => {
it("extracts the PR number from the ref if needed", async () => {
restoreTest = mockEvent(
"merge_group",
{},
{
INPUT_LABELS: "enhancement",
INPUT_MODE: "exactly",
INPUT_COUNT: "1",
GITHUB_TOKEN: "mock-token-here-abc",
},
{
ref: "refs/heads/gh-readonly-queue/main/pr-28-a3c310584587d4b97c2df0cb46fe050cc46a15d6",
},
);

mockLabels(["enhancement", "bug"]);

await action();
expect(core.setOutput).toBeCalledTimes(2);
expect(core.setOutput).toBeCalledWith("status", "success");
expect(core.setOutput).toBeCalledWith("labels", "enhancement");
});

it("prefers the issue number that is set in the payload to extracting from a ref", async () => {
restoreTest = mockEvent(
"merge_group",
{
issue: {
number: 28,
},
},
{
INPUT_LABELS: "enhancement",
INPUT_MODE: "exactly",
INPUT_COUNT: "1",
GITHUB_TOKEN: "mock-token-here-abc",
},
{
// This would lead to an error as there are no mocks for PR 999
ref: "refs/heads/gh-readonly-queue/main/pr-999-a3c310584587d4b97c2df0cb46fe050cc46a15d6",
},
);

mockLabels(["enhancement", "bug"]);

await action();
expect(core.setOutput).toBeCalledTimes(2);
expect(core.setOutput).toBeCalledWith("status", "success");
expect(core.setOutput).toBeCalledWith("labels", "enhancement");
});
});
});

function mockPr(env) {
Expand Down Expand Up @@ -683,8 +737,18 @@ function mockListComments(comments) {
);
}

function mockEvent(eventName, mockPayload, additionalParams = {}) {
function mockEvent(
eventName,
mockPayload,
additionalParams,
additionalContext = {},
) {
github.context.payload = mockPayload;
github.context.eventName = eventName;

for (const key in additionalContext) {
github.context[key] = additionalContext[key];
}

const params = {
GITHUB_EVENT_NAME: eventName,
Expand Down

0 comments on commit a4fafed

Please sign in to comment.