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

Switch to using @actions/core #44

Merged
merged 2 commits into from Dec 30, 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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -8,7 +8,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
node-version: [16.x, 18.x]

env:
CI: true
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Expand Up @@ -8,7 +8,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install deps and build
run: npm ci --only=production && npm run build
- name: Automatically build action
uses: JasonEtco/build-and-tag-action@v1
uses: JasonEtco/build-and-tag-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -35,7 +35,7 @@ jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: mheap/github-action-required-labels@v2
- uses: mheap/github-action-required-labels@v3
with:
mode: exactly
count: 1
Expand All @@ -46,7 +46,7 @@ By default this actions reads `event.json`, which will not detect when a label i
To force an API call, set the `GITHUB_TOKEN` environment variable like so:

```yaml
- uses: mheap/github-action-required-labels@v2
- uses: mheap/github-action-required-labels@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand All @@ -58,7 +58,7 @@ To force an API call, set the `GITHUB_TOKEN` environment variable like so:
### Prevent merging if a label exists

```yaml
- uses: mheap/github-action-required-labels@v2
- uses: mheap/github-action-required-labels@v3
with:
mode: exactly
count: 0
Expand All @@ -68,7 +68,7 @@ To force an API call, set the `GITHUB_TOKEN` environment variable like so:
### Post a comment when the check fails

```yaml
- uses: mheap/github-action-required-labels@v2
- uses: mheap/github-action-required-labels@v3
with:
mode: exactly
count: 1
Expand All @@ -79,7 +79,7 @@ To force an API call, set the `GITHUB_TOKEN` environment variable like so:
### Require multiple labels

```yaml
- uses: mheap/github-action-required-labels@v2
- uses: mheap/github-action-required-labels@v3
with:
mode: minimum
count: 2
Expand All @@ -89,7 +89,7 @@ To force an API call, set the `GITHUB_TOKEN` environment variable like so:
### Exit with a neutral result rather than failure

```yaml
- uses: mheap/github-action-required-labels@v2
- uses: mheap/github-action-required-labels@v3
with:
mode: minimum
count: 2
Expand All @@ -115,7 +115,7 @@ jobs:
status: ${{ steps.check-labels.outputs.status }}
steps:
- id: check-labels
uses: mheap/github-action-required-labels@v2
uses: mheap/github-action-required-labels@v3
with:
mode: exactly
count: 1
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Expand Up @@ -7,6 +7,10 @@ branding:
icon: check-square
color: blue
inputs:
token:
description: The GitHub token to use when calling the API
default: ${{ github.token }}
required: false
labels:
description: "Comma separated list of labels to match"
required: true
Expand Down
188 changes: 95 additions & 93 deletions index.js
@@ -1,109 +1,111 @@
const { Toolkit } = require("actions-toolkit");

Toolkit.run(async (tools) => {
// Process inputs for use later
const mode = tools.inputs.mode;
const count = parseInt(tools.inputs.count, 10);
const allowedLabels = tools.inputs.labels
.split(",")
.map((l) => l.trim())
.filter((r) => r);

const exitType = tools.inputs.exit_type || "failure";

// Validate inputs
if (tools.inputs.count === "") {
tools.exit.failure(`[count] input is not provided`);
return;
}
const core = require("@actions/core");
const github = require("@actions/github");

if (allowedLabels.length === 0) {
tools.exit.failure("[labels] input is empty or not provided");
return;
}
async function action() {
try {
const token = core.getInput("token", { required: true });
const octokit = github.getOctokit(token);

const allowedModes = ["exactly", "minimum", "maximum"];
if (!allowedModes.includes(mode)) {
tools.exit.failure(
`Unknown mode input [${mode}]. Must be one of: ${allowedModes.join(", ")}`
);
return;
}
// Process inputs for use later
const mode = core.getInput("mode", { required: true });
const count = parseInt(core.getInput("count", { required: true }), 10);
const allowedLabels = core
.getInput("labels", { required: true })
.split(",")
.map((l) => l.trim())
.filter((r) => r);

const allowedExitCodes = ["success", "neutral", "failure"];
if (!allowedExitCodes.includes(exitType)) {
tools.exit.failure(
`Unknown exit_code input [${exitType}]. Must be one of: ${allowedExitCodes.join(
", "
)}`
);
return;
}
const exitType = core.getInput("exit_type") || "failure";
const shouldAddComment = core.getInput("add_comment") == "true";

// If a token is provided, call the API, otherwise read the event.json file
let labels;
if (process.env.GITHUB_TOKEN) {
labels = (await tools.github.issues.listLabelsOnIssue(tools.context.issue))
.data;
} else {
labels = tools.context.payload.pull_request.labels;
}
const allowedModes = ["exactly", "minimum", "maximum"];
if (!allowedModes.includes(mode)) {
await exitWithError(
exitType,
octokit,
shouldAddComment,
`Unknown mode input [${mode}]. Must be one of: ${allowedModes.join(
", "
)}`
);
return;
}

const allowedExitCodes = ["success", "failure"];
if (!allowedExitCodes.includes(exitType)) {
await exitWithError(
exitType,
octokit,
shouldAddComment,
`Unknown exit_code input [${exitType}]. Must be one of: ${allowedExitCodes.join(
", "
)}`
);
return;
}

// Fetch the labels 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,
})
).data;

const appliedLabels = labels.map((label) => label.name);
const appliedLabels = labels.map((label) => label.name);

// How many labels overlap?
let intersection = allowedLabels.filter((x) => appliedLabels.includes(x));
// How many labels overlap?
let intersection = allowedLabels.filter((x) => appliedLabels.includes(x));

if (mode === "exactly" && intersection.length !== count) {
await exitWithError(
tools,
exitType,
`Label error. Requires exactly ${count} of: ${allowedLabels.join(
// Is there an error?
let errorMode;
if (mode === "exactly" && intersection.length !== count) {
errorMode = "exactly";
} else if (mode === "minimum" && intersection.length < count) {
errorMode = "at least";
} else if (mode === "maximum" && intersection.length > count) {
errorMode = "at most";
}

// If so, add a comment (if enabled) and fail the run
if (errorMode !== undefined) {
const errorMessage = `Label error. Requires ${errorMode} ${count} of: ${allowedLabels.join(
", "
)}. Found: ${appliedLabels.join(", ")}`
);
return;
)}. Found: ${appliedLabels.join(", ")}`;
await exitWithError(exitType, octokit, shouldAddComment, errorMessage);
return;
}

core.setOutput("status", "success");
} catch (e) {
core.setFailed(e.message);
}
}

if (mode === "minimum" && intersection.length < count) {
await exitWithError(
tools,
exitType,
`Label error. Requires at least ${count} of: ${allowedLabels.join(
", "
)}. Found: ${appliedLabels.join(", ")}`
);
return;
async function exitWithError(exitType, octokit, shouldAddComment, message) {
if (shouldAddComment) {
await octokit.rest.issues.createComment({
...github.context.repo,
issue_number: github.context.issue.number,
body: message,
});
}

if (mode === "maximum" && intersection.length > count) {
await exitWithError(
tools,
exitType,
`Label error. Requires at most ${count} of: ${allowedLabels.join(
", "
)}. Found: ${appliedLabels.join(", ")}`
);
core.setOutput("status", "failure");

if (exitType === "success") {
core.warning(message);
return;
}

tools.outputs.status = "success";
tools.exit.success("Complete");
});

async function exitWithError(tools, exitType, message) {
if (tools.inputs.add_comment == "true") {
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);
core.setFailed(message);
}

/* istanbul ignore next */
if (require.main === module) {
action();
}

module.exports = action;