redmine_remotes 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/project_remote_issues_controller.rb +44 -0
- data/app/controllers/remote_issues_controller.rb +14 -0
- data/app/models/redmine_remotes/tableless/add_remote_issue/_local_issue.rb +57 -0
- data/app/models/redmine_remotes/tableless/add_remote_issue/_provider_issue.rb +19 -0
- data/app/models/redmine_remotes/tableless/add_remote_issue/_remote_issue.rb +27 -0
- data/app/models/redmine_remotes/tableless/add_remote_issue.rb +65 -0
- data/app/models/remote_issue.rb +17 -0
- data/app/models/remote_tracker/_jira.rb +11 -0
- data/app/models/remote_tracker.rb +12 -1
- data/app/models/remote_user.rb +4 -2
- data/app/views/project_remote_issues/_trackers.html.erb +30 -0
- data/app/views/project_remote_issues/index.html.erb +2 -0
- data/app/views/project_remote_issues/new.html.erb +12 -0
- data/config/initializers/001_patches.rb +1 -0
- data/config/initializers/nonproject_modules.rb +6 -0
- data/config/locales/en.yml +6 -2
- data/config/locales/pt-BR.yml +6 -2
- data/config/routes.rb +7 -0
- data/db/migrate/20190912000000_create_remote_issues.rb +13 -0
- data/init.rb +10 -0
- data/lib/redmine_remotes/jira/entities/issue.rb +37 -0
- data/lib/redmine_remotes/jira/instance.rb +26 -0
- data/lib/redmine_remotes/patches/issue.rb +20 -0
- data/lib/redmine_remotes/rest_provider/entity.rb +18 -0
- data/lib/redmine_remotes/rest_provider/http_response.rb +31 -0
- data/lib/redmine_remotes/rest_provider/instance.rb +53 -0
- data/lib/redmine_remotes/version.rb +1 -1
- data/lib/tasks/redmine_remotes.rake +24 -0
- metadata +74 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9520f14afbdb893e412eb0147142ac2ceee118152436f62a8a2d2e9a6b0b48dd
|
4
|
+
data.tar.gz: f388fd2ae10c72cec289ad779a994fd099748e991878e275bba9b2ed645adedc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d86ac7fb4ba1d2a0c687770f453645ee2738acc6c8110df8f5b85ea716c0ce53cfa744517a130e779183f666cdc2d4263215e229b1305828bddae1b895708c04
|
7
|
+
data.tar.gz: 2477b10e006b1240faa0ddf2374def403e65878686a74f54fc1744e7df08327da7ed541cd1f49d7bd939a9e810f2b29964bfcbabdaed45c8119a8019da3bd868
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ProjectRemoteIssuesController < ApplicationController
|
4
|
+
before_action :find_project
|
5
|
+
before_action :find_remote_tracker, only: %i[create new]
|
6
|
+
|
7
|
+
def index
|
8
|
+
@trackers = ::RemoteTracker.order(profile: :asc, root_url: :asc, username: :asc)
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
@add_issue = model_class.new(context_params)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
@add_issue = model_class.new(create_params)
|
17
|
+
if @add_issue.save
|
18
|
+
flash[:notice] = "Demanda salva: \##{@add_issue.local_issue.id}"
|
19
|
+
redirect_to url_for(action: 'index', id: @project.identifier, tracker_id: @remote_tracker.id)
|
20
|
+
else
|
21
|
+
render 'new'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def model_class
|
28
|
+
::RedmineRemotes::Tableless::AddRemoteIssue
|
29
|
+
end
|
30
|
+
|
31
|
+
def context_params
|
32
|
+
{ project_id: @project.id, remote_tracker_id: @remote_tracker.id }
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_params
|
36
|
+
params.fetch(model_class.model_name.param_key).permit(
|
37
|
+
:issue_remote_code, :local_tracker_id
|
38
|
+
).merge(context_params)
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_remote_tracker
|
42
|
+
@remote_tracker = ::RemoteTracker.find(params[:tracker_id])
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RemoteIssuesController < ApplicationController
|
4
|
+
READ_PERMISSION = 'remote_issue.read'
|
5
|
+
WRITE_PERMISSION = 'remote_issue.write'
|
6
|
+
PERMISSIONS = READ_PERMISSION
|
7
|
+
|
8
|
+
layout 'nonproject_modules'
|
9
|
+
require_permission PERMISSIONS
|
10
|
+
|
11
|
+
active_scaffold :remote_issue do |conf|
|
12
|
+
conf.columns[:tracker].form_ui = :select
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedmineRemotes
|
4
|
+
module Tableless
|
5
|
+
class AddRemoteIssue < ::EacRailsUtils::TablelessModel
|
6
|
+
private
|
7
|
+
|
8
|
+
def create_local_issue
|
9
|
+
return true if local_issue.save
|
10
|
+
|
11
|
+
fetch_record_errors(local_issue, default_column: :issue_remote_code)
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def local_issue_uncached
|
16
|
+
::Issue.new(
|
17
|
+
subject: local_issue_subject, project: project, tracker: local_tracker,
|
18
|
+
priority: local_issue_priority, author: local_issue_author, status: local_issue_status,
|
19
|
+
created_on: provider_issue.created_on, updated_on: provider_issue.updated_on
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def local_issue_priority
|
24
|
+
::IssuePriority.default
|
25
|
+
end
|
26
|
+
|
27
|
+
def local_issue_subject
|
28
|
+
"[#{provider_issue.code}] #{provider_issue.subject}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def local_issue_author_uncached
|
32
|
+
return nil if provider_issue.blank?
|
33
|
+
|
34
|
+
::RemoteUser.find_local_user(
|
35
|
+
provider_issue.author_login,
|
36
|
+
remote_tracker
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def local_issue_status
|
41
|
+
local_issue_status_from_remote_tracker || local_issue_status_from_local_tracker
|
42
|
+
end
|
43
|
+
|
44
|
+
def local_issue_status_from_remote_tracker
|
45
|
+
::RemoteIssueStatus.find_local_issue_status(
|
46
|
+
provider_issue.status_name,
|
47
|
+
remote_tracker,
|
48
|
+
local_tracker
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def local_issue_status_from_local_tracker
|
53
|
+
local_tracker.default_status
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedmineRemotes
|
4
|
+
module Tableless
|
5
|
+
class AddRemoteIssue < ::EacRailsUtils::TablelessModel
|
6
|
+
private
|
7
|
+
|
8
|
+
def provider_issue_uncached
|
9
|
+
return nil unless remote_tracker.present? && issue_remote_code.present?
|
10
|
+
|
11
|
+
remote_tracker.find_remote_issue(issue_remote_code)
|
12
|
+
rescue ::RedmineRemotes::RestProvider::HttpResponse => e
|
13
|
+
errors.add(:issue_remote_code, "Requisição a \"#{e.url}\" retornou com status #{e.status}")
|
14
|
+
puts "====> #{e.body}"
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedmineRemotes
|
4
|
+
module Tableless
|
5
|
+
class AddRemoteIssue < ::EacRailsUtils::TablelessModel
|
6
|
+
private
|
7
|
+
|
8
|
+
def create_remote_issue
|
9
|
+
return true if remote_issue.save
|
10
|
+
|
11
|
+
fetch_record_errors(remote_issue, default_column: :issue_remote_code)
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def update_remote_issue_with_issue
|
16
|
+
return true if remote_issue.update(local_issue: local_issue)
|
17
|
+
|
18
|
+
fetch_record_errors(remote_issue, default_column: :issue_remote_code)
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def remote_issue_uncached
|
23
|
+
::RemoteIssue.new(remote_tracker: remote_tracker, remote_code: issue_remote_code)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eac_ruby_utils/require_sub'
|
4
|
+
require 'eac_ruby_utils/simple_cache'
|
5
|
+
require 'eac/model'
|
6
|
+
|
7
|
+
module RedmineRemotes
|
8
|
+
module Tableless
|
9
|
+
class AddRemoteIssue < ::EacRailsUtils::TablelessModel
|
10
|
+
include ::EacRubyUtils::SimpleCache
|
11
|
+
include ::Eac::Model
|
12
|
+
::EacRubyUtils.require_sub(__FILE__)
|
13
|
+
|
14
|
+
attribute :issue_remote_code, ::String
|
15
|
+
attribute :local_tracker_id, ::Integer
|
16
|
+
attribute :project_id, ::Integer
|
17
|
+
attribute :remote_tracker_id, ::Integer
|
18
|
+
|
19
|
+
belongs_to :local_tracker, class_name: 'Tracker'
|
20
|
+
belongs_to :project, class_name: 'Project'
|
21
|
+
belongs_to :remote_tracker, class_name: 'RemoteTracker'
|
22
|
+
|
23
|
+
validates :local_tracker, presence: true
|
24
|
+
validates :remote_tracker, presence: true
|
25
|
+
validates :project, presence: true
|
26
|
+
validates :issue_remote_code, presence: true
|
27
|
+
|
28
|
+
validate :tracker_in_project
|
29
|
+
validate :author_present
|
30
|
+
validate :provider_issue_present
|
31
|
+
|
32
|
+
def save
|
33
|
+
return false unless valid?
|
34
|
+
return false unless create_remote_issue
|
35
|
+
return false unless create_local_issue
|
36
|
+
return false unless update_remote_issue_with_issue
|
37
|
+
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
def tracker_in_project
|
42
|
+
return unless local_tracker.present? && project.present?
|
43
|
+
return if project.trackers.include?(local_tracker)
|
44
|
+
|
45
|
+
errors.add(:local_tracker, 'is not a tracker of project')
|
46
|
+
end
|
47
|
+
|
48
|
+
def author_present
|
49
|
+
return if provider_issue.blank?
|
50
|
+
return if local_issue_author.present?
|
51
|
+
|
52
|
+
errors.add(:remote_code,
|
53
|
+
"Usuário local não encontrado para \"#{provider_issue.author_login}\"")
|
54
|
+
end
|
55
|
+
|
56
|
+
def provider_issue_present
|
57
|
+
return if issue_remote_code.blank?
|
58
|
+
return if provider_issue.present?
|
59
|
+
|
60
|
+
errors.add(:remote_code,
|
61
|
+
"Demanda remota não encontrada com o código \"#{issue_remote_code}\"")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RemoteIssue < ActiveRecord::Base
|
4
|
+
include ::RedmineRemotes::Sanitizer
|
5
|
+
|
6
|
+
downcase_columns :remote_code
|
7
|
+
|
8
|
+
belongs_to :remote_tracker, class_name: 'RemoteTracker', inverse_of: :issues
|
9
|
+
belongs_to :local_issue, class_name: 'Issue', inverse_of: :remote_issue
|
10
|
+
|
11
|
+
validates :remote_tracker, presence: true
|
12
|
+
validates :remote_code, presence: true, uniqueness: { scope: [:remote_tracker] }
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"#{remote_tracker}|#{remote_code}"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RemoteTracker < ActiveRecord::Base
|
4
|
+
def jira_find_remote_issue(issue_id)
|
5
|
+
jira_create_instance.find_issue(issue_id)
|
6
|
+
end
|
7
|
+
|
8
|
+
def jira_create_instance
|
9
|
+
::RedmineRemotes::Jira::Instance.new(root_url, username, password)
|
10
|
+
end
|
11
|
+
end
|
@@ -4,9 +4,14 @@ require 'eac_ruby_utils/listable'
|
|
4
4
|
require 'validate_url'
|
5
5
|
|
6
6
|
class RemoteTracker < ActiveRecord::Base
|
7
|
+
require_relative 'remote_tracker/_jira'
|
8
|
+
|
7
9
|
include ::EacRubyUtils::Listable
|
8
10
|
|
9
|
-
|
11
|
+
has_many :issues, class_name: 'RemoteIssue', inverse_of: :remote_tracker,
|
12
|
+
dependent: :restrict_with_error
|
13
|
+
|
14
|
+
lists.add_string :profile, :jira
|
10
15
|
|
11
16
|
has_many :issue_statuses, class_name: 'RemoteIssueStatus', inverse_of: :remote_tracker,
|
12
17
|
dependent: :destroy
|
@@ -23,4 +28,10 @@ class RemoteTracker < ActiveRecord::Base
|
|
23
28
|
def to_s
|
24
29
|
"#{root_url} [#{profile_label}, #{username}]"
|
25
30
|
end
|
31
|
+
|
32
|
+
def find_remote_issue(issue_id)
|
33
|
+
raise 'Profile blank' if profile.blank?
|
34
|
+
|
35
|
+
send("#{profile}_find_remote_issue", issue_id)
|
36
|
+
end
|
26
37
|
end
|
data/app/models/remote_user.rb
CHANGED
@@ -12,14 +12,16 @@ class RemoteUser < ActiveRecord::Base
|
|
12
12
|
validates :local_user, presence: true
|
13
13
|
|
14
14
|
class << self
|
15
|
-
def find_local_user(remote_login,
|
16
|
-
[
|
15
|
+
def find_local_user(remote_login, remote_tracker = nil)
|
16
|
+
[remote_tracker, nil].each do |tracker|
|
17
17
|
remote_user = ::RemoteUser.where(
|
18
18
|
remote_tracker: tracker,
|
19
19
|
remote_login: remote_login_sanitize(remote_login)
|
20
20
|
).first
|
21
21
|
return remote_user.local_user if remote_user
|
22
22
|
end
|
23
|
+
return remote_tracker.default_local_user if remote_tracker.present?
|
24
|
+
|
23
25
|
nil
|
24
26
|
end
|
25
27
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<h3>Trackers</h3>
|
2
|
+
<% if @trackers.any? %>
|
3
|
+
<table class="list files">
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<th>Profile</th>
|
7
|
+
<th>Root URL</th>
|
8
|
+
<th>Username</th>
|
9
|
+
<th></th>
|
10
|
+
</tr>
|
11
|
+
</thead>
|
12
|
+
<tbody>
|
13
|
+
<% @trackers.each do |tracker| %>
|
14
|
+
<tr>
|
15
|
+
<td><%= tracker.profile %></td>
|
16
|
+
<td><%= tracker.root_url %></td>
|
17
|
+
<td><%= tracker.username %></td>
|
18
|
+
<td class="buttons">
|
19
|
+
<%= link_to 'Add issue', new_project_remote_issue_path(
|
20
|
+
id: @project.identifier,
|
21
|
+
tracker_id: tracker.id
|
22
|
+
) %>
|
23
|
+
</td>
|
24
|
+
</tr>
|
25
|
+
<% end %>
|
26
|
+
</tbody>
|
27
|
+
</table>
|
28
|
+
<% else %>
|
29
|
+
<p><em>No trackers registered.</em></p>
|
30
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h2><%= @tracker %> » Add Remote Issue</h2>
|
2
|
+
<%= labelled_form_for @add_issue, :url => create_project_remote_issue_path(
|
3
|
+
id: @project.identifier,
|
4
|
+
tracker_id: @remote_tracker.id
|
5
|
+
), method: :post do |f| %>
|
6
|
+
<%= error_messages_for 'add_issue' %>
|
7
|
+
<div class="box tabular">
|
8
|
+
<p><%= f.select :local_tracker_id, @project.trackers.map {|t| [t.to_s, t.id]} %></p>
|
9
|
+
<p><%= f.text_field :issue_remote_code %></p>
|
10
|
+
</div>
|
11
|
+
<%= submit_tag l(:button_save) %>
|
12
|
+
<% end %>
|
@@ -5,6 +5,11 @@
|
|
5
5
|
::RemoteTrackersController::WRITE_PERMISSION,
|
6
6
|
dependencies: [::RemoteTrackersController::READ_PERMISSION]
|
7
7
|
)
|
8
|
+
::GroupPermission.add_permission(::RemoteIssuesController::READ_PERMISSION)
|
9
|
+
::GroupPermission.add_permission(
|
10
|
+
::RemoteIssuesController::WRITE_PERMISSION,
|
11
|
+
dependencies: [::RemoteIssuesController::READ_PERMISSION]
|
12
|
+
)
|
8
13
|
::GroupPermission.add_permission(::RemoteIssueStatusesController::READ_PERMISSION)
|
9
14
|
::GroupPermission.add_permission(
|
10
15
|
::RemoteIssueStatusesController::WRITE_PERMISSION,
|
@@ -18,6 +23,7 @@
|
|
18
23
|
|
19
24
|
Redmine::MenuManager.map ::RedmineRemotes::SLUG.to_sym do |menu|
|
20
25
|
menu.push_controller(:remote_trackers)
|
26
|
+
menu.push_controller(:remote_issues)
|
21
27
|
menu.push_controller(:remote_issue_statuses)
|
22
28
|
menu.push_controller(:remote_users)
|
23
29
|
end
|
data/config/locales/en.yml
CHANGED
@@ -3,8 +3,12 @@ en:
|
|
3
3
|
listable:
|
4
4
|
remote_tracker:
|
5
5
|
profile:
|
6
|
-
|
7
|
-
label:
|
6
|
+
jira:
|
7
|
+
label: Jira
|
8
|
+
field_issue_remote_code: Remote issue's code
|
9
|
+
field_local_tracker: Local tracker
|
10
|
+
label_remote_issues: Remote issues
|
8
11
|
label_remote_trackers: Remote trackers
|
9
12
|
label_remote_issue_statuses: Remote issue statuses
|
10
13
|
label_remote_users: Remote users
|
14
|
+
label_remotes: Remotes
|
data/config/locales/pt-BR.yml
CHANGED
@@ -3,8 +3,12 @@ pt-BR:
|
|
3
3
|
listable:
|
4
4
|
remote_tracker:
|
5
5
|
profile:
|
6
|
-
|
7
|
-
label:
|
6
|
+
jira:
|
7
|
+
label: Jira
|
8
|
+
field_issue_remote_code: Código da demanda remota
|
9
|
+
field_local_tracker: Tipo de tarefa local
|
10
|
+
label_remote_issues: Demandas remotas
|
8
11
|
label_remote_trackers: Trackers remotos
|
9
12
|
label_remote_issue_statuses: Situações de demandas remotas
|
10
13
|
label_remote_users: Usuários remotos
|
14
|
+
label_remotes: Remotos
|
data/config/routes.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RedmineApp::Application.routes.draw do
|
4
|
+
get '/projects/:id/remotes', to: 'project_remote_issues#index'
|
5
|
+
get '/projects/:id/tracker/:tracker_id/new_issue', to: 'project_remote_issues#new',
|
6
|
+
as: 'new_project_remote_issue'
|
7
|
+
post '/projects/:id/tracker/:tracker_id/new_issue', to: 'project_remote_issues#create',
|
8
|
+
as: 'create_project_remote_issue'
|
9
|
+
resources(:project_remote_issues, only: [:index])
|
4
10
|
resources(:remote_trackers) { as_routes }
|
11
|
+
resources(:remote_issues) { as_routes }
|
5
12
|
resources(:remote_issue_statuses) { as_routes }
|
6
13
|
resources(:remote_users) { as_routes }
|
7
14
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateRemoteIssues < ActiveRecord::Migration
|
4
|
+
def change
|
5
|
+
create_table :remote_issues do |t|
|
6
|
+
t.references :remote_tracker, index: true
|
7
|
+
t.references :local_issue, index: true, nullable: true
|
8
|
+
t.string :remote_code
|
9
|
+
end
|
10
|
+
add_foreign_key :remote_issues, :remote_trackers, column: :remote_tracker_id
|
11
|
+
add_foreign_key :remote_issues, :issues, column: :local_issue_id
|
12
|
+
end
|
13
|
+
end
|
data/init.rb
CHANGED
@@ -7,4 +7,14 @@ Redmine::Plugin.register ::RedmineRemotes::SLUG.to_sym do
|
|
7
7
|
author ::RedmineRemotes::AUTHOR
|
8
8
|
description ::RedmineRemotes::SUMMARY
|
9
9
|
version ::RedmineRemotes::VERSION
|
10
|
+
|
11
|
+
project_module :redmine_remotes do
|
12
|
+
permission :view_trackers, project_remote_issues: [:index]
|
13
|
+
permission :add_issues, project_remote_issues: %i[new create]
|
14
|
+
end
|
15
|
+
|
16
|
+
Redmine::MenuManager.map :project_menu do |menu|
|
17
|
+
menu.push :remotes_issues, { controller: 'project_remote_issues', action: 'index' },
|
18
|
+
caption: :label_remotes, after: :issues
|
19
|
+
end
|
10
20
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedmineRemotes
|
4
|
+
module Jira
|
5
|
+
module Entities
|
6
|
+
class Issue < ::RedmineRemotes::RestProvider::Entity
|
7
|
+
def code
|
8
|
+
data.fetch('key')
|
9
|
+
end
|
10
|
+
|
11
|
+
def created_on
|
12
|
+
fields.fetch('created')
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields
|
16
|
+
data.fetch('fields')
|
17
|
+
end
|
18
|
+
|
19
|
+
def subject
|
20
|
+
fields.fetch('summary')
|
21
|
+
end
|
22
|
+
|
23
|
+
def status_name
|
24
|
+
fields.fetch('status').fetch('name')
|
25
|
+
end
|
26
|
+
|
27
|
+
def updated_on
|
28
|
+
fields.fetch('updated')
|
29
|
+
end
|
30
|
+
|
31
|
+
def author_login
|
32
|
+
fields.fetch('reporter').fetch('key')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedmineRemotes
|
4
|
+
module Jira
|
5
|
+
class Instance < ::RedmineRemotes::RestProvider::Instance
|
6
|
+
ISSUE_ID_PATTERN = /\A([a-z][a-z0-9]+)\-(\d+)\z/i.freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def parse_issue_id(global_issue_id)
|
10
|
+
m = ISSUE_ID_PATTERN.match(global_issue_id)
|
11
|
+
return nil unless m
|
12
|
+
|
13
|
+
::OpenStruct.new(provider_issue_id: m[0], project_id: m[1], project_issue_id: m[2])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_service_url(service_url_suffix)
|
18
|
+
"#{root_url}/rest/api/latest#{service_url_suffix}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def issue_get_url_suffix(provider_issue_id)
|
22
|
+
"/issue/#{provider_issue_id}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EacRedmineUsability
|
4
|
+
module Patches
|
5
|
+
module Issue
|
6
|
+
extend ::ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
has_one :remote_issue, class_name: 'RemoteIssue',
|
10
|
+
inverse_of: :local_issue, dependent: :restrict_with_error,
|
11
|
+
foreign_key: :local_issue_id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_dependency 'issue'
|
18
|
+
patch = ::EacRedmineUsability::Patches::Issue
|
19
|
+
target = ::Issue
|
20
|
+
target.send(:include, patch) unless target.included_modules.include?(patch)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eac_ruby_utils/simple_cache'
|
4
|
+
|
5
|
+
module RedmineRemotes
|
6
|
+
module RestProvider
|
7
|
+
class Entity
|
8
|
+
include ::EacRubyUtils::SimpleCache
|
9
|
+
|
10
|
+
attr_reader :instance, :data
|
11
|
+
|
12
|
+
def initialize(instance, data)
|
13
|
+
@instance = instance
|
14
|
+
@data = data
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedmineRemotes
|
4
|
+
module RestProvider
|
5
|
+
class HttpResponse < ::StandardError
|
6
|
+
class << self
|
7
|
+
def new_from_curl_easy(curl_easy)
|
8
|
+
new(
|
9
|
+
curl_easy.url,
|
10
|
+
curl_easy.status.to_i,
|
11
|
+
curl_easy.body_str
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :url, :status, :body
|
17
|
+
|
18
|
+
def initialize(url, status, body)
|
19
|
+
@url = url
|
20
|
+
@status = status
|
21
|
+
@body = body
|
22
|
+
end
|
23
|
+
|
24
|
+
def body_or_raise
|
25
|
+
return body if status == 200
|
26
|
+
|
27
|
+
raise self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'curb'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module RedmineRemotes
|
7
|
+
module RestProvider
|
8
|
+
# Abstract methods
|
9
|
+
# * parse_issue_id(global_issue_id)
|
10
|
+
# * self.build_service_url(service_url_suffix)
|
11
|
+
# * self.issue_get_url_suffix(provider_issue_id)
|
12
|
+
class Instance
|
13
|
+
attr_reader :root_url, :username, :password
|
14
|
+
|
15
|
+
def initialize(root_url, username, password)
|
16
|
+
@root_url = root_url
|
17
|
+
@username = username
|
18
|
+
@password = password
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_issue(global_issue_id)
|
22
|
+
parsed = self.class.parse_issue_id(global_issue_id)
|
23
|
+
parsed.present? ? issue(parsed.provider_issue_id) : nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def issue(provider_issue_id)
|
27
|
+
issue_class.new(self, request(issue_get_url_suffix(provider_issue_id)))
|
28
|
+
end
|
29
|
+
|
30
|
+
def request(service_url_suffix)
|
31
|
+
JSON.parse(curl_perform(service_url_suffix).body_or_raise)
|
32
|
+
end
|
33
|
+
|
34
|
+
def issue_class
|
35
|
+
"#{self.class.name.deconstantize}::Entities::Issue".constantize
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# @return [RedmineRemotes::RestProvider::HttpResponse]
|
41
|
+
def curl_perform(service_url_suffix)
|
42
|
+
c = ::Curl::Easy.new(build_service_url(service_url_suffix))
|
43
|
+
c.http_auth_types = :basic
|
44
|
+
c.username = username
|
45
|
+
c.password = password
|
46
|
+
c.headers['Accept'] = 'application/json'
|
47
|
+
return ::RedmineRemotes::RestProvider::HttpResponse.new_from_curl_easy(c) if c.perform
|
48
|
+
|
49
|
+
raise 'Curl failed'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -8,4 +8,28 @@ namespace :redmine_remotes do
|
|
8
8
|
t.verbose = false
|
9
9
|
t.warning = false
|
10
10
|
end
|
11
|
+
|
12
|
+
namespace :issues do
|
13
|
+
desc 'Adds a remote issue.'
|
14
|
+
task :add, [:remote_tracker_id, :issue_remote_code, :project_identifier, :local_tracker_id] => :environment do |t, args|
|
15
|
+
remote_tracker = ::RemoteTracker.find(args.remote_tracker_id)
|
16
|
+
::Rails.logger.info("Remote tracker: #{remote_tracker}")
|
17
|
+
|
18
|
+
project = ::Project.find_by_identifier(args.project_identifier)
|
19
|
+
::Rails.logger.info("Project: #{project}")
|
20
|
+
|
21
|
+
local_tracker = args.local_tracker_id ? ::Tracker.find(args.local_tracker_id) : project.trackers.first
|
22
|
+
::Rails.logger.info("Local tracker: #{local_tracker}")
|
23
|
+
|
24
|
+
add = ::RedmineRemotes::Tableless::AddRemoteIssue.new(
|
25
|
+
remote_tracker: remote_tracker, project: project, local_tracker: local_tracker,
|
26
|
+
issue_remote_code: args.issue_remote_code
|
27
|
+
)
|
28
|
+
if add.save
|
29
|
+
::Rails.logger.info "[Success] Issue ID: \"#{add.local_issue.id}\""
|
30
|
+
else
|
31
|
+
::Rails.logger.info "[Failed] #{add.errors.messages.pretty_inspect}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
11
35
|
end
|
metadata
CHANGED
@@ -1,15 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redmine_remotes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eduardo Henrique Bogoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aranha-parsers
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.2.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.2.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: curb
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.9'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.9.10
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.9'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.9.10
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: eac_rails_utils
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.5'
|
60
|
+
type: :runtime
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.5'
|
13
67
|
- !ruby/object:Gem::Dependency
|
14
68
|
name: eac_ruby_utils
|
15
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,12 +110,23 @@ executables: []
|
|
56
110
|
extensions: []
|
57
111
|
extra_rdoc_files: []
|
58
112
|
files:
|
113
|
+
- app/controllers/project_remote_issues_controller.rb
|
59
114
|
- app/controllers/remote_issue_statuses_controller.rb
|
115
|
+
- app/controllers/remote_issues_controller.rb
|
60
116
|
- app/controllers/remote_trackers_controller.rb
|
61
117
|
- app/controllers/remote_users_controller.rb
|
118
|
+
- app/models/redmine_remotes/tableless/add_remote_issue.rb
|
119
|
+
- app/models/redmine_remotes/tableless/add_remote_issue/_local_issue.rb
|
120
|
+
- app/models/redmine_remotes/tableless/add_remote_issue/_provider_issue.rb
|
121
|
+
- app/models/redmine_remotes/tableless/add_remote_issue/_remote_issue.rb
|
122
|
+
- app/models/remote_issue.rb
|
62
123
|
- app/models/remote_issue_status.rb
|
63
124
|
- app/models/remote_tracker.rb
|
125
|
+
- app/models/remote_tracker/_jira.rb
|
64
126
|
- app/models/remote_user.rb
|
127
|
+
- app/views/project_remote_issues/_trackers.html.erb
|
128
|
+
- app/views/project_remote_issues/index.html.erb
|
129
|
+
- app/views/project_remote_issues/new.html.erb
|
65
130
|
- config/initializers/000_dependencies.rb
|
66
131
|
- config/initializers/001_patches.rb
|
67
132
|
- config/initializers/nonproject_modules.rb
|
@@ -72,12 +137,19 @@ files:
|
|
72
137
|
- db/migrate/20190910182842_create_remote_users.rb
|
73
138
|
- db/migrate/20190910203552_create_remote_issue_statuses.rb
|
74
139
|
- db/migrate/20190911165556_rename_issue_status_id_to_local_issue_status_id_in_remote_issue_statuses.rb
|
140
|
+
- db/migrate/20190912000000_create_remote_issues.rb
|
75
141
|
- db/migrate/20190913195930_add_default_local_user_id_to_remote_trackers.rb
|
76
142
|
- init.rb
|
77
143
|
- lib/redmine_remotes.rb
|
144
|
+
- lib/redmine_remotes/jira/entities/issue.rb
|
145
|
+
- lib/redmine_remotes/jira/instance.rb
|
146
|
+
- lib/redmine_remotes/patches/issue.rb
|
78
147
|
- lib/redmine_remotes/patches/issue_status.rb
|
79
148
|
- lib/redmine_remotes/patches/tracker.rb
|
80
149
|
- lib/redmine_remotes/patches/user.rb
|
150
|
+
- lib/redmine_remotes/rest_provider/entity.rb
|
151
|
+
- lib/redmine_remotes/rest_provider/http_response.rb
|
152
|
+
- lib/redmine_remotes/rest_provider/instance.rb
|
81
153
|
- lib/redmine_remotes/sanitizer.rb
|
82
154
|
- lib/redmine_remotes/version.rb
|
83
155
|
- lib/tasks/redmine_remotes.rake
|