Add ClickUp->Redmine migration script
This commit is contained in:
parent
e587f8980b
commit
54782f3d5b
|
@ -0,0 +1,200 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'net/http'
|
||||
require 'thor'
|
||||
require 'json'
|
||||
|
||||
class RedmineMigration < Thor
|
||||
desc "import LIST_ID", "import tickets from a ClickUp list"
|
||||
def import(list_id, project_id, tracker_id)
|
||||
tasks = ClickUp.tasks(list_id)
|
||||
issues = []
|
||||
tasks.each do |task|
|
||||
issue = Issue.new(
|
||||
name: task['name'],
|
||||
description: task['text_content'],
|
||||
status: task['status']['status'],
|
||||
author: task['creator']['email'],
|
||||
estimate: task['time_estimate'], # Check this
|
||||
)
|
||||
print 'T'
|
||||
comments = ClickUp.comments(task['id'])
|
||||
|
||||
comments.each do |comment|
|
||||
c = Comment.new(
|
||||
text: comment['comment_text'],
|
||||
author: comment['user']['email'],
|
||||
)
|
||||
|
||||
issue.comments << c
|
||||
end
|
||||
print 'C'
|
||||
issues << issue
|
||||
end
|
||||
|
||||
issues.each do |issue|
|
||||
issue_response = Redmine.create_issue(
|
||||
issue:,
|
||||
project_id:,
|
||||
tracker_id:,
|
||||
)
|
||||
puts issue.inspect
|
||||
puts issue_response.inspect
|
||||
issue.id = issue_response['issue']['id']
|
||||
issue.comments.each do |comment|
|
||||
next unless comment.class == Comment # I don’t know why I need this 😭
|
||||
|
||||
puts 'goo'
|
||||
puts issue.inspect
|
||||
puts issue_response.inspect
|
||||
Redmine.add_comment(
|
||||
issue_id: issue.id,
|
||||
text: comment.text,
|
||||
author: comment.author,
|
||||
)
|
||||
end if issue.comments.any?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Issue
|
||||
attr_accessor :name, :description, :status, :author, :comments, :estimate, :id
|
||||
|
||||
def initialize(name:, description:, status:, author:, estimate:)
|
||||
@name = name
|
||||
@description = description
|
||||
@status = status
|
||||
@author = author
|
||||
@comments = [],
|
||||
@estimate = estimate
|
||||
end
|
||||
end
|
||||
|
||||
class Comment
|
||||
attr_accessor :text, :author
|
||||
|
||||
def initialize(text:, author:)
|
||||
@text = text
|
||||
@author = author
|
||||
end
|
||||
end
|
||||
|
||||
class Redmine
|
||||
def self.create_issue(issue:, project_id:, tracker_id:)
|
||||
api_call(
|
||||
:post,
|
||||
"issues.json",
|
||||
params: {
|
||||
issue: {
|
||||
project_id: project_id,
|
||||
tracker_id: tracker_id,
|
||||
subject: issue.name,
|
||||
description: issue.description,
|
||||
estimated_hours: issue.estimate,
|
||||
}
|
||||
},
|
||||
as_user: issue.author
|
||||
)
|
||||
end
|
||||
|
||||
def self.add_comment(issue_id:, text:, author: nil)
|
||||
api_call(
|
||||
:put,
|
||||
"issues/#{issue_id}.json",
|
||||
params: {
|
||||
issue: {
|
||||
notes: text,
|
||||
}
|
||||
},
|
||||
as_user: author
|
||||
)
|
||||
end
|
||||
|
||||
def self.api_call(method, path, params: {}, as_user: nil)
|
||||
url = URI.parse("https://redmine.foxsoft.co.uk/#{path}")
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
http.use_ssl = true
|
||||
|
||||
headers = {
|
||||
'Content-Type' => 'application/json',
|
||||
'X-Redmine-API-Key' => api_token,
|
||||
}
|
||||
headers['X-Redmine-Switch-User'] = as_user if as_user
|
||||
case method
|
||||
when :post
|
||||
request = Net::HTTP::Post.new(
|
||||
url,
|
||||
headers
|
||||
)
|
||||
when :put
|
||||
request = Net::HTTP::Put.new(
|
||||
url,
|
||||
headers
|
||||
)
|
||||
end
|
||||
request.body = params.to_json
|
||||
|
||||
response = http.request(request)
|
||||
|
||||
return api_call(method, path, params: params) if response.code.to_i == 412
|
||||
JSON.parse(response.read_body) unless response.is_a?(Net::HTTPNoContent)
|
||||
end
|
||||
|
||||
def self.api_token
|
||||
ENV['REDMINE_API_KEY']
|
||||
end
|
||||
end
|
||||
|
||||
class ClickUp
|
||||
def self.available_workspaces
|
||||
api_call("team")["teams"]
|
||||
end
|
||||
|
||||
def self.folders(workspace_id)
|
||||
api_call("space/#{workspace_id}/folder", params: { archived: false })['folders']
|
||||
end
|
||||
|
||||
def self.spaces
|
||||
api_call("team/#{team_id}/space",
|
||||
params: {archived: false})['spaces']
|
||||
end
|
||||
|
||||
def self.tasks(list_id)
|
||||
api_call("list/#{list_id}/task")['tasks']
|
||||
end
|
||||
|
||||
def self.comments(task_id)
|
||||
api_call("task/#{task_id}/comment")['comments']
|
||||
end
|
||||
|
||||
def self.lists(folder_id)
|
||||
api_call("folder/#{folder_id}/list")['lists']
|
||||
end
|
||||
|
||||
def self.api_call(url, params: {})
|
||||
url = URI("https://api.clickup.com/api/v2/#{url}")
|
||||
url.query = URI.encode_www_form(params)
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
http.use_ssl = true
|
||||
|
||||
request = Net::HTTP::Get.new(url)
|
||||
request['Authorization'] = api_token
|
||||
|
||||
response = http.request(request)
|
||||
json = JSON.parse(response.read_body)
|
||||
if json.has_key?('err')
|
||||
puts "ClickUp API returned an error:"
|
||||
puts "\t#{json['ECODE']}"
|
||||
puts "\t#{json['err']}"
|
||||
exit
|
||||
end
|
||||
|
||||
json
|
||||
end
|
||||
|
||||
def self.api_token
|
||||
ENV['CLICKUP_API_KEY']
|
||||
end
|
||||
end
|
||||
|
||||
RedmineMigration.start
|
Loading…
Reference in New Issue