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

feat: Toggle pull-request draft status #485

Merged
merged 47 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
a17cba0
Add markPullRequestReadyForReview convertPullRequestToDraft
peaceiris Aug 8, 2021
fb09f4c
Add draft field
peaceiris Aug 8, 2021
2058798
chore: npm run build
peaceiris Aug 8, 2021
2414b99
chore: remove lib/index.js
peaceiris Aug 8, 2021
3809eb5
feat: Enable groupConsoleLog always
peaceiris Aug 8, 2021
91864b7
Add id
peaceiris Aug 9, 2021
73b60f6
chore: npm run build
peaceiris Aug 9, 2021
9714557
chore: remove lib/index.js
peaceiris Aug 9, 2021
46887fc
fix: query format
peaceiris Aug 9, 2021
5117fb9
chore: npm run build
peaceiris Aug 9, 2021
c4ee50a
chore: remove lib/index.js
peaceiris Aug 9, 2021
fa21147
fix: Skip comment if body is empty
peaceiris Aug 9, 2021
00439c7
Add log
peaceiris Aug 9, 2021
d43e26d
chore: npm run build
peaceiris Aug 9, 2021
762d884
chore: remove lib/index.js
peaceiris Aug 9, 2021
0276f64
fix: Add Draft type
peaceiris Aug 9, 2021
25e9b6b
chore: npm run build
peaceiris Aug 9, 2021
42b988e
chore: remove lib/index.js
peaceiris Aug 9, 2021
2a89be3
Dump context
peaceiris Aug 9, 2021
b785a39
chore: npm run build
peaceiris Aug 9, 2021
10d5256
chore: remove lib/index.js
peaceiris Aug 9, 2021
f8ebf22
Dump error.stack
peaceiris Aug 9, 2021
8f1d9e2
Integrate pre-release
peaceiris Aug 9, 2021
bb171f7
chore: npm run build
peaceiris Aug 9, 2021
aec2377
chore: remove lib/index.js
peaceiris Aug 9, 2021
2d35a86
Add source-map
peaceiris Aug 9, 2021
a9fde28
chore: npm run build
peaceiris Aug 9, 2021
c3f963c
chore: remove lib/index.js
peaceiris Aug 9, 2021
fedf1bd
git rev-parse HEAD
peaceiris Aug 9, 2021
99a0849
Fix pre-release task
peaceiris Aug 9, 2021
3c5b8ca
fix: interface IContextLoader
peaceiris Aug 9, 2021
6615ab5
chore(release): Add build assets
peaceiris Aug 9, 2021
d42cfcd
chore(release): Remove build assets [skip ci]
peaceiris Aug 9, 2021
6325bcc
Add type Id
peaceiris Aug 9, 2021
f1812f1
chore(release): Add build assets
peaceiris Aug 9, 2021
caab7b4
chore(release): Remove build assets [skip ci]
peaceiris Aug 9, 2021
523e167
Make id optional
peaceiris Aug 9, 2021
f9cd69c
chore(release): Add build assets
peaceiris Aug 9, 2021
be1e6f6
chore(release): Remove build assets [skip ci]
peaceiris Aug 9, 2021
8f9dbfb
Remove type Id
peaceiris Aug 9, 2021
b17cc73
chore(release): Add build assets
peaceiris Aug 9, 2021
597c259
chore(release): Remove build assets [skip ci]
peaceiris Aug 9, 2021
55d725b
Access optional node_id
peaceiris Aug 9, 2021
06a7f62
chore(release): Add build assets
peaceiris Aug 9, 2021
b281bc3
chore(release): Remove build assets [skip ci]
peaceiris Aug 9, 2021
d2a6db3
test: pr ACTIONS_LABEL_COMMENTER_TEST
peaceiris Aug 10, 2021
aecdba5
Merge branch 'main' into feat-draft
peaceiris Aug 11, 2021
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
1 change: 1 addition & 0 deletions .github/label-commenter-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ labels:
pr:
body: Thank you @{{ pull_request.user.login }} for suggesting this. Please follow the pull request templates.
action: close
draft: true
unlabeled:
issue:
body: Thank you for following the template. The repository owner will reply.
Expand Down
13 changes: 7 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ all:
release:
bash ./scripts/release.sh

.PHONY: pre-release
pre-release:
.PHONY: create-pre-release
create-pre-release:
bash ./scripts/pre-release.sh
git rev-parse HEAD

.PHONY: remove-pre-release
remove-pre-release:
git rm -f ./lib/index.js
git commit -m "chore: remove lib/index.js"
.PHONY: pre-release
pre-release: create-pre-release
git rm -f ./lib/*
git commit -m "chore(release): Remove build assets [skip ci]"
331 changes: 184 additions & 147 deletions __tests__/classes/action-processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ const commentBody = `hello`;
const githubClient = getOctokit('token');
const issueMock: Issue = {
githubClient: githubClient,
id: 'MDExOlB1bGxSZXF1ZXN0NzA2MTE5NTg0',
number: 1,
locked: false,
setLocked: jest.fn(),
createComment: jest.fn(),
updateState: jest.fn(),
lock: jest.fn(),
unlock: jest.fn()
unlock: jest.fn(),
markPullRequestReadyForReview: jest.fn(),
convertPullRequestToDraft: jest.fn()
};
const tests = ['issue', 'pr'];

// beforeAll(() => {
// });
Expand All @@ -25,157 +29,190 @@ afterEach(() => {
jest.resetModules();
});

describe('issue', () => {
test('Comment and close', async () => {
const config: IConfig = {
parentFieldName: 'labels.invalid.labeled.issue',
labelIndex: '0',
action: 'close',
locking: undefined,
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Comment and close', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.invalid.labeled.${t}`,
labelIndex: '0',
action: 'close',
locking: undefined,
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});

test('Comment, close, and lock without lockReason', async () => {
const config: IConfig = {
parentFieldName: 'labels.locked (resolved).labeled.issue',
labelIndex: '0',
action: 'close',
locking: 'lock',
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(1);
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Comment, close, and lock without lockReason', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.locked (resolved).labeled.${t}`,
labelIndex: '0',
action: 'close',
locking: 'lock',
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(1);
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});

test('Comment, close, and lock with lockReason', async () => {
const config: IConfig = {
parentFieldName: 'labels.locked (spam).labeled.issue',
labelIndex: '0',
action: 'close',
locking: 'lock',
lockReason: 'spam'
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(1);
expect(issueMock.lock).toBeCalledWith('spam');
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Comment, close, and lock with lockReason', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.locked (spam).labeled.${t}`,
labelIndex: '0',
action: 'close',
locking: 'lock',
lockReason: 'spam'
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(1);
expect(issueMock.lock).toBeCalledWith('spam');
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});

test('Unlock, open and comment', async () => {
const config: IConfig = {
parentFieldName: 'labels.locked (heated).labeled.issue',
labelIndex: '0',
action: 'open',
locking: 'unlock',
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('open');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(1);
});
describe('Unlock, open and comment', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.locked (heated).labeled.${t}`,
labelIndex: '0',
action: 'open',
locking: 'unlock',
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('open');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(1);
});
}
});

test('Comment and open', async () => {
const config: IConfig = {
parentFieldName: 'labels.invalid.labeled.issue',
labelIndex: '0',
action: 'open',
locking: undefined,
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('open');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Comment and open', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.invalid.labeled.${t}`,
labelIndex: '0',
action: 'open',
locking: undefined,
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(1);
expect(issueMock.createComment).toBeCalledWith(commentBody);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('open');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});

test('Open without comment if the issue is locked', async () => {
const config: IConfig = {
parentFieldName: 'labels.invalid.labeled.issue',
labelIndex: '0',
action: 'open',
locking: undefined,
lockReason: undefined
};
const issueMock: Issue = {
githubClient: githubClient,
number: 1,
locked: true,
setLocked: jest.fn(),
createComment: jest.fn(),
updateState: jest.fn(),
lock: jest.fn(),
unlock: jest.fn()
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(0);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('open');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Open without comment if the issue is locked', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.invalid.labeled.${t}`,
labelIndex: '0',
action: 'open',
locking: undefined,
lockReason: undefined
};
const issueMock: Issue = {
githubClient: githubClient,
id: 'MDExOlB1bGxSZXF1ZXN0NzA2MTE5NTg0',
number: 1,
locked: true,
setLocked: jest.fn(),
createComment: jest.fn(),
updateState: jest.fn(),
lock: jest.fn(),
unlock: jest.fn(),
markPullRequestReadyForReview: jest.fn(),
convertPullRequestToDraft: jest.fn()
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(0);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('open');
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});

test('Skip all actions for a label that has no configuration', async () => {
const config: IConfig = {
parentFieldName: 'labels.unknown.labeled.issue',
labelIndex: '',
action: undefined,
locking: undefined,
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(0);
expect(issueMock.updateState).toBeCalledTimes(0);
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Skip all actions for a label that has no configuration', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.unknown.labeled.${t}`,
labelIndex: '',
action: undefined,
locking: undefined,
lockReason: undefined
};
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(0);
expect(issueMock.updateState).toBeCalledTimes(0);
expect(issueMock.lock).toBeCalledTimes(0);
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});

test('Skip comment if body is empty', async () => {
const config: IConfig = {
parentFieldName: 'labels.spam.labeled.issue',
labelIndex: '1',
action: 'close',
locking: 'lock',
lockReason: 'spam'
};
const commentBody = '';
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(0);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(1);
expect(issueMock.lock).toBeCalledWith('spam');
expect(issueMock.unlock).toBeCalledTimes(0);
});
describe('Skip comment if body is empty', () => {
for (const t of tests) {
test(`${t}`, async () => {
const config: IConfig = {
parentFieldName: `labels.spam.labeled.${t}`,
labelIndex: '1',
action: 'close',
locking: 'lock',
lockReason: 'spam'
};
const commentBody = '';
const actionProcessor = new ActionProcessor(config, commentBody, issueMock);
await actionProcessor.process();
expect(issueMock.createComment).toBeCalledTimes(0);
expect(issueMock.updateState).toBeCalledTimes(1);
expect(issueMock.updateState).toBeCalledWith('closed');
expect(issueMock.lock).toBeCalledTimes(1);
expect(issueMock.lock).toBeCalledWith('spam');
expect(issueMock.unlock).toBeCalledTimes(0);
});
}
});
Loading