kuroko2 0.2.3 → 0.3.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/kuroko2/definition_linker.js +1 -1
  3. data/app/assets/stylesheets/kuroko2/application.scss +4 -0
  4. data/app/controllers/kuroko2/api/job_instances_controller.rb +3 -2
  5. data/app/controllers/kuroko2/dashboard_controller.rb +1 -1
  6. data/app/controllers/kuroko2/job_definitions_controller.rb +2 -2
  7. data/app/controllers/kuroko2/job_instances_controller.rb +8 -18
  8. data/app/controllers/kuroko2/tokens_controller.rb +3 -3
  9. data/app/controllers/kuroko2/users_controller.rb +17 -1
  10. data/app/models/kuroko2/job_definition.rb +11 -0
  11. data/app/models/kuroko2/job_instance.rb +19 -2
  12. data/app/models/kuroko2/job_schedule.rb +3 -6
  13. data/app/models/kuroko2/job_suspend_schedule.rb +1 -1
  14. data/app/models/kuroko2/token.rb +8 -0
  15. data/app/views/kuroko2/execution_logs/index.json.jbuilder +1 -1
  16. data/app/views/kuroko2/job_definitions/_form.html.slim +6 -1
  17. data/app/views/kuroko2/job_definitions/_list.html.slim +12 -5
  18. data/app/views/kuroko2/job_definitions/_search_results.html.slim +10 -3
  19. data/app/views/kuroko2/job_definitions/show.html.slim +5 -3
  20. data/app/views/kuroko2/job_timelines/dataset.json.jbuilder +1 -1
  21. data/app/views/kuroko2/logs/index.html.slim +6 -6
  22. data/app/views/kuroko2/tokens/index.html.slim +2 -2
  23. data/app/views/kuroko2/users/edit.html.slim +37 -0
  24. data/app/views/kuroko2/users/show.html.slim +8 -4
  25. data/db/migrate/026_add_webhook_url_to_job_definitions.rb +5 -0
  26. data/lib/autoload/kuroko2/workflow/engine.rb +4 -6
  27. data/lib/autoload/kuroko2/workflow/notifier/concerns/chat_message_builder.rb +12 -0
  28. data/lib/autoload/kuroko2/workflow/notifier/hipchat.rb +30 -4
  29. data/lib/autoload/kuroko2/workflow/notifier/mail.rb +9 -1
  30. data/lib/autoload/kuroko2/workflow/notifier/slack.rb +31 -4
  31. data/lib/autoload/kuroko2/workflow/notifier/webhook.rb +173 -0
  32. data/lib/autoload/kuroko2/workflow/task/queue.rb +2 -2
  33. data/lib/autoload/kuroko2/workflow/task/sub_process.rb +2 -4
  34. data/lib/kuroko2/version.rb +1 -1
  35. data/spec/controllers/users_controller_spec.rb +51 -2
  36. data/spec/dummy/config/kuroko2.yml +2 -0
  37. data/spec/dummy/db/schema.rb +76 -92
  38. data/spec/dummy/log/development.log +1143 -0
  39. data/spec/dummy/log/test.log +271238 -0
  40. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-Q/-QhKaYdB1JJGAsq6Ih7uQZJD46XkY5Gw0-38DBDVg3Y.cache +1 -0
  41. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-h/-h4P8jVHGGfJVwG36J8kBUkHFa3HHGNiJQz0936uaxg.cache +1 -0
  42. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/24/24laeo7m53bkbst3Gxu4hlJY-EbnK-rQxH-DA4ujzwY.cache +1 -0
  43. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2e/2eEFzw4UUZHJizptl3nT5jVv3IL25_RdYImr3lAVlJ4.cache +1 -0
  44. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2z/2z8OmZrK1FFsPb8zq9RFli2IVM0gOna92hieZ4cK36c.cache +0 -0
  45. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4K/4Ky9Fg4qo8d_i8bJF6NOhDpxHuJ5kIX8n0w6C8wdHDU.cache +3 -0
  46. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Di/Di9ZEIp2OLO96tkqFN21AWfdoAhc0OCBOJb3o8RUk1I.cache +0 -0
  47. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ex/ExgjnrLZM8Hc_uT_sWVaQSNR26tGYCGUsbJDXs9GYO0.cache +1 -0
  48. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/FJ/FJW4oZDLKhsjg_UHdycQAY88BFtnMeeLCuArx6HIMdM.cache +0 -0
  49. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Iq/IqSpSELRWrOQtOK8F6mGZFPvfafM4yn8gB_VquH9E50.cache +1 -0
  50. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/JJ/JJ2dvNSAjiGkZZs_1Dz2TMWDJs4HypQ95b26cHN13I0.cache +1 -0
  51. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/LJ/LJsVKu6GCC14s20BfJEDXwajK6-xWF72ANX5ONOTX1w.cache +1 -0
  52. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/LL/LLCxb9El_km568UsA8DDOe8Vh3pPKE8IU6ZNww9ie8s.cache +1 -0
  53. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Pq/pqeS6zqHUdv-_25W2PSQMm31ql_cIpaK1iqEcfiNyUQ.cache +0 -0
  54. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Q9/Q9TwXzoqqs8Dm9v25gjZxYIkZW1UKm2X8g2koo5aYhQ.cache +1 -0
  55. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QJ/QJNiKbGgll2T_0mhQus6ZL9a2SM4Xqz7vs2V2KbELPw.cache +1 -0
  56. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QV/QVVeFw88kC-7HfzOk_dCVoFBnz9W_7-gmJFYh-Xlh-0.cache +0 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Qs/QsTn160WUaI8_u8tE8rz37XiSV9qLvSxiXAR-tCtV3Y.cache +0 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/V2/V2QhbjrEGa7in5Uj1P-3E1Ziw2AGno_ADefUhPNHw_A.cache +0 -0
  59. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Vj/VjICw6h8uQ_278ekFlu1znnPR8Gz1vWF_mRgy0KjZXs.cache +1 -0
  60. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/dH/dHFrKzzqtF3aoKs2wAI8z0CNHZoNuytfiHur9Zgz9z0.cache +1 -0
  61. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fE/fEFAQG1Uqt2e58VitSFoPsjVjntfPtgL9RKoKHUTS9U.cache +1 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fM/FMdA_jabowoG5SAWE93G7Hu8A-5GhfzC9Gjy3EJp1Ts.cache +1 -0
  63. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hI/hIIciXZzgFWXdW0lamhs4r5zFFr4hnXvWAuOihCS5qI.cache +0 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hW/hWOkA9ZbQJy1YfEXThjYPOiXRDVRgAeW8TmLm-uQCYk.cache +1 -0
  65. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/iv/ivrIChCv2olhH20VXJQTJgVWlx3t9ncsYxV0QfLT0Bs.cache +0 -0
  66. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/k3/k31T18tx4gR2rhpmDMYMLUa8KPDt7QRIR_qRK56LOdE.cache +0 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oB/oB0c7AuqQVdgqJDgphXXOHw3SXqbDUYfZWxxm9-v_is.cache +0 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ou/ouMQatdL-PPhPVPw5o0xm5EBkVeVWLti06EUEVmfOBo.cache +1 -0
  69. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qM/qMZbagtANt1BI7qOJXWEpzxx1qa-IKMkyOy6EKEIIbE.cache +0 -0
  70. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/rc/rcceqGk009vh5_tK6Y-i1dvbYQwuUtRF888xZcnZrj8.cache +1 -0
  71. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sJ/sJOLo6McRe1YhfgIaGhcDaAoulIdYY7Rs07TAKmrSoY.cache +0 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sh/shGRyWpXjqxMTGB3As4Vibs8VGS0bZHHd4s0qabhwXI.cache +1 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sr/SRfo3vCtDVy0qd-OB9dv5a-xIVTHkJZDn8XwY_ymy7g.cache +1 -0
  74. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vV/vV3Loym0NolgPoXFEVPOr5rDgB_Q5kvUA3InuEEvEvQ.cache +1 -0
  75. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wK/wK5S37PPHfwFm-4mrLMMPdOZ29-H75zo1T2gmErWjLI.cache +0 -0
  76. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wm/wm_qI7_LCxbnH6p7BK1Pqcocl-6TcULzTERICGZIdL0.cache +1 -0
  77. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zC/zCYIl3BglB_fMHME2oqK30CF97CBUG09R0ICLpE-pIM.cache +0 -0
  78. data/spec/features/dashborad_spec.rb +10 -3
  79. data/spec/features/users_spec.rb +20 -4
  80. data/spec/models/job_instance_spec.rb +1 -1
  81. data/spec/models/token_spec.rb +38 -0
  82. data/spec/workflow/notifier/hipchat_spec.rb +91 -0
  83. data/spec/workflow/notifier/mail_spec.rb +18 -2
  84. data/spec/workflow/notifier/slack_spec.rb +85 -0
  85. data/spec/workflow/notifier/webhook_spec.rb +187 -0
  86. data/spec/workflow/task/queue_spec.rb +11 -0
  87. metadata +93 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82f8904d52f7ed97320ff851e35b91b5913d8baf
4
- data.tar.gz: c1fe3a881e302a1823a47aa37176756ae8de7470
3
+ metadata.gz: 05a36b6a990355277232fb05c8fee73420178657
4
+ data.tar.gz: ff0313b72bea3ff95c7961f92193ae7350cbee68
5
5
  SHA512:
6
- metadata.gz: 13794a4c4d2ceb7ae4ed9d38a1bc76fda67a853756c3cdc2a855141fab8d83fceb26b48de303747a0527e8c3cdef7d04e1748019892e436ad2253e074af0c776
7
- data.tar.gz: af34902e44039abf0efbdb912674a3196e8f7a7279aa968c09b4e0ba40270daeb2fe5a6c5e6eeaf6404593834d6a11e85d11acfcc75f7fa8fe11cd102ae972d7
6
+ metadata.gz: 94d255d97eed6354e37040ebff9c4bd2e4692c44f79bf3b7a9596a6ac5a12cd3c7b0585f3550b647b8453454a9b3d8352bc16427373576e03815761424b6df75
7
+ data.tar.gz: 9069f81f985f8b57b9885230be1eecfa6561f3fd0987afcfa041e4826f46560b89feb4817ea7b3832fbc90351cb84ab431cd115fbc1004f5edda3d4344feabdf
@@ -1,6 +1,6 @@
1
1
  jQuery(function ($) {
2
2
  function setDeifinitionLink(script) {
3
- script = script.replace(/sub_process:\s+(\d+)\s*\n/, function(match, jobId) {
3
+ script = script.replace(/sub_process:\s+(\d+)\s*$/gm, function(match, jobId) {
4
4
  return '<a href="/definitions/' + jobId + '">' + match + '</a>';
5
5
  });
6
6
 
@@ -13,6 +13,10 @@
13
13
  padding-top: 10px;
14
14
  }
15
15
 
16
+ .spacer-right-3 {
17
+ margin-right: 3px;
18
+ }
19
+
16
20
  .nowrap {
17
21
  white-space: nowrap;
18
22
  }
@@ -19,10 +19,11 @@ class Kuroko2::Api::JobInstancesController < Kuroko2::Api::ApplicationController
19
19
  raise HTTP::Forbidden.new("#{definition.name} is not allowed to be executed via API")
20
20
  end
21
21
 
22
- instance = definition.job_instances.create(
22
+ instance = definition.create_instance(
23
23
  script: definition.script.prepend(env_script),
24
+ launched_by: "instances API (#{basic_user_name})"
24
25
  )
25
- instance.logs.info("Launched by instances API (#{basic_user_name})")
26
+
26
27
  Kuroko2::Api::JobInstanceResource.new(instance)
27
28
  end
28
29
 
@@ -1,6 +1,6 @@
1
1
  class Kuroko2::DashboardController < Kuroko2::ApplicationController
2
2
  def index
3
- @definitions = current_user.job_definitions
3
+ @definitions = current_user.job_definitions.includes(:tags, :job_instances, :job_schedules)
4
4
 
5
5
  @input_tags = params[:tag] || []
6
6
  if @input_tags.present?
@@ -2,7 +2,7 @@ class Kuroko2::JobDefinitionsController < Kuroko2::ApplicationController
2
2
  before_action :set_definition, only: [:show, :edit, :update, :destroy]
3
3
 
4
4
  def index
5
- rel = Kuroko2::JobDefinition
5
+ rel = Kuroko2::JobDefinition.joins(:admins).includes(:tags, :job_instances, :job_schedules, :admins)
6
6
  query = query_params[:q]
7
7
 
8
8
  if query.present?
@@ -83,7 +83,7 @@ class Kuroko2::JobDefinitionsController < Kuroko2::ApplicationController
83
83
  end
84
84
 
85
85
  def definition_params
86
- params.require(:job_definition).permit(:name, :description, :script, :notify_cancellation, :hipchat_room, :hipchat_notify_finished, :suspended, :prevent_multi, :prevent_multi_on_failure, :hipchat_additional_text, :text_tags, :api_allowed, :slack_channel)
86
+ params.require(:job_definition).permit(:name, :description, :script, :notify_cancellation, :hipchat_room, :hipchat_notify_finished, :suspended, :prevent_multi, :prevent_multi_on_failure, :hipchat_additional_text, :text_tags, :api_allowed, :slack_channel, :webhook_url)
87
87
  end
88
88
 
89
89
  def query_params
@@ -9,24 +9,18 @@ class Kuroko2::JobInstancesController < Kuroko2::ApplicationController
9
9
  end
10
10
 
11
11
  def create
12
+ creation_params = { launched_by: current_user.name }
12
13
  if params[:job_definition].present?
13
- @instance = @definition.job_instances.create(params.require(:job_definition).permit(:script))
14
- else
15
- @instance = @definition.job_instances.create
14
+ creation_params.merge!(params.require(:job_definition).permit(:script).to_h.symbolize_keys)
16
15
  end
17
16
 
18
- if @instance
19
- @instance.logs.info("Launched by #{current_user.name}.")
20
-
21
- redirect_to job_definition_job_instance_path(@definition, @instance)
22
- else
23
- raise HTTP::BadRequest
24
- end
17
+ @instance = @definition.create_instance(creation_params)
18
+ redirect_to job_definition_job_instance_path(@definition, @instance)
25
19
  end
26
20
 
27
21
  def show
28
- @logs = @instance.logs
29
- @tokens = @instance.tokens
22
+ @logs = @instance.logs.order(:id)
23
+ @tokens = @instance.tokens.order(:id)
30
24
 
31
25
  if params[:mode] == :naked
32
26
  render partial: 'instance', layout: false
@@ -37,11 +31,7 @@ class Kuroko2::JobInstancesController < Kuroko2::ApplicationController
37
31
 
38
32
  def destroy
39
33
  if @instance.cancelable?
40
- ActiveRecord::Base.transaction { @instance.cancel }
41
-
42
- message = "This job was canceled by #{current_user.name}."
43
- @instance.logs.warn(message)
44
- Kuroko2.logger.warn(message)
34
+ ActiveRecord::Base.transaction { @instance.cancel(by: current_user.name) }
45
35
  end
46
36
 
47
37
  redirect_to job_definition_job_instance_path(@definition, @instance)
@@ -54,7 +44,7 @@ class Kuroko2::JobInstancesController < Kuroko2::ApplicationController
54
44
  execution.update_column(:execution_id, nil) if execution
55
45
  end
56
46
 
57
- @instance.cancel
47
+ @instance.cancel(by: current_user.name)
58
48
  end
59
49
 
60
50
  message = "Force canceled by #{current_user.name}."
@@ -14,12 +14,12 @@ class Kuroko2::TokensController < Kuroko2::ApplicationController
14
14
  def update
15
15
  @instance = @token.job_instance
16
16
 
17
- case params[:invoke]
18
- when 'skip'
17
+ case
18
+ when params[:invoke] == 'skip' && @token.skippable?
19
19
  @instance.logs.info("Skipped by #{current_user.name}.")
20
20
 
21
21
  @engine.skip(@token)
22
- when 'retry'
22
+ when params[:invoke] == 'retry' && @token.retryable?
23
23
  @instance.logs.info("Retry by #{current_user.name}.")
24
24
 
25
25
  @engine.retry(@token)
@@ -1,5 +1,6 @@
1
1
  class Kuroko2::UsersController < Kuroko2::ApplicationController
2
- before_action :set_user, only: [:destroy]
2
+ before_action :set_user, only: [:edit, :update, :destroy]
3
+ before_action :require_group_user, only: [:edit, :update, :destroy]
3
4
 
4
5
  def index
5
6
  @user = Kuroko2::User.new
@@ -23,6 +24,17 @@ class Kuroko2::UsersController < Kuroko2::ApplicationController
23
24
  @related_tags = @definitions.includes(:tags).map(&:tags).flatten.uniq
24
25
  end
25
26
 
27
+ def edit
28
+ end
29
+
30
+ def update
31
+ if @user.update(user_params)
32
+ redirect_to user_path(@user)
33
+ else
34
+ render action: :edit
35
+ end
36
+ end
37
+
26
38
  def create
27
39
  @user = Kuroko2::User.new(user_params)
28
40
  @user.provider = Kuroko2::User::GROUP_PROVIDER
@@ -59,4 +71,8 @@ class Kuroko2::UsersController < Kuroko2::ApplicationController
59
71
  def page_params
60
72
  params.permit(:page)
61
73
  end
74
+
75
+ def require_group_user
76
+ head :bad_request if @user.google_account?
77
+ end
62
78
  end
@@ -77,6 +77,7 @@ class Kuroko2::JobDefinition < Kuroko2::ApplicationRecord
77
77
  with: /\A#[^\.\s]+\z/, allow_blank: true,
78
78
  message: ' must start with # and must not include any dots or spaces'
79
79
  }
80
+ validates :webhook_url, format: { with: /\A#{URI::regexp(%w(http https))}\z/, allow_blank: true }
80
81
 
81
82
  def proceed_multi_instance?
82
83
  tokens = Kuroko2::Token.where(job_definition_id: self.id)
@@ -93,6 +94,16 @@ class Kuroko2::JobDefinition < Kuroko2::ApplicationRecord
93
94
  end
94
95
  end
95
96
 
97
+ def create_instance(script: nil, launched_by:, token: nil )
98
+ message = "Launched by #{launched_by}"
99
+
100
+ if token.present?
101
+ message = "(token #{token.uuid}) #{message}"
102
+ end
103
+
104
+ job_instances.create!(script: script, log_message: message)
105
+ end
106
+
96
107
  private
97
108
 
98
109
  def confirm_active_instances
@@ -3,6 +3,8 @@ class Kuroko2::JobInstance < Kuroko2::ApplicationRecord
3
3
 
4
4
  belongs_to :job_definition
5
5
 
6
+ attr_accessor :log_message
7
+
6
8
  has_many :logs, dependent: :delete_all do
7
9
  def info(message)
8
10
  add('INFO', message)
@@ -26,6 +28,7 @@ class Kuroko2::JobInstance < Kuroko2::ApplicationRecord
26
28
  has_one :memory_consumption_log, dependent: :destroy
27
29
 
28
30
  before_create :copy_script
31
+ after_create :notify_launch
29
32
  after_create :generate_token
30
33
 
31
34
  scope :working, -> { where(finished_at: nil, canceled_at: nil) }
@@ -43,10 +46,16 @@ class Kuroko2::JobInstance < Kuroko2::ApplicationRecord
43
46
  tokens.first.try(:cancelable?)
44
47
  end
45
48
 
46
- def cancel
49
+ def cancel(by:)
47
50
  self.tokens.destroy(*self.tokens)
48
51
  self.executions.destroy(*self.executions)
49
52
  self.touch(:canceled_at)
53
+
54
+ message = "This job was canceled by #{by}."
55
+ self.logs.warn(message)
56
+ Kuroko2.logger.warn(message)
57
+
58
+ Kuroko2::Workflow::Notifier.notify(:cancellation, self) if job_definition.hipchat_notify_finished?
50
59
  end
51
60
 
52
61
  # Log given value if it is greater than stored one.
@@ -84,6 +93,14 @@ class Kuroko2::JobInstance < Kuroko2::ApplicationRecord
84
93
  self.script = job_definition.try(:script) if self.script.blank?
85
94
  end
86
95
 
96
+ def notify_launch
97
+ if log_message
98
+ Kuroko2.logger.info(log_message)
99
+ self.logs.info(log_message)
100
+ Kuroko2::Workflow::Notifier.notify(:launch, self)
101
+ end
102
+ end
103
+
87
104
  def generate_token
88
105
  unless self.job_definition
89
106
  raise 'No parent association is found'
@@ -112,7 +129,7 @@ class Kuroko2::JobInstance < Kuroko2::ApplicationRecord
112
129
  self.logs.warn(message)
113
130
  Kuroko2.logger.warn(message)
114
131
 
115
- Kuroko2::Workflow::Notifier.notify(:cancellation, self)
132
+ Kuroko2::Workflow::Notifier.notify(:cancellation, self) if job_definition.notify_cancellation
116
133
  end
117
134
  end
118
135
  end
@@ -47,7 +47,7 @@ class Kuroko2::JobSchedule < Kuroko2::ApplicationRecord
47
47
  end
48
48
  end
49
49
 
50
- scheduled_times
50
+ scheduled_times.map(&:in_time_zone)
51
51
  end
52
52
 
53
53
  def suspend_times(time_from, time_to)
@@ -81,11 +81,8 @@ class Kuroko2::JobSchedule < Kuroko2::ApplicationRecord
81
81
  elsif suspend_times.include?(time)
82
82
  Kuroko2.logger.info("Skipped schedule suspended \"##{definition.id} #{definition.name}\" that is scheduled at #{I18n.l(time, format: :short)} by `#{schedule.cron}`")
83
83
  else
84
- message = "Launched \"##{definition.id} #{definition.name}\" that is scheduled at #{I18n.l(time, format: :short)} by `#{schedule.cron}`"
85
- Kuroko2.logger.info(message)
86
-
87
- instance = definition.job_instances.create
88
- instance.logs.info(message)
84
+ launched_by = "\"##{definition.id} #{definition.name}\" that is scheduled at #{I18n.l(time, format: :short)} by `#{schedule.cron}`"
85
+ definition.create_instance(launched_by: launched_by)
89
86
  end
90
87
  end
91
88
  end
@@ -19,7 +19,7 @@ class Kuroko2::JobSuspendSchedule < Kuroko2::ApplicationRecord
19
19
  end
20
20
  end
21
21
 
22
- suspend_times
22
+ suspend_times.map(&:in_time_zone)
23
23
  end
24
24
 
25
25
  private
@@ -90,6 +90,14 @@ class Kuroko2::Token < Kuroko2::ApplicationRecord
90
90
  end
91
91
  end
92
92
 
93
+ def skippable?
94
+ failure? || waiting?
95
+ end
96
+
97
+ def retryable?
98
+ failure?
99
+ end
100
+
93
101
  private
94
102
 
95
103
  def set_default_values
@@ -1,7 +1,7 @@
1
1
  json.token @response.next_forward_token
2
2
  json.events do
3
3
  json.array! @response.events do |event|
4
- json.timestamp l(Time.at(event.timestamp/1000), format: :short)
4
+ json.timestamp Time.at(event.timestamp/1000).in_time_zone
5
5
  begin
6
6
  log = JSON.parse(event.message)
7
7
  json.message rinku_auto_link(html_escape(log['message']), :urls)
@@ -32,14 +32,19 @@
32
32
 
33
33
  label Notification
34
34
  .form-group
35
+ label Hipchat Room Name
35
36
  = form.text_field :hipchat_room, class: 'form-control', placeholder: 'Hipchat Room name'
36
37
  .form-group
38
+ label Slack Channel
37
39
  = form.text_field :slack_channel, class: 'form-control', placeholder: '#slack-channel'
40
+ .form-group
41
+ label Webhook URL
42
+ = form.text_field :webhook_url, class: 'form-control', placeholder: 'http://example.com/webhook/endpoint'
38
43
 
39
44
  .checkbox
40
45
  label
41
46
  = form.check_box :hipchat_notify_finished
42
- ' Notify success event to Slack/Hipchat
47
+ ' Notify all event to Slack/Hipchat/Webhook
43
48
 
44
49
  .checkbox
45
50
  label
@@ -4,9 +4,9 @@
4
4
  tr
5
5
  th #
6
6
  th.col-md-3 Name
7
- th.col-md-3 Next Job
8
- th.col-md-2 Latest Status
9
- th.col-md-8 data-defaultsort='disabled' Description
7
+ th.col-md-2 Next Job
8
+ th.col-md-1 Latest Status
9
+ th.col-md-5 data-defaultsort='disabled' Tags / Description
10
10
  th.col-md-1 data-defaultsort='disabled' &nbsp;
11
11
  tbody
12
12
  - for definition in definitions
@@ -19,8 +19,15 @@
19
19
  - else
20
20
  td data-value="9999999999" --
21
21
  td= labeled_status(definition.job_instances.take)
22
- td= first_line(definition.description)
23
22
  td
24
- = link_to raw('<i class="fa fa-chevron-right"></i> View Details'), definition, class: 'btn btn-sm btn-default'
23
+ - definition.tags.each do |tag|
24
+ =link_to tag.name, { 'tag': [tag.name] }, class: 'label label-default spacer-right-3'
25
+ = first_line(definition.description)
26
+ td
27
+ = link_to definition, class: 'btn btn-sm btn-default' do
28
+ i class="fa fa-chevron-right"
29
+ | &nbsp;
30
+ span class="small" View Details
31
+
25
32
  - else
26
33
  .text-muted.well.well-sm.no-shadow There are no favorite job definitions.
@@ -26,7 +26,7 @@
26
26
  th #
27
27
  th.col-md-3 Name
28
28
  th.col-md-3 Administrators
29
- th.col-md-5 Description
29
+ th.col-md-5 Tags / Description
30
30
  th.col-md-1 &nbsp;
31
31
  - for definition in definitions
32
32
  tr
@@ -39,9 +39,16 @@
39
39
  - definition.admins.each do |user|
40
40
  = link_to user.name, user_path(user)
41
41
  br
42
- td= first_line(definition.description)
43
42
  td
44
- = link_to raw('<i class="fa fa-chevron-right"></i> View Details'), definition, class: 'btn btn-sm btn-default'
43
+ - definition.tags.each do |tag|
44
+ =link_to tag.name, job_definitions_path('tag': [tag.name]), class: 'label label-default spacer-right-3'
45
+ = first_line(definition.description)
46
+ td
47
+ = link_to definition, class: 'btn btn-sm btn-default' do
48
+ i class="fa fa-chevron-right"
49
+ | &nbsp;
50
+ span class="small" View Details
51
+
45
52
  - else
46
53
  - if params[:q].present?
47
54
  .text-muted.well.well-sm.no-shadow No results found for the query.
@@ -19,7 +19,7 @@
19
19
 
20
20
  h4= 'Tags'
21
21
  - for tag in @definition.tags
22
- =link_to tag.name, job_definitions_path(tag: [tag.name]), class: 'badge'
22
+ =link_to tag.name, job_definitions_path(tag: [tag.name]), class: 'label label-default spacer-right-3'
23
23
 
24
24
  h3= 'Administrator'.pluralize(@definition.admins.count)
25
25
  ul.media-list
@@ -43,16 +43,18 @@
43
43
  - if @definition.hipchat_room.present? || @definition.slack_channel.present?
44
44
  - if @definition.hipchat_notify_finished?
45
45
  li
46
- 'Notify all event to Slack/Hipchat
46
+ 'Notify all event to Slack/Hipchat/Webhook
47
47
  ul
48
+ li webhook url: #{@definition.webhook_url}
48
49
  li hipchat room: #{@definition.hipchat_room}
49
50
  li slack channel: #{@definition.slack_channel}
50
51
  - if @definition.hipchat_additional_text
51
52
  li Failure notification text: #{@definition.hipchat_additional_text}
52
53
  - else
53
54
  li
54
- 'Notify failure event to Slack/Hipchat
55
+ 'Notify failure event to Slack/Hipchat/Webhook
55
56
  ul
57
+ li webhook url: #{@definition.webhook_url}
56
58
  li hipchat room: #{@definition.hipchat_room}
57
59
  li slack channel: #{@definition.slack_channel}
58
60
  - if @definition.hipchat_additional_text
@@ -5,7 +5,7 @@ json.data do
5
5
  json.id instance.id
6
6
  json.content "<a href='#{job_definition_job_instance_path(instance.job_definition, instance)}'>##{instance.job_definition.id} #{instance.job_definition.name}</a>"
7
7
  json.start instance.created_at.strftime('%Y-%m-%d %H:%M:%S')
8
- json.end (instance.error_at || instance.canceled_at || instance.finished_at).try!(:strftime, '%Y-%m-%d %H:%M:%S')
8
+ json.end (instance.error_at || instance.canceled_at || instance.finished_at || Time.current).try!(:strftime, '%Y-%m-%d %H:%M:%S')
9
9
  json.group instance.job_definition.id
10
10
  end
11
11
  end