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 authors MatchConfig option #563

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -19,13 +19,17 @@ For more control over matching, you can provide a match object instead of a simp
```yml
- any: ['list', 'of', 'globs']
all: ['list', 'of', 'globs']
authors: ['list', 'of', 'authors'] # github users
```

One or both fields can be provided for fine-grained matching. Unlike the top-level list, the list of path globs provided to `any` and `all` must ALL match against a path for the label to be applied.

Also, the `authors` field is a list of GitHub usernames that must ALL match the PR author for the label to be applied.

The fields are defined as follows:
* `any`: match ALL globs against ANY changed path
* `all`: match ALL globs against ALL changed paths
* `authors`: match ALL authors against the PR author

A simple path glob is the equivalent to `any: ['glob']`. More specifically, the following two configurations are equivalent:
```yml
Expand Down Expand Up @@ -80,6 +84,10 @@ source:
frontend:
- any: ['src/**/*.js']
all: ['!src/main.js']

dev-team:
- any: ['src/**/*']
authors: ['user1', 'user2', 'user3']
```

### Create Workflow
Expand Down
5 changes: 4 additions & 1 deletion __mocks__/@actions/github.ts
@@ -1,7 +1,10 @@
export const context = {
payload: {
pull_request: {
number: 123
number: 123,
user: {
login: 'monalisa'
}
}
},
repo: {
Expand Down
24 changes: 22 additions & 2 deletions __tests__/labeler.test.ts
@@ -1,4 +1,4 @@
import {checkGlobs} from '../src/labeler';
import {MatchConfig, checkGlobs} from '../src/labeler';

import * as core from '@actions/core';

Expand All @@ -10,7 +10,7 @@ beforeAll(() => {
});
});

const matchConfig = [{any: ['*.txt']}];
const matchConfig: MatchConfig[] = [{any: ['*.txt']}];

describe('checkGlobs', () => {
it('returns true when our pattern does match changed files', () => {
Expand All @@ -26,4 +26,24 @@ describe('checkGlobs', () => {

expect(result).toBeFalsy();
});

it('returns true when PR author is in the list of authors', () => {
const matchConfigWithAuthor: MatchConfig[] = [
{any: ['*.txt'], authors: ['monalisa', 'hubot']}
];
const changedFiles = ['foo.txt'];

const result = checkGlobs(changedFiles, matchConfigWithAuthor);
expect(result).toBeTruthy();
});

it('returns false when PR author is not in the list of authors', () => {
const matchConfigWithAuthor: MatchConfig[] = [
{any: ['*.txt'], authors: ['foo', 'bar']}
];
const changedFiles = ['foo.txt'];

const result = checkGlobs(changedFiles, matchConfigWithAuthor);
expect(result).toBeFalsy();
});
});
25 changes: 25 additions & 0 deletions dist/index.js
Expand Up @@ -96,6 +96,13 @@ function getPrNumber() {
}
return pullRequest.number;
}
function getPrAuthor() {
const pullRequest = github.context.payload.pull_request;
if (!pullRequest) {
return undefined;
}
return pullRequest.user.login;
}
function getChangedFiles(client, prNumber) {
return __awaiter(this, void 0, void 0, function* () {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
Expand Down Expand Up @@ -207,6 +214,19 @@ function checkAll(changedFiles, globs) {
core.debug(` "all" patterns matched all files`);
return true;
}
function checkAuthors(authors) {
const prAuthor = getPrAuthor();
if (!prAuthor) {
core.info('Could not get pull request author from context, exiting');
return false;
}
if (authors.includes(prAuthor)) {
core.debug(` author ${prAuthor} is on the list`);
return true;
}
core.debug(` author ${prAuthor} is not on the list`);
return false;
}
function checkMatch(changedFiles, matchConfig) {
if (matchConfig.all !== undefined) {
if (!checkAll(changedFiles, matchConfig.all)) {
Expand All @@ -218,6 +238,11 @@ function checkMatch(changedFiles, matchConfig) {
return false;
}
}
if (matchConfig.authors !== undefined) {
if (!checkAuthors(matchConfig.authors)) {
return false;
}
}
return true;
}
function addLabels(client, prNumber, labels) {
Expand Down
33 changes: 32 additions & 1 deletion src/labeler.ts
Expand Up @@ -3,9 +3,10 @@ import * as github from '@actions/github';
import * as yaml from 'js-yaml';
import {Minimatch} from 'minimatch';

interface MatchConfig {
export interface MatchConfig {
all?: string[];
any?: string[];
authors?: string[];
}

type StringOrMatchConfig = string | MatchConfig;
Expand Down Expand Up @@ -71,6 +72,14 @@ function getPrNumber(): number | undefined {
return pullRequest.number;
}

function getPrAuthor(): string | undefined {
const pullRequest = github.context.payload.pull_request;
if (!pullRequest) {
return undefined;
}
return pullRequest.user.login;
}

async function getChangedFiles(
client: ClientType,
prNumber: number
Expand Down Expand Up @@ -213,6 +222,22 @@ function checkAll(changedFiles: string[], globs: string[]): boolean {
return true;
}

function checkAuthors(authors: string[]): boolean {
const prAuthor = getPrAuthor();
if (!prAuthor) {
core.info('Could not get pull request author from context, exiting');
return false;
}

if (authors.includes(prAuthor)) {
core.debug(` author ${prAuthor} is on the list`);
return true;
}

core.debug(` author ${prAuthor} is not on the list`);
return false;
}

function checkMatch(changedFiles: string[], matchConfig: MatchConfig): boolean {
if (matchConfig.all !== undefined) {
if (!checkAll(changedFiles, matchConfig.all)) {
Expand All @@ -226,6 +251,12 @@ function checkMatch(changedFiles: string[], matchConfig: MatchConfig): boolean {
}
}

if (matchConfig.authors !== undefined) {
if (!checkAuthors(matchConfig.authors)) {
return false;
}
}

return true;
}

Expand Down