runsheets 0.0.1

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +98 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +277 -0
  5. data/bin/runsheets +12 -0
  6. data/examples/about-the-examples.md +40 -0
  7. data/examples/directory_based_runbooks/hello/rollback.md +11 -0
  8. data/examples/directory_based_runbooks/hello/runbook.md +40 -0
  9. data/examples/directory_based_runbooks/hello/steps/010-say-hello.md +33 -0
  10. data/examples/directory_based_runbooks/hello/steps/020-inspect-ruby.md +28 -0
  11. data/examples/directory_based_runbooks/hello/steps/030-take-a-breath.md +11 -0
  12. data/examples/directory_based_runbooks/hello/steps/035-keep-a-clock-running.md +21 -0
  13. data/examples/directory_based_runbooks/hello/steps/040-exercise-failure.md +26 -0
  14. data/examples/directory_based_runbooks/hello/steps/045-check-the-greeting.md +18 -0
  15. data/examples/directory_based_runbooks/hello/verify.md +18 -0
  16. data/examples/directory_based_runbooks/staging-teardown/rollback.md +28 -0
  17. data/examples/directory_based_runbooks/staging-teardown/runbook.md +57 -0
  18. data/examples/directory_based_runbooks/staging-teardown/steps/010-confirm-nothing-to-preserve.md +18 -0
  19. data/examples/directory_based_runbooks/staging-teardown/steps/020-snapshot-the-database.md +47 -0
  20. data/examples/directory_based_runbooks/staging-teardown/steps/030-stop-the-pipeline.md +32 -0
  21. data/examples/directory_based_runbooks/staging-teardown/steps/040-drain-the-ecs-services.md +35 -0
  22. data/examples/directory_based_runbooks/staging-teardown/steps/050-record-the-final-row-counts.md +41 -0
  23. data/examples/directory_based_runbooks/staging-teardown/steps/060-delete-the-stack.md +56 -0
  24. data/examples/directory_based_runbooks/staging-teardown/verify.md +40 -0
  25. data/examples/single_md_file_runbooks/db-maintenance.md +163 -0
  26. data/examples/single_md_file_runbooks/disk-space-triage.md +90 -0
  27. data/examples/single_md_file_runbooks/disk-usage-glossary.md +48 -0
  28. data/examples/single_md_file_runbooks/policies/cleanup-policy.md +33 -0
  29. data/examples/single_md_file_runbooks/policies/images/triage-flow.svg +44 -0
  30. data/examples/single_md_file_runbooks/runbooks_with_scripts/.loki +17 -0
  31. data/examples/single_md_file_runbooks/runbooks_with_scripts/asgard-tasks.md +135 -0
  32. data/examples/single_md_file_runbooks/runbooks_with_scripts/checks.loki +27 -0
  33. data/examples/single_md_file_runbooks/runbooks_with_scripts/greet.loki +6 -0
  34. data/lib/runsheets/assets.rb +780 -0
  35. data/lib/runsheets/block.rb +118 -0
  36. data/lib/runsheets/cli.rb +424 -0
  37. data/lib/runsheets/config/defaults.yml +44 -0
  38. data/lib/runsheets/config.rb +139 -0
  39. data/lib/runsheets/diff.rb +67 -0
  40. data/lib/runsheets/execution.rb +144 -0
  41. data/lib/runsheets/executor.rb +157 -0
  42. data/lib/runsheets/expectation.rb +101 -0
  43. data/lib/runsheets/fences.rb +172 -0
  44. data/lib/runsheets/front_matter.rb +29 -0
  45. data/lib/runsheets/library.rb +268 -0
  46. data/lib/runsheets/pages/chooser.rb +408 -0
  47. data/lib/runsheets/pages/search.rb +119 -0
  48. data/lib/runsheets/pages/tree.rb +88 -0
  49. data/lib/runsheets/pages.rb +947 -0
  50. data/lib/runsheets/redactor.rb +88 -0
  51. data/lib/runsheets/renderer.rb +229 -0
  52. data/lib/runsheets/run.rb +330 -0
  53. data/lib/runsheets/run_record.rb +371 -0
  54. data/lib/runsheets/runbook.rb +301 -0
  55. data/lib/runsheets/search.rb +129 -0
  56. data/lib/runsheets/session.rb +307 -0
  57. data/lib/runsheets/session_log.rb +114 -0
  58. data/lib/runsheets/single_file.rb +93 -0
  59. data/lib/runsheets/step.rb +91 -0
  60. data/lib/runsheets/version.rb +5 -0
  61. data/lib/runsheets/web.rb +537 -0
  62. data/lib/runsheets.rb +90 -0
  63. data/sig/runsheets.rbs +4 -0
  64. metadata +226 -0
data/lib/runsheets.rb ADDED
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "digest"
5
+ require "json"
6
+ require "pathname"
7
+ require "securerandom"
8
+ require "shellwords"
9
+ require "time"
10
+ require "yaml"
11
+
12
+ require_relative "runsheets/version"
13
+
14
+ # runsheets: executable runbooks served from a local web page.
15
+ #
16
+ # A runbook is a directory of markdown files, or a single file (see Runbook).
17
+ # Fenced code blocks that opt in through their info string (see Block) can be
18
+ # executed from the browser; everything that happens during a run is captured
19
+ # into a RunRecord, the runsheet.
20
+ #
21
+ # The web layer (Web, Pages, Assets) and the command line (CLI) are loaded on
22
+ # demand so the model can be used without Sinatra.
23
+ module Runsheets
24
+ class Error < StandardError; end
25
+ class RunbookError < Error; end
26
+ class RunError < Error; end
27
+
28
+ autoload :Assets, File.expand_path("runsheets/assets", __dir__)
29
+ autoload :CLI, File.expand_path("runsheets/cli", __dir__)
30
+ autoload :Pages, File.expand_path("runsheets/pages", __dir__)
31
+ autoload :Web, File.expand_path("runsheets/web", __dir__)
32
+
33
+ class << self
34
+ attr_writer :runs_dir
35
+
36
+ # The settings in force (see Config). Until configure is called they come
37
+ # from the config file, the environment and the bundled defaults.
38
+ def config = @config ||= Config.new
39
+
40
+ # Build and install the settings; overrides beat every other layer and
41
+ # path names the config file. The CLI calls this with what it parsed.
42
+ def configure(overrides = nil, path: nil) = @config = Config.new(overrides, path:)
43
+
44
+ # Forget the installed settings so the next call to config rebuilds them.
45
+ def reset_config! = @config = nil
46
+
47
+ # Where run records are written: an explicit assignment, else the
48
+ # configured runs_dir (--runs-dir, RUNSHEETS_RUNS_DIR, config file).
49
+ def runs_dir = @runs_dir || config.runs_dir
50
+
51
+ # Write +text+ to +path+ through a temporary file renamed into place, so
52
+ # a reader (or a crash) never sees half a record.
53
+ def write_atomic(path, text)
54
+ tmp = "#{path}.#{Process.pid}.#{Thread.current.object_id}.tmp"
55
+ File.write(tmp, text)
56
+ File.rename(tmp, path)
57
+ ensure
58
+ File.delete(tmp) if tmp && File.exist?(tmp)
59
+ end
60
+
61
+ # The last +bytes+ of a file as UTF-8 text ("" when it is missing), so a
62
+ # page never reads a whole multi-gigabyte output or log.
63
+ def read_tail(path, bytes)
64
+ return "" unless path && File.file?(path)
65
+
66
+ size = File.size(path)
67
+ File.binread(path, [bytes, size].min, [size - bytes, 0].max).force_encoding("UTF-8").scrub
68
+ end
69
+ end
70
+ end
71
+
72
+ require_relative "runsheets/config"
73
+ require_relative "runsheets/front_matter"
74
+ require_relative "runsheets/fences"
75
+ require_relative "runsheets/block"
76
+ require_relative "runsheets/renderer"
77
+ require_relative "runsheets/step"
78
+ require_relative "runsheets/single_file"
79
+ require_relative "runsheets/runbook"
80
+ require_relative "runsheets/library"
81
+ require_relative "runsheets/search"
82
+ require_relative "runsheets/diff"
83
+ require_relative "runsheets/expectation"
84
+ require_relative "runsheets/redactor"
85
+ require_relative "runsheets/execution"
86
+ require_relative "runsheets/executor"
87
+ require_relative "runsheets/run_record"
88
+ require_relative "runsheets/session_log"
89
+ require_relative "runsheets/run"
90
+ require_relative "runsheets/session"
data/sig/runsheets.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Runsheets
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,226 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: runsheets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dewayne VanHoozer
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: sinatra
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '4.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '4.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rackup
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: puma
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '6.4'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '6.4'
54
+ - !ruby/object:Gem::Dependency
55
+ name: kramdown
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.4'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.4'
68
+ - !ruby/object:Gem::Dependency
69
+ name: kramdown-parser-gfm
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.1'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.1'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rouge
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '4.0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '4.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: myway_config
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.1'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.1'
110
+ - !ruby/object:Gem::Dependency
111
+ name: logger
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ description: |
125
+ runsheets turns a directory of markdown files into an executable runbook served
126
+ from a local web page. Fenced code blocks the author marks as runnable get a Run
127
+ button; every execution, its output, exit status and timing, and every operator
128
+ acknowledgement is captured in order into a run record (the runsheet). The tool
129
+ binds to loopback only, executes only blocks that opt in, and modifies nothing in
130
+ the runbook directory.
131
+ email:
132
+ - dewayne@vanhoozer.me
133
+ executables:
134
+ - runsheets
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - CHANGELOG.md
139
+ - LICENSE.txt
140
+ - README.md
141
+ - bin/runsheets
142
+ - examples/about-the-examples.md
143
+ - examples/directory_based_runbooks/hello/rollback.md
144
+ - examples/directory_based_runbooks/hello/runbook.md
145
+ - examples/directory_based_runbooks/hello/steps/010-say-hello.md
146
+ - examples/directory_based_runbooks/hello/steps/020-inspect-ruby.md
147
+ - examples/directory_based_runbooks/hello/steps/030-take-a-breath.md
148
+ - examples/directory_based_runbooks/hello/steps/035-keep-a-clock-running.md
149
+ - examples/directory_based_runbooks/hello/steps/040-exercise-failure.md
150
+ - examples/directory_based_runbooks/hello/steps/045-check-the-greeting.md
151
+ - examples/directory_based_runbooks/hello/verify.md
152
+ - examples/directory_based_runbooks/staging-teardown/rollback.md
153
+ - examples/directory_based_runbooks/staging-teardown/runbook.md
154
+ - examples/directory_based_runbooks/staging-teardown/steps/010-confirm-nothing-to-preserve.md
155
+ - examples/directory_based_runbooks/staging-teardown/steps/020-snapshot-the-database.md
156
+ - examples/directory_based_runbooks/staging-teardown/steps/030-stop-the-pipeline.md
157
+ - examples/directory_based_runbooks/staging-teardown/steps/040-drain-the-ecs-services.md
158
+ - examples/directory_based_runbooks/staging-teardown/steps/050-record-the-final-row-counts.md
159
+ - examples/directory_based_runbooks/staging-teardown/steps/060-delete-the-stack.md
160
+ - examples/directory_based_runbooks/staging-teardown/verify.md
161
+ - examples/single_md_file_runbooks/db-maintenance.md
162
+ - examples/single_md_file_runbooks/disk-space-triage.md
163
+ - examples/single_md_file_runbooks/disk-usage-glossary.md
164
+ - examples/single_md_file_runbooks/policies/cleanup-policy.md
165
+ - examples/single_md_file_runbooks/policies/images/triage-flow.svg
166
+ - examples/single_md_file_runbooks/runbooks_with_scripts/.loki
167
+ - examples/single_md_file_runbooks/runbooks_with_scripts/asgard-tasks.md
168
+ - examples/single_md_file_runbooks/runbooks_with_scripts/checks.loki
169
+ - examples/single_md_file_runbooks/runbooks_with_scripts/greet.loki
170
+ - lib/runsheets.rb
171
+ - lib/runsheets/assets.rb
172
+ - lib/runsheets/block.rb
173
+ - lib/runsheets/cli.rb
174
+ - lib/runsheets/config.rb
175
+ - lib/runsheets/config/defaults.yml
176
+ - lib/runsheets/diff.rb
177
+ - lib/runsheets/execution.rb
178
+ - lib/runsheets/executor.rb
179
+ - lib/runsheets/expectation.rb
180
+ - lib/runsheets/fences.rb
181
+ - lib/runsheets/front_matter.rb
182
+ - lib/runsheets/library.rb
183
+ - lib/runsheets/pages.rb
184
+ - lib/runsheets/pages/chooser.rb
185
+ - lib/runsheets/pages/search.rb
186
+ - lib/runsheets/pages/tree.rb
187
+ - lib/runsheets/redactor.rb
188
+ - lib/runsheets/renderer.rb
189
+ - lib/runsheets/run.rb
190
+ - lib/runsheets/run_record.rb
191
+ - lib/runsheets/runbook.rb
192
+ - lib/runsheets/search.rb
193
+ - lib/runsheets/session.rb
194
+ - lib/runsheets/session_log.rb
195
+ - lib/runsheets/single_file.rb
196
+ - lib/runsheets/step.rb
197
+ - lib/runsheets/version.rb
198
+ - lib/runsheets/web.rb
199
+ - sig/runsheets.rbs
200
+ homepage: https://github.com/madbomber/runsheets
201
+ licenses:
202
+ - MIT
203
+ metadata:
204
+ homepage_uri: https://github.com/madbomber/runsheets
205
+ source_code_uri: https://github.com/madbomber/runsheets
206
+ changelog_uri: https://github.com/madbomber/runsheets/blob/main/CHANGELOG.md
207
+ bug_tracker_uri: https://github.com/madbomber/runsheets/issues
208
+ rubygems_mfa_required: 'true'
209
+ rdoc_options: []
210
+ require_paths:
211
+ - lib
212
+ required_ruby_version: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ version: '3.4'
217
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ requirements: []
223
+ rubygems_version: 4.0.22
224
+ specification_version: 4
225
+ summary: 'Executable runbooks: markdown steps rendered in the browser, run and recorded.'
226
+ test_files: []