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 updating existing open issue with the same title if it exists #71

Merged
merged 25 commits into from
Dec 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2801877
Add updating existing open issue with the same title if it exists
PrinsFrank Nov 7, 2020
d72764d
Remove detailed error handling
PrinsFrank Nov 9, 2020
887a28f
Updated updateExisting boolean logic
PrinsFrank Nov 9, 2020
6f32d24
Use search api instead of issues api to retrieve the issue to update
PrinsFrank Nov 9, 2020
9a624e8
Add debug output
PrinsFrank Nov 9, 2020
92e9d03
Move order from q parameter to it's own parameter
PrinsFrank Nov 9, 2020
12b969b
Change search in title query format
PrinsFrank Nov 9, 2020
30b4e8b
Get the first existing item
PrinsFrank Nov 9, 2020
888eb9a
Readd debug info
PrinsFrank Nov 9, 2020
a375984
Readd debug info
PrinsFrank Nov 9, 2020
554e4ce
get items from data key
PrinsFrank Nov 9, 2020
28e26f1
fix incorrect issue to issues api key
PrinsFrank Nov 9, 2020
3771399
Add debugging output for issue to update
PrinsFrank Nov 9, 2020
a63d82d
Add debugging output for issue to update
PrinsFrank Nov 9, 2020
386a450
Use correct issue key for number property
PrinsFrank Nov 9, 2020
ce5f9f5
More debugging info
PrinsFrank Nov 9, 2020
8990bf6
More debugging info
PrinsFrank Nov 9, 2020
47db154
More debugging info
PrinsFrank Nov 9, 2020
7ad7797
Add missing repo context
PrinsFrank Nov 9, 2020
5d9ceef
Remove debugging info
PrinsFrank Nov 9, 2020
2045b7e
Exit on updated issue
PrinsFrank Nov 9, 2020
2c8e282
Change update_existing option in the readme to boolean instead of string
PrinsFrank Nov 9, 2020
8f88328
Add tests for updating an existing issue when it exists
PrinsFrank Nov 10, 2020
4bbf357
Processed feedback (Check on templated title, truthyness check, capit…
PrinsFrank Nov 12, 2020
7b908a1
Update tests after checking more strictly on titles
PrinsFrank Nov 12, 2020
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ steps:

### Inputs

Want to use Action logic to determine who to assign the issue to? You can pass an input containing the following options:
Want to use Action logic to determine who to assign the issue to, to assign a milestone or to update an existing issue with the same title? You can pass an input containing the following options:

```yaml
steps:
Expand All @@ -84,8 +84,11 @@ steps:
with:
assignees: JasonEtco, octocat
milestone: 1
update_existing: true
```

The `assignees` and `milestone` speak for themselves, the `update_existing` param can be passed and set to `true` when you want an existing open issue with the **exact same title** when it exists.

### Outputs

If you need the number or URL of the issue that was created for another Action, you can use the `number` or `url` outputs, respectively. For example:
Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ branding:
inputs:
assignees:
description: GitHub handle of the user(s) to assign the issue (comma-separated)
required: false
milestone:
description: Number of the milestone to assign the issue to
required: false
filename:
description: The name of the file to use as the issue template
default: .github/ISSUE_TEMPLATE.md
required: false
update_existing:
description: Update an open existing issue with the same title if it exists
required: false
outputs:
number:
description: Number of the issue that was created
Expand Down
33 changes: 31 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function listToArray (list) {
Toolkit.run(async tools => {
const template = tools.inputs.filename || '.github/ISSUE_TEMPLATE.md'
const assignees = tools.inputs.assignees
const updateExisting = Boolean(tools.inputs.update_existing)
const env = nunjucks.configure({ autoescape: false })
env.addFilter('date', dateFilter)

Expand All @@ -33,11 +34,39 @@ Toolkit.run(async tools => {
body: env.renderString(body, templateVariables),
title: env.renderString(attributes.title, templateVariables)
}

tools.log.debug('Templates compiled', templated)
tools.log.info(`Creating new issue ${templated.title}`)

if (updateExisting) {
let existingIssue
tools.log.info(`Fetching issues with title "${templated.title}"`)
try {
const existingIssues = await tools.github.search.issuesAndPullRequests({
q: `is:open is:issue repo:${process.env.GITHUB_REPOSITORY} in:title ${templated.title}`,
order: 'created'
})
existingIssue = existingIssues.data.items.find(issue => issue.title === templated.title)
} catch (err) {
tools.exit.failure(err)
}
if (existingIssue) {
try {
const issue = await tools.github.issues.update({
...tools.context.repo,
issue_number: existingIssue.number,
body: templated.body
})
core.setOutput('number', String(issue.data.number))
core.setOutput('url', issue.data.html_url)
tools.exit.success(`Updated issue ${issue.data.title}#${issue.data.number}: ${issue.data.html_url}`)
} catch (err) {
tools.exit.failure(err)
}
}
tools.log.info('No existing issue found to update')
}

// Create the new issue
tools.log.info(`Creating new issue ${templated.title}`)
try {
const issue = await tools.github.issues.create({
...tools.context.repo,
Expand Down
26 changes: 26 additions & 0 deletions tests/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ Array [
]
`;

exports[`create-an-issue creates a new issue when updating existing issues is enabled but no issues with the same title exist 1`] = `
Object {
"assignees": Array [
"octocat",
"JasonEtco",
],
"body": "Goodbye!",
"labels": Array [],
"milestone": "1",
"title": "Hello!",
}
`;

exports[`create-an-issue creates a new issue with a milestone passed by input 1`] = `
Object {
"assignees": Array [
Expand Down Expand Up @@ -179,3 +192,16 @@ Array [
],
]
`;

exports[`create-an-issue updates an existing issue with the same title 1`] = `
Object {
"assignees": Array [
"octocat",
"JasonEtco",
],
"body": "Goodbye!",
"labels": Array [],
"milestone": "1",
"title": "Hello!",
}
`;
51 changes: 51 additions & 0 deletions tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,57 @@ describe('create-an-issue', () => {
expect(tools.log.success).toHaveBeenCalled()
})

it('creates a new issue when updating existing issues is enabled but no issues with the same title exist', async () => {
nock.cleanAll()
nock('https://api.github.com')
.get(/\/search\/issues.*/).reply(200, {
items: []
})
.post(/\/repos\/.*\/.*\/issues/).reply(200, (_, body) => {
params = body
return {
title: body.title,
number: 1,
html_url: 'www'
}
})

process.env.INPUT_UPDATE_EXISTING = 'true'

await actionFn(tools)
expect(params).toMatchSnapshot()
expect(tools.log.info).toHaveBeenCalledWith('No existing issue found to update')
expect(tools.log.success).toHaveBeenCalled()
})

it('updates an existing issue with the same title', async () => {
nock.cleanAll()
nock('https://api.github.com')
.get(/\/search\/issues.*/).reply(200, {
items: [{ number: 1, title: 'Hello!' }]
})
.patch(/\/repos\/.*\/.*\/issues\/.*/).reply(200, {})
process.env.INPUT_UPDATE_EXISTING = 'true'

await actionFn(tools)
expect(params).toMatchSnapshot()
expect(tools.exit.success).toHaveBeenCalled()
})

it('exits when updating an issue fails', async () => {
nock.cleanAll()
nock('https://api.github.com')
.get(/\/search\/issues.*/).reply(200, {
items: [{ number: 1, title: 'Hello!' }]
})
.patch(/\/repos\/.*\/.*\/issues\/.*/).reply(500, {
message: 'Updating issue failed'
})

await actionFn(tools)
expect(tools.exit.failure).toHaveBeenCalled()
})

it('logs a helpful error if creating an issue throws an error', async () => {
nock.cleanAll()
nock('https://api.github.com')
Expand Down