Skip to content

Commit

Permalink
Merge pull request #71 from zombocom/schneems/fix-save-on-error
Browse files Browse the repository at this point in the history
Include all code blocks in event of failure
  • Loading branch information
schneems authored Nov 22, 2024
2 parents 36dbcd3 + 06f1ffe commit 44facf7
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## HEAD

- Fix: Include all code sections in the event of a failure, not just the last one (https://github.com/zombocom/rundoc/pull/71)

## 3.1.0

- 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. ()
Expand Down
2 changes: 1 addition & 1 deletion lib/rundoc/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def call
to: on_failure_dir
)

on_failure_dir.join("RUNDOC_FAILED.md").write(Rundoc::CodeSection.partial_result_to_doc)
on_failure_dir.join("RUNDOC_FAILED.md").write(Rundoc::Parser.partial_result_to_doc)
end

private def on_success(output)
Expand Down
4 changes: 3 additions & 1 deletion lib/rundoc/code_section.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# frozen_string_literal: true

module Rundoc
# holds code, parses and creates CodeCommand
# A code secttion respesents a block of fenced code
#
# A document can have multiple code sections
class CodeSection
class ParseError < StandardError
def initialize(options = {})
Expand Down
21 changes: 20 additions & 1 deletion lib/rundoc/parser.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module Rundoc
# This poorly named class is responsible for taking in the raw markdown and running it
#
# It works by pulling out the code blocks (CodeSection), and putting them onto a stack.
# It then executes each in turn and records the results.
class Parser
DEFAULT_KEYWORD = ":::"
INDENT_BLOCK = '(?<before_indent>(^\s*$\n|\A)(^(?:[ ]{4}|\t))(?<indent_contents>.*)(?<after_indent>[^\s].*$\n?(?:(?:^\s*$\n?)*^(?:[ ]{4}|\t).*[^\s].*$\n?)*))'
Expand All @@ -7,6 +11,7 @@ class Parser
COMMAND_REGEX = ->(keyword) {
/^#{keyword}(?<tag>(\s|=|-|>)?(=|-|>)?)\s*(?<command>(\S)+)\s+(?<statement>.*)$/
}
PARTIAL_RESULT = []

attr_reader :contents, :keyword, :stack, :context

Expand All @@ -17,6 +22,7 @@ def initialize(contents, context:, keyword: DEFAULT_KEYWORD)
@keyword = keyword
@stack = []
partition
PARTIAL_RESULT.clear
end

def to_md
Expand All @@ -27,13 +33,26 @@ def to_md
else
s
end
PARTIAL_RESULT.replace(result)
end
result.join("")

self.class.to_doc(result: result)
rescue => e
File.write("README.md", result.join(""))
raise e
end

def self.partial_result_to_doc
out = to_doc(result: PARTIAL_RESULT)
unfinished = CodeSection.partial_result_to_doc
out << unfinished if unfinished
out
end

def self.to_doc(result:)
result.join("")
end

# split into [before_code, code, after_code], process code, and re-run until tail is empty
def partition
until contents.empty?
Expand Down
53 changes: 52 additions & 1 deletion test/integration/failure_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,58 @@
require "test_helper"

class IntegrationFailureTest < Minitest::Test
def test_writes_to_dir_on_failure
def test_writes_to_dir_on_failure_two_block
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

source_path = dir.join("RUNDOC.md")
source_path.write <<~EOF
```
:::>> $ mkdir one
:::>> $ touch one/rofl.txt
```
```
:::>> $ mkdir two
:::>> $ touch two/rofl.txt
:::>> $ touch does/not/exist.txt
```
EOF

io = StringIO.new

error = nil
begin
Rundoc::CLI.new(
io: io,
source_path: source_path,
on_success_dir: dir.join(SUCCESS_DIRNAME)
).call
rescue => e
error = e
end

assert error
assert_includes error.message, "exited with non zero status"

refute dir.join(SUCCESS_DIRNAME).join("two").exist?
refute dir.join(SUCCESS_DIRNAME).join("two").join("rofl.txt").exist?

assert dir.join(FAILURE_DIRNAME).join("two").exist?
assert dir.join(FAILURE_DIRNAME).join("two").join("rofl.txt").exist?

doc = dir.join(FAILURE_DIRNAME).join("RUNDOC_FAILED.md").read
assert_includes doc, "$ mkdir one"
assert_includes doc, "$ touch one/rofl.txt"

assert_includes doc, "$ mkdir two"
assert_includes doc, "$ touch two/rofl.txt"
end
end
end

def test_writes_to_dir_on_failure_one_block
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)
Expand Down

0 comments on commit 44facf7

Please sign in to comment.