From d5c291cdd34c6a10ebd33b10b274bb073113df2f Mon Sep 17 00:00:00 2001 From: Schneems Date: Wed, 20 Nov 2024 16:26:40 -0600 Subject: [PATCH 1/5] Refactor logic to method --- lib/rundoc/code_section.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/rundoc/code_section.rb b/lib/rundoc/code_section.rb index 118fed3..2ccd6ad 100644 --- a/lib/rundoc/code_section.rb +++ b/lib/rundoc/code_section.rb @@ -73,6 +73,10 @@ def render return "" if hidden? + self.class.to_doc(result: result, env: env) + end + + def self.to_doc(result: , env: ) array = [env[:before]] result.flatten! From f611acab311bd3cb2efd668f81e5abd9b1220c7e Mon Sep 17 00:00:00 2001 From: Schneems Date: Wed, 20 Nov 2024 16:28:29 -0600 Subject: [PATCH 2/5] Store partial results in memory --- lib/rundoc/code_section.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/rundoc/code_section.rb b/lib/rundoc/code_section.rb index 2ccd6ad..2be28e6 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,6 +74,9 @@ 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? From 5e07870149b371fe3527069cacf6a66482a2a4a1 Mon Sep 17 00:00:00 2001 From: Schneems Date: Wed, 20 Nov 2024 16:29:25 -0600 Subject: [PATCH 3/5] Write partial results on failure Previously if a command failed you lose the resulting doc, including everything up to that point which might be salvalgable. With this change a partial result is written to disk on failure. --- lib/rundoc/cli.rb | 2 ++ lib/rundoc/code_section.rb | 4 +++ test/integration/failure_test.rb | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 test/integration/failure_test.rb diff --git a/lib/rundoc/cli.rb b/lib/rundoc/cli.rb index 7371a96..173e4b5 100644 --- a/lib/rundoc/cli.rb +++ b/lib/rundoc/cli.rb @@ -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 2be28e6..ed2af35 100644 --- a/lib/rundoc/code_section.rb +++ b/lib/rundoc/code_section.rb @@ -84,6 +84,10 @@ def render self.class.to_doc(result: result, env: env) end + def self.partial_result_to_doc + self.to_doc(result: PARTIAL_RESULT, env: PARTIAL_ENV) + end + def self.to_doc(result: , env: ) array = [env[:before]] 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 From efe88939a9f83303acd48b621aa6732c4f04af21 Mon Sep 17 00:00:00 2001 From: Schneems Date: Wed, 20 Nov 2024 16:39:38 -0600 Subject: [PATCH 4/5] Capture warning in IO --- CHANGELOG.md | 2 ++ lib/rundoc/cli.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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 173e4b5..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 From 1c483a649d8a616f6b281486b7cf2c470e97752c Mon Sep 17 00:00:00 2001 From: Schneems Date: Wed, 20 Nov 2024 16:44:02 -0600 Subject: [PATCH 5/5] Linter --- lib/rundoc/code_section.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rundoc/code_section.rb b/lib/rundoc/code_section.rb index ed2af35..b9d4537 100644 --- a/lib/rundoc/code_section.rb +++ b/lib/rundoc/code_section.rb @@ -85,10 +85,10 @@ def render end def self.partial_result_to_doc - self.to_doc(result: PARTIAL_RESULT, env: PARTIAL_ENV) + to_doc(result: PARTIAL_RESULT, env: PARTIAL_ENV) end - def self.to_doc(result: , env: ) + def self.to_doc(result:, env:) array = [env[:before]] result.flatten!