mirror of
https://github.com/actions/labeler.git
synced 2025-12-12 12:37:48 +00:00
* Adding pr-number as an optional parameter * Updated README * Tests on the pr-number parameter * Added missing | to table * re-built script * Adding support for multiple pr-numbers * excluded .idea * Updated readme to reflect that there might be more than one PR * Additional warning * Removed unused * Reformatted and re-built * Corrected message * Removed required check * Added (s) to pull request numbers in the description Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com> * Reworded PR-number parameter description Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com> * adding getMultilineInput into the tests * Fixing tests for single pr * Fixing tests for multiple prs * Updated README.md to make it more obvious that it can take a list of PRs * Added example that labels PR's 1-3 * Handled no pull requests better (from code review) * Handled no pull requests better (from code review) * Handled missing pull request better (from code review) * Back out suggested change as it broke the tests * Rebuilt dist * Update src/labeler.ts Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com> * Added Emphasis to the note Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com> * Changed mockInput for pr-number to be string[] --------- Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
310 lines
8.5 KiB
TypeScript
310 lines
8.5 KiB
TypeScript
import {run} from '../src/labeler';
|
|
import * as github from '@actions/github';
|
|
import * as core from '@actions/core';
|
|
|
|
const fs = jest.requireActual('fs');
|
|
|
|
jest.mock('@actions/core');
|
|
jest.mock('@actions/github');
|
|
|
|
const gh = github.getOctokit('_');
|
|
const setLabelsMock = jest.spyOn(gh.rest.issues, 'setLabels');
|
|
const reposMock = jest.spyOn(gh.rest.repos, 'getContent');
|
|
const paginateMock = jest.spyOn(gh, 'paginate');
|
|
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
|
|
const coreWarningMock = jest.spyOn(core, 'warning');
|
|
const setOutputSpy = jest.spyOn(core, 'setOutput');
|
|
|
|
const yamlFixtures = {
|
|
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
|
|
};
|
|
|
|
const configureInput = (
|
|
mockInput: Partial<{
|
|
'repo-token': string;
|
|
'configuration-path': string;
|
|
'sync-labels': boolean;
|
|
dot: boolean;
|
|
'pr-number': string[];
|
|
}>
|
|
) => {
|
|
jest
|
|
.spyOn(core, 'getInput')
|
|
.mockImplementation((name: string, ...opts) => mockInput[name]);
|
|
jest
|
|
.spyOn(core, 'getMultilineInput')
|
|
.mockImplementation((name: string, ...opts) => mockInput[name]);
|
|
jest
|
|
.spyOn(core, 'getBooleanInput')
|
|
.mockImplementation((name: string, ...opts) => mockInput[name]);
|
|
};
|
|
|
|
afterAll(() => jest.restoreAllMocks());
|
|
|
|
describe('run', () => {
|
|
it('(with dot: false) adds labels to PRs that match our glob patterns', async () => {
|
|
configureInput({});
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.pdf');
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: []
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(1);
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledWith({
|
|
owner: 'monalisa',
|
|
repo: 'helloworld',
|
|
issue_number: 123,
|
|
labels: ['touched-a-pdf-file']
|
|
});
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'new-labels',
|
|
'touched-a-pdf-file'
|
|
);
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'all-labels',
|
|
'touched-a-pdf-file'
|
|
);
|
|
});
|
|
|
|
it('(with dot: true) adds labels to PRs that match our glob patterns', async () => {
|
|
configureInput({dot: true});
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('.foo.pdf');
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: []
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(1);
|
|
expect(setLabelsMock).toHaveBeenCalledWith({
|
|
owner: 'monalisa',
|
|
repo: 'helloworld',
|
|
issue_number: 123,
|
|
labels: ['touched-a-pdf-file']
|
|
});
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'new-labels',
|
|
'touched-a-pdf-file'
|
|
);
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'all-labels',
|
|
'touched-a-pdf-file'
|
|
);
|
|
});
|
|
|
|
it('(with dot: false) does not add labels to PRs that do not match our glob patterns', async () => {
|
|
configureInput({});
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('.foo.pdf');
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: []
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(0);
|
|
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
|
|
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', '');
|
|
});
|
|
|
|
it('(with dot: true) does not add labels to PRs that do not match our glob patterns', async () => {
|
|
configureInput({dot: true});
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.txt');
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it('(with sync-labels: true) it deletes preexisting PR labels that no longer match the glob pattern', async () => {
|
|
configureInput({
|
|
'repo-token': 'foo',
|
|
'configuration-path': 'bar',
|
|
'sync-labels': true
|
|
});
|
|
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.txt');
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: [{name: 'touched-a-pdf-file'}, {name: 'manually-added'}]
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(1);
|
|
expect(setLabelsMock).toHaveBeenCalledWith({
|
|
owner: 'monalisa',
|
|
repo: 'helloworld',
|
|
issue_number: 123,
|
|
labels: ['manually-added']
|
|
});
|
|
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
|
|
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', 'manually-added');
|
|
});
|
|
|
|
it('(with sync-labels: false) it issues no delete calls even when there are preexisting PR labels that no longer match the glob pattern', async () => {
|
|
configureInput({
|
|
'repo-token': 'foo',
|
|
'configuration-path': 'bar',
|
|
'sync-labels': false
|
|
});
|
|
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.txt');
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: [{name: 'touched-a-pdf-file'}, {name: 'manually-added'}]
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(0);
|
|
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'all-labels',
|
|
'touched-a-pdf-file,manually-added'
|
|
);
|
|
});
|
|
|
|
it('(with sync-labels: false) it only logs the excess labels', async () => {
|
|
configureInput({
|
|
'repo-token': 'foo',
|
|
'configuration-path': 'bar',
|
|
'sync-labels': false
|
|
});
|
|
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.pdf');
|
|
|
|
const existingLabels = Array.from({length: 100}).map((_, idx) => ({
|
|
name: `existing-label-${idx}`
|
|
}));
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: existingLabels
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(0);
|
|
|
|
expect(coreWarningMock).toHaveBeenCalledTimes(1);
|
|
expect(coreWarningMock).toHaveBeenCalledWith(
|
|
'Maximum of 100 labels allowed. Excess labels: touched-a-pdf-file',
|
|
{title: 'Label limit for a PR exceeded'}
|
|
);
|
|
const allLabels: string = existingLabels.map(i => i.name).join(',');
|
|
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
|
|
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', allLabels);
|
|
});
|
|
|
|
it('(with pr-number: array of one item, uses the PR number specified in the parameters', async () => {
|
|
configureInput({
|
|
'repo-token': 'foo',
|
|
'configuration-path': 'bar',
|
|
'pr-number': ['104']
|
|
});
|
|
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.pdf');
|
|
|
|
getPullMock.mockResolvedValue(<any>{
|
|
data: {
|
|
labels: [{name: 'manually-added'}]
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(1);
|
|
expect(setLabelsMock).toHaveBeenCalledWith({
|
|
owner: 'monalisa',
|
|
repo: 'helloworld',
|
|
issue_number: 104,
|
|
labels: ['manually-added', 'touched-a-pdf-file']
|
|
});
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'new-labels',
|
|
'touched-a-pdf-file'
|
|
);
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'all-labels',
|
|
'manually-added,touched-a-pdf-file'
|
|
);
|
|
});
|
|
|
|
it('(with pr-number: array of two items, uses the PR number specified in the parameters', async () => {
|
|
configureInput({
|
|
'repo-token': 'foo',
|
|
'configuration-path': 'bar',
|
|
'pr-number': ['104', '150']
|
|
});
|
|
|
|
usingLabelerConfigYaml('only_pdfs.yml');
|
|
mockGitHubResponseChangedFiles('foo.pdf');
|
|
|
|
getPullMock.mockResolvedValueOnce(<any>{
|
|
data: {
|
|
labels: [{name: 'manually-added'}]
|
|
}
|
|
});
|
|
|
|
getPullMock.mockResolvedValueOnce(<any>{
|
|
data: {
|
|
labels: []
|
|
}
|
|
});
|
|
|
|
await run();
|
|
|
|
expect(setLabelsMock).toHaveBeenCalledTimes(2);
|
|
expect(setLabelsMock).toHaveBeenCalledWith({
|
|
owner: 'monalisa',
|
|
repo: 'helloworld',
|
|
issue_number: 104,
|
|
labels: ['manually-added', 'touched-a-pdf-file']
|
|
});
|
|
expect(setLabelsMock).toHaveBeenCalledWith({
|
|
owner: 'monalisa',
|
|
repo: 'helloworld',
|
|
issue_number: 150,
|
|
labels: ['touched-a-pdf-file']
|
|
});
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'new-labels',
|
|
'touched-a-pdf-file'
|
|
);
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'all-labels',
|
|
'manually-added,touched-a-pdf-file'
|
|
);
|
|
});
|
|
});
|
|
|
|
function usingLabelerConfigYaml(fixtureName: keyof typeof yamlFixtures): void {
|
|
reposMock.mockResolvedValue(<any>{
|
|
data: {content: yamlFixtures[fixtureName], encoding: 'utf8'}
|
|
});
|
|
}
|
|
|
|
function mockGitHubResponseChangedFiles(...files: string[]): void {
|
|
const returnValue = files.map(f => ({filename: f}));
|
|
paginateMock.mockReturnValue(<any>returnValue);
|
|
}
|