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

Add comment on failure #36

Merged
merged 3 commits into from Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Expand Up @@ -65,6 +65,17 @@ To force an API call, set the `GITHUB_TOKEN` environment variable like so:
labels: "do not merge"
```

### Post a comment when the check fails

```yaml
- uses: mheap/github-action-required-labels@v2
with:
mode: exactly
count: 1
labels: "semver:patch, semver:minor, semver:major"
add_comment: true
```

### Require multiple labels

```yaml
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Expand Up @@ -16,6 +16,10 @@ inputs:
count:
description: "The required number of labels to match"
required: true
comment:
description: "Add a comment to the PR if required labels are missing"
default: "false"
required: false
exit_type:
description: "The exit type of the action. One of: failure, success, neutral"
required: false
32 changes: 26 additions & 6 deletions index.js
Expand Up @@ -55,8 +55,9 @@ Toolkit.run(async (tools) => {
let intersection = allowedLabels.filter((x) => appliedLabels.includes(x));

if (mode === "exactly" && intersection.length !== count) {
tools.outputs.status = "failure";
tools.exit[exitType](
await exitWithError(
tools,
exitType,
`Label error. Requires exactly ${count} of: ${allowedLabels.join(
", "
)}. Found: ${appliedLabels.join(", ")}`
Expand All @@ -65,8 +66,9 @@ Toolkit.run(async (tools) => {
}

if (mode === "minimum" && intersection.length < count) {
tools.outputs.status = "failure";
tools.exit[exitType](
await exitWithError(
tools,
exitType,
`Label error. Requires at least ${count} of: ${allowedLabels.join(
", "
)}. Found: ${appliedLabels.join(", ")}`
Expand All @@ -75,8 +77,9 @@ Toolkit.run(async (tools) => {
}

if (mode === "maximum" && intersection.length > count) {
tools.outputs.status = "failure";
tools.exit[exitType](
await exitWithError(
tools,
exitType,
`Label error. Requires at most ${count} of: ${allowedLabels.join(
", "
)}. Found: ${appliedLabels.join(", ")}`
Expand All @@ -87,3 +90,20 @@ Toolkit.run(async (tools) => {
tools.outputs.status = "success";
tools.exit.success("Complete");
});

async function exitWithError(tools, exitType, message) {
if (tools.inputs.add_comment) {
if (process.env.GITHUB_TOKEN) {
await tools.github.issues.createComment({
...tools.context.issue,
body: message,
});
} else {
throw new Error(
"The GITHUB_TOKEN environment variable must be set to add a comment"
);
}
}
tools.outputs.status = "failure";
tools.exit[exitType](message);
}
78 changes: 78 additions & 0 deletions index.test.js
@@ -1,6 +1,8 @@
const { Toolkit } = require("actions-toolkit");
const core = require("@actions/core");
const mockedEnv = require("mocked-env");
const nock = require("nock");
nock.disableNetConnect();

describe("Required Labels", () => {
let action, tools;
Expand Down Expand Up @@ -44,6 +46,82 @@ describe("Required Labels", () => {
restore();
restoreTest();
jest.resetModules();

if (!nock.isDone()) {
throw new Error(
`Not all nock interceptors were used: ${JSON.stringify(
nock.pendingMocks()
)}`
);
}
nock.cleanAll();
});

describe("interacts with the API", () => {
it("fetches the labels from the API", async () => {
restoreTest = mockPr(tools, [], {
INPUT_LABELS: "enhancement",
INPUT_MODE: "exactly",
INPUT_COUNT: "1",
GITHUB_TOKEN: "mock-token-here-abc",
});

nock("https://api.github.com")
.get("/repos/mheap/missing-repo/issues/28/labels")
.reply(200, [{ name: "enhancement" }, { name: "bug" }]);

await action(tools);
expect(core.setOutput).toBeCalledTimes(1);
expect(core.setOutput).toBeCalledWith("status", "success");
expect(tools.exit.success).toBeCalledTimes(1);
expect(tools.exit.success).toBeCalledWith("Complete");
});

it("fetches the labels from the API (and fails)", async () => {
restoreTest = mockPr(tools, ["enhancement"], {
INPUT_LABELS: "enhancement",
INPUT_MODE: "exactly",
INPUT_COUNT: "1",
GITHUB_TOKEN: "mock-token-here-abc",
});

nock("https://api.github.com")
.get("/repos/mheap/missing-repo/issues/28/labels")
.reply(200, [{ name: "bug" }]);

await action(tools);
expect(core.setOutput).toBeCalledTimes(1);
expect(core.setOutput).toBeCalledWith("status", "failure");
expect(tools.exit.failure).toBeCalledTimes(1);
expect(tools.exit.failure).toBeCalledWith(
"Label error. Requires exactly 1 of: enhancement. Found: bug"
);
});

it("posts a comment when enabled", async () => {
restoreTest = mockPr(tools, ["enhancement"], {
INPUT_LABELS: "enhancement",
INPUT_MODE: "exactly",
INPUT_COUNT: "1",
INPUT_ADD_COMMENT: "true",
GITHUB_TOKEN: "mock-token-here-abc",
});

nock("https://api.github.com")
.get("/repos/mheap/missing-repo/issues/28/labels")
.reply(200, [{ name: "bug" }]);

nock("https://api.github.com")
.post("/repos/mheap/missing-repo/issues/28/comments", {
body: "Label error. Requires exactly 1 of: enhancement. Found: bug",
})
.reply(201);

await action(tools);
expect(tools.exit.failure).toBeCalledWith(
"Label error. Requires exactly 1 of: enhancement. Found: bug"
);
});
});

describe("success", () => {
Expand Down
67 changes: 67 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -15,6 +15,7 @@
},
"devDependencies": {
"jest": "^28.1.1",
"nock": "^13.2.9",
"prettier": "^2.7.1"
},
"license": "MIT"
Expand Down