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.
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