Skip to content

Commit

Permalink
feat: add create issue command
Browse files Browse the repository at this point in the history
  • Loading branch information
kid-icarus committed May 28, 2024
1 parent b068a6b commit 0dbabe9
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Please follow along with the [initial release discussion](https://github.com/kid

## ⚡️ Requirements

- Install [http.nvim](https://github.com/jcdickinson/http.nvim)
- Instead of using the Jira API directly in all cases, this plugin leverages the [jira-cli tool](https://github.com/ankitpokhrel/jira-cli) to interact with Jira. You'll need to install it and configure it with your Jira credentials in order to use some of the features of this plugin.

## 📦 Installation

Expand Down Expand Up @@ -82,6 +82,7 @@ There is only an Jira <object> <action> [arguments] command.
|---|---|---|
| issue | view [issue_id] | View the given issue, if none provided it will attempt to extract one out of the current git branch (disabled via `use_git_branch_issue_id`), else falls back to a prompt |
| | transition [issue_id] [transition_name] | Transition the ticket to a given status. Will attempt to extract issue ID from git branch, and will prompt if no options given
| | create | Create a new issue. Will prompt for all required fields. It will also prompt you to create a branch with the created issue ID in the name.

Additionally, the transition command has a Telescope picker.

Expand All @@ -95,4 +96,5 @@ There are no default mappings, but you can create your own. Here's an example:
local t = require 'telescope'
vim.keymap.set('n', '<leader>jv', '<cmd>Jira issue view<cr>', {})
vim.keymap.set('n', '<leader>jt', t.extensions.jira.transitions, {})
vim.keymap.set('n', '<leader>jc', '<cmd>Jira issue create<cr>', {})
```
42 changes: 42 additions & 0 deletions lua/jira/api_client.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local utils = require 'jira.utils'
local config = require 'jira.config'
local curl = require 'plenary.curl'
local _, Job = pcall(require, 'plenary.job')

local M = {}
local transition_cache = {}
Expand Down Expand Up @@ -81,4 +82,45 @@ M.transition_issue = function(transition_id, issue_id)
})
end

-- Creates an issue with the given type, summary, and optional description file path
-- @param issue table - the issue to create
-- @param issue.type string - the type of the issue
-- @param issue.summary string - the summary of the issue
-- @param issue.descriptionFile string - the path to the file containing the description
-- @return table - the issue id and link
-- e.g. { issue_id = 'ABC-1234', link = 'https://blah.atlassian.net/ABC-1234' }
M.create_issue = function(issue)
local type = issue.type
local summary = issue.summary
local descriptionFilePath = issue.descriptionFile
assert(type, 'Missing issue type')
assert(summary, 'Missing issue summary')

local args = { 'issue', 'create', '-t', type, '-s', summary }
if descriptionFilePath then
table.insert(args, '-T')
table.insert(args, descriptionFilePath)
end

local job = Job:new {
enable_recording = true,
interactive = false,
command = 'jira',
args = args,
on_exit = function(_, code)
if code ~= 0 then
vim.nofity('Error creating issue', vim.log.levels.ERROR)
end
end,
}
job:sync()
local lines = job:result()
-- last line is the issue id
-- e.g. 'Issue created: ABC-1234'
-- extract the issue id:
-- 'ABC-1234'
local issue_id = lines[#lines]:match '([A-Z]+%-[0-9]+)'
return { issue_id = issue_id, link = lines[#lines] }
end

return M
108 changes: 108 additions & 0 deletions lua/jira/commands.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local api_client = require 'jira.api_client'
local utils = require 'jira.utils'
local M = {}
local config = require 'jira.config'

M.setup = function()
vim.api.nvim_create_user_command('Jira', function(opts)
Expand All @@ -16,6 +17,9 @@ M.setup = function()
transition = function(transition_name, issue_id)
M.transition_issue_name(transition_name, issue_id)
end,
create = function(args)
M.create_issue(args)
end,
},
}
end
Expand Down Expand Up @@ -106,4 +110,108 @@ function M.transition_issue_name(transition_name, issue_id)
end
end

local function get_char_input()
local char = vim.fn.getchar()
-- if char is escape
if char == 27 then
return nil
end
return vim.fn.nr2char(char)
end

local function clear_prompt()
vim.api.nvim_command 'normal! :'
end

-- create a git branch with the issue id
-- @param issue_id string - the issue id to use for the branch
-- @param branch_suffix string - the suffix to append to the branch name
local create_git_branch = function(issue_id, branch_suffix)
local branch_from = config.get_config().git_trunk_branch
vim.ui.input({
prompt = 'Enter branch to create branch from [esc to cancel]: ',
default = branch_from or 'main',
}, function(value)
branch_from = value
end)

if not branch_from or branch_from == '' then
return
end

utils.create_git_branch(issue_id, branch_suffix, branch_from)
end

function M.create_issue(issueType)
if not issueType then
vim.ui.input({
prompt = 'Issue type: ',
default = 'Task',
}, function(value)
issueType = value
end)
end
if not issueType or issueType == '' then
return
end

local summary
vim.ui.input({
prompt = 'Summary: ',
}, function(value)
summary = value
end)

if not summary or summary == '' then
return
end

clear_prompt()
print 'Edit description? (y/N)'
local res = get_char_input()
clear_prompt()
-- if user cancels
if res == nil then
return
end
local edit_description = false
if res:match '\r' or res:match '\n' or res:match 'n' or res:match 'N' then
edit_description = false
end
if res:match 'y' or res:match 'Y' then
edit_description = true
end

if not edit_description then
local r = api_client.create_issue {
type = issueType,
summary = summary,
}
vim.notify(r.link)
create_git_branch(r.issue_id, summary)
return
end

local tempfile = vim.fn.tempname()
local bufnr = vim.api.nvim_create_buf(true, false)
vim.api.nvim_buf_set_name(bufnr, tempfile)
vim.api.nvim_buf_set_option(bufnr, 'filetype', 'markdown')
vim.cmd 'split'
local win = vim.api.nvim_get_current_win()
vim.api.nvim_win_set_buf(win, bufnr)
vim.api.nvim_create_autocmd('BufWritePost', {
buffer = bufnr,
callback = function()
local r = api_client.create_issue {
type = issueType,
summary = summary,
descriptionFile = tempfile,
}
vim.notify(r.link)
create_git_branch(r.issue_id, summary)
vim.api.nvim_buf_delete(bufnr, { force = true })
end,
})
end

return M
5 changes: 5 additions & 0 deletions lua/jira/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ M.defaults = {
token = vim.env.JIRA_API_TOKEN,
},
use_git_branch_issue_id = true,
git_branch_prefix = 'feature/',
}

local config = {}
Expand All @@ -15,6 +16,10 @@ function M.get_config()
return config or M.defaults
end

function M.set_current_issue(issue_id)
config.current_issue = issue_id
end

function M.setup(user_config)
user_config = user_config or {}
config = vim.tbl_deep_extend('force', M.defaults, user_config)
Expand Down
21 changes: 21 additions & 0 deletions lua/jira/utils.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
local M = {}
local _, Job = pcall(require, 'plenary.job')
local config = require 'jira.config'

function Set(list)
local set = {}
Expand Down Expand Up @@ -324,4 +326,23 @@ M.get_issue_id = function(issue_id)
return issue_id
end

M.create_git_branch = function(issue_id, branch_suffix, branch_from)
-- replace whitespace with hyphens
branch_suffix = branch_suffix:gsub('%s', '-')
-- lowercase and strip all non-alphanumeric characters
branch_suffix = branch_suffix:gsub('[^%w-]+', ''):lower()

local branch_prefix = config.get_config().git_branch_prefix
local branch = branch_prefix .. issue_id .. '/' .. branch_suffix
Job:new({
command = 'git',
args = { 'branch', branch, branch_from or 'main' },
on_exit = function(_, code)
if code ~= 0 then
vim.notify('Error creating branch', vim.log.levels.ERROR)
end
end,
}):sync()
end

return M

0 comments on commit 0dbabe9

Please sign in to comment.