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

Added label filter #18

Merged
merged 7 commits into from
Jun 5, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ You can find all the inputs in [the action file](./action.yml) but let's walk th
- It is **not** _case sensitive_.
- It works great in conjuction with [`paritytech/list-team-members`](https://github.com/paritytech/list-team-members)
- It can use the output directly to ignore any issues made by a member of a team.
- `requiredLabels`: Collections of labels separated by commas that should be required when searching for a PR.
- Only needs to have one of the included labels.
- If you have labels: `A,B` the issue will be taken into consideration if it has: `A`, `B` or both `A` and `B`.
- Short for `Only include issues with at least one of the required labels`.
- **optional**
- **Important**: If set be sure to connect the names by comma.
- Example: `feature,bug,good first issue`
- It is **not** _case sensitive_.

#### Accessing other repositories

Expand Down
6 changes: 5 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ inputs:
required: false
description: Collections of usernames separated by commas that should be ignored if they are the author of the issue.
type: string
requiredLabels:
required: false
description: Collections of labels separated by commas that should be required when searching for a issue.
type: string
outputs:
repo:
description: 'The name of the repo in owner/repo pattern'
Expand All @@ -38,4 +42,4 @@ outputs:

runs:
using: 'docker'
image: 'docker://ghcr.io/paritytech/stale-issues-finder/action:0.0.6'
image: 'docker://ghcr.io/paritytech/stale-issues-finder/action:0.1.0'
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stale-issues-finder",
"version": "0.0.6",
"version": "0.1.0",
"description": "Find what issues have been stale for a given time",
"main": "src/index.ts",
"engines": {
Expand Down
3 changes: 3 additions & 0 deletions src/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ export const byNoComments = (issue: IssueData): boolean => issue.comments === 0;

export const isNotFromAuthor = ({ user }: IssueData, authors: string[]): boolean =>
!authors.some((author) => author.toLowerCase() === user?.login.toLowerCase());

export const byLabels = (issue: IssueData, requiredLabels: string[]): boolean =>
issue.labels?.map((l) => l.name.toLowerCase()).some((l) => requiredLabels.map((lb) => lb.toLowerCase()).includes(l));
22 changes: 21 additions & 1 deletion src/github/issuesParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,28 @@ const getAllIssues = async (octokit: InstanceType<typeof GitHub>, repo: Repo): P
fullPage = data.length > 99;
}

// parse the label data
const parsedIssues = issues.map((issue) => {
const labels: Label[] = [];
for (const label of issue.labels) {
let parsedLabel: Label;
if (typeof label === "string") {
parsedLabel = { id: 0, name: label, description: label, url: "" };
} else {
parsedLabel = {
id: label.id ?? 0,
name: label.name ?? "",
description: label.description ?? "",
url: label.url ?? "",
};
}
labels.push(parsedLabel);
}
return { ...issue, labels };
});

debug(`Found a total of ${issues.length} issues`);
return issues;
return parsedIssues;
};

export const fetchIssues = async (octokit: InstanceType<typeof GitHub>, repo: Repo): Promise<IssueData[]> => {
Expand Down
13 changes: 11 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { context, getOctokit } from "@actions/github";
import { Context } from "@actions/github/lib/context";
import moment from "moment";

import { byNoComments, isNotFromAuthor, olderThanDays } from "./filters";
import { byLabels, byNoComments, isNotFromAuthor, olderThanDays } from "./filters";
import { fetchIssues } from "./github/issuesParser";

const daysSinceDate = (date: string): number => moment().diff(moment(date), "days");
Expand All @@ -20,7 +20,13 @@ const getFiltersFromInput = (): Filters => {
ignoreAuthors = authorsToIgnore.split(",");
}

return { daysStale, noComments, notFromAuthor: ignoreAuthors };
let requiredLabels: string[] = [];
const labels = getInput("requiredLabels");
if (labels) {
requiredLabels = labels.split(",");
}

return { daysStale, noComments, notFromAuthor: ignoreAuthors, requiredLabels };
};

const generateMarkdownMessage = (issues: IssueData[], repo: { owner: string; repo: string }) => {
Expand Down Expand Up @@ -59,6 +65,9 @@ const filterIssues = (issues: IssueData[] | undefined, filters: Filters) => {
if (filters.notFromAuthor.length > 0) {
filteredData = filteredData.filter((is) => isNotFromAuthor(is, filters.notFromAuthor));
}
if (filters.requiredLabels?.length > 0) {
filteredData = filteredData.filter((fd) => byLabels(fd, filters.requiredLabels));
}

return filteredData;
};
Expand Down
9 changes: 9 additions & 0 deletions src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare global {
comments: number;
/** If user was deleted it is going to be null */
user: { login: string } | null;
labels: Label[];
}

interface Repo {
Expand All @@ -19,6 +20,14 @@ declare global {
noComments?: boolean;
daysStale: number;
notFromAuthor: string[];
requiredLabels: string[];
}

interface Label {
id: number;
url: string;
name: string;
description: string;
}
}

Expand Down