diff --git a/CHANGELOG.md b/CHANGELOG.md index 9900553..308c167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## HEAD +- Fix: Partial output of the document is now written to disk in a `RUNDOC_FAILED.md` file (https://github.com/zombocom/rundoc/pull/69) + ## 3.0.1 - 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) diff --git a/lib/rundoc/cli.rb b/lib/rundoc/cli.rb index 7371a96..1426a8d 100644 --- a/lib/rundoc/cli.rb +++ b/lib/rundoc/cli.rb @@ -152,7 +152,7 @@ def call output = begin parser.to_md rescue StandardError, SignalException => e - warn "Received exception: #{e.inspect}, cleaning up before re-raise" + io.puts "Received exception: #{e.inspect}, cleaning up before re-raise" on_fail raise e end @@ -190,6 +190,8 @@ def call from: execution_context.output_dir, to: on_failure_dir ) + + on_failure_dir.join("RUNDOC_FAILED.md").write(Rundoc::CodeSection.partial_result_to_doc) end private def on_success(output) diff --git a/lib/rundoc/code_section.rb b/lib/rundoc/code_section.rb index 118fed3..b9d4537 100644 --- a/lib/rundoc/code_section.rb +++ b/lib/rundoc/code_section.rb @@ -30,6 +30,9 @@ def initialize(options = {}) AUTOGEN_WARNING = "\n" attr_accessor :original, :fence, :lang, :code, :commands, :keyword + PARTIAL_RESULT = [] + PARTIAL_ENV = {} + def initialize(match, keyword:, context:) @original = match.to_s @commands = [] @@ -40,6 +43,8 @@ def initialize(match, keyword:, context:) @lang = match[:lang] @code = match[:contents] parse_code_command + PARTIAL_RESULT.clear + PARTIAL_ENV.clear end def render @@ -69,10 +74,21 @@ def render tmp_result << code_output if code_command.render_result? result << tmp_result unless code_command.hidden? + + PARTIAL_RESULT.replace(result) + PARTIAL_ENV.replace(env) end return "" if hidden? + self.class.to_doc(result: result, env: env) + end + + def self.partial_result_to_doc + to_doc(result: PARTIAL_RESULT, env: PARTIAL_ENV) + end + + def self.to_doc(result:, env:) array = [env[:before]] result.flatten! diff --git a/test/integration/failure_test.rb b/test/integration/failure_test.rb new file mode 100644 index 0000000..4dac8af --- /dev/null +++ b/test/integration/failure_test.rb @@ -0,0 +1,46 @@ +require "test_helper" + +class IntegrationFailureTest < Minitest::Test + def test_writes_to_dir_on_failure + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + dir = Pathname(dir) + + source_path = dir.join("RUNDOC.md") + source_path.write <<~EOF + ``` + :::>> $ mkdir lol + :::>> $ touch lol/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("lol").exist? + refute dir.join(SUCCESS_DIRNAME).join("lol").join("rofl.txt").exist? + + assert dir.join(FAILURE_DIRNAME).join("lol").exist? + assert dir.join(FAILURE_DIRNAME).join("lol").join("rofl.txt").exist? + + doc = dir.join(FAILURE_DIRNAME).join("RUNDOC_FAILED.md").read + assert_includes doc, "$ mkdir lol" + assert_includes doc, "$ touch lol/rofl.txt" + end + end + end +end