rundoc 3.0.2 → 3.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|