-
Notifications
You must be signed in to change notification settings - Fork 0
Add man page generation to release workflow #343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: Release | ||
|
||
on: | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
env: | ||
CARGO_TERM_COLOR: always | ||
BUILD_PROFILE: release | ||
steps: | ||
- uses: actions/checkout@v5 | ||
- name: Setup Rust | ||
uses: leynos/shared-actions/.github/actions/setup-rust@c6559452842af6a83b83429129dccaf910e34562 | ||
- name: Build | ||
run: make release | ||
- name: Upload release assets | ||
uses: softprops/action-gh-release@v2 | ||
Check warningCode scanning / CodeQL Unpinned tag for a non-immutable Action in workflow Medium
Unpinned 3rd party Action 'Release' step
Uses Step Error loading related location Loading There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. security (yaml.github-actions.security.third-party-action-not-pinned-to-commit-sha): An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload. Source: opengrep |
||
with: | ||
files: | | ||
target/generated-man/wireframe.1 | ||
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainFail fast if the man page was not generated. Add an existence check before the upload to surface build.rs or Makefile - name: Build
run: make release
+ - name: Verify generated man page exists
+ run: |
+ test -s target/generated-man/wireframe.1 \
+ || { echo "wireframe.1 missing"; exit 1; }
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
files: |
target/generated-man/wireframe.1 #!/bin/bash
# Search for man page references
rg -n 'wireframe\.1' -n .
# Search for generated-man directory usage
rg -n 'generated-man' -n .
# Show Makefile rules for man page generation
fd '^Makefile$' -x sed -n '1,200p' Makefile
# Inspect build.rs if present for man page creation logic
fd 'build.rs' -x sed -n '1,200p' build.rs 🏁 Script executed: #!/usr/bin/env bash
# Locate references to the generated man page
rg -n 'wireframe\.1' .
rg -n 'generated-man' .
# Inspect Makefile for man page generation rules
if [ -f Makefile ]; then
sed -n '1,200p' Makefile
fi
# Inspect build.rs for man page creation logic
if [ -f build.rs ]; then
sed -n '1,200p' build.rs
fi Length of output: 2719 Fail fast if generated man page is missing - name: Build
run: make release
+ - name: Verify generated man page exists
+ run: |
+ test -s target/generated-man/wireframe.1 \
+ || { echo "wireframe.1 missing"; exit 1; }
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
files: |
target/generated-man/wireframe.1 🧰 Tools🪛 GitHub Check: CodeQL[warning] 22-22: Unpinned tag for a non-immutable Action in workflow 🤖 Prompt for AI Agents
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ metrics = { version = "0.24.2", optional = true } | |
metrics-exporter-prometheus = { version = "0.17.2", optional = true, features = ["http-listener"] } | ||
thiserror = "2.0.16" | ||
static_assertions = "1" | ||
clap = { version = "4.5", features = ["derive"] } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use caret requirements per dependency policy Adopt caret SemVer ranges for new deps per repository rules. Apply: -clap = { version = "4.5", features = ["derive"] }
+clap = { version = "^4.5", features = ["derive"] } -[build-dependencies]
-clap = { version = "4.5", features = ["derive"] }
-clap_mangen = "0.2"
+[build-dependencies]
+clap = { version = "^4.5", features = ["derive"] }
+clap_mangen = "^0.2" Also applies to: 67-70 🤖 Prompt for AI Agents
|
||
|
||
[dev-dependencies] | ||
rstest = "0.26.1" | ||
|
@@ -63,6 +64,10 @@ tokio = { version = "1.47.1", default-features = false, features = [ | |
"test-util", | ||
] } | ||
|
||
[build-dependencies] | ||
clap = { version = "4.5", features = ["derive"] } | ||
clap_mangen = "0.2" | ||
|
||
[features] | ||
default = ["metrics"] | ||
metrics = ["dep:metrics", "dep:metrics-exporter-prometheus"] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
//! Build script generating manual pages from the CLI definition. | ||
use std::{fs, path::PathBuf}; | ||
|
||
use clap::CommandFactory; | ||
use clap_mangen::Man; | ||
|
||
#[path = "src/cli.rs"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider moving the CLI definition to the library and writing directly to the file to simplify build script logic. Here’s one way to both remove the
// src/lib.rs
use clap::CommandFactory;
mod cli;
pub use cli::Cli;
/// convenience constructor for build.rs
pub fn build_cli() -> clap::Command {
Cli::command()
}
// build.rs
use std::{fs, path::PathBuf};
use clap_mangen::Man;
// import your crate as a library
use mycrate::build_cli;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("cargo:rerun-if-changed=src/cli.rs");
let out_dir = PathBuf::from("target/generated-man");
fs::create_dir_all(&out_dir)?;
let mut file = fs::File::create(out_dir.join("wireframe.1"))?;
Man::new(build_cli()).render(&mut file)?;
Ok(())
} Now you’ve
|
||
mod cli; | ||
|
||
fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
println!("cargo:rerun-if-changed=src/cli.rs"); | ||
|
||
let out_dir = PathBuf::from("target/generated-man"); | ||
fs::create_dir_all(&out_dir)?; | ||
|
||
let cmd = cli::Cli::command(); | ||
let man = Man::new(cmd); | ||
let mut buf: Vec<u8> = Vec::new(); | ||
man.render(&mut buf)?; | ||
Comment on lines
+14
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Avoid writing build output into crate sources The build script writes the generated man page to Useful? React with 👍 / 👎. |
||
fs::write(out_dir.join("wireframe.1"), buf)?; | ||
|
||
Comment on lines
+14
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Verify release workflow builds before upload Ensure the release workflow compiles the crate (thus running build.rs) and uploads the expected artefact path. Execute: #!/bin/bash
set -euo pipefail
# Find release workflows
fd -t f -g ".github/workflows/*.yml" -x sh -c '
echo "== {} ==";
rg -n "cargo build" {} || true;
rg -n "files:\s*target/generated-man/wireframe\.1" {} || true;
rg -n "permissions:\s*[\r\n]+(\s*)contents:\s*write" {} || true
' If the upload happens in a matrix or multi‑job workflow, gate the upload with needs: build and a path existence check to fail fast when the man page is missing. 🤖 Prompt for AI Agents
|
||
Ok(()) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,9 @@ | ||||||||||||||
# Command line interface | ||||||||||||||
|
||||||||||||||
Wireframe includes a small command line interface for demonstration. The CLI | ||||||||||||||
uses `clap` to parse arguments. An optional `--name` flag allows customising | ||||||||||||||
the greeting printed by the `wireframe` binary. | ||||||||||||||
Comment on lines
+3
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Adopt Oxford -ize spelling and wrap to 80 columns. Replace -ise with -ize and reflow to respect the docs wrapping rule. - Wireframe includes a small command line interface for demonstration. The CLI
- uses `clap` to parse arguments. An optional `--name` flag allows customising
- the greeting printed by the `wireframe` binary.
+ Wireframe includes a small command line interface for demonstration. The
+ CLI uses `clap` to parse arguments. An optional `--name` flag allows
+ customizing the greeting printed by the `wireframe` binary. 📝 Committable suggestion
Suggested change
🧰 Tools🪛 LanguageTool[style] ~4-~4: Would you like to use the Oxford spelling “customizing”? The spelling ‘customising’ is also correct. (OXFORD_SPELLING_Z_NOT_S) 🤖 Prompt for AI Agents
|
||||||||||||||
|
||||||||||||||
Manual pages are generated during the build via `clap_mangen`. The `build.rs` | ||||||||||||||
script writes `wireframe.1` to `target/generated-man`, and the `release` GitHub | ||||||||||||||
workflow uploads this file. | ||||||||||||||
Comment on lines
+7
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Link libraries inline and keep lines ≤80 chars. Add inline links and reflow. - Manual pages are generated during the build via `clap_mangen`. The `build.rs`
- script writes `wireframe.1` to `target/generated-man`, and the `release` GitHub
- workflow uploads this file.
+ Manual pages are generated during the build via
+ [`clap_mangen`](https://crates.io/crates/clap_mangen). The `build.rs` script
+ writes `wireframe.1` to `target/generated-man`, and the `release` GitHub
+ workflow uploads this file. Add a minimal usage block after this paragraph: ```sh
# Run the CLI
cargo run -- -n Alice
# View the generated man page locally
man -l target/generated-man/wireframe.1
In docs/cli.md around lines 7-9, the paragraph about manual page generation
|
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,28 @@ | ||||||||||||||||
//! Command line interface for the wireframe example binary. | ||||||||||||||||
//! | ||||||||||||||||
//! Provides a tiny CLI to demonstrate argument parsing and man page | ||||||||||||||||
//! generation. | ||||||||||||||||
Comment on lines
+1
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Tighten module docs to en‑GB hyphenation Hyphenate “command‑line” in line with house style. -//! Command line interface for the wireframe example binary.
+//! Command‑line interface for the Wireframe example binary.
//!
-//! Provides a tiny CLI to demonstrate argument parsing and man page
-//! generation.
+//! Provides a tiny CLI to demonstrate argument parsing and man‑page generation. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||
use clap::Parser; | ||||||||||||||||
|
||||||||||||||||
/// Command line arguments for the `wireframe` binary. | ||||||||||||||||
#[derive(Debug, Parser)] | ||||||||||||||||
#[command(name = "wireframe", version, about = "Example Wireframe binary")] | ||||||||||||||||
pub struct Cli { | ||||||||||||||||
/// Name to greet. | ||||||||||||||||
#[arg(short, long)] | ||||||||||||||||
pub name: Option<String>, | ||||||||||||||||
} | ||||||||||||||||
Comment on lines
+8
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Document a usage example in Rustdoc Add a minimal example to aid /// Command line arguments for the `wireframe` binary.
#[derive(Debug, Parser)]
#[command(name = "wireframe", version, about = "Example Wireframe binary")]
pub struct Cli {
@@
pub name: Option<String>,
}
+
+/// # Examples
+/// Run with a name:
+/// ```shell
+/// wireframe --name Sam
+/// ``` 🤖 Prompt for AI Agents
|
||||||||||||||||
|
||||||||||||||||
#[cfg(test)] | ||||||||||||||||
mod tests { | ||||||||||||||||
use clap::Parser; | ||||||||||||||||
|
||||||||||||||||
use super::Cli; | ||||||||||||||||
|
||||||||||||||||
#[test] | ||||||||||||||||
fn parses_name_option() { | ||||||||||||||||
let cli = Cli::parse_from(["wireframe", "--name", "Sam"]); | ||||||||||||||||
assert_eq!(cli.name.as_deref(), Some("Sam")); | ||||||||||||||||
} | ||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,20 @@ | ||
//! Minimal binary demonstrating `wireframe` usage. | ||
//! | ||
//! Currently prints a greeting and exits. | ||
//! Parses CLI arguments and prints a greeting. | ||
|
||
mod cli; | ||
|
||
use clap::Parser; | ||
|
||
fn main() { | ||
// Enable structured logging for examples and integration tests. | ||
// Applications embedding the library should install their own subscriber. | ||
tracing_subscriber::fmt::init(); | ||
println!("Hello from Wireframe!"); | ||
|
||
let cli = cli::Cli::parse(); | ||
if let Some(name) = cli.name { | ||
println!("Hello, {name} from Wireframe!"); | ||
} else { | ||
println!("Hello from Wireframe!"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Pin actions/checkout to a commit SHA.
Apply the same immutability policy to first‑party actions.
📝 Committable suggestion
🤖 Prompt for AI Agents