workspaces 0.1.11 → 0.1.13
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.
- checksums.yaml +4 -4
- data/DESIGN.md +9 -3
- data/README.md +31 -3
- data/lib/workspaces/build_history.rb +83 -0
- data/lib/workspaces/config.rb +3 -0
- data/lib/workspaces/coordinator.rb +72 -9
- data/lib/workspaces/dashboard/app.js +148 -42
- data/lib/workspaces/dashboard/styles.css +82 -50
- data/lib/workspaces/dashboard/template.html.erb +18 -10
- data/lib/workspaces/dashboard_view.rb +66 -4
- data/lib/workspaces/duration_format.rb +36 -0
- data/lib/workspaces/paths.rb +16 -0
- data/lib/workspaces/presentation.rb +42 -12
- data/lib/workspaces/progress.rb +122 -0
- data/lib/workspaces/step_log.rb +55 -0
- data/lib/workspaces/tee_log.rb +7 -1
- data/lib/workspaces/version.rb +1 -1
- data/lib/workspaces/workflow.rb +16 -5
- metadata +6 -2
data/lib/workspaces/tee_log.rb
CHANGED
|
@@ -26,10 +26,16 @@ module Workspaces
|
|
|
26
26
|
$stdout.print(prefixed(scrubbed))
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# The filtering applied to everything written. Public so StepLog can copy exactly what the
|
|
30
|
+
# combined log received, instead of reimplementing the rules.
|
|
31
|
+
def scrub_text(message)
|
|
32
|
+
@overrides.scrub(message)
|
|
33
|
+
end
|
|
34
|
+
|
|
29
35
|
private
|
|
30
36
|
|
|
31
37
|
def scrub(message)
|
|
32
|
-
|
|
38
|
+
scrub_text(message)
|
|
33
39
|
end
|
|
34
40
|
|
|
35
41
|
def prefixed(message)
|
data/lib/workspaces/version.rb
CHANGED
data/lib/workspaces/workflow.rb
CHANGED
|
@@ -3,12 +3,15 @@ require_relative 'recipe'
|
|
|
3
3
|
require_relative 'command_runner'
|
|
4
4
|
require_relative 'backend'
|
|
5
5
|
require_relative 'environment_overrides'
|
|
6
|
+
require_relative 'step_log'
|
|
7
|
+
require_relative 'duration_format'
|
|
6
8
|
|
|
7
9
|
module Workspaces
|
|
8
10
|
class Workflow
|
|
9
11
|
def initialize(workspace, log, state: StateStore.new(Config.state_file))
|
|
10
12
|
@workspace = workspace
|
|
11
|
-
@
|
|
13
|
+
@combined_log = log
|
|
14
|
+
@log = StepLog.new(log, workspace.id)
|
|
12
15
|
@state = state
|
|
13
16
|
@backend = Backend.new(workspace.id)
|
|
14
17
|
end
|
|
@@ -18,6 +21,7 @@ module Workspaces
|
|
|
18
21
|
overrides = EnvironmentOverrides.new(@workspace.id).load
|
|
19
22
|
steps = recipe.for_operation(restart: restart)
|
|
20
23
|
publish_steps(steps)
|
|
24
|
+
StepLog.reset(@workspace.id)
|
|
21
25
|
@backend.stop!
|
|
22
26
|
context = build_context(@backend.reserve!)
|
|
23
27
|
runner = CommandRunner.new(@workspace.path, @log)
|
|
@@ -27,6 +31,8 @@ module Workspaces
|
|
|
27
31
|
rescue StandardError
|
|
28
32
|
@backend.stop!
|
|
29
33
|
raise
|
|
34
|
+
ensure
|
|
35
|
+
@log.finish_step
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
private
|
|
@@ -50,6 +56,7 @@ module Workspaces
|
|
|
50
56
|
def execute(step, recipe, context, runner, overrides)
|
|
51
57
|
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
52
58
|
progress(step, 'active')
|
|
59
|
+
@log.begin_step(step.fetch('id'))
|
|
53
60
|
@log.puts "==> #{step.fetch('name')}"
|
|
54
61
|
command = recipe.command(step, context)
|
|
55
62
|
env = recipe.env(step, context, overrides: overrides)
|
|
@@ -60,7 +67,10 @@ module Workspaces
|
|
|
60
67
|
@backend.ensure_alive! if @server_started
|
|
61
68
|
end
|
|
62
69
|
@server_started = true if step['background']
|
|
63
|
-
rescue StandardError
|
|
70
|
+
rescue StandardError => e
|
|
71
|
+
# The reason a step failed is not command output, so the step file would otherwise end
|
|
72
|
+
# without it. Record it where the step's own accordion can show it.
|
|
73
|
+
@log.puts "ERROR: #{e.message}"
|
|
64
74
|
finish_step(step, 'failed', started_at)
|
|
65
75
|
raise
|
|
66
76
|
else
|
|
@@ -70,14 +80,15 @@ module Workspaces
|
|
|
70
80
|
def finish_step(step, status, started_at)
|
|
71
81
|
duration = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at).round(3)
|
|
72
82
|
progress(step, status, duration_seconds: duration)
|
|
73
|
-
@log.puts format('==> %s %s (
|
|
83
|
+
@log.puts format('==> %s %s (%s)', step.fetch('name'), status, DurationFormat.call(duration))
|
|
74
84
|
end
|
|
75
85
|
|
|
76
86
|
def progress(step, status, duration_seconds: nil)
|
|
77
87
|
@state.transaction do |data|
|
|
78
88
|
entry = data.fetch(@workspace.id)
|
|
79
|
-
entry['steps'].find { |item| item['key'] == step['id'] }
|
|
80
|
-
|
|
89
|
+
record = entry['steps'].find { |item| item['key'] == step['id'] }
|
|
90
|
+
record.merge!('state' => status, 'duration_seconds' => duration_seconds)
|
|
91
|
+
record['started_at'] = Time.now.utc.iso8601(3) if status == 'active'
|
|
81
92
|
entry['message'] = step['name']
|
|
82
93
|
entry['current_step'] = step['id']
|
|
83
94
|
entry['updated_at'] = Time.now.utc.iso8601
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: workspaces
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Workspaces contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -71,6 +71,7 @@ files:
|
|
|
71
71
|
- exe/workspaces
|
|
72
72
|
- lib/workspaces.rb
|
|
73
73
|
- lib/workspaces/backend.rb
|
|
74
|
+
- lib/workspaces/build_history.rb
|
|
74
75
|
- lib/workspaces/child_env.rb
|
|
75
76
|
- lib/workspaces/cli.rb
|
|
76
77
|
- lib/workspaces/command_runner.rb
|
|
@@ -83,15 +84,18 @@ files:
|
|
|
83
84
|
- lib/workspaces/dashboard/styles.css
|
|
84
85
|
- lib/workspaces/dashboard/template.html.erb
|
|
85
86
|
- lib/workspaces/dashboard_view.rb
|
|
87
|
+
- lib/workspaces/duration_format.rb
|
|
86
88
|
- lib/workspaces/environment_overrides.rb
|
|
87
89
|
- lib/workspaces/front_door.rb
|
|
88
90
|
- lib/workspaces/paths.rb
|
|
89
91
|
- lib/workspaces/port_allocator.rb
|
|
90
92
|
- lib/workspaces/presentation.rb
|
|
93
|
+
- lib/workspaces/progress.rb
|
|
91
94
|
- lib/workspaces/proxy_middleware.rb
|
|
92
95
|
- lib/workspaces/recipe.rb
|
|
93
96
|
- lib/workspaces/registry.rb
|
|
94
97
|
- lib/workspaces/state_store.rb
|
|
98
|
+
- lib/workspaces/step_log.rb
|
|
95
99
|
- lib/workspaces/tee_log.rb
|
|
96
100
|
- lib/workspaces/tls.rb
|
|
97
101
|
- lib/workspaces/version.rb
|