redmine_remotes 0.11.0 → 0.15.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/project_remote_issues_controller/create.rb +1 -1
  3. data/app/controllers/project_remote_issues_controller/update.rb +1 -1
  4. data/app/controllers/remote_trackers_controller.rb +4 -1
  5. data/app/models/remote_issue.rb +11 -0
  6. data/app/models/remote_issue_fetch/base.rb +45 -0
  7. data/app/models/remote_issue_fetch/base/_local_issue.rb +77 -0
  8. data/app/models/remote_issue_fetch/base/_provider_issue.rb +18 -0
  9. data/app/models/remote_issue_fetch/base/_remote_issue.rb +19 -0
  10. data/app/models/remote_issue_fetch/create.rb +44 -0
  11. data/app/models/remote_issue_fetch/create/_local_issue.rb +21 -0
  12. data/app/models/remote_issue_fetch/create/_remote_issue.rb +21 -0
  13. data/app/models/remote_issue_fetch/update.rb +18 -0
  14. data/app/models/remote_issue_fetch/update/_local_issue.rb +15 -0
  15. data/app/models/remote_issue_fetch/update/_remote_issue.rb +15 -0
  16. data/app/models/remote_tracker.rb +7 -1
  17. data/app/models/remote_tracker/find_issue_local_status.rb +1 -1
  18. data/app/models/remote_tracker/remote.rb +32 -8
  19. data/app/models/remote_tracker_fetch.rb +47 -0
  20. data/app/models/remote_tracker_fetch/provider.rb +13 -0
  21. data/app/models/remote_tracker_fetch/remote_issues.rb +27 -0
  22. data/app/models/remote_tracker_fetch/remote_tracker.rb +16 -0
  23. data/app/models/remote_user/find_local_user.rb +3 -3
  24. data/config/initializers/001_patches.rb +1 -0
  25. data/config/locales/en.yml +1 -0
  26. data/config/locales/pt-BR.yml +1 -0
  27. data/config/routes.rb +6 -5
  28. data/db/migrate/20190531171641_create_remote_trackers.rb +1 -1
  29. data/db/migrate/20190910182842_create_remote_users.rb +1 -1
  30. data/db/migrate/20190910203552_create_remote_issue_statuses.rb +1 -1
  31. data/db/migrate/20190912000000_create_remote_issues.rb +1 -1
  32. data/db/migrate/20200602192120_add_outdated_at_to_remote_issues.rb +7 -0
  33. data/db/migrate/20200602194753_add_fetched_at_to_remote_issues.rb +7 -0
  34. data/db/migrate/20200602203020_add_fetched_at_to_remote_trackers.rb +7 -0
  35. data/lib/redmine_remotes/esosti/entities/issue.rb +40 -1
  36. data/lib/redmine_remotes/esosti/instance.rb +8 -5
  37. data/lib/redmine_remotes/jira/entities/issue.rb +6 -2
  38. data/lib/redmine_remotes/jira/instance.rb +4 -17
  39. data/lib/redmine_remotes/jobs/fetch_issues.rb +31 -0
  40. data/lib/redmine_remotes/jobs/fetch_trackers.rb +30 -0
  41. data/lib/redmine_remotes/patches/avmtrf1_rest_provider_instance.rb +22 -0
  42. data/lib/redmine_remotes/version.rb +1 -1
  43. data/lib/tasks/redmine_remotes.rake +16 -11
  44. metadata +49 -27
  45. data/app/models/redmine_remotes/tableless/remote_issue_fetch/base.rb +0 -39
  46. data/app/models/redmine_remotes/tableless/remote_issue_fetch/base/_local_issue.rb +0 -67
  47. data/app/models/redmine_remotes/tableless/remote_issue_fetch/base/_provider_issue.rb +0 -22
  48. data/app/models/redmine_remotes/tableless/remote_issue_fetch/create.rb +0 -57
  49. data/app/models/redmine_remotes/tableless/remote_issue_fetch/create/_local_issue.rb +0 -25
  50. data/app/models/redmine_remotes/tableless/remote_issue_fetch/create/_remote_issue.rb +0 -32
  51. data/app/models/redmine_remotes/tableless/remote_issue_fetch/update.rb +0 -30
  52. data/app/models/redmine_remotes/tableless/remote_issue_fetch/update/_local_issue.rb +0 -19
  53. data/app/models/redmine_remotes/tableless/remote_issue_fetch/update/_remote_issue.rb +0 -19
  54. data/lib/redmine_remotes/rest_provider/http_response.rb +0 -31
  55. data/lib/redmine_remotes/rest_provider/instance.rb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7fe74fdd135a685b96165bd9ed58d166cfb9ba5b28535eca5bc25f12a730e656
4
- data.tar.gz: ceb58f6cebd35a0db510929df86cac7465be85f1de0f79717e2fda174fe69b90
3
+ metadata.gz: 6f6710957b993d233b258cc399182801aaf348281e51df537cf4d10721309154
4
+ data.tar.gz: f9fc4342d569bf8359696a330eddb9c980293ee17f3e2a72be03c5fa6c0b5103
5
5
  SHA512:
6
- metadata.gz: 77dbf10449d5d38021cf698ab65ce4225cf33377e6e5a3b4cf25ca52bba04f9216959c83a26b8cfacd25a703f887d0cb597fe0b4b28b56737c3f9baa2b89effb
7
- data.tar.gz: 61dcddd64c24be40ed2dfacf389f535c1c56beab448b17cd817bce2e3164000b2ea190cdb195a7cfedd0f7bf59890ccdd5bc6f566870608c362a9c1e4962e633
6
+ metadata.gz: 27bb24d1b92d9c58e388cd0b14bf150e0ffa09d3a540baf41a5417eb6318ee707a4a18bbc59fc4fbd60d01e2924c0ce432741d8c9b630634852a8600101eec74
7
+ data.tar.gz: ea5eae31d4a6eff4e51d6b72428b798302bab4c49120ad2635c119313928234e4a82f0e43f658f79b80077449604f91efa92d1d5529747c5bf3757e80aa109ea
@@ -30,7 +30,7 @@ class ProjectRemoteIssuesController < ApplicationController
30
30
  end
31
31
 
32
32
  def create_model_class
33
- ::RedmineRemotes::Tableless::RemoteIssueFetch::Create
33
+ ::RemoteIssueFetch::Create
34
34
  end
35
35
 
36
36
  def create_params
@@ -14,7 +14,7 @@ class ProjectRemoteIssuesController < ApplicationController
14
14
  private
15
15
 
16
16
  def update_model_class
17
- ::RedmineRemotes::Tableless::RemoteIssueFetch::Update
17
+ ::RemoteIssueFetch::Update
18
18
  end
19
19
 
20
20
  def update_params
@@ -14,7 +14,10 @@ class RemoteTrackersController < ApplicationController
14
14
  conf.columns[:password].form_ui = :password
15
15
  conf.columns[:profile].form_ui = :select
16
16
  conf.columns[:default_local_user].form_ui = :select
17
- %w[list show].each { |action| conf.send(action).columns.exclude :password }
17
+ %w[list show].each do |action|
18
+ conf.send(action).columns.exclude :password
19
+ conf.send(action).columns << :fetched_at
20
+ end
18
21
  end
19
22
 
20
23
  private
@@ -12,6 +12,17 @@ class RemoteIssue < ActiveRecord::Base
12
12
  validates :remote_tracker, presence: true
13
13
  validates :remote_code, presence: true, uniqueness: { scope: [:remote_tracker] }
14
14
 
15
+ scope :outdated, lambda {
16
+ t = arel_table
17
+ where(
18
+ t[:fetched_at].eq(nil)
19
+ .or(
20
+ t[:outdated_at].not_eq(nil)
21
+ .and(t[:fetched_at].lt(t[:outdated_at]))
22
+ )
23
+ )
24
+ }
25
+
15
26
  def to_s
16
27
  "#{remote_tracker}|#{remote_code}"
17
28
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_rails_utils/models/fetch_errors'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module RemoteIssueFetch
7
+ class Base < ::EacRailsUtils::Models::Tableless
8
+ enable_simple_cache
9
+ require_sub __FILE__
10
+ include ::EacRailsUtils::Models::FetchErrors
11
+
12
+ validates :fetched_at, presence: true
13
+ validates :local_tracker, presence: true
14
+ validates :remote_tracker, presence: true
15
+ validates :issue_remote_code, presence: true
16
+
17
+ validate :author_present
18
+ validate :provider_issue_present
19
+
20
+ def author_present
21
+ return if provider_issue.blank?
22
+ return if local_issue_author.present?
23
+
24
+ errors.add(:remote_code,
25
+ "Usuário local não encontrado para \"#{provider_issue.author_login}\"")
26
+ end
27
+
28
+ def provider_issue_present
29
+ return if issue_remote_code.blank?
30
+ return if provider_issue.present?
31
+
32
+ errors.add(:remote_code,
33
+ "Demanda remota não encontrada com o código \"#{issue_remote_code}\"")
34
+ end
35
+
36
+ def save
37
+ ::Issue.transaction do
38
+ return false unless valid?
39
+ return false unless save_local_issue
40
+ return false unless save_remote_issue
41
+ end
42
+ true
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Base < ::EacRailsUtils::Models::Tableless
5
+ private
6
+
7
+ DESCRIPTION_SECTION_SEPARATOR = "\n\n"
8
+
9
+ def save_local_issue
10
+ save_local_issue_except_create_on && save_local_issue_created_on
11
+ end
12
+
13
+ def save_local_issue_created_on
14
+ local_issue_provider_attributes[:created_on].if_present do |created_on|
15
+ if created_on.present? && local_issue.created_on != created_on
16
+ local_issue.update_column( # rubocop:disable Rails/SkipsModelValidations
17
+ :created_on, created_on
18
+ )
19
+ end
20
+ end
21
+
22
+ true
23
+ end
24
+
25
+ def save_local_issue_except_create_on
26
+ local_issue_provider_attributes.except(:created_on)
27
+ .each { |attr, value| local_issue.send("#{attr}=", value) }
28
+ return true if local_issue.save
29
+
30
+ fetch_record_errors(local_issue, default_column: default_error_column)
31
+ false
32
+ end
33
+
34
+ def local_issue_provider_attributes
35
+ {
36
+ subject: local_issue_subject, author: local_issue_author, status: local_issue_status,
37
+ description: local_issue_description,
38
+ created_on: provider_issue.created_on
39
+ }
40
+ end
41
+
42
+ def local_issue_subject
43
+ "[#{provider_issue.code}] #{provider_issue.subject}".truncate(100)
44
+ end
45
+
46
+ def local_issue_author_uncached
47
+ return nil if provider_issue.blank?
48
+
49
+ ::RemoteUser.find_local_user(
50
+ provider_issue.author_login,
51
+ remote_tracker,
52
+ true
53
+ )
54
+ end
55
+
56
+ def local_issue_status
57
+ remote_tracker.try(:find_local_issue_status, local_tracker, provider_issue.status_name, true)
58
+ end
59
+
60
+ def local_issue_description
61
+ [local_issue_extra_description(:before), provider_issue.description,
62
+ local_issue_extra_description(:after), local_issue_import_footer]
63
+ .reject(&:blank?).map(&:strip).join("\n\n----\n\n") + "\n"
64
+ end
65
+
66
+ def local_issue_extra_description(position)
67
+ extra = provider_issue.try("extra_description_#{position}").if_present('')
68
+ extra = extra.map { |k, v| "* *#{k}:* #{v}" } if extra.is_a?(::Hash)
69
+ extra = extra.map { |v| "#{v}\n" }.join if extra.is_a?(::Enumerable)
70
+ extra.to_s
71
+ end
72
+
73
+ def local_issue_import_footer
74
+ "_Demanda remota importada de #{provider_issue.human_view_url}._"
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Base < ::EacRailsUtils::Models::Tableless
5
+ private
6
+
7
+ def provider_issue_uncached
8
+ return nil if [remote_tracker, issue_remote_code].any?(&:blank?)
9
+
10
+ remote_tracker.find_remote_issue(issue_remote_code)
11
+ rescue ::Avmtrf1::RestProvider::Response => e
12
+ errors.add(default_error_column,
13
+ "Requisição a \"#{e.url}\" retornou com status #{e.status}")
14
+ ::Rails.logger.warn(e.body)
15
+ nil
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Base < ::EacRailsUtils::Models::Tableless
5
+ private
6
+
7
+ def fetched_at_uncached
8
+ ::Time.zone.now
9
+ end
10
+
11
+ def save_remote_issue
12
+ remote_issue.fetched_at = fetched_at
13
+ return true if remote_issue.save
14
+
15
+ fetch_record_errors(remote_issue, default_column: default_error_column)
16
+ false
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Create < ::RemoteIssueFetch::Base
5
+ require_sub __FILE__
6
+
7
+ attribute :issue_remote_code, ::String
8
+ attribute :local_tracker_id, ::Integer
9
+ attribute :project_id, ::Integer
10
+ attribute :remote_tracker_id, ::Integer
11
+
12
+ belongs_to :local_tracker, class_name: 'Tracker'
13
+ belongs_to :project, class_name: 'Project'
14
+ belongs_to :remote_tracker, class_name: 'RemoteTracker'
15
+
16
+ validates :project, presence: true
17
+
18
+ validate :tracker_in_project
19
+
20
+ def default_error_column
21
+ :issue_remote_code
22
+ end
23
+
24
+ def save
25
+ remote_issue_by_remote_code.present? ? update : super
26
+ end
27
+
28
+ def tracker_in_project
29
+ return unless local_tracker.present? && project.present?
30
+ return if project.trackers.include?(local_tracker)
31
+
32
+ errors.add(:local_tracker, 'is not a tracker of project')
33
+ end
34
+
35
+ def update
36
+ update_record = ::RemoteIssueFetch::Update
37
+ .new(remote_issue: remote_issue_by_remote_code)
38
+ return true if update_record.save
39
+
40
+ fetch_record_errors(update_record, default_column: default_error_column)
41
+ false
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Create < ::RemoteIssueFetch::Base
5
+ private
6
+
7
+ def local_issue_provider_attributes
8
+ super.merge(
9
+ project: project, tracker: local_tracker, priority: local_issue_priority
10
+ )
11
+ end
12
+
13
+ def local_issue_uncached
14
+ remote_issue_by_remote_code.if_present(&:local_issue) || ::Issue.new
15
+ end
16
+
17
+ def local_issue_priority
18
+ ::IssuePriority.default
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Create < ::RemoteIssueFetch::Base
5
+ private
6
+
7
+ def remote_issue_uncached
8
+ remote_issue_by_remote_code.if_blank do
9
+ ::RemoteIssue.new(remote_tracker: remote_tracker, remote_code: issue_remote_code,
10
+ local_issue: local_issue)
11
+ end
12
+ end
13
+
14
+ def remote_issue_by_remote_code_uncached
15
+ ::RemoteIssue.find_by(
16
+ remote_tracker: remote_tracker,
17
+ remote_code: ::RemoteIssue.remote_code_sanitize(issue_remote_code)
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module RemoteIssueFetch
6
+ class Update < ::RemoteIssueFetch::Base
7
+ require_sub __FILE__
8
+
9
+ attribute :remote_issue_id, ::Integer
10
+ belongs_to :remote_issue
11
+
12
+ validates :remote_issue, presence: true
13
+
14
+ def default_error_column
15
+ :remote_issue_id
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Update < ::RemoteIssueFetch::Base
5
+ private
6
+
7
+ def local_issue
8
+ remote_issue.local_issue
9
+ end
10
+
11
+ def local_tracker
12
+ local_issue.if_present(&:tracker)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RemoteIssueFetch
4
+ class Update < ::RemoteIssueFetch::Base
5
+ private
6
+
7
+ def issue_remote_code
8
+ remote_issue.remote_code
9
+ end
10
+
11
+ def remote_tracker
12
+ remote_issue.remote_tracker
13
+ end
14
+ end
15
+ end
@@ -27,6 +27,12 @@ class RemoteTracker < ActiveRecord::Base
27
27
  validates :password, presence: true
28
28
  validates :default_local_user, presence: true
29
29
 
30
+ scope :fetchable, -> { where(profile: fetchable_profiles) }
31
+
32
+ def fetchable?
33
+ self.class.fetchable_profiles.include?(profile)
34
+ end
35
+
30
36
  def find_local_issue_status(local_tracker, remote_status_name, register_not_found = false)
31
37
  ::RemoteTracker::FindIssueLocalStatus.new(self, local_tracker, remote_status_name,
32
38
  register_not_found).result
@@ -37,6 +43,6 @@ class RemoteTracker < ActiveRecord::Base
37
43
  end
38
44
 
39
45
  def setting_value(name)
40
- ::RemoteTrackerSetting.where(remote_tracker: self, name: name).first.if_present(&:value)
46
+ ::RemoteTrackerSetting.find_by(remote_tracker: self, name: name).if_present(&:value)
41
47
  end
42
48
  end
@@ -22,7 +22,7 @@ class RemoteTracker < ActiveRecord::Base
22
22
  end
23
23
 
24
24
  def result_by_remote_issue_status
25
- ::RemoteIssueStatus.where(remote_issue_status_find_attributes).first.try(:local_issue_status)
25
+ ::RemoteIssueStatus.find_by(remote_issue_status_find_attributes).try(:local_issue_status)
26
26
  end
27
27
 
28
28
  def result_by_local_issue_status
@@ -1,19 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'eac_ruby_utils/core_ext'
4
+
3
5
  class RemoteTracker < ActiveRecord::Base
4
6
  module Remote
5
- def find_remote_issue(issue_id)
6
- remote_instance.find_issue(issue_id)
7
- end
7
+ common_concern
8
+
9
+ module ClassMethods
10
+ def fetchable_profiles
11
+ @fetchable_profiles ||= lists.profile.values.select do |profile|
12
+ profile_fetchable?(profile)
13
+ end
14
+ end
8
15
 
9
- def remote_instance
10
- remote_instance_class.new(self, root_url, username, password)
16
+ def profile_fetchable?(profile)
17
+ provider_instance_class(profile).method_defined?(:fetch_issues_changed)
18
+ end
19
+
20
+ def provider_instance_class(profile)
21
+ lists.profile.value_validate!(profile)
22
+
23
+ ::RedmineRemotes.const_get(profile.capitalize).const_get('Instance')
24
+ end
11
25
  end
12
26
 
13
- def remote_instance_class
14
- raise 'Profile blank' if profile.blank?
27
+ module InstanceMethods
28
+ def find_remote_issue(issue_id)
29
+ remote_instance.find_issue(issue_id)
30
+ end
31
+
32
+ def remote_instance
33
+ r = remote_instance_class.new(root_url, username, password)
34
+ r.send('remote_tracker=', self)
35
+ r
36
+ end
15
37
 
16
- ::RedmineRemotes.const_get(profile.capitalize).const_get('Instance')
38
+ def remote_instance_class
39
+ self.class.provider_instance_class(profile)
40
+ end
17
41
  end
18
42
  end
19
43
  end