Dotentv & scripting - #519
Conversation
There was a problem hiding this comment.
Pull request overview
Adds dotenv-based configuration and in-process BookGen scripting while removing legacy configuration and JSON-argument support.
Changes:
- Adds dotenv parsing, configuration loading, and executable path resolution.
- Adds script execution and command-instance caching.
- Updates rendering dependencies, lifecycle handling, tests, and documentation.
Reviewed changes
Copilot reviewed 70 out of 70 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
Test/Bookgen.Tests/UT_OpenCli.cs |
Updates parser construction. |
Test/Bookgen.Tests/TestEnvironment.cs |
Uses dotenv settings. |
Test/Bookgen.Tests/TestAppSettings.cs |
Removes obsolete test settings. |
Test/Bookgen.Tests/Commands/CommandTestBase.cs |
Updates resolver namespace. |
Test/Bookgen.Tests/Cli/UT_DotEnvParser.cs |
Tests dotenv parsing. |
Test/Bookgen.Tests/Cli/UT_CommandRunner.cs |
Disposes command runner. |
Source/BookGen/Properties/launchSettings.json |
Changes debug profile. |
Source/BookGen/Program.cs |
Loads dotenv configuration. |
Source/BookGen/packages.lock.json |
Updates locked dependencies. |
Source/BookGen/Infrastructure/ProgramPathResolver.cs |
Resolves paths from dotenv. |
Source/BookGen/GlobalOptionParsers/WaitDebuggerParser.cs |
Adds logger dependency. |
Source/BookGen/GlobalOptionParsers/RuntimePrintingParser.cs |
Adopts value callback. |
Source/BookGen/GlobalOptionParsers/LogToFileParser.cs |
Adopts value callback. |
Source/BookGen/GlobalOptionParsers/JsonLogParser.cs |
Adopts value callback. |
Source/BookGen/GlobalOptionParsers/DotEnvFileParser.cs |
Adds env-file option. |
Source/BookGen/GlobalOptionParsers/AttachDebuggerParser.cs |
Adds logger dependency. |
Source/BookGen/Commands/ScriptCommand.cs |
Adds script execution. |
Source/BookGen/Commands/JsonArgsCommand.cs |
Removes JSON template command. |
Source/BookGen/Commands/folder/SearchCommand.cs |
Updates namespace imports. |
Source/BookGen/Commands/Folder/PreviewCommand.cs |
Updates namespace imports. |
Source/BookGen/Commands/Convert/QrCodeCommand.cs |
Reuses rendering interop. |
Source/BookGen/Commands/Convert/Md2HtmlCommand.cs |
Reuses rendering interop. |
Source/BookGen/Commands/Convert/Math2SvgCommand.cs |
Reuses rendering interop. |
Source/BookGen/Commands/Convert/Diagram2SvgCommand.cs |
Reuses rendering interop. |
Source/BookGen/Commands/ConfigCommand.cs |
Removes configuration command. |
Source/BookGen/Commands/Build/BuildWordpressCommand.cs |
Updates resolver namespace. |
Source/BookGen/Commands/Build/BuildWebCommand.cs |
Updates resolver namespace. |
Source/BookGen/Commands/Build/BuildPrintCommand.cs |
Updates resolver namespace. |
Source/BookGen/Commands/Build/BuildPlugin.cs |
Removes obsolete import. |
Source/BookGen/Commands/Build/BuildFeedCommand.cs |
Updates resolver namespace. |
Source/BookGen/Commands/Build/BuildExportCommand.cs |
Updates resolver namespace. |
Source/BookGen/Commands/Build/BuildEpub.cs |
Updates resolver namespace. |
Source/BookGen/Commands/Book/ValidateCommand.cs |
Removes obsolete import. |
Source/BookGen/Commands/Book/StatsCommand.cs |
Removes obsolete import. |
Source/BookGen/Commands/Book/LinksCommand.cs |
Removes obsolete import. |
Source/BookGen/BuildCommandBase.cs |
Removes obsolete import. |
Source/BookGen.Shellprog/Program.cs |
Disposes command runner. |
Source/BookGen.Lib/Rendering/Markdown/RenderInterop/RenderInterop.cs |
Makes image configuration mutable. |
Source/BookGen.Lib/Rendering/Markdown/RenderInterop/IRenderInterop.cs |
Removes obsolete import. |
Source/BookGen.Lib/Pipeline/IBookEnvironment.cs |
Removes obsolete import. |
Source/BookGen.Lib/packages.lock.json |
Updates locked dependencies. |
Source/BookGen.Lib/IProgramPathResolver.cs |
Moves resolver interface namespace. |
Source/BookGen.Lib/Http/PreviewRoutes.cs |
Removes obsolete import. |
Source/BookGen.Lib/Http/HttpServerFactory.cs |
Removes obsolete import. |
Source/BookGen.Lib/Domain/IO/AppSetting.cs |
Removes legacy settings model. |
Source/BookGen.Lib/BookGen.Lib.csproj |
Excludes legacy settings files. |
Source/BookGen.Lib/BookEnvironment.cs |
Removes obsolete import. |
Source/BookGen.Lib/AppSettings/IReadOnlyAppSettings.cs |
Removes legacy interface. |
Source/BookGen.Lib/AppSettings/IAppSettings.cs |
Removes mutable settings interface. |
Source/BookGen.Lib/AppSettings/AppSettings.cs |
Removes legacy implementation. |
Source/BookGen.Contents/BookGen.env |
Adds default env template. |
Source/BookGen.Contents/BookGen.Contents.csproj |
Copies env template. |
Source/BookGen.Cli/IGlobalOptionParser.cs |
Replaces old parser implementation. |
Source/BookGen.Cli/GlobalOptionParser.cs |
Adds value-taking global options. |
Source/BookGen.Cli/Dotenv/EnvironmentException.cs |
Adds dotenv parse errors. |
Source/BookGen.Cli/Dotenv/DotEnvSettings.cs |
Adds dotenv setting storage. |
Source/BookGen.Cli/Dotenv/DotEnvParser.cs |
Implements dotenv parsing. |
Source/BookGen.Cli/CommandRunner.cs |
Caches and disposes commands. |
Source/BookGen.Cli/ArgumentJsonItem.cs |
Removes JSON argument model. |
Experiments/Bookgen.Experiments/IDotEnv.cs |
Adds experimental dotenv API. |
Experiments/Bookgen.Experiments/EnvironmentException.cs |
Adds experimental errors. |
Experiments/Bookgen.Experiments/DotEnvParser.cs |
Adds experimental parser. |
Experiments/Bookgen.Experiments/DotEnv.cs |
Adds experimental storage. |
Experiments/Bookgen.Experiments/Bookgen.Experiments.csproj |
Exposes internals to tests. |
Experiments/Bookgen.Experiments.Tests/DotenvParserTests.cs |
Tests experimental parser. |
Docs/scripts.md |
Documents scripting. |
Docs/changelog.md |
Records breaking changes. |
Docs/bookgen.toc.json |
Adds scripting documentation. |
Directory.Packages.props |
Updates rendering dependencies. |
BookGen.slnx |
Adds scripting documentation. |
Suppressed comments (1)
Source/BookGen.Cli/Dotenv/DotEnvParser.cs:188
- Whitespace immediately before a valid inline
#comment makesvalueEnd > end, so a standard entry such asFOO=bar # commentthrows ENV001 instead of parsingbar. The referenced env specification explicitly permits this form; only apply the trailing-whitespace rejection when no comment was found.
// Trailing whitespace on an unquoted value is not allowed.
if (valueEnd > end)
{
throw EnvironmentException.Env001(line);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 86 out of 86 changed files in this pull request and generated 1 comment.
Suppressed comments (12)
Test/Bookgen.Tests/Cli/UT_DotEnvParser.cs:101
Contains.Keyis a dictionary constraint, whileenv.Keysis the key collection itself. This assertion should check collection membership.
Test/Bookgen.Tests/Cli/UT_DotEnvParser.cs:126Contains.Keyis a dictionary constraint, whileenv.Keysis the key collection itself. This assertion should check collection membership.
Experiments/Bookgen.Experiments.Tests/DotenvParserTests.cs:94Contains.Keyis a dictionary constraint, whileenv.Keysis the key collection itself. Use the collection constraint here.
Assert.That(env.Keys, Contains.Key("PRIVATE_KEY"));
Experiments/Bookgen.Experiments.Tests/DotenvParserTests.cs:119
Contains.Keyis a dictionary constraint, whileenv.Keysis the key collection itself. Use the collection constraint here.
Assert.That(env.Keys, Contains.Key("LONG_MESSAGE"));
Source/BookGen/Commands/ScriptCommand.cs:92
- This logs the original line after tokenization, so text that the script syntax treats as a comment is still emitted. The new sample
cmd1 ... #log this shouldn't be loggedtherefore writes that exact text through the “Running” message, contradicting the documented behavior that trailing comments are ignored.
Source/BookGen/Commands/ScriptCommand.cs:94 - The enclosing cancellation token is not forwarded to the invoked command. If a script step is long-running, cancellation of
ExecuteAsync(including the new test timeout token) cannot interrupt this await; cancellation is only observed after the step eventually returns. Extend the runner proxy API so nested command execution accepts and links this token.
Source/BookGen/Commands/ScriptCommand.cs:115 - Continuation detection runs before comment stripping, so a backslash inside a trailing comment incorrectly consumes the next command. For example,
cmd1 # note \followed bycmd2becomes one logical line; tokenization stops at#, andcmd2is silently skipped even though comments are documented as ending at the line boundary. Detect comments/quotes while deciding whether the final backslash is syntactic.
Source/BookGen.Cli/Dotenv/DotEnvParser.cs:192 - A normal inline comment preceded by whitespace is rejected here. For
FOO=bar # comment,sawCommentis true butvalueEnd > endbecause of the space before#, causing ENV001 instead of returningbar. The linked .env specification explicitly shows this form as valid; only enforce the trailing-whitespace rule when no comment was found.
// Trailing whitespace on an unquoted value is not allowed.
if (valueEnd > end)
{
throw EnvironmentException.Env001(line);
Test/Bookgen.Tests/Cli/UT_DotEnvParser.cs:62
Contains.Keyexpects a dictionary, butenv.Keysis only anIEnumerable<string>/key collection, so this assertion fails even when the key exists. Assert collection membership (or callenv.ContainsKey) instead. The same mismatch is repeated below forPRIVATE_KEYandLONG_MESSAGE.
This issue also appears in the following locations of the same file:
- line 101
- line 126
Experiments/Bookgen.Experiments.Tests/DotenvParserTests.cs:55
Contains.Keyexpects a dictionary, butenv.Keysis only the key collection, so this assertion does not test membership correctly. The same mismatch recurs below forPRIVATE_KEYandLONG_MESSAGE.
This issue also appears in the following locations of the same file:
- line 94
- line 119
Assert.That(env.Keys, Contains.Key(expectedKey));
Source/BookGen/Commands/Convert/Md2HtmlCommand.cs:28
- This command now owns a native-backed
RenderInterop, butUT_Md2HtmlCommandcreates it throughCommandTestBase, which has no teardown that disposesCommand. Each test therefore leaves its V8 engine alive. Add a base teardown that disposes commands implementingIDisposable.
Source/BookGen.Cli/Dotenv/DotEnvParser.cs:182 - Leading whitespace on continuation lines is significant according to the linked .env specification, but this call strips it. Thus
VALUE=first\followed by an indentedsecondis parsed asfirst\nsecondinstead of preserving the two spaces. Resume at column zero for continuation values.
line = next;
pos = SkipWhitespace(line, 0);
continue;
No description provided.