redmine_remotes 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/project_remote_issues_controller.rb +44 -0
  3. data/app/controllers/remote_issues_controller.rb +14 -0
  4. data/app/models/redmine_remotes/tableless/add_remote_issue/_local_issue.rb +57 -0
  5. data/app/models/redmine_remotes/tableless/add_remote_issue/_provider_issue.rb +19 -0
  6. data/app/models/redmine_remotes/tableless/add_remote_issue/_remote_issue.rb +27 -0
  7. data/app/models/redmine_remotes/tableless/add_remote_issue.rb +65 -0
  8. data/app/models/remote_issue.rb +17 -0
  9. data/app/models/remote_tracker/_jira.rb +11 -0
  10. data/app/models/remote_tracker.rb +12 -1
  11. data/app/models/remote_user.rb +4 -2
  12. data/app/views/project_remote_issues/_trackers.html.erb +30 -0
  13. data/app/views/project_remote_issues/index.html.erb +2 -0
  14. data/app/views/project_remote_issues/new.html.erb +12 -0
  15. data/config/initializers/001_patches.rb +1 -0
  16. data/config/initializers/nonproject_modules.rb +6 -0
  17. data/config/locales/en.yml +6 -2
  18. data/config/locales/pt-BR.yml +6 -2
  19. data/config/routes.rb +7 -0
  20. data/db/migrate/20190912000000_create_remote_issues.rb +13 -0
  21. data/init.rb +10 -0
  22. data/lib/redmine_remotes/jira/entities/issue.rb +37 -0
  23. data/lib/redmine_remotes/jira/instance.rb +26 -0
  24. data/lib/redmine_remotes/patches/issue.rb +20 -0
  25. data/lib/redmine_remotes/rest_provider/entity.rb +18 -0
  26. data/lib/redmine_remotes/rest_provider/http_response.rb +31 -0
  27. data/lib/redmine_remotes/rest_provider/instance.rb +53 -0
  28. data/lib/redmine_remotes/version.rb +1 -1
  29. data/lib/tasks/redmine_remotes.rake +24 -0
  30. metadata +74 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7ec7641f2a0fa365011119971dbe87875bd2d89a0b1a309f4849498810eb4c2
4
- data.tar.gz: 2b5877691f690622b098bbea6551e77b415e4a10727573f4cb9b8d490e78963d
3
+ metadata.gz: 9520f14afbdb893e412eb0147142ac2ceee118152436f62a8a2d2e9a6b0b48dd
4
+ data.tar.gz: f388fd2ae10c72cec289ad779a994fd099748e991878e275bba9b2ed645adedc
5
5
  SHA512:
6
- metadata.gz: 8afb48ab0775f253e431a024e518fa466e6881768e50c47418a15db4e488dd660f3f478973fb373c7ca624aaca1daaeab20cbf60071619a797a5771c07e03d24
7
- data.tar.gz: 70c63885ccb1fb9c6273586688128f76b4f1dba485016a1a58d9692caa121b42a465ce7a83d63c4ac4245e0f3e941a919c38d48ff799387bbdacb07111a354e7
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
- lists.add_string :profile, :stub
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
@@ -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, tracker = nil)
16
- [tracker, nil].each do |tracker|
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,2 @@
1
+ <h2><%= t(:label_remote_issues) %></h2>
2
+ <%= render partial: 'trackers' %>
@@ -0,0 +1,12 @@
1
+ <h2><%= @tracker %> &#187; 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 %>
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'redmine_remotes/patches/issue'
3
4
  require 'redmine_remotes/patches/issue_status'
4
5
  require 'redmine_remotes/patches/tracker'
5
6
  require 'redmine_remotes/patches/user'
@@ -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
@@ -3,8 +3,12 @@ en:
3
3
  listable:
4
4
  remote_tracker:
5
5
  profile:
6
- stub:
7
- label: Stub profile
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
@@ -3,8 +3,12 @@ pt-BR:
3
3
  listable:
4
4
  remote_tracker:
5
5
  profile:
6
- stub:
7
- label: Stub profile
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
@@ -3,7 +3,7 @@
3
3
  module RedmineRemotes
4
4
  SLUG = 'redmine_remotes'
5
5
  NAME = 'Redmine Remotes'
6
- VERSION = '0.4.0'
6
+ VERSION = '0.5.0'
7
7
  AUTHOR = 'Eduardo Henrique Bogoni'
8
8
  SUMMARY = 'Integração do Redmine com trackers diversos.'
9
9
  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.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-09-18 00:00:00.000000000 Z
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