rundoc 3.0.2 → 3.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +28 -0
- data/lib/rundoc/cli.rb +14 -2
- data/lib/rundoc/cli_argument_parser.rb +6 -1
- data/lib/rundoc/code_command/background/process_spawn.rb +2 -2
- data/lib/rundoc/code_command/background/start.rb +1 -0
- data/lib/rundoc/code_section.rb +3 -1
- data/lib/rundoc/context/execution.rb +5 -2
- data/lib/rundoc/parser.rb +20 -1
- data/lib/rundoc/version.rb +1 -1
- data/test/integration/failure_test.rb +52 -1
- data/test/integration/with_contents_flag_test.rb +35 -0
- data/test/test_helper.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d21f4ac48ad2eab762969c03ce386aeb097f99162d38716e4736de44c9bbac83
|
4
|
+
data.tar.gz: 79f9be265a84d8474e3ed7d55d90781e9999790b6cf5e578943db89e0fec7ee9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcf456c89f09000ddeeaf7aa22654acf419f36294b9e88dec9735f9ec3fcab315085dd6ee97cbd63eb580078e009968219b5240a6fe7a6db4c022d1b878d97cb
|
7
|
+
data.tar.gz: 8e2ee0bd6fa26b8b8906ec9b2267a9e98feedc40b54dc53ca457937a7199865c2c6b7663837a067802426321fc93740da3038289ea516139a573a1e5679c8724
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
## HEAD
|
2
2
|
|
3
|
+
## 3.1.1
|
4
|
+
|
5
|
+
- Fix: Include all code sections in the event of a failure, not just the last one (https://github.com/zombocom/rundoc/pull/71)
|
6
|
+
|
7
|
+
## 3.1.0
|
8
|
+
|
9
|
+
- Add: `--with-contents` flag that accepts a directory. The **contents** of the directory (and not the directory itself) will be copied into the working dir before execution. This is useful for debugging a single rundoc step. ()
|
10
|
+
|
11
|
+
For example if `RUNDOC.md` features many smaller docs:
|
12
|
+
|
13
|
+
```
|
14
|
+
:::>> rundoc.require "./intro.md"
|
15
|
+
:::>> rundoc.require "../shared/install_cli.md"
|
16
|
+
:::>> rundoc.require "./clone_app.md"
|
17
|
+
```
|
18
|
+
|
19
|
+
If the command fails on `clone_app.md` then you can rapidly iterate by calling `$ rundoc ./clone_app.md --with-contents failed/my-app` but be careful to not use the same failure directory etc or it will be replaced.
|
20
|
+
|
3
21
|
## 3.0.2
|
4
22
|
|
5
23
|
- Fix: Partial output of the document is now written to disk in a `RUNDOC_FAILED.md` file (https://github.com/zombocom/rundoc/pull/69)
|
data/README.md
CHANGED
@@ -88,6 +88,7 @@ This will generate a project folder with your project in it, and a markdown `REA
|
|
88
88
|
- [background.stop](#background)
|
89
89
|
- [background.log.read](#background)
|
90
90
|
- [background.log.clear](#background)
|
91
|
+
- [background.wait](#background)
|
91
92
|
- Take screenshots
|
92
93
|
- [website.visit](#screenshots)
|
93
94
|
- [website.nav](#screenshots)
|
@@ -410,6 +411,13 @@ To start a process, pass in the command as the first arg, and give it a name (so
|
|
410
411
|
:::>> background.start("rails server", name: "server")
|
411
412
|
```
|
412
413
|
|
414
|
+
- Arguments
|
415
|
+
- name: Identifier of the background process, used in later invocations.
|
416
|
+
- wait (Optional): A string to wait for before continuing. This is useful to block moving on until an event happend such as a server was booted or web request was received. Also see `background.wait`
|
417
|
+
- timeout (Optional): A number of seconds to wait for a given string to be found in the logs.
|
418
|
+
- out (Optional): A bash redirect. Defaults to `2>&1` to merge stderr and stdout together.
|
419
|
+
- allow_fail (Optional): Set to `true` if the command exiting shouldn't halt doc generation. Poorly named, may be renamed in the future.
|
420
|
+
|
413
421
|
You can make the background process wait until it receives a certain string in the logs. For instance to make sure that the server is fully booted:
|
414
422
|
|
415
423
|
```
|
@@ -422,18 +430,38 @@ You can stop the process by referencing the name:
|
|
422
430
|
:::-- background.stop(name: "server")
|
423
431
|
```
|
424
432
|
|
433
|
+
- Arguments
|
434
|
+
- name
|
435
|
+
|
425
436
|
You can also get the log contents:
|
426
437
|
|
427
438
|
```
|
428
439
|
:::>> background.log.read(name: "server")
|
429
440
|
```
|
430
441
|
|
442
|
+
- Arguments
|
443
|
+
- name
|
444
|
+
|
431
445
|
You can also truncate the logs:
|
432
446
|
|
433
447
|
```
|
434
448
|
:::>> background.log.clear(name: "server")
|
435
449
|
```
|
436
450
|
|
451
|
+
- Arguments
|
452
|
+
- name
|
453
|
+
|
454
|
+
You can also wait for a given string to appear in the logs:
|
455
|
+
|
456
|
+
```
|
457
|
+
:::>> background.wait(name: "server", wait: "method=GET")
|
458
|
+
```
|
459
|
+
|
460
|
+
- Arguments
|
461
|
+
- name
|
462
|
+
- wait: Same as `background.start` a string value to look for before continuing.
|
463
|
+
- timeout: Maximum number of seconds to wait
|
464
|
+
|
437
465
|
## Screenshots
|
438
466
|
|
439
467
|
You'll need selenium and `chromedriver` installed on your system to make screenshots work. On a mac you can run:
|
data/lib/rundoc/cli.rb
CHANGED
@@ -24,6 +24,7 @@ module Rundoc
|
|
24
24
|
on_success_dir: nil,
|
25
25
|
on_failure_dir: nil,
|
26
26
|
output_filename: nil,
|
27
|
+
with_contents_dir: nil,
|
27
28
|
screenshots_dirname: nil
|
28
29
|
)
|
29
30
|
@io = io
|
@@ -37,6 +38,7 @@ module Rundoc
|
|
37
38
|
@execution_context = Rundoc::Context::Execution.new(
|
38
39
|
output_dir: Dir.mktmpdir,
|
39
40
|
source_path: source_path,
|
41
|
+
with_contents_dir: with_contents_dir,
|
40
42
|
screenshots_dirname: screenshots_dirname
|
41
43
|
)
|
42
44
|
|
@@ -136,13 +138,23 @@ module Rundoc
|
|
136
138
|
|
137
139
|
source_contents = execution_context.source_path.read
|
138
140
|
if on_failure_dir.exist? && !Dir.empty?(on_failure_dir)
|
139
|
-
io.puts "##
|
141
|
+
io.puts "## erring on failure directory #{on_failure_dir}"
|
140
142
|
clean_dir(
|
141
143
|
dir: on_failure_dir,
|
142
144
|
description: "on failure directory"
|
143
145
|
)
|
144
146
|
end
|
145
147
|
|
148
|
+
if execution_context.with_contents_dir
|
149
|
+
io.puts "## Copying contents from #{execution_context.with_contents_dir} to tmp working dir"
|
150
|
+
Dir.chdir(execution_context.with_contents_dir) do
|
151
|
+
FileUtils.cp_r(
|
152
|
+
".",
|
153
|
+
execution_context.output_dir
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
146
158
|
io.puts "## Working dir is #{execution_context.output_dir}"
|
147
159
|
Dir.chdir(execution_context.output_dir) do
|
148
160
|
parser = Rundoc::Parser.new(
|
@@ -191,7 +203,7 @@ module Rundoc
|
|
191
203
|
to: on_failure_dir
|
192
204
|
)
|
193
205
|
|
194
|
-
on_failure_dir.join("RUNDOC_FAILED.md").write(Rundoc::
|
206
|
+
on_failure_dir.join("RUNDOC_FAILED.md").write(Rundoc::Parser.partial_result_to_doc)
|
195
207
|
end
|
196
208
|
|
197
209
|
private def on_success(output)
|
@@ -8,7 +8,8 @@ module Rundoc
|
|
8
8
|
#
|
9
9
|
# Example:
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# options = Rundoc::CLIArgumentParser.new(argv: ARGV).call.options
|
12
|
+
# cli = Rundoc::CLI.new(**options)
|
12
13
|
# cli.call
|
13
14
|
#
|
14
15
|
class CLIArgumentParser
|
@@ -109,6 +110,10 @@ module Rundoc
|
|
109
110
|
@exit_obj.exit(0)
|
110
111
|
end
|
111
112
|
|
113
|
+
opts.on("--with-contents <dir>", "Copies contents of directory into the tmp working dir") do |v|
|
114
|
+
options[:with_contents_dir] = v
|
115
|
+
end
|
116
|
+
|
112
117
|
opts.on("--on-success-dir <dir>", "Success dir, relative to CWD. i.e. `<rundoc.md/dir>/#{CLI::DEFAULTS::ON_SUCCESS_DIR}/`.") do |v|
|
113
118
|
options[:on_success_dir] = v
|
114
119
|
end
|
@@ -43,7 +43,7 @@ class Rundoc::CodeCommand::Background
|
|
43
43
|
@tasks[name]
|
44
44
|
end
|
45
45
|
|
46
|
-
attr_reader :log, :pid
|
46
|
+
attr_reader :log, :pid, :command
|
47
47
|
|
48
48
|
def initialize(command, timeout: 5, log: Tempfile.new("log"), out: "2>&1")
|
49
49
|
@command = command
|
@@ -68,7 +68,7 @@ class Rundoc::CodeCommand::Background
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
rescue Timeout::Error
|
71
|
-
raise "Timeout waiting for #{@command.inspect} to find a match using #{wait_value.inspect} in \n'#{log.read}'"
|
71
|
+
raise "Timeout (#{timeout_value}s) waiting for #{@command.inspect} to find a match using #{wait_value.inspect} in \n'#{log.read}'"
|
72
72
|
end
|
73
73
|
|
74
74
|
def alive?
|
data/lib/rundoc/code_section.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Rundoc
|
4
|
-
#
|
4
|
+
# A code secttion respesents a block of fenced code
|
5
|
+
#
|
6
|
+
# A document can have multiple code sections
|
5
7
|
class CodeSection
|
6
8
|
class ParseError < StandardError
|
7
9
|
def initialize(options = {})
|
@@ -9,13 +9,16 @@ module Rundoc
|
|
9
9
|
# The directory we are actively manipulating
|
10
10
|
:output_dir,
|
11
11
|
# Directory to store screenshots, relative to output_dir
|
12
|
-
:screenshots_dir
|
12
|
+
:screenshots_dir,
|
13
|
+
# Directory we are copying from, i.e. a directory to source from could be nil
|
14
|
+
:with_contents_dir
|
13
15
|
|
14
|
-
def initialize(source_path:, output_dir:, screenshots_dirname:)
|
16
|
+
def initialize(source_path:, output_dir:, screenshots_dirname:, with_contents_dir:)
|
15
17
|
@source_path = Pathname(source_path).expand_path
|
16
18
|
@source_dir = @source_path.parent
|
17
19
|
@output_dir = Pathname(output_dir).expand_path
|
18
20
|
@screenshots_dir = @output_dir.join(screenshots_dirname).expand_path
|
21
|
+
@with_contents_dir = with_contents_dir
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
data/lib/rundoc/parser.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
module Rundoc
|
2
|
+
# This poorly named class is responsible for taking in the raw markdown and running it
|
3
|
+
#
|
4
|
+
# It works by pulling out the code blocks (CodeSection), and putting them onto a stack.
|
5
|
+
# It then executes each in turn and records the results.
|
2
6
|
class Parser
|
3
7
|
DEFAULT_KEYWORD = ":::"
|
4
8
|
INDENT_BLOCK = '(?<before_indent>(^\s*$\n|\A)(^(?:[ ]{4}|\t))(?<indent_contents>.*)(?<after_indent>[^\s].*$\n?(?:(?:^\s*$\n?)*^(?:[ ]{4}|\t).*[^\s].*$\n?)*))'
|
@@ -7,6 +11,7 @@ module Rundoc
|
|
7
11
|
COMMAND_REGEX = ->(keyword) {
|
8
12
|
/^#{keyword}(?<tag>(\s|=|-|>)?(=|-|>)?)\s*(?<command>(\S)+)\s+(?<statement>.*)$/
|
9
13
|
}
|
14
|
+
PARTIAL_RESULT = []
|
10
15
|
|
11
16
|
attr_reader :contents, :keyword, :stack, :context
|
12
17
|
|
@@ -17,6 +22,7 @@ module Rundoc
|
|
17
22
|
@keyword = keyword
|
18
23
|
@stack = []
|
19
24
|
partition
|
25
|
+
PARTIAL_RESULT.clear
|
20
26
|
end
|
21
27
|
|
22
28
|
def to_md
|
@@ -27,13 +33,26 @@ module Rundoc
|
|
27
33
|
else
|
28
34
|
s
|
29
35
|
end
|
36
|
+
PARTIAL_RESULT.replace(result)
|
30
37
|
end
|
31
|
-
|
38
|
+
|
39
|
+
self.class.to_doc(result: result)
|
32
40
|
rescue => e
|
33
41
|
File.write("README.md", result.join(""))
|
34
42
|
raise e
|
35
43
|
end
|
36
44
|
|
45
|
+
def self.partial_result_to_doc
|
46
|
+
out = to_doc(result: PARTIAL_RESULT)
|
47
|
+
unfinished = CodeSection.partial_result_to_doc
|
48
|
+
out << unfinished if unfinished
|
49
|
+
out
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.to_doc(result:)
|
53
|
+
result.join("")
|
54
|
+
end
|
55
|
+
|
37
56
|
# split into [before_code, code, after_code], process code, and re-run until tail is empty
|
38
57
|
def partition
|
39
58
|
until contents.empty?
|
data/lib/rundoc/version.rb
CHANGED
@@ -1,7 +1,58 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class IntegrationFailureTest < Minitest::Test
|
4
|
-
def
|
4
|
+
def test_writes_to_dir_on_failure_two_block
|
5
|
+
Dir.mktmpdir do |dir|
|
6
|
+
Dir.chdir(dir) do
|
7
|
+
dir = Pathname(dir)
|
8
|
+
|
9
|
+
source_path = dir.join("RUNDOC.md")
|
10
|
+
source_path.write <<~EOF
|
11
|
+
```
|
12
|
+
:::>> $ mkdir one
|
13
|
+
:::>> $ touch one/rofl.txt
|
14
|
+
```
|
15
|
+
|
16
|
+
```
|
17
|
+
:::>> $ mkdir two
|
18
|
+
:::>> $ touch two/rofl.txt
|
19
|
+
:::>> $ touch does/not/exist.txt
|
20
|
+
```
|
21
|
+
EOF
|
22
|
+
|
23
|
+
io = StringIO.new
|
24
|
+
|
25
|
+
error = nil
|
26
|
+
begin
|
27
|
+
Rundoc::CLI.new(
|
28
|
+
io: io,
|
29
|
+
source_path: source_path,
|
30
|
+
on_success_dir: dir.join(SUCCESS_DIRNAME)
|
31
|
+
).call
|
32
|
+
rescue => e
|
33
|
+
error = e
|
34
|
+
end
|
35
|
+
|
36
|
+
assert error
|
37
|
+
assert_includes error.message, "exited with non zero status"
|
38
|
+
|
39
|
+
refute dir.join(SUCCESS_DIRNAME).join("two").exist?
|
40
|
+
refute dir.join(SUCCESS_DIRNAME).join("two").join("rofl.txt").exist?
|
41
|
+
|
42
|
+
assert dir.join(FAILURE_DIRNAME).join("two").exist?
|
43
|
+
assert dir.join(FAILURE_DIRNAME).join("two").join("rofl.txt").exist?
|
44
|
+
|
45
|
+
doc = dir.join(FAILURE_DIRNAME).join("RUNDOC_FAILED.md").read
|
46
|
+
assert_includes doc, "$ mkdir one"
|
47
|
+
assert_includes doc, "$ touch one/rofl.txt"
|
48
|
+
|
49
|
+
assert_includes doc, "$ mkdir two"
|
50
|
+
assert_includes doc, "$ touch two/rofl.txt"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_writes_to_dir_on_failure_one_block
|
5
56
|
Dir.mktmpdir do |dir|
|
6
57
|
Dir.chdir(dir) do
|
7
58
|
dir = Pathname(dir)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class WithContentsFlagTest < Minitest::Test
|
4
|
+
def test_with_contents_flag
|
5
|
+
Dir.mktmpdir do |dir|
|
6
|
+
Dir.chdir(dir) do
|
7
|
+
dir = Pathname(dir)
|
8
|
+
|
9
|
+
contents_dir = dir.join("contents").tap { |p| p.mkpath }
|
10
|
+
FileUtils.touch(contents_dir.join("file1.txt"))
|
11
|
+
|
12
|
+
source_path = dir.join("RUNDOC.md")
|
13
|
+
source_path.write <<~EOF
|
14
|
+
```
|
15
|
+
:::>> $ ls
|
16
|
+
```
|
17
|
+
EOF
|
18
|
+
|
19
|
+
refute dir.join(SUCCESS_DIRNAME).join("file1.txt").exist?
|
20
|
+
|
21
|
+
io = StringIO.new
|
22
|
+
Rundoc::CLI.new(
|
23
|
+
io: io,
|
24
|
+
source_path: source_path,
|
25
|
+
on_success_dir: dir.join(SUCCESS_DIRNAME),
|
26
|
+
with_contents_dir: contents_dir
|
27
|
+
).call
|
28
|
+
|
29
|
+
doc = dir.join(SUCCESS_DIRNAME).join("README.md").read
|
30
|
+
assert_includes doc, "$ ls"
|
31
|
+
assert_includes doc, "file1.txt"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -23,6 +23,7 @@ class Minitest::Test
|
|
23
23
|
Rundoc::Context::Execution.new(
|
24
24
|
output_dir: output_dir || Pathname("/dev/null"),
|
25
25
|
source_path: source_path || Pathname("/dev/null"),
|
26
|
+
with_contents_dir: nil,
|
26
27
|
screenshots_dirname: screenshots_dirname || Pathname("/dev/null")
|
27
28
|
)
|
28
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rundoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Schneeman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -265,6 +265,7 @@ files:
|
|
265
265
|
- test/integration/print_test.rb
|
266
266
|
- test/integration/require_test.rb
|
267
267
|
- test/integration/website_test.rb
|
268
|
+
- test/integration/with_contents_flag_test.rb
|
268
269
|
- test/rundoc/cli_argument_parser_test.rb
|
269
270
|
- test/rundoc/code_commands/append_file_test.rb
|
270
271
|
- test/rundoc/code_commands/background_test.rb
|