redmine_remotes 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/remote_trackers_controller.rb +4 -1
  3. data/app/models/redmine_remotes/tableless/remote_issue_fetch/base.rb +10 -0
  4. data/app/models/redmine_remotes/tableless/remote_issue_fetch/base/_remote_issue.rb +23 -0
  5. data/app/models/redmine_remotes/tableless/remote_issue_fetch/create.rb +1 -10
  6. data/app/models/redmine_remotes/tableless/remote_issue_fetch/create/_remote_issue.rb +0 -7
  7. data/app/models/redmine_remotes/tableless/remote_issue_fetch/update.rb +0 -7
  8. data/app/models/redmine_remotes/tableless/remote_tracker_fetch.rb +51 -0
  9. data/app/models/redmine_remotes/tableless/remote_tracker_fetch/provider.rb +17 -0
  10. data/app/models/redmine_remotes/tableless/remote_tracker_fetch/remote_issues.rb +31 -0
  11. data/app/models/redmine_remotes/tableless/remote_tracker_fetch/remote_tracker.rb +20 -0
  12. data/app/models/remote_issue.rb +11 -0
  13. data/app/models/remote_tracker.rb +6 -0
  14. data/app/models/remote_tracker/remote.rb +30 -8
  15. data/config/locales/en.yml +1 -0
  16. data/config/locales/pt-BR.yml +1 -0
  17. data/db/migrate/20200602192120_add_outdated_at_to_remote_issues.rb +7 -0
  18. data/db/migrate/20200602194753_add_fetched_at_to_remote_issues.rb +7 -0
  19. data/db/migrate/20200602203020_add_fetched_at_to_remote_trackers.rb +7 -0
  20. data/lib/redmine_remotes/esosti/instance.rb +25 -0
  21. data/lib/redmine_remotes/jobs/fetch_issues.rb +31 -0
  22. data/lib/redmine_remotes/jobs/fetch_trackers.rb +30 -0
  23. data/lib/redmine_remotes/version.rb +1 -1
  24. data/lib/tasks/redmine_remotes.rake +12 -0
  25. metadata +14 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70c4977d8154fa08f7d03093a35dc948c5bd78639a2a2ce42352e58c5d737050
4
- data.tar.gz: 8c56794c3633be3b5e731800025a61a73a8df6e17c50776a87790659e0b3235d
3
+ metadata.gz: 58582fa98456cc3680589a4484b45bda211d8db71b78a47418b2bd3208ca6997
4
+ data.tar.gz: 17d859506c16a9a5529bca6dcec6d5b200e1a0aed24b712b048ae4c254be1671
5
5
  SHA512:
6
- metadata.gz: 546876674ce5856dacf18ed183ddca546dcbdbe2ae17ede908b2512e18af12512f9fd8449d829a82105c654994f62a6a01589c42a2b7e055f5e94a64a182cec2
7
- data.tar.gz: 2e821818b0294b9e8b889612666a7a10c0eb494abe661743bc8f9122ca741285364aea93e679bb30068b73c9aec7f53aa25f1c1e96b95a0ba2d887199509c280
6
+ metadata.gz: 654d4c3c6cf0db58ba7bd17c672dbd2bb88b936496d541f08282f5c09dd859f3b79ef000e8b9e71c834a82cbc73149596597c0d061021711fba933a7d2420925
7
+ data.tar.gz: 8d30c37a42a67e84b1db2d1ba74d1c75008014315d9871935e94059d7ec0ce6018a0b374df03a34941ef8bdb858913b38df002670a5307c1cb2fee811165a253
@@ -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
@@ -11,6 +11,7 @@ module RedmineRemotes
11
11
  require_sub __FILE__
12
12
  include ::EacRailsUtils::Models::FetchErrors
13
13
 
14
+ validates :fetched_at, presence: true
14
15
  validates :local_tracker, presence: true
15
16
  validates :remote_tracker, presence: true
16
17
  validates :issue_remote_code, presence: true
@@ -33,6 +34,15 @@ module RedmineRemotes
33
34
  errors.add(:remote_code,
34
35
  "Demanda remota não encontrada com o código \"#{issue_remote_code}\"")
35
36
  end
37
+
38
+ def save
39
+ ::Issue.transaction do
40
+ return false unless valid?
41
+ return false unless save_local_issue
42
+ return false unless save_remote_issue
43
+ end
44
+ true
45
+ end
36
46
  end
37
47
  end
38
48
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedmineRemotes
4
+ module Tableless
5
+ module RemoteIssueFetch
6
+ class Base < ::EacRailsUtils::Models::Tableless
7
+ private
8
+
9
+ def fetched_at_uncached
10
+ ::Time.zone.now
11
+ end
12
+
13
+ def save_remote_issue
14
+ remote_issue.fetched_at = fetched_at
15
+ return true if remote_issue.save
16
+
17
+ fetch_record_errors(remote_issue, default_column: default_error_column)
18
+ false
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -19,21 +19,12 @@ module RedmineRemotes
19
19
 
20
20
  validate :tracker_in_project
21
21
 
22
- def create
23
- ::Issue.transaction do
24
- return false unless valid?
25
- return false unless save_local_issue
26
- return false unless create_remote_issue
27
- end
28
- true
29
- end
30
-
31
22
  def default_error_column
32
23
  :issue_remote_code
33
24
  end
34
25
 
35
26
  def save
36
- remote_issue_by_remote_code.present? ? update : create
27
+ remote_issue_by_remote_code.present? ? update : super
37
28
  end
38
29
 
39
30
  def tracker_in_project
@@ -6,13 +6,6 @@ module RedmineRemotes
6
6
  class Create < ::RedmineRemotes::Tableless::RemoteIssueFetch::Base
7
7
  private
8
8
 
9
- def create_remote_issue
10
- return true if remote_issue.save
11
-
12
- fetch_record_errors(remote_issue, default_column: default_error_column)
13
- false
14
- end
15
-
16
9
  def remote_issue_uncached
17
10
  remote_issue_by_remote_code.if_blank do
18
11
  ::RemoteIssue.new(remote_tracker: remote_tracker, remote_code: issue_remote_code,
@@ -16,13 +16,6 @@ module RedmineRemotes
16
16
  def default_error_column
17
17
  :remote_issue_id
18
18
  end
19
-
20
- def save
21
- return false unless valid?
22
- return false unless save_local_issue
23
-
24
- true
25
- end
26
19
  end
27
20
  end
28
21
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module RedmineRemotes
6
+ module Tableless
7
+ class RemoteTrackerFetch < ::EacRailsUtils::Models::Tableless
8
+ require_sub __FILE__, include_modules: true, require_dependency: true
9
+ enable_simple_cache
10
+ include ::EacRailsUtils::Models::FetchErrors
11
+
12
+ attribute :remote_tracker_id, ::Integer
13
+ belongs_to :remote_tracker, class_name: 'RemoteTracker'
14
+
15
+ validates :remote_tracker, presence: true
16
+ validates :start_time, presence: true
17
+ validates :end_time, presence: true
18
+ validate :remote_tracker_fetchable_validation
19
+
20
+ def save
21
+ ::Issue.transaction do
22
+ return false unless valid?
23
+ return false unless save_remote_issues
24
+ return false unless save_remote_tracker
25
+ end
26
+ true
27
+ end
28
+
29
+ def default_error_column
30
+ :remote_tracker_id
31
+ end
32
+
33
+ private
34
+
35
+ def end_time_uncached
36
+ ::Time.zone.now
37
+ end
38
+
39
+ def start_time_uncached
40
+ remote_tracker.try(:fetched_at) || end_time
41
+ end
42
+
43
+ def remote_tracker_fetchable_validation
44
+ return if remote_tracker.blank?
45
+ return if remote_tracker.fetchable?
46
+
47
+ errors.add(:remote_tracker, "Remote tracker \"#{remote_tracker}\" is not fetchable")
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module RedmineRemotes
6
+ module Tableless
7
+ class RemoteTrackerFetch < ::EacRailsUtils::Models::Tableless
8
+ module Provider
9
+ private
10
+
11
+ def provider_issues_codes
12
+ remote_tracker.remote_instance.fetch_issues_changed(start_time, end_time)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module RedmineRemotes
6
+ module Tableless
7
+ class RemoteTrackerFetch < ::EacRailsUtils::Models::Tableless
8
+ module RemoteIssues
9
+ private
10
+
11
+ def save_remote_issues
12
+ remote_issues.all? { |remote_issue| save_remote_issue(remote_issue) }
13
+ end
14
+
15
+ def save_remote_issue(remote_issue)
16
+ return true if remote_issue.update(outdated_at: end_time)
17
+
18
+ fetch_record_errors(remote_issue, default_column: default_error_column)
19
+ false
20
+ end
21
+
22
+ def remote_issues_uncached
23
+ provider_issues_codes.map do |code|
24
+ ::RemoteIssue.where(remote_tracker: remote_tracker,
25
+ remote_code: ::RemoteIssue.remote_code_sanitize(code)).first
26
+ end.reject(&:blank?)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module RedmineRemotes
6
+ module Tableless
7
+ class RemoteTrackerFetch < ::EacRailsUtils::Models::Tableless
8
+ module RemoteTracker
9
+ private
10
+
11
+ def save_remote_tracker
12
+ return true if remote_tracker.update(fetched_at: end_time)
13
+
14
+ fetch_record_errors(remote_tracker, default_column: default_error_column)
15
+ false
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -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
@@ -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
@@ -1,19 +1,41 @@
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
+ remote_instance_class.new(self, root_url, username, password)
34
+ end
15
35
 
16
- ::RedmineRemotes.const_get(profile.capitalize).const_get('Instance')
36
+ def remote_instance_class
37
+ self.class.provider_instance_class(profile)
38
+ end
17
39
  end
18
40
  end
19
41
  end
@@ -22,3 +22,4 @@ en:
22
22
  label_remote_issue_statuses: Remote issue statuses
23
23
  label_remote_users: Remote users
24
24
  label_remotes: Remotes
25
+ menu_redmine_remotes: Remotes
@@ -22,3 +22,4 @@ pt-BR:
22
22
  label_remote_issue_statuses: Situações de demandas remotas
23
23
  label_remote_users: Usuários remotos
24
24
  label_remotes: Remotos
25
+ menu_redmine_remotes: Remotos
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddOutdatedAtToRemoteIssues < ActiveRecord::Migration
4
+ def change
5
+ add_column :remote_issues, :outdated_at, :datetime
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddFetchedAtToRemoteIssues < ActiveRecord::Migration
4
+ def change
5
+ add_column :remote_issues, :fetched_at, :timestamp
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddFetchedAtToRemoteTrackers < ActiveRecord::Migration
4
+ def change
5
+ add_column :remote_trackers, :fetched_at, :datetime
6
+ end
7
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'avmtrf1/esosti/raw_data_sanitizer'
4
+
3
5
  module RedmineRemotes
4
6
  module Esosti
5
7
  class Instance < ::RedmineRemotes::RestProvider::Instance
@@ -25,6 +27,29 @@ module RedmineRemotes
25
27
  def issue_human_view_url(ticket_uid)
26
28
  "#{root_url}/itsm/ui/maximo.jsp?event=loadapp&value=ms_viewsr&uniqueid=#{ticket_uid}"
27
29
  end
30
+
31
+ def fetch_issues_changed(start_time, _end_time)
32
+ changed_parse_result(request(changed_url_suffix(start_time)))
33
+ end
34
+
35
+ private
36
+
37
+ def changed_parse_result(raw_data)
38
+ ::Avmtrf1::Esosti::RawDataSanitizer.sanitize(
39
+ raw_data.fetch('TICKETMboSet').fetch('TICKET')
40
+ ).map do |ticket|
41
+ ::RemoteIssue.remote_code_sanitize(ticket.fetch('Attributes').fetch('TICKETID'))
42
+ end
43
+ end
44
+
45
+ def changed_url_suffix(since)
46
+ '/mbo/ticket?_includecols=ticketid&changedate=~gt~' +
47
+ ::CGI.escape(formatted_time(since))
48
+ end
49
+
50
+ def formatted_time(time)
51
+ time.strftime('%FT%T%:z')
52
+ end
28
53
  end
29
54
  end
30
55
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedmineRemotes
4
+ module Jobs
5
+ class FetchIssues
6
+ enable_simple_cache
7
+
8
+ def run
9
+ ::Rails.logger.info("Issues to fetch: #{issues_to_fetch.count}")
10
+ issues_to_fetch.each { |issue| fetch_issue(issue) }
11
+ end
12
+
13
+ private
14
+
15
+ def issues_to_fetch_uncached
16
+ ::RemoteIssue.outdated
17
+ end
18
+
19
+ def fetch_issue(remote_issue)
20
+ ::Rails.logger.info 'Fetching remote issue ' \
21
+ "\"#{remote_issue}|\##{remote_issue.local_issue.id}\""
22
+ record = ::RedmineRemotes::Tableless::RemoteIssueFetch::Update.new(
23
+ remote_issue: remote_issue
24
+ )
25
+ return if record.save
26
+
27
+ ::Rails.logger.warn "Fetch failed with errors: #{record.errors.messages}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedmineRemotes
4
+ module Jobs
5
+ class FetchTrackers
6
+ enable_simple_cache
7
+
8
+ def run
9
+ ::Rails.logger.info("Trackers to fetch: #{trackers_to_fetch.count}")
10
+ trackers_to_fetch.each { |tracker| fetch_tracker(tracker) }
11
+ end
12
+
13
+ private
14
+
15
+ def fetch_tracker(remote_tracker)
16
+ ::Rails.logger.info "Fetch remote tracker \"#{remote_tracker}\"..."
17
+ record = ::RedmineRemotes::Tableless::RemoteTrackerFetch.new(
18
+ remote_tracker: remote_tracker
19
+ )
20
+ return if record.save
21
+
22
+ ::Rails.logger.warn "Fetched failed with errors: #{record.errors.messages}"
23
+ end
24
+
25
+ def trackers_to_fetch_uncached
26
+ ::RemoteTracker.where(profile: ::RemoteTracker::PROFILE_ESOSTI)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -3,7 +3,7 @@
3
3
  module RedmineRemotes
4
4
  SLUG = 'redmine_remotes'
5
5
  NAME = 'Redmine Remotes'
6
- VERSION = '0.12.0'
6
+ VERSION = '0.13.0'
7
7
  AUTHOR = 'Eduardo Henrique Bogoni'
8
8
  SUMMARY = 'Integração do Redmine com trackers diversos.'
9
9
  end
@@ -38,5 +38,17 @@ namespace :redmine_remotes do
38
38
  ::Rails.logger.info "[Failed] #{add.errors.messages.pretty_inspect}"
39
39
  end
40
40
  end
41
+
42
+ desc 'Fetch all remote issues.'
43
+ task fetch: :environment do
44
+ ::RedmineRemotes::Jobs::FetchIssues.new.run
45
+ end
46
+ end
47
+
48
+ namespace :trackers do
49
+ desc 'Fetch all remote trackers.'
50
+ task fetch: :environment do
51
+ ::RedmineRemotes::Jobs::FetchTrackers.new.run
52
+ end
41
53
  end
42
54
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmine_remotes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.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: 2020-06-02 00:00:00.000000000 Z
11
+ date: 2020-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aranha-parsers
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.28'
33
+ version: '0.29'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.28'
40
+ version: '0.29'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: curb
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -124,12 +124,17 @@ files:
124
124
  - app/models/redmine_remotes/tableless/remote_issue_fetch/base.rb
125
125
  - app/models/redmine_remotes/tableless/remote_issue_fetch/base/_local_issue.rb
126
126
  - app/models/redmine_remotes/tableless/remote_issue_fetch/base/_provider_issue.rb
127
+ - app/models/redmine_remotes/tableless/remote_issue_fetch/base/_remote_issue.rb
127
128
  - app/models/redmine_remotes/tableless/remote_issue_fetch/create.rb
128
129
  - app/models/redmine_remotes/tableless/remote_issue_fetch/create/_local_issue.rb
129
130
  - app/models/redmine_remotes/tableless/remote_issue_fetch/create/_remote_issue.rb
130
131
  - app/models/redmine_remotes/tableless/remote_issue_fetch/update.rb
131
132
  - app/models/redmine_remotes/tableless/remote_issue_fetch/update/_local_issue.rb
132
133
  - app/models/redmine_remotes/tableless/remote_issue_fetch/update/_remote_issue.rb
134
+ - app/models/redmine_remotes/tableless/remote_tracker_fetch.rb
135
+ - app/models/redmine_remotes/tableless/remote_tracker_fetch/provider.rb
136
+ - app/models/redmine_remotes/tableless/remote_tracker_fetch/remote_issues.rb
137
+ - app/models/redmine_remotes/tableless/remote_tracker_fetch/remote_tracker.rb
133
138
  - app/models/remote_issue.rb
134
139
  - app/models/remote_issue_status.rb
135
140
  - app/models/remote_tracker.rb
@@ -158,6 +163,9 @@ files:
158
163
  - db/migrate/20200505153200_add_timestamps_to_redmine_trackers.rb
159
164
  - db/migrate/20200505160938_add_timestamps_to_remote_issues.rb
160
165
  - db/migrate/20200505161002_add_timestamps_to_remote_users.rb
166
+ - db/migrate/20200602192120_add_outdated_at_to_remote_issues.rb
167
+ - db/migrate/20200602194753_add_fetched_at_to_remote_issues.rb
168
+ - db/migrate/20200602203020_add_fetched_at_to_remote_trackers.rb
161
169
  - init.rb
162
170
  - lib/redmine_remotes.rb
163
171
  - lib/redmine_remotes/esosti.rb
@@ -165,6 +173,8 @@ files:
165
173
  - lib/redmine_remotes/esosti/instance.rb
166
174
  - lib/redmine_remotes/jira/entities/issue.rb
167
175
  - lib/redmine_remotes/jira/instance.rb
176
+ - lib/redmine_remotes/jobs/fetch_issues.rb
177
+ - lib/redmine_remotes/jobs/fetch_trackers.rb
168
178
  - lib/redmine_remotes/patches/issue.rb
169
179
  - lib/redmine_remotes/patches/issue_status.rb
170
180
  - lib/redmine_remotes/patches/project.rb