redmine_remotes 0.11.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
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