command_proposal 1.0.9 → 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ae6c3b31f79557ffddfc4cc86435547b0523e204ff618d88160b4b7caa16da7
4
- data.tar.gz: e2fdfb9505a9c10815f5503a3db917ef63b019b83a2f86b4f5d5dd30e704a8c1
3
+ metadata.gz: d57823efe2c4175b2786f8346a67ea68e96804bc980f06fc4afb0feb30a8dc9a
4
+ data.tar.gz: 212e7e868bf94fe559701ee696fc5487a9a17bcc3b549f35880843d8564f927d
5
5
  SHA512:
6
- metadata.gz: 7199f95ffb1a7f26b8c58f96bc7d249d2d9429b7104fba4016aedcc3fcf0a355ea6748de16a7e136d0ab5c2bd927df14c173e5a84439b49993500031abd43601
7
- data.tar.gz: 3d9c1bf0cbfa570679e8d149402278cfb34a453368ea8e5da72744ec93043ef199cfe92eac2233f91d692f4aa8a7d882245a15bc6c132271dd4438616a41a711
6
+ metadata.gz: 96795b4fff0569ca5ed7c965cc1d27dcaa2fd753301a62cee0da1a0e7f684daa9489b5ca5f51f195bd58a8a86c3f9f77aea2b9e21017fc6c14c5ee61b73169e3
7
+ data.tar.gz: 6e15d7c2aeadeb488bfc35784cdeb2626a29cfa18f6a98264af30d35e45ecc7b8df8d8356d70ef4e7b07ca2228c78149dfd3a0bd7bc77e6ad00a3d17df2d63b1
@@ -141,6 +141,16 @@ cmdDocReady(function() {
141
141
  line.textContent = console_input.textContent
142
142
 
143
143
  console_input.textContent = ""
144
+
145
+ var result = document.createElement("div")
146
+ result.classList.add("result")
147
+
148
+ var spinner = document.createElement("i")
149
+ spinner.className = "fa fa-circle-o-notch fa-spin cmd-icon-grey"
150
+ result.append(spinner)
151
+
152
+ line.appendChild(result)
153
+
144
154
  lines.appendChild(line)
145
155
  stored_entry = undefined
146
156
  history_cmd_idx = undefined
@@ -167,6 +177,8 @@ cmdDocReady(function() {
167
177
  done: function(res, status, req) {
168
178
  if (status == 200) {
169
179
  var json = JSON.parse(res)
180
+ line.querySelector(".result").remove()
181
+
170
182
  var result = document.createElement("div")
171
183
  result.classList.add("result")
172
184
 
@@ -174,7 +186,21 @@ cmdDocReady(function() {
174
186
  result.classList.add("cmd-error")
175
187
  result.textContent = json.error
176
188
  } else {
177
- result.textContent = json.result
189
+ var truncate = 2000
190
+ if (json.result.length > truncate-3) {
191
+ result.textContent = json.result.slice(0, truncate-3) + "..."
192
+ var encoded = encodeURIComponent(json.result)
193
+
194
+ var download = document.createElement("a")
195
+ download.classList.add("cmd-truncated-download")
196
+ download.setAttribute("href", "data:application/txt," + encoded)
197
+ download.setAttribute("download", "result.txt")
198
+ download.textContent = "Output truncated. Click here to download full result."
199
+
200
+ line.insertAdjacentElement("afterend", download)
201
+ } else {
202
+ result.textContent = json.result
203
+ }
178
204
  }
179
205
 
180
206
  line.appendChild(result)
@@ -29,6 +29,7 @@ cmdDocReady(function() {
29
29
  }
30
30
  document.querySelector("td[data-iteration-status]").innerText = json.status
31
31
  document.querySelector("td[data-iteration-duration]").innerText = json.duration
32
+ document.querySelector("td[data-iteration-started]").innerText = json.started_at
32
33
 
33
34
  if (continue_statuses.includes(json.status)) {
34
35
  setTimeout(function() { pingFeed(terminal) }, 1000)
@@ -4,13 +4,13 @@ cmdDocReady(function() {
4
4
  function setReadOnlyUI(cm) {
5
5
  cm.getWrapperElement().classList.add("CodeMirror-readonly")
6
6
 
7
- pencil = document.createElement("i")
7
+ var pencil = document.createElement("i")
8
8
  pencil.className = "fa fa-pencil fa-stack-1x"
9
9
 
10
- ban = document.createElement("i")
10
+ var ban = document.createElement("i")
11
11
  ban.className = "fa fa-ban fa-stack-2x fa-flip-horizontal"
12
12
 
13
- stack = document.createElement("span")
13
+ var stack = document.createElement("span")
14
14
  stack.className = "fa-stack fa-2x"
15
15
  stack.append(pencil)
16
16
  stack.append(ban)
@@ -6,6 +6,12 @@
6
6
  width: 100%;
7
7
  }
8
8
 
9
+ .cmd-truncated-download {
10
+ font-size: 12px;
11
+ color: grey;
12
+ text-decoration: underline;
13
+ }
14
+
9
15
  .cmd-flex-row {
10
16
  display: flex;
11
17
  }
@@ -29,3 +35,20 @@
29
35
  background: lightgrey;
30
36
  }
31
37
  }
38
+
39
+ .cmd-pagination {
40
+ text-align: center;
41
+ margin-top: 10px;
42
+
43
+ .cmd-pagination-link {
44
+ text-decoration: none;
45
+
46
+ &:hover {
47
+ text-decoration: underline;
48
+ }
49
+
50
+ &.current-page {
51
+ font-weight: bold;
52
+ }
53
+ }
54
+ }
@@ -6,14 +6,12 @@
6
6
  background: #112435;
7
7
  padding: 10px 20px;
8
8
  padding-left: 40px;
9
- overflow-x: auto;
10
- overflow-y: visible;
11
9
  color: lime;
12
10
  font-family: monospace;
13
11
  text-align: left;
14
- white-space: nowrap;
15
- white-space: pre;
16
12
  counter-reset: line-count;
13
+ white-space: pre-wrap;
14
+ word-wrap: break-word;
17
15
 
18
16
  .line {
19
17
  min-height: 18px;
@@ -67,6 +65,3 @@
67
65
  color: black;
68
66
  }
69
67
  }
70
- .cmd-terminal {
71
- white-space: pre-wrap;
72
- }
@@ -28,14 +28,18 @@ class ::CommandProposal::IterationsController < ::CommandProposal::EngineControl
28
28
 
29
29
  return error!("Session has expired. Please start a new session.") if runner.nil?
30
30
 
31
-
32
31
  @task.user = command_user # Separate from update to ensure it's set first
33
32
  @task.update(code: params[:code]) # Creates a new iteration
34
33
  @iteration = @task.current_iteration
35
34
  @iteration.update(status: :approved) # Task was already approved, and this is line-by-line
36
35
 
37
- # in-sync
38
- runner.execute(@iteration)
36
+ # async, but wait for the job to finish
37
+ ::CommandProposal::CommandRunnerJob.perform_later(@iteration.id)
38
+ loop do
39
+ sleep 0.2
40
+
41
+ break if @iteration.reload.complete?
42
+ end
39
43
 
40
44
  render json: {
41
45
  result: @iteration.result
@@ -65,6 +65,7 @@ class ::CommandProposal::RunnerController < ::CommandProposal::EngineController
65
65
  result: @iteration.result,
66
66
  status: @iteration.status,
67
67
  duration: humanized_duration(@iteration.duration),
68
+ started_at: @iteration.started_at&.strftime("%b %-d '%y, %-l:%M%P")
68
69
  }.tap do |response|
69
70
  if @iteration.started?
70
71
  response[:endpoint] = runner_url(@task, @iteration)
@@ -17,7 +17,8 @@ class ::CommandProposal::TasksController < ::CommandProposal::EngineController
17
17
  @tasks = ::CommandProposal::Task.includes(:iterations)
18
18
  @tasks = @tasks.order(Arel.sql("COALESCE(command_proposal_tasks.last_executed_at, command_proposal_tasks.created_at) DESC"))
19
19
  @tasks = @tasks.search(params[:search]) if params[:search].present?
20
- @tasks = @tasks.where(session_type: params[:filter]) if params[:filter].present?
20
+ @tasks = @tasks.by_session(params[:filter])
21
+ @tasks = @tasks.cmd_page(params[:page])
21
22
  end
22
23
 
23
24
  def show
@@ -37,7 +38,8 @@ class ::CommandProposal::TasksController < ::CommandProposal::EngineController
37
38
  end
38
39
 
39
40
  def new
40
- @task = ::CommandProposal::Task.new(session_type: params[:session_type])
41
+ @task = ::CommandProposal::Task.new
42
+ @task.session_type = params[:session_type] if params[:session_type].in?(::CommandProposal::Task.session_types)
41
43
 
42
44
  render "form"
43
45
  end
@@ -51,6 +53,7 @@ class ::CommandProposal::TasksController < ::CommandProposal::EngineController
51
53
  def create
52
54
  @task = ::CommandProposal::Task.new(task_params.except(:code))
53
55
  @task.user = command_user
56
+ @task.skip_approval = true unless approval_required?
54
57
 
55
58
  # Cannot create the iteration until the task is created, so save then update
56
59
  if @task.save && @task.update(task_params)
@@ -69,6 +72,7 @@ class ::CommandProposal::TasksController < ::CommandProposal::EngineController
69
72
  def update
70
73
  @task = ::CommandProposal::Task.find_by!(friendly_id: params[:id])
71
74
  @task.user = command_user
75
+ @task.skip_approval = true unless approval_required?
72
76
 
73
77
  if @task.update(task_params)
74
78
  redirect_to cmd_path(@task)
@@ -22,6 +22,15 @@ module ::CommandProposal::ParamsHelper
22
22
  end
23
23
  end
24
24
 
25
+ def current_path(new_params={})
26
+ if @task.present?
27
+ new_params.merge!(iteration: @iteration.id) if @iteration.present? && !@iteration.primary_iteration?
28
+ cmd_path(@task, new_params)
29
+ else
30
+ cmd_path(:tasks, current_params(new_params))
31
+ end
32
+ end
33
+
25
34
  def truthy?(val)
26
35
  val.to_s.downcase.in?(["true", "t", "1"])
27
36
  end
@@ -60,4 +69,38 @@ module ::CommandProposal::ParamsHelper
60
69
  return "< 1s" if str_parts.none?
61
70
  str_parts.join(" ")
62
71
  end
72
+
73
+ def div(opts={}, &block)
74
+ "<div #{opts.map { |k, v| "#{k}=\"#{v}\"" }.join(" ")}>#{yield}</div>".html_safe
75
+ end
76
+
77
+ def command_paginate(paged_collection)
78
+ collection = paged_collection.unscope(:limit, :offset)
79
+
80
+ per = ::CommandProposal::PAGINATION_PER
81
+ total_pages = (collection.count / per.to_f).ceil
82
+ current_page = params[:page].presence&.to_i || 1
83
+
84
+ return if total_pages <= 1
85
+
86
+ div(class: "cmd-pagination") do
87
+ links = []
88
+ links << ["<<", { page: 1 }] if current_page > 1
89
+ links << ["<", { page: current_page - 1 }] if current_page > 1
90
+
91
+ (current_page-2..current_page+2).each do |page_window|
92
+ next if page_window < 1
93
+ next if page_window > total_pages
94
+
95
+ links << [page_window, { page: page_window }]
96
+ end
97
+
98
+ links << [">", page: current_page + 1] if current_page < total_pages
99
+ links << [">>", page: total_pages] if current_page < total_pages
100
+
101
+ links.map do |link_text, link_params|
102
+ "<a class=\"cmd-pagination-link #{'current-page' if link_params[:page] == current_page}\" href=\"#{current_path(link_params)}\">#{link_text}</a>"
103
+ end.join("\n")
104
+ end
105
+ end
63
106
  end
@@ -2,14 +2,14 @@ module CommandProposal
2
2
  module PermissionsHelper
3
3
  def can_command?(user=command_user)
4
4
  return false unless permitted_to_use?
5
- return true unless cmd_config.approval_required?
5
+ return true unless approval_required?
6
6
 
7
7
  command_user.try("#{cmd_config.role_scope}?")
8
8
  end
9
9
 
10
10
  def can_approve?(iteration)
11
11
  return false unless permitted_to_use?
12
- return true unless cmd_config.approval_required?
12
+ return true unless approval_required?
13
13
  return if iteration.nil?
14
14
 
15
15
  command_user.try("#{cmd_config.role_scope}?") && !current_is_author?(iteration)
@@ -17,11 +17,15 @@ module CommandProposal
17
17
 
18
18
  def has_approval?(task)
19
19
  return false unless permitted_to_use?
20
- return true unless cmd_config.approval_required?
20
+ return true unless approval_required?
21
21
 
22
22
  task&.approved?
23
23
  end
24
24
 
25
+ def approval_required?
26
+ cmd_config.approval_required?
27
+ end
28
+
25
29
  def current_is_author?(iteration)
26
30
  return false unless permitted_to_use?
27
31
 
@@ -21,6 +21,10 @@ class ::CommandProposal::Iteration < ApplicationRecord
21
21
  serialize :args, ::CommandProposal::Service::JSONWrapper
22
22
  include ::CommandProposal::Service::ExternalBelong
23
23
 
24
+ TRUNCATE_COUNT = 2000
25
+ # Also hardcoded in JS: app/assets/javascripts/command_proposal/console.js
26
+ PAGINATION_PER = 2
27
+
24
28
  has_many :comments
25
29
  belongs_to :task
26
30
  external_belongs_to :requester
@@ -37,6 +41,12 @@ class ::CommandProposal::Iteration < ApplicationRecord
37
41
  terminated: 7, # Closed via server restart
38
42
  }
39
43
 
44
+ scope :cmd_page, ->(page=nil) {
45
+ page = page.presence&.to_i || 1
46
+ per = ::CommandProposal::PAGINATION_PER
47
+ limit(per).offset(per * (page - 1))
48
+ }
49
+
40
50
  delegate :name, to: :task
41
51
  delegate :description, to: :task
42
52
  delegate :session_type, to: :task
@@ -52,6 +62,10 @@ class ::CommandProposal::Iteration < ApplicationRecord
52
62
  ::CommandProposal::Task.module.where(friendly_id: bring_str.scan(/\s+\:(\w+),?/).flatten)
53
63
  end
54
64
 
65
+ def primary_iteration?
66
+ task.primary_iteration == self
67
+ end
68
+
55
69
  def complete?
56
70
  success? || failed? || cancelled? || terminated?
57
71
  end
@@ -70,6 +84,10 @@ class ::CommandProposal::Iteration < ApplicationRecord
70
84
  (completed_at || stopped_at || Time.current) - started_at
71
85
  end
72
86
 
87
+ def end_time
88
+ completed_at || stopped_at || Time.current
89
+ end
90
+
73
91
  def force_reset
74
92
  # Debugging method. Should never actually be called.
75
93
  update(status: :approved, result: nil, completed_at: nil, stopped_at: nil, started_at: nil)
@@ -7,7 +7,7 @@
7
7
 
8
8
  class ::CommandProposal::Task < ApplicationRecord
9
9
  self.table_name = :command_proposal_tasks
10
- attr_accessor :user
10
+ attr_accessor :user, :skip_approval
11
11
 
12
12
  has_many :iterations
13
13
  has_many :ordered_iterations, -> { order(created_at: :desc) }, class_name: "CommandProposal::Iteration"
@@ -15,12 +15,24 @@ class ::CommandProposal::Task < ApplicationRecord
15
15
  scope :search, ->(text) {
16
16
  where("name ILIKE :q OR description ILIKE :q", q: "%#{text}%")
17
17
  }
18
+ scope :by_session, ->(filter) {
19
+ if filter.present?
20
+ where(session_type: filter) if filter.to_s.in?(session_types.keys)
21
+ else
22
+ where(session_type: :function)
23
+ end
24
+ }
25
+ scope :cmd_page, ->(page=nil) {
26
+ page = page.presence&.to_i || 1
27
+ per = ::CommandProposal::PAGINATION_PER
28
+ limit(per).offset(per * (page - 1))
29
+ }
18
30
 
19
31
  enum session_type: {
20
- # Task will have multiple iterations that are all essentially the same just with code changes
21
- task: 0,
22
32
  # Function iterations are much like tasks
23
33
  function: 1,
34
+ # Task will have multiple iterations that are all essentially the same just with code changes
35
+ task: 0,
24
36
  # Console iterations are actually line by line, so order matters
25
37
  console: 2,
26
38
  # Modules are included in tasks and not run independently
@@ -79,7 +91,17 @@ class ::CommandProposal::Task < ApplicationRecord
79
91
  end
80
92
 
81
93
  def code=(new_code)
82
- iterations.create(code: new_code, requester: user)
94
+ if skip_approval
95
+ iterations.create(
96
+ code: new_code,
97
+ requester: user,
98
+ status: :approved,
99
+ approver: user,
100
+ approved_at: Time.current
101
+ )
102
+ else
103
+ iterations.create(code: new_code, requester: user)
104
+ end
83
105
  end
84
106
 
85
107
  private
@@ -1,8 +1,18 @@
1
1
  <% if lines.none? && !(skip_empty ||= false) -%><div class="line"></div><% end
2
2
  -%><% lines.each do |iteration| -%>
3
- <div class="line"><%= iteration.code -%><%
4
- if iteration.result.present?
5
- -%><div class="result"><%= iteration.result %></div><%
6
- end
7
- -%></div>
8
- <% end -%>
3
+ <div class="line"><%= iteration.code
4
+ -%><div class="result"><%=
5
+ truncate = ::CommandProposal::Iteration::TRUNCATE_COUNT
6
+ if iteration.result.present?
7
+ iteration.result.truncate(truncate)
8
+ elsif iteration.completed?
9
+ "Error: No response"
10
+ else
11
+ content_tag :i, nil, class: "fa fa-circle-o-notch fa-spin cmd-icon-grey"
12
+ end
13
+ %></div
14
+ ></div><%=
15
+ if iteration.result.length > truncate
16
+ link_to("Output truncated. Click here to download full result.", "data:application/txt,#{ERB::Util.url_encode(iteration.result)}", class: "cmd-truncated-download", download: "result.txt")
17
+ end
18
+ %><% end -%>
@@ -1,4 +1,8 @@
1
1
  <% if lines.blank? && !(skip_empty ||= false) -%><div class="line"></div><% end
2
2
  -%><% lines&.split("\n").each do |line|
3
- -%><div class="line"><%= line -%></div><%
3
+ truncate = ::CommandProposal::Iteration::TRUNCATE_COUNT
4
+ -%><div class="line"><%= line.truncate(truncate) -%></div><%=
5
+ if line.length > truncate
6
+ link_to("Output truncated. Click here to download full result.", "data:application/txt,#{ERB::Util.url_encode(line)}", class: "cmd-truncated-download", download: "result.txt")
7
+ end -%><%
4
8
  end -%>
@@ -7,15 +7,12 @@
7
7
  <!-- <th>Diff</th> -->
8
8
  </thead>
9
9
  <tbody>
10
- <% primary_iteration = @task.primary_iteration %>
11
- <% @task.iterations.where.not(id: @iteration&.id).order(created_at: :desc).each do |iteration| %>
10
+ <% paginated_iterations = @task.iterations.cmd_page(params[:page]) %>
11
+ <% paginated_iterations.order(created_at: :desc).each do |iteration| %>
12
12
  <tr>
13
13
  <td>
14
- <% if iteration.id == primary_iteration&.id %>
15
- <%= link_to iteration.created_at.strftime("%b %-d, %Y at %H:%M"), cmd_path(@task) %>
16
- <% else %>
17
- <%= link_to iteration.created_at.strftime("%b %-d, %Y at %H:%M"), cmd_path(@task, iteration: iteration.id) %>
18
- <% end %>
14
+ <%= ">" if iteration == @iteration %>
15
+ <%= link_to iteration.created_at.strftime("%b %-d, %Y at %H:%M"), cmd_path(@task, iteration: iteration.id) %>
19
16
  </td>
20
17
  <td><%= iteration.status.capitalize %></td>
21
18
  <!-- <td><%#= iteration.comments.count %></td> -->
@@ -24,4 +21,6 @@
24
21
  <% end %>
25
22
  </tbody>
26
23
  </table>
24
+
25
+ <%= command_paginate paginated_iterations %>
27
26
  <% end %>
@@ -10,7 +10,7 @@
10
10
  <tr>
11
11
  <td><%= @iteration&.requester_name.presence || "ID: #{@iteration&.requester_id}" if @iteration&.requester_id.present? %></td>
12
12
  <td><%= @iteration&.approver_name.presence || "ID: #{@iteration&.approver_id}" if @iteration&.approver_id.present? %></td>
13
- <td><%= @iteration&.started_at&.strftime("%b %-d '%y, %-l:%M%P") %></td>
13
+ <td data-iteration-started><%= @iteration&.started_at&.strftime("%b %-d '%y, %-l:%M%P") %></td>
14
14
  <td data-iteration-status><%= @iteration&.status&.capitalize %></td>
15
15
  <td data-iteration-duration><%= humanized_duration(@iteration&.duration) %></td>
16
16
  </tr>
@@ -1,9 +1,11 @@
1
1
  <div class="cmd-wrapper">
2
- <%= link_to "New #{params[:filter].presence&.capitalize || 'Command'}", cmd_path(:new, :task, session_type: params[:filter] || :task) %> <br>
2
+ <% filter_name = params[:filter].presence&.capitalize %>
3
+ <% filter_name = filter_name.blank? || filter_name == "All" ? "Command" : filter_name %>
4
+ <%= link_to "New #{filter_name}", cmd_path(:new, :task, session_type: params[:filter] || :task) %> <br>
3
5
  <br>
4
- <%= link_to "All", cmd_path(:tasks, current_params.except(:filter)), class: "cmd-tab #{:active unless params.key?(:filter)}"
6
+ <%= link_to "All", toggled_param(filter: :all), class: "cmd-tab #{:active if params[:filter] == "all"}"
5
7
  %><% ::CommandProposal::Task.session_types.each_with_index do |(session_type, _session_enum), idx| %><%=
6
- selected = params[:filter] == session_type.to_s
8
+ selected = params[:filter] == session_type.to_s || (!params.key?(:filter) && session_type == "function")
7
9
  # Offset closing RB tags to fix spacing issues
8
10
  link_to session_type.capitalize, toggled_param(filter: session_type), class: "cmd-tab #{:active if selected}"
9
11
  %><% end %>
@@ -42,4 +44,6 @@
42
44
  <% end %>
43
45
  <% end %>
44
46
  </div>
47
+
48
+ <%= command_paginate @tasks %>
45
49
  </div>
@@ -66,7 +66,7 @@ module CommandProposal
66
66
  # Rollback the create/update if anything fails
67
67
  ActiveRecord::Base.transaction do
68
68
  command_request if @task.function? && @iteration.approved_at? && @iteration.complete?
69
- @iteration.update(@params)
69
+ @iteration.update(@params.merge(requester: @user))
70
70
 
71
71
  error!("Cannot run without approval.") unless has_approval?(@task)
72
72
  end
@@ -91,7 +91,8 @@ module CommandProposal
91
91
  if ::CommandProposal.sessions.key?("task:#{@task.id}")
92
92
  @task.first_iteration.update(status: :success, completed_at: Time.current)
93
93
  else
94
- @task.first_iteration.update(status: :terminated, completed_at: Time.current)
94
+ ended_at = @task.iterations.last&.end_time || Time.current
95
+ @task.first_iteration.update(status: :terminated, completed_at: ended_at)
95
96
  end
96
97
  ::CommandProposal.sessions.delete("task:#{@task.id}")
97
98
  end
@@ -10,6 +10,31 @@ module CommandProposal
10
10
  new.execute(task.primary_iteration)
11
11
  end
12
12
 
13
+ def self.command(friendly_id, user, params={})
14
+ # Hack magic because requires are not playing well with spring
15
+ require "command_proposal/services/command_interpreter"
16
+
17
+ params = params.to_unsafe_h if params.is_a?(ActionController::Parameters)
18
+
19
+ iteration = ::CommandProposal::Services::CommandInterpreter.command(
20
+ ::CommandProposal::Task.find_by!(friendly_id: friendly_id).primary_iteration,
21
+ :run,
22
+ user,
23
+ { args: params }
24
+ )
25
+
26
+ start = Time.current
27
+ wait_time = 5 # seconds
28
+ loop do
29
+ sleep 0.4
30
+
31
+ break if iteration.reload.complete?
32
+ break if Time.current - start > wait_time
33
+ end
34
+
35
+ iteration
36
+ end
37
+
13
38
  def initialize
14
39
  @session = session
15
40
  end
@@ -51,7 +76,11 @@ module CommandProposal
51
76
 
52
77
  def run
53
78
  begin
54
- @session.eval("#{bring_function};params = #{@iteration.args || {}}.with_indifferent_access")
79
+ params_str = ""
80
+ unless @iteration.task.console? # Don't bring params into the console
81
+ params_str = "params = #{@iteration.args || {}}.with_indifferent_access"
82
+ end
83
+ @session.eval("#{bring_function};#{params_str}")
55
84
  rescue Exception => e # rubocop:disable Lint/RescueException - Yes, rescue full Exception so that we can catch typos in evals as well
56
85
  return @iteration.result = results_from_exception(e)
57
86
  end
@@ -63,9 +92,10 @@ module CommandProposal
63
92
 
64
93
  running_thread = Thread.new do
65
94
  begin
66
- # Run bring functions in here so we can capture any string outputs
95
+ # Run `bring` functions in here so we can capture any string outputs
67
96
  # OR! Run the full runner and instead of saving to an iteration, return the string for prepending here
68
97
  result = @session.eval("_ = (#{@iteration.code})").inspect # rubocop:disable Security/Eval - Eval is scary, but in this case it's exactly what we need.
98
+ result = nil unless @iteration.task.console? # Only store final result for consoles
69
99
  status = :success
70
100
  rescue Exception => e # rubocop:disable Lint/RescueException - Yes, rescue full Exception so that we can catch typos in evals as well
71
101
  status = :failed
@@ -95,7 +125,7 @@ module CommandProposal
95
125
 
96
126
  $stdout = stored_stdout
97
127
  @iteration.status = status
98
- @iteration.result = [output, "#{result || 'nil'}"].compact.join("\n")
128
+ @iteration.result = [output, result].compact.join("\n")
99
129
  end
100
130
 
101
131
  def bring_function
@@ -1,3 +1,3 @@
1
1
  module CommandProposal
2
- VERSION = "1.0.9"
2
+ VERSION = "1.0.13"
3
3
  end
@@ -6,6 +6,8 @@ require "command_proposal/services/shut_down"
6
6
 
7
7
  module CommandProposal
8
8
  class Error < StandardError; end
9
+ PAGINATION_PER = 10
10
+
9
11
  def self.sessions
10
12
  @sessions ||= {}
11
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: command_proposal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rocco Nicholls
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-14 00:00:00.000000000 Z
11
+ date: 2022-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails