feat: Add man page and update release workflow (#22)#26
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a Unix man page for sql-pipe (written in scdoc) and wires man-page generation + packaging into the Zig build and GitHub release workflow.
Changes:
- Added
docs/sql-pipe.1.scdman page (scdoc format). - Added
zig build manstep to generatesql-pipe.1.gzwhenscdocis available. - Updated release workflow to install
scdoc, generate the man page, and upload it with release artifacts.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| docs/sql-pipe.1.scd | Introduces scdoc man page content for sql-pipe. |
| build.zig | Adds optional build step to generate and gzip the man page. |
| .github/workflows/release.yml | Installs scdoc, runs zig build man, and uploads man page in artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.github/workflows/release.yml
Outdated
| apt-get update | ||
| apt-get install -y scdoc |
There was a problem hiding this comment.
apt-get typically requires root privileges on GitHub-hosted runners; without sudo, this step will fail with permission denied. Use sudo apt-get update / sudo apt-get install -y scdoc (or run within a root container) so the release workflow is reliable.
| apt-get update | |
| apt-get install -y scdoc | |
| sudo apt-get update | |
| sudo apt-get install -y scdoc |
build.zig
Outdated
| // Generate man page from scdoc source if scdoc is available (optional dependency) | ||
| const man_step = b.step("man", "Generate man page with scdoc (optional)"); | ||
| const build_man = b.addSystemCommand(&.{ | ||
| "bash", "-c", | ||
| \\if command -v scdoc >/dev/null 2>&1; then | ||
| \\ mkdir -p zig-out/share/man/man1 | ||
| \\ scdoc < docs/sql-pipe.1.scd | gzip -c > zig-out/share/man/man1/sql-pipe.1.gz | ||
| \\ echo "✓ Generated man page: zig-out/share/man/man1/sql-pipe.1.gz" | ||
| \\else | ||
| \\ echo "⚠ scdoc not found. Install it to generate man page." | ||
| \\ echo " Manual source: docs/sql-pipe.1.scd" | ||
| \\fi | ||
| }); | ||
| man_step.dependOn(&build_man.step); | ||
|
|
There was a problem hiding this comment.
The man build step hard-depends on bash even though the intent is for scdoc to be the optional dependency. On systems without bash in PATH (notably Windows), zig build man will fail before it can even check for scdoc. Consider avoiding the shell entirely by using Zig build APIs (e.g., locate scdoc/gzip with findProgram, pass args directly, and create the output via tracked build steps), or at least use a more portable shell strategy if cross-platform support is intended.
| // Generate man page from scdoc source if scdoc is available (optional dependency) | |
| const man_step = b.step("man", "Generate man page with scdoc (optional)"); | |
| const build_man = b.addSystemCommand(&.{ | |
| "bash", "-c", | |
| \\if command -v scdoc >/dev/null 2>&1; then | |
| \\ mkdir -p zig-out/share/man/man1 | |
| \\ scdoc < docs/sql-pipe.1.scd | gzip -c > zig-out/share/man/man1/sql-pipe.1.gz | |
| \\ echo "✓ Generated man page: zig-out/share/man/man1/sql-pipe.1.gz" | |
| \\else | |
| \\ echo "⚠ scdoc not found. Install it to generate man page." | |
| \\ echo " Manual source: docs/sql-pipe.1.scd" | |
| \\fi | |
| }); | |
| man_step.dependOn(&build_man.step); | |
| // Generate man page from scdoc source if scdoc (and gzip) are available (optional dependencies) | |
| const man_step = b.step("man", "Generate man page with scdoc (optional)"); | |
| // Try to locate scdoc; if not found, just log a warning and leave the step as a no-op. | |
| var have_tools = true; | |
| const scdoc_prog = b.findProgram(&.{ "scdoc" }, &.{}) catch |err| blk_scdoc: { | |
| std.log.warn("scdoc not found ({s}); skipping man page generation. Manual source: docs/sql-pipe.1.scd", .{@errorName(err)}); | |
| have_tools = false; | |
| break :blk_scdoc ""; | |
| }; | |
| // Try to locate gzip; if not found, log a warning and skip compression. | |
| const gzip_prog = b.findProgram(&.{ "gzip" }, &.{}) catch |err| blk_gzip: { | |
| std.log.warn("gzip not found ({s}); skipping man page compression; man page will not be generated.", .{@errorName(err)}); | |
| have_tools = false; | |
| break :blk_gzip ""; | |
| }; | |
| if (have_tools) { | |
| const man_dir = "zig-out/share/man/man1"; | |
| const man_src = "docs/sql-pipe.1.scd"; | |
| const man_out = "zig-out/share/man/man1/sql-pipe.1"; | |
| // Ensure the output directory exists at build configuration time. | |
| std.fs.cwd().makePath(man_dir) catch |err| { | |
| std.log.warn("failed to create man page directory '{s}': {s}", .{ man_dir, @errorName(err) }); | |
| }; | |
| // Run scdoc directly to generate the uncompressed man page file. | |
| const scdoc_cmd = b.addSystemCommand(&[_][]const u8{ | |
| scdoc_prog, | |
| "-f", "man", | |
| "-o", man_out, | |
| man_src, | |
| }); | |
| // Compress the generated man page using gzip; produces man_out ++ ".gz". | |
| const gzip_cmd = b.addSystemCommand(&[_][]const u8{ | |
| gzip_prog, | |
| "-kf", | |
| man_out, | |
| }); | |
| gzip_cmd.step.dependOn(&scdoc_cmd.step); | |
| man_step.dependOn(&gzip_cmd.step); | |
| } |
| \\ mkdir -p zig-out/share/man/man1 | ||
| \\ scdoc < docs/sql-pipe.1.scd | gzip -c > zig-out/share/man/man1/sql-pipe.1.gz | ||
| \\ echo "✓ Generated man page: zig-out/share/man/man1/sql-pipe.1.gz" | ||
| \\else | ||
| \\ echo "⚠ scdoc not found. Install it to generate man page." | ||
| \\ echo " Manual source: docs/sql-pipe.1.scd" | ||
| \\fi | ||
| }); |
There was a problem hiding this comment.
Because the scdoc input and gzip output are referenced only inside a shell redirection, the Zig build graph can’t reliably track docs/sql-pipe.1.scd as an input or zig-out/share/man/man1/sql-pipe.1.gz as an output. This can lead to stale manpages in incremental builds (doc edits not triggering regeneration). Prefer wiring the command so the build system can see the input file and produced output (e.g., pass the input as an explicit file argument and capture the output as an explicit output artifact) rather than relying on shell redirection.
| \\ mkdir -p zig-out/share/man/man1 | |
| \\ scdoc < docs/sql-pipe.1.scd | gzip -c > zig-out/share/man/man1/sql-pipe.1.gz | |
| \\ echo "✓ Generated man page: zig-out/share/man/man1/sql-pipe.1.gz" | |
| \\else | |
| \\ echo "⚠ scdoc not found. Install it to generate man page." | |
| \\ echo " Manual source: docs/sql-pipe.1.scd" | |
| \\fi | |
| }); | |
| \\ # $1 = input .scd file (provided by Zig build) | |
| \\ # $2 = output .gz file (provided by Zig build) | |
| \\ mkdir -p "$(dirname "$2")" | |
| \\ scdoc < "$1" | gzip -c > "$2" | |
| \\ echo "✓ Generated man page: $2" | |
| \\else | |
| \\ echo "⚠ scdoc not found. Install it to generate man page." | |
| \\ echo " Manual source: docs/sql-pipe.1.scd" | |
| \\fi, | |
| "sql-pipe-man", | |
| }); | |
| // Declare the scdoc source as an explicit input and the gzipped manpage as an explicit output | |
| build_man.addFileArg(b.path("docs/sql-pipe.1.scd")); | |
| _ = build_man.addOutputFileArg("share/man/man1/sql-pipe.1.gz"); |
docs/sql-pipe.1.scd
Outdated
| $ echo 'name,age | ||
| $ Alice,30 | ||
| $ Bob,25' | sql-pipe 'SELECT * FROM t' | ||
| name,age | ||
| Alice,30 | ||
| Bob,25 |
There was a problem hiding this comment.
This example reads like three separate shell commands (each prefixed with $), but the intent is to provide multi-line CSV input. As written, it’s not a valid command sequence and is likely to confuse users. Consider rewriting using a here-doc (e.g., cat <<'EOF' ... EOF | sql-pipe ...) or printf with \\n, and only use $ for actual commands (not for data lines).
| $ echo 'name,age | |
| $ Alice,30 | |
| $ Bob,25' | sql-pipe 'SELECT * FROM t' | |
| name,age | |
| Alice,30 | |
| Bob,25 | |
| $ cat <<'EOF' | sql-pipe 'SELECT * FROM t' | |
| name,age | |
| Alice,30 | |
| Bob,25 | |
| EOF | |
| name,age | |
| Alice,30 | |
| Bob,25 |
3cd1d0a to
878431a
Compare
Review Feedback Applied ✅All Copilot reviewer suggestions have been incorporated: 1. release.yml — Fixed
|
- Create docs/sql-pipe.1.scd in scdoc format covering NAME, SYNOPSIS, DESCRIPTION, OPTIONS, EXAMPLES, EXIT CODES, AUTHORS, and SEE ALSO sections - Update build.zig to add 'zig build man' step that generates sql-pipe.1.gz using scdoc when available (optional dependency) - Update release.yml to install scdoc and generate man page during release builds - Include sql-pipe.1.gz in release artifacts - Man page is consistent with --help output and documents all options and exit codes Closes #22
878431a to
fd39035
Compare
scdoc Parsing Issue Fixed ✅The build was failing because scdoc interprets asterisks ( Solution Applied:
Verification:The man page is now successfully generated and properly formatted. All examples are now valid scdoc syntax. |
Description
Implements a Unix manual page for
sql-pipeusing scdoc format and integrates it into the release workflow.Acceptance Criteria - Completed
docs/sql-pipe.1.scdwritten in scdoc format covering: NAME, SYNOPSIS, DESCRIPTION, OPTIONS, EXAMPLES, EXIT CODES, AUTHORS, SEE ALSObuild.zigaddszig build manstep that generatessql-pipe.1.gzwhenscdocis available (optional dependency)--helpoutputImplementation Details
Files Created
docs/sql-pipe.1.scd: scdoc formatted man page with complete documentationFiles Modified
build.zig: Added optional build stepzig build manthat generatessql-pipe.1.gzusing scdoc.github/workflows/release.yml:zig build manduring release buildssql-pipe.1.gzin release artifactsTesting
The man page can be generated locally with:
Once installed (via Homebrew/AUR or manually to
/usr/share/man/man1/), it can be viewed with:Notes
--helpwith more detail and Unix conventionsCloses #22"