rundoc 2.0.1 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +10 -7
- data/CHANGELOG.md +15 -0
- data/CONTRIBUTING.md +25 -0
- data/README.md +35 -48
- data/Rakefile +5 -1
- data/bin/rundoc +4 -17
- data/lib/rundoc/cli.rb +208 -49
- data/lib/rundoc/cli_argument_parser.rb +140 -0
- data/lib/rundoc/code_command/bash.rb +8 -1
- data/lib/rundoc/code_command/rundoc/depend_on.rb +1 -24
- data/lib/rundoc/code_command/rundoc/require.rb +13 -7
- data/lib/rundoc/code_command/website/driver.rb +7 -5
- data/lib/rundoc/code_command/website/navigate.rb +1 -1
- data/lib/rundoc/code_command/website/screenshot.rb +7 -2
- data/lib/rundoc/code_command/website/visit.rb +4 -2
- data/lib/rundoc/code_section.rb +7 -7
- data/lib/rundoc/context/after_build.rb +14 -0
- data/lib/rundoc/context/execution.rb +22 -0
- data/lib/rundoc/parser.rb +8 -4
- data/lib/rundoc/version.rb +1 -1
- data/lib/rundoc.rb +13 -5
- data/rundoc.gemspec +1 -0
- data/test/fixtures/cnb/ruby/download.md +22 -0
- data/test/fixtures/cnb/ruby/image_structure.md +34 -0
- data/test/fixtures/cnb/ruby/intro.md +5 -0
- data/test/fixtures/cnb/ruby/multiple_langs.md +43 -0
- data/test/fixtures/cnb/ruby/rundoc.md +48 -0
- data/test/fixtures/cnb/ruby/what_is_pack_build.md +18 -0
- data/test/fixtures/cnb/shared/call_to_action.md +11 -0
- data/test/fixtures/cnb/shared/configure_builder.md +23 -0
- data/test/fixtures/cnb/shared/install_pack.md +14 -0
- data/test/fixtures/cnb/shared/pack_build.md +20 -0
- data/test/fixtures/cnb/shared/procfile.md +13 -0
- data/test/fixtures/cnb/shared/use_the_image.md +52 -0
- data/test/fixtures/cnb/shared/what_is_a_builder.md +18 -0
- data/test/fixtures/rails_4/rundoc.md +1 -1
- data/test/fixtures/rails_5/rundoc.md +1 -1
- data/test/fixtures/rails_7/rundoc.md +0 -1
- data/test/fixtures/rails_8/rundoc.md +481 -0
- data/test/fixtures/simple_git/rundoc.md +13 -0
- data/test/integration/after_build_test.rb +62 -0
- data/test/integration/print_test.rb +9 -9
- data/test/integration/require_test.rb +63 -0
- data/test/integration/website_test.rb +35 -0
- data/test/rundoc/cli_argument_parser_test.rb +118 -0
- data/test/rundoc/code_section_test.rb +40 -8
- data/test/rundoc/parser_test.rb +3 -3
- data/test/rundoc/peg_parser_test.rb +6 -6
- data/test/system/exe_cli_test.rb +231 -0
- data/test/test_helper.rb +74 -1
- metadata +41 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89f953193be8aea0831e65e251a1d0cc8a3796573fe5818a6eb4ae2ed0e489d4
|
4
|
+
data.tar.gz: 9ea2f3a42906fa0c79cbb39862ec5300b4688dcce15df8991cf0a99e2d7c60da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4aba6794da79ce27d6a4072e0cda4c7e2525030f0bd7c7925aaca8708a3adbd2632a0bb32c2ea451bc5f58ebc4a674ab4012ec6ddaeae7114ffbcefbafb53b35
|
7
|
+
data.tar.gz: fef87625649965fdd3dd5817e55d73299e1ebf67cfb3f9895c45d2c26b410af566f43540490a7c4ec7198b31f86d9c14079701b25981f7689b99644775f8e55f
|
data/.gitignore
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
-
test/fixtures
|
2
|
-
test/fixtures
|
3
|
-
test/fixtures
|
4
|
-
|
5
|
-
test/fixtures
|
6
|
-
test/fixtures/*/*/tmp/
|
7
|
-
test/fixtures/*/*/myapp/
|
1
|
+
test/fixtures/**/*/rundoc_output/
|
2
|
+
test/fixtures/**/*/rundoc_failure/
|
3
|
+
test/fixtures/**/*/project/
|
4
|
+
test/fixtures/**/*/tmp/
|
5
|
+
test/fixtures/**/*/myapp/
|
8
6
|
|
7
|
+
coverage/
|
9
8
|
|
10
9
|
*.gem
|
11
10
|
|
12
11
|
.DS_Store
|
13
12
|
Gemfile.lock
|
14
13
|
.env
|
14
|
+
|
15
|
+
# IDEs
|
16
|
+
.idea/
|
17
|
+
.vscode/
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
## HEAD
|
2
2
|
|
3
|
+
## 3.0.1
|
4
|
+
|
5
|
+
- Fix: Save in-progress work in the "failure" directory when the rundoc command is interrupted via a signal such as `SIGTERM` (https://github.com/zombocom/rundoc/pull/67)
|
6
|
+
|
7
|
+
## 3.0.0
|
8
|
+
|
9
|
+
- Change: Default directories are now `rundoc_output` (instead of `project`) and `rundoc_failure` (instead of `tmp`).
|
10
|
+
- Change: Non-empty directories for success or failure paths will now halt execution unless `--force` is used
|
11
|
+
- Change: The CLI command `rundoc build --path <path>` is now `rundoc <path>`
|
12
|
+
- Change: `rundoc.depend_on` is removed in favor of `:::-- rundoc.require` (https://github.com/zombocom/rundoc/pull/58)
|
13
|
+
- Change: `Rundoc.project_root=` is removed, please use `Rundoc.after_build` instead (https://github.com/zombocom/rundoc/pull/58)
|
14
|
+
- Change: Location of screenshots is now consistent (https://github.com/zombocom/rundoc/pull/57)
|
15
|
+
- Fix: Bash commands now stream their outputs while they're running (https://github.com/zombocom/rundoc/pull/57)
|
16
|
+
- Change: Minimum selenium-webdriver is now 4.x. (https://github.com/zombocom/rundoc/pull/41)
|
17
|
+
|
3
18
|
## 2.0.1
|
4
19
|
|
5
20
|
- Bugfix: Code blocks without a following newline are now being recognized and executed (https://github.com/zombocom/rundoc/pull/51)
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
## Run the tests
|
4
|
+
|
5
|
+
```
|
6
|
+
$ bundle exec rake test
|
7
|
+
```
|
8
|
+
|
9
|
+
## Run one test
|
10
|
+
|
11
|
+
```
|
12
|
+
$ bundle exec m <path/to/file.rb>
|
13
|
+
```
|
14
|
+
|
15
|
+
## Run the linter
|
16
|
+
|
17
|
+
```
|
18
|
+
$ bundle exec standardrb
|
19
|
+
```
|
20
|
+
|
21
|
+
## Run the local cli
|
22
|
+
|
23
|
+
```
|
24
|
+
$ bin/rundoc <path/to/rundoc.md>
|
25
|
+
```
|
data/README.md
CHANGED
@@ -4,29 +4,37 @@
|
|
4
4
|
|
5
5
|
## What
|
6
6
|
|
7
|
-
|
7
|
+
Turn your tutorials into tests and never let your docs be out of date again.
|
8
8
|
|
9
|
-
|
9
|
+
Start off by writing your tutorial in modified-markdown, then execute it with `rundoc`. If there's a problem with following the directions, then your tutorial will fail to build. When it succeeds, the real world output is embedded in the output markdown file. That means your tutorials will have the EXACT output that your readers will see.
|
10
10
|
|
11
|
-
|
11
|
+
## Quickstart
|
12
12
|
|
13
|
-
|
14
|
-
:::>> $ gem install rails --no-document
|
15
|
-
```
|
13
|
+
Install the Ruby library:
|
16
14
|
|
17
|
-
|
15
|
+
$ gem install rundoc
|
18
16
|
|
19
|
-
|
17
|
+
Make a rundoc file:
|
20
18
|
|
19
|
+
$ mkdir /tmp/rundoc-demo
|
20
|
+
$ cd /tmp/rundoc-demo
|
21
|
+
$ cat <<'EOF' > ./RUNDOC.md
|
21
22
|
```
|
22
|
-
$
|
23
|
-
Successfully installed rails-5.2.2
|
24
|
-
1 gem installed
|
23
|
+
:::>> $ echo Hello World
|
25
24
|
```
|
25
|
+
EOF
|
26
26
|
|
27
|
-
|
27
|
+
Run it:
|
28
28
|
|
29
|
-
|
29
|
+
$ rundoc --on-success-dir=rundoc_output ./RUNDOC.md
|
30
|
+
|
31
|
+
View the output
|
32
|
+
|
33
|
+
$ cat rundoc_output/README.md
|
34
|
+
```
|
35
|
+
$ echo Hello World
|
36
|
+
Hello World
|
37
|
+
```
|
30
38
|
|
31
39
|
## Install
|
32
40
|
|
@@ -44,15 +52,15 @@ gem 'rundoc'
|
|
44
52
|
|
45
53
|
## Use It
|
46
54
|
|
47
|
-
Run the `rundoc
|
55
|
+
Run the `rundoc` command on any rundoc-flavored markdown file:
|
48
56
|
|
49
57
|
```sh
|
50
|
-
$
|
58
|
+
$ rundoc <test/fixtures/rails_7/rundoc.md>
|
51
59
|
```
|
52
60
|
|
53
61
|
> Note: This command will create and manipulate directories in the working directory of your source markdown file. Best practice is to have your source markdown file in its own empty directory.
|
54
62
|
|
55
|
-
This will generate a project folder with your project in it, and a markdown README.md with the parsed output of the markdown docs
|
63
|
+
This will generate a project folder with your project in it, and a markdown `README.md` with the parsed output of the markdown docs. See `rundoc --help` for more configuration options.
|
56
64
|
|
57
65
|
## Quick docs
|
58
66
|
|
@@ -87,7 +95,6 @@ This will generate a project folder with your project in it, and a markdown READ
|
|
87
95
|
- Configure RunDOC
|
88
96
|
- [rundoc.configure](#configure)
|
89
97
|
- Import and compose documents
|
90
|
-
- [rundoc.depend_on](#compose-multiple-rundoc-documents)
|
91
98
|
- [rundoc.require](#compose-multiple-rundoc-documents)
|
92
99
|
|
93
100
|
## RunDOC Syntax
|
@@ -164,7 +171,6 @@ Different commands will do different things with this input. For example the `ru
|
|
164
171
|
end
|
165
172
|
```
|
166
173
|
|
167
|
-
|
168
174
|
And the `website.visit` command allows you to navigate and manipulate a webpage via a Capybara API:
|
169
175
|
|
170
176
|
```
|
@@ -220,14 +226,12 @@ Current Commands:
|
|
220
226
|
|
221
227
|
Anything you pass to `$` will be run in a shell. If a shell command returns a non-zero exit status an error will be raised. If you expect a non-zero exit status use `fail.$` instead:
|
222
228
|
|
223
|
-
|
224
229
|
```
|
225
230
|
:::>> fail.$ cat /dev/null/foo
|
226
231
|
```
|
227
232
|
|
228
233
|
Even though this command returns a non zero exit status, the contents of the command will be written since we're stating that we don't care if the command fails. This would be the output:
|
229
234
|
|
230
|
-
|
231
235
|
```
|
232
236
|
$ cat /dev/null/foo
|
233
237
|
cat: /dev/null/foo: Not a directory
|
@@ -235,7 +239,6 @@ Even though this command returns a non zero exit status, the contents of the com
|
|
235
239
|
|
236
240
|
Some commands may be custom, for example when running `cd` you likely want to change the working directory that your script is running in. To do this we need to run `Dir.chdir` instead of shelling out. So this works as you would expect:
|
237
241
|
|
238
|
-
|
239
242
|
```
|
240
243
|
:::>> $ cd myapp/config
|
241
244
|
:::>> $ cat database.yml
|
@@ -455,7 +458,6 @@ The result of the screenshot command will be to replace the code section with a
|
|
455
458
|
|
456
459
|
Once you've visited a website you can further navigate using `website.nav` or `website.navigate`:
|
457
460
|
|
458
|
-
|
459
461
|
```
|
460
462
|
:::>> website.visit(name: "localhost", url: "http://localhost:3000")
|
461
463
|
:::>> website.navigate(name: "localhost")
|
@@ -487,26 +489,20 @@ The bucketeer addon on Heroku is supported out of the box. To specify project sp
|
|
487
489
|
|
488
490
|
## Compose multiple RunDOC documents
|
489
491
|
|
490
|
-
|
491
|
-
|
492
|
-
For example on day two (`day_two/rundoc.md`) of the tutorials you could:
|
492
|
+
You can also break up your document into smaller components using `rundoc.require`:
|
493
493
|
|
494
494
|
```
|
495
|
-
|
495
|
+
:::>> rundoc.require "../day_one/rundoc.md"
|
496
496
|
```
|
497
497
|
|
498
|
-
|
499
|
-
|
500
|
-
You can also break up your document into smaller components:
|
498
|
+
This will prepend the code section with the generated contents of `rundoc.require`.
|
501
499
|
|
500
|
+
If you want to execute another tutorial as a pre-requisite but not embed the results you can use `:::--`:
|
502
501
|
|
503
502
|
```
|
504
|
-
|
503
|
+
:::-- rundoc.require "../day_one/rundoc.md"
|
505
504
|
```
|
506
505
|
|
507
|
-
This will replace the code section with the generated contents of `rundoc.require`.
|
508
|
-
|
509
|
-
|
510
506
|
## Dotenv support
|
511
507
|
|
512
508
|
If you need to specify project specific environment variables create a file called `.env` at the same directory as your `rundoc.md` and it will be imported. Add this file to your `.gitignore` so you don't accidentally share with the world
|
@@ -523,13 +519,12 @@ Note: Make sure you run this as a hidden command (with `-`).
|
|
523
519
|
|
524
520
|
**After Build**
|
525
521
|
|
526
|
-
This will eval any code you put under that line (in Ruby). If you want to run some code after you're done building your docs you could use `Rundoc.configure` block and call the `after_build` method like this:
|
527
|
-
|
522
|
+
This will eval any code you put under that line (in Ruby) when the build was successful but before the contents are finalized on disk. If you want to run some code after you're done building your docs you could use `Rundoc.configure` block and call the `after_build` method like this:
|
528
523
|
|
529
524
|
```
|
530
525
|
:::-- rundoc.configure
|
531
526
|
Rundoc.configure do |config|
|
532
|
-
config.after_build do
|
527
|
+
config.after_build do |context|
|
533
528
|
puts "you could push to GitHub here"
|
534
529
|
puts "You could do anything here"
|
535
530
|
puts "This code will run after the docs are done building"
|
@@ -537,19 +532,11 @@ This will eval any code you put under that line (in Ruby). If you want to run so
|
|
537
532
|
end
|
538
533
|
```
|
539
534
|
|
535
|
+
The `context` object will have details about the structure of the output directory structure. The stable API is:
|
540
536
|
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
```
|
546
|
-
:::-- rundoc.configure
|
547
|
-
Rundoc.configure do |config|
|
548
|
-
config.project_root = "myapp"
|
549
|
-
end
|
550
|
-
```
|
551
|
-
|
552
|
-
This will also be the root directory that the `after_build` is executed in.
|
537
|
+
- `context.output_dir`: A [Pathname](https://rubyapi.org/3.3/o/pathname) containing the absolute path to the top level directory where all commands are were executed. If your script runs `rails new myapp` then this directory would contain another directory named `myapp`. Only modifications to this directory will be persisted to the final `--output-dir`.
|
538
|
+
- `context.screenshots_dir`: A [Pathname](https://rubyapi.org/3.3/o/pathname) containing the absolute path to the directory where screenshots were saved. It is guaranteed to be somewhere within the `context.output_dir`
|
539
|
+
- `context.output_markdown_path`: A [Pathname](https://rubyapi.org/3.3/o/pathname) containing the absolute path to the final markdown file. This is guaranteed to be in the `context.output_dir`
|
553
540
|
|
554
541
|
**Filter Sensitive Info**
|
555
542
|
|
data/Rakefile
CHANGED
@@ -10,6 +10,10 @@ task default: [:test]
|
|
10
10
|
Rake::TestTask.new(:test) do |t|
|
11
11
|
t.libs << "lib"
|
12
12
|
t.libs << "test"
|
13
|
-
t.pattern =
|
13
|
+
t.pattern = [
|
14
|
+
"test/rundoc/**/*_test.rb",
|
15
|
+
"test/system/**/*_test.rb",
|
16
|
+
"test/integration/**/*_test.rb"
|
17
|
+
]
|
14
18
|
t.verbose = false
|
15
19
|
end
|
data/bin/rundoc
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$stdout.sync = true
|
4
|
+
$stderr.sync = true
|
4
5
|
|
5
6
|
unless File.respond_to? :realpath
|
6
7
|
class File #:nodoc:
|
@@ -13,22 +14,8 @@ end
|
|
13
14
|
$: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
|
14
15
|
|
15
16
|
require 'rundoc'
|
16
|
-
require 'thor'
|
17
17
|
|
18
|
-
|
18
|
+
options = Rundoc::CLIArgumentParser.new(argv: ARGV).call.options
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
@path = options[:path]
|
23
|
-
end
|
24
|
-
|
25
|
-
default_task :help
|
26
|
-
|
27
|
-
desc "build", "turns rundoc file into docs and a project"
|
28
|
-
class_option :path, banner: "path/to/file.md", optional: true, default: 'rundoc.md'
|
29
|
-
def build
|
30
|
-
Rundoc::CLI.new.build(path: @path)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
RundocThorCLI.start(ARGV)
|
20
|
+
cli = Rundoc::CLI.new(**options)
|
21
|
+
cli.call
|
data/lib/rundoc/cli.rb
CHANGED
@@ -1,82 +1,241 @@
|
|
1
1
|
module Rundoc
|
2
2
|
class CLI
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
module DEFAULTS
|
4
|
+
ON_FAILURE_DIR = # <path/to/rundoc.md/..> +
|
5
|
+
"rundoc_failure"
|
6
|
+
ON_SUCCESS_DIR = # <path/to/rundoc.md/..> +
|
7
|
+
"rundoc_output"
|
8
|
+
DOTENV_PATH = # <path/to/rundoc.md/..> +
|
9
|
+
".env"
|
10
|
+
OUTPUT_FILENAME = "README.md"
|
11
|
+
SCREENSHOTS_DIR = "screenshots"
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :io, :on_success_dir, :on_failure_dir, :dotenv_path, :cli_cmd, :cli_args, :force
|
15
|
+
attr_reader :execution_context, :after_build_context
|
16
|
+
|
17
|
+
def initialize(
|
18
|
+
source_path:,
|
19
|
+
io: $stderr,
|
20
|
+
cli_cmd: $0,
|
21
|
+
cli_args: $*,
|
22
|
+
force: false,
|
23
|
+
dotenv_path: nil,
|
24
|
+
on_success_dir: nil,
|
25
|
+
on_failure_dir: nil,
|
26
|
+
output_filename: nil,
|
27
|
+
screenshots_dirname: nil
|
28
|
+
)
|
29
|
+
@io = io
|
30
|
+
@force = force
|
31
|
+
@cli_cmd = cli_cmd
|
32
|
+
@cli_args = cli_args
|
33
|
+
|
34
|
+
screenshots_dirname = check_relative_path(screenshots_dirname || DEFAULTS::SCREENSHOTS_DIR)
|
35
|
+
output_filename = check_relative_path(output_filename || DEFAULTS::OUTPUT_FILENAME)
|
36
|
+
|
37
|
+
@execution_context = Rundoc::Context::Execution.new(
|
38
|
+
output_dir: Dir.mktmpdir,
|
39
|
+
source_path: source_path,
|
40
|
+
screenshots_dirname: screenshots_dirname
|
41
|
+
)
|
42
|
+
|
43
|
+
@after_build_context = Context::AfterBuild.new(
|
44
|
+
output_dir: execution_context.output_dir,
|
45
|
+
screenshots_dir: execution_context.screenshots_dir,
|
46
|
+
output_markdown_path: @execution_context.output_dir.join(output_filename)
|
47
|
+
)
|
48
|
+
|
49
|
+
@dotenv_path = if dotenv_path
|
50
|
+
Pathname(dotenv_path)
|
51
|
+
else
|
52
|
+
@execution_context.source_dir.join(DEFAULTS::DOTENV_PATH)
|
53
|
+
end
|
54
|
+
|
55
|
+
@on_success_dir = if on_success_dir
|
56
|
+
Pathname(on_success_dir)
|
57
|
+
else
|
58
|
+
@execution_context.source_dir.join(DEFAULTS::ON_SUCCESS_DIR)
|
59
|
+
end.expand_path
|
60
|
+
|
61
|
+
@on_failure_dir = if on_failure_dir
|
62
|
+
Pathname(on_failure_dir)
|
63
|
+
else
|
64
|
+
@execution_context.source_dir.join(DEFAULTS::ON_FAILURE_DIR)
|
65
|
+
end.expand_path
|
66
|
+
end
|
67
|
+
|
68
|
+
def force?
|
69
|
+
force
|
70
|
+
end
|
71
|
+
|
72
|
+
# Ensures that the value passed in cannot escape the current directory
|
73
|
+
#
|
74
|
+
# Examples:
|
75
|
+
#
|
76
|
+
# - `/tmp/whatever` is invalid
|
77
|
+
# - `whatever/../..` is invalid
|
78
|
+
#
|
79
|
+
private def check_relative_path(path)
|
80
|
+
path = Pathname(path)
|
81
|
+
if path.absolute?
|
82
|
+
raise "Path must be relative but it is not: #{path}"
|
83
|
+
end
|
84
|
+
|
85
|
+
if path.each_filename.any? { |part| part == ".." }
|
86
|
+
raise "path cannot contain `..` but it does: #{path}"
|
87
|
+
end
|
88
|
+
path
|
89
|
+
end
|
90
|
+
|
91
|
+
def load_dotenv
|
92
|
+
if File.exist?(dotenv_path)
|
93
|
+
io.puts("Found .env file #{dotenv_path}, loading")
|
11
94
|
require "dotenv"
|
12
|
-
Dotenv.load(
|
13
|
-
ENV["AWS_ACCESS_KEY_ID"] ||= ENV["BUCKETEER_AWS_ACCESS_KEY_ID"]
|
95
|
+
Dotenv.load(dotenv_path)
|
14
96
|
ENV["AWS_REGION"] ||= ENV["BUCKETEER_AWS_REGION"]
|
15
|
-
ENV["AWS_SECRET_ACCESS_KEY"] ||= ENV["BUCKETEER_AWS_SECRET_ACCESS_KEY"]
|
16
97
|
ENV["AWS_BUCKET_NAME"] ||= ENV["BUCKETEER_BUCKET_NAME"]
|
98
|
+
ENV["AWS_ACCESS_KEY_ID"] ||= ENV["BUCKETEER_AWS_ACCESS_KEY_ID"]
|
99
|
+
ENV["AWS_SECRET_ACCESS_KEY"] ||= ENV["BUCKETEER_AWS_SECRET_ACCESS_KEY"]
|
100
|
+
else
|
101
|
+
io.puts("## No .env file found #{dotenv_path}, skipping dotenv loading")
|
17
102
|
end
|
103
|
+
end
|
18
104
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
FileUtils.remove_entry_secure(tmp_dir) if tmp_dir.exist?
|
23
|
-
tmp_dir.mkdir
|
24
|
-
banner = <<~HEREDOC
|
105
|
+
def prepend_cli_banner(contents)
|
106
|
+
<<~HEREDOC
|
25
107
|
<!-- STOP
|
26
108
|
This file was generated by a rundoc script, do not modify it.
|
27
109
|
|
28
110
|
Instead modify the rundoc script and re-run it.
|
29
111
|
|
30
|
-
Command: #{
|
112
|
+
Command: #{cli_cmd} #{cli_args.join(" ")}
|
31
113
|
STOP -->
|
114
|
+
#{contents}
|
32
115
|
HEREDOC
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_directories_empty!
|
119
|
+
[on_success_dir, on_failure_dir].each do |dir|
|
120
|
+
dir.mkpath
|
121
|
+
|
122
|
+
next if Dir.empty?(dir)
|
33
123
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
124
|
+
if force?
|
125
|
+
io.puts "## WARNING: #{dir} is not empty, it may be cleared due to running with the `--force` flag"
|
126
|
+
else
|
127
|
+
raise "## ABORTING: #{dir} is not empty, clear it or re-run with `--force` flag"
|
128
|
+
end
|
39
129
|
end
|
130
|
+
end
|
40
131
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
132
|
+
def call
|
133
|
+
io.puts "## Running your docs"
|
134
|
+
load_dotenv
|
135
|
+
check_directories_empty!
|
136
|
+
|
137
|
+
source_contents = execution_context.source_path.read
|
138
|
+
if on_failure_dir.exist? && !Dir.empty?(on_failure_dir)
|
139
|
+
io.puts "## earing on failure directory #{on_failure_dir}"
|
140
|
+
clean_dir(
|
141
|
+
dir: on_failure_dir,
|
142
|
+
description: "on failure directory"
|
143
|
+
)
|
46
144
|
end
|
47
145
|
|
48
|
-
|
146
|
+
io.puts "## Working dir is #{execution_context.output_dir}"
|
147
|
+
Dir.chdir(execution_context.output_dir) do
|
148
|
+
parser = Rundoc::Parser.new(
|
149
|
+
source_contents,
|
150
|
+
context: execution_context
|
151
|
+
)
|
152
|
+
output = begin
|
153
|
+
parser.to_md
|
154
|
+
rescue StandardError, SignalException => e
|
155
|
+
warn "Received exception: #{e.inspect}, cleaning up before re-raise"
|
156
|
+
on_fail
|
157
|
+
raise e
|
158
|
+
end
|
159
|
+
|
160
|
+
on_success(output)
|
161
|
+
end
|
162
|
+
ensure
|
163
|
+
# Stop any hanging background tasks
|
164
|
+
Rundoc::CodeCommand::Background::ProcessSpawn.tasks.each do |name, task|
|
165
|
+
next unless task.alive?
|
49
166
|
|
50
|
-
|
167
|
+
io.puts "Warning background task is still running, cleaning up: name: #{name}"
|
168
|
+
task.stop
|
169
|
+
end
|
51
170
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
171
|
+
if execution_context.output_dir.exist?
|
172
|
+
clean_dir(
|
173
|
+
dir: execution_context.output_dir,
|
174
|
+
description: "tmp working directory"
|
175
|
+
)
|
56
176
|
end
|
177
|
+
end
|
178
|
+
|
179
|
+
private def clean_dir(dir:, description:)
|
180
|
+
io.puts "## Cleaning #{description}, #{dir}"
|
181
|
+
|
182
|
+
FileUtils.remove_entry_secure(dir)
|
183
|
+
end
|
57
184
|
|
58
|
-
|
185
|
+
private def on_fail
|
186
|
+
io.puts "## Failed, debug contents are in #{on_failure_dir}"
|
187
|
+
on_failure_dir.mkpath
|
59
188
|
|
60
|
-
|
189
|
+
move_dir_contents(
|
190
|
+
from: execution_context.output_dir,
|
191
|
+
to: on_failure_dir
|
192
|
+
)
|
193
|
+
end
|
61
194
|
|
62
|
-
|
63
|
-
puts "
|
64
|
-
|
195
|
+
private def on_success(output)
|
196
|
+
io.puts "## Success! sanitizing output"
|
197
|
+
Rundoc.sanitize!(output)
|
198
|
+
output = prepend_cli_banner(output)
|
65
199
|
|
66
|
-
puts "
|
67
|
-
|
68
|
-
File.write(source_path, source_contents)
|
200
|
+
io.puts "## Writing RUNdoc output to #{after_build_context.output_markdown_path}"
|
201
|
+
after_build_context.output_markdown_path.write(output)
|
69
202
|
|
70
|
-
|
71
|
-
|
203
|
+
begin
|
204
|
+
io.puts "## Running after build scripts "
|
205
|
+
Rundoc.run_after_build(after_build_context)
|
206
|
+
rescue => e
|
207
|
+
on_fail
|
208
|
+
raise e
|
72
209
|
end
|
73
|
-
ensure
|
74
|
-
Rundoc::CodeCommand::Background::ProcessSpawn.tasks.each do |name, task|
|
75
|
-
next unless task.alive?
|
76
210
|
|
77
|
-
|
78
|
-
|
211
|
+
io.puts "## Saving to #{on_success_dir}"
|
212
|
+
if on_success_dir.exist?
|
213
|
+
clean_dir(
|
214
|
+
dir: on_success_dir,
|
215
|
+
description: "on success directory"
|
216
|
+
)
|
217
|
+
end
|
218
|
+
on_success_dir.mkpath
|
219
|
+
|
220
|
+
move_dir_contents(
|
221
|
+
from: execution_context.output_dir,
|
222
|
+
to: on_success_dir
|
223
|
+
)
|
224
|
+
|
225
|
+
io.puts "## Finished"
|
226
|
+
end
|
227
|
+
|
228
|
+
def move_dir_contents(from:, to:)
|
229
|
+
io.puts("## Moving contents from #{from} to #{to}")
|
230
|
+
|
231
|
+
Dir.glob(File.join(from, "{*,.*}")).each do |item|
|
232
|
+
next if item.end_with?(".", "..")
|
233
|
+
|
234
|
+
FileUtils.mv(item, to)
|
79
235
|
end
|
80
236
|
end
|
81
237
|
end
|
82
238
|
end
|
239
|
+
|
240
|
+
require_relative "context/execution"
|
241
|
+
require_relative "context/after_build"
|