Skip to content

Cargo run tool#3832

Open
timon-schelling wants to merge 9 commits intomasterfrom
cargo-run-tool
Open

Cargo run tool#3832
timon-schelling wants to merge 9 commits intomasterfrom
cargo-run-tool

Conversation

@timon-schelling
Copy link
Member

@timon-schelling timon-schelling commented Feb 25, 2026

depends on #3808

usage: cargo run [<command>] [release|debug|profiling]

commands:
  web               Run the dev server
  web build         Build the web version
  desktop           Run the desktop app
  desktop build     Build the desktop version

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @timon-schelling, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the project's build and execution mechanisms by introducing a new Rust-based command-line tool. This tool consolidates various npm run and cargo run commands into a single, unified cargo run interface, improving consistency and ease of use for developers. The change also involves a cleanup of the Nix flake setup and removal of redundant root-level JavaScript package files, simplifying the overall project structure.

Highlights

  • Unified Build/Run Tool: Introduced a new tools/building Rust crate to centralize and simplify project build and run commands, replacing various npm run scripts with a single cargo run interface.
  • Nix Configuration Refactoring: Refactored the Nix flake configuration by moving core logic to .nix/default.nix and simplifying the root flake.nix, enhancing modularity and clarity.
  • Dependency Management Cleanup: Removed root-level package.json and package-lock.json files, streamlining the project's dependency management by centralizing frontend scripts within the frontend directory.
  • Documentation Update: Updated project setup documentation to reflect the new cargo run commands for web and desktop development, ensuring users have accurate instructions.
Changelog
  • .envrc
    • Removed the direnv configuration for Nix flakes.
  • .nix/default.nix
    • Added a new Nix file containing the main flake outputs definition, including packages, devShells, and formatter.
  • .nix/flake.nix
    • Removed, as its functionality was split and moved.
  • .nix/shell.nix
    • Removed, simplifying the Nix development environment setup.
  • Cargo.lock
    • Updated to include the new building package.
  • Cargo.toml
    • Added tools/building to workspace members and default members.
    • Removed node-graph/graphene-cli from default members.
  • flake.lock
    • Renamed from .nix/flake.lock.
    • Updated to remove the flake-compat input.
  • flake.nix
    • Added a simplified root flake file that imports the main configuration from .nix/default.nix.
  • package-lock.json
    • Removed the root-level npm lock file.
  • package.json
    • Removed the root-level npm package file, centralizing frontend scripts within the frontend directory.
  • tools/building/Cargo.toml
    • Added the manifest for the new building Rust crate.
  • tools/building/src/lib.rs
    • Added utility functions for executing shell commands and handling build profiles.
  • tools/building/src/main.rs
    • Added the main entry point for the building tool, providing subcommands for web and desktop operations (run/build) with profile selection.
  • website/content/volunteer/guide/project-setup/_index.md
    • Updated project run commands from npm start to cargo run.
    • Adjusted profiling and production commands to use the new cargo run syntax.
Ignored Files
  • Ignored by pattern: .github/workflows/** (3)
    • .github/workflows/build-linux-bundle.yml
    • .github/workflows/build-nix-package.yml
    • .github/workflows/provide-shaders.yml
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new building crate to replace the root package.json scripts for running and building the project, which is a great simplification. However, I've found a few issues in the implementation of this new tool. The command runner can panic on empty command strings, and the argument parsing logic doesn't correctly handle all the commands mentioned in the updated documentation, specifically cargo run build and cargo run -- production. I've provided suggestions to fix these issues, along with some minor improvements for code clarity and correctness.

@timon-schelling timon-schelling force-pushed the cargo-run-tool branch 2 times, most recently from 16fca60 to 8cb8c29 Compare February 25, 2026 18:48
Base automatically changed from cef-credits to master February 26, 2026 11:12
@timon-schelling timon-schelling marked this pull request as ready for review March 2, 2026 18:46
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 33 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".nix/default.nix">

<violation number="1" location=".nix/default.nix:47">
P2: The `// inputs` merge gives flake inputs precedence over explicitly constructed args. If a flake input name ever collides with a key like `lib`, `pkgs`, or `system`, the carefully constructed value will be silently overridden. Reverse the merge order so explicit values take precedence:
```nix
args = inputs // {
    inherit system;
    ...
};
```</violation>
</file>

<file name="tools/building/src/lib.rs">

<violation number="1" location="tools/building/src/lib.rs:74">
P1: The `ExitStatus` returned by `.wait()` is silently discarded. If the spawned command exits with a non-zero status (i.e., fails), execution continues to the next command without any error. For a build tool where commands are chained sequentially, this means a failed step won't stop the pipeline. Check the exit status and panic (or return an error) on failure.</violation>
</file>

<file name="tools/third-party-licenses/src/main.rs">

<violation number="1" location="tools/third-party-licenses/src/main.rs:63">
P3: Prefer returning `ExitCode` from `main()` instead of calling `std::process::exit(1)`. This avoids bypassing Rust's stack unwinding and is the idiomatic way to signal a non-zero exit code now that the heavy lifting is in `run()`.

(Based on your team's feedback about avoiding `exit()` and preferring returning for cleanup.) [FEEDBACK_USED]</violation>
</file>

<file name="desktop/bundle/src/common.rs">

<violation number="1" location="desktop/bundle/src/common.rs:50">
P2: Return an error instead of panicking so callers can handle command failures via the Result the function already exposes.</violation>
</file>

<file name=".github/workflows/comment-!build-commands.yml">

<violation number="1" location=".github/workflows/comment-!build-commands.yml:85">
P0: The `!build-debug` command will never work. The job-level `if` condition (line 24) still gates on `!build-dev`, so a `!build-debug` comment won't even start the job. The job-level condition, the usage comment (line 3), and the error message (line 92) all need to be updated from `!build-dev` to `!build-debug` to match this rename.</violation>
</file>

<file name="tools/building/src/deps.rs">

<violation number="1" location="tools/building/src/deps.rs:158">
P2: Bug: terminal check is on `stdout`, but the prompt is written to `stderr` and input is read from `stdin`. If `stdout` is redirected but `stdin`/`stderr` are terminals, this incorrectly skips the interactive prompt. The check should be on `std::io::stdin()` to determine if a user can respond interactively.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@timon-schelling
Copy link
Member Author

@cubic-dev-ai

@cubic-dev-ai
Copy link

cubic-dev-ai bot commented Mar 3, 2026

@cubic-dev-ai

@timon-schelling I have started the AI code review. It will take a few minutes to complete.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 33 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/bundle/src/common.rs">

<violation number="1" location="desktop/bundle/src/common.rs:50">
P2: This function returns `Result<(), Box<dyn Error>>` but panics instead of returning an `Err`. While replacing `std::process::exit(1)` with `panic!` is a step in the right direction (it allows unwinding), the idiomatic fix is to return an error so callers can handle it via `?`. This keeps the `Result` return type meaningful and avoids bypassing cleanup.

(Based on your team's feedback about avoiding `exit()` and preferring returning for cleanup.) [FEEDBACK_USED]</violation>
</file>

<file name="tools/building/src/deps.rs">

<violation number="1" location="tools/building/src/deps.rs:158">
P2: Terminal check is on `stdout`, but all output goes to `stderr`. This should check `stderr` (where the prompt is printed) and/or `stdin` (where input is read). With the current code, piping stdout (common for build tools) would incorrectly suppress the interactive installation prompt.</violation>
</file>

<file name="tools/building/src/lib.rs">

<violation number="1" location="tools/building/src/lib.rs:53">
P2: Typo: `comand` should be `command`. This misspelling appears in three public function signatures and a local variable, making it part of the public API.

(Based on your team's feedback about using consistent, precise terminology in names and docs.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@timon-schelling
Copy link
Member Author

@cubic-dev-ai

@cubic-dev-ai
Copy link

cubic-dev-ai bot commented Mar 3, 2026

@cubic-dev-ai

@timon-schelling I have started the AI code review. It will take a few minutes to complete.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 34 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tools/building/src/lib.rs">

<violation number="1" location="tools/building/src/lib.rs:37">
P2: Bug: explicitly passing `"run"` as the action keyword causes parsing to fail. Unlike `"build"`, `"run"` is not matched and consumed, so it leaks into the profile-parsing step where it's unrecognized, causing `parse` to return `None`. Add a match arm for `"run"` that consumes the token.</violation>
</file>

<file name="desktop/src/lib.rs">

<violation number="1" location="desktop/src/lib.rs:88">
P2: Inconsistent error handling: this "already running" path uses `panic!()` while the same condition in the lock acquisition above (line ~62) uses `tracing::error!` + `std::process::exit(1)`. Consider handling both consistently — either both panic or both log-and-exit.</violation>
</file>

<file name="desktop/bundle/src/common.rs">

<violation number="1" location="desktop/bundle/src/common.rs:50">
P2: Function returns `Result` but panics instead of returning `Err`. Since `run_command` already declares `Result<(), Box<dyn Error>>` as its return type, it should return an error here rather than panicking. This lets callers (e.g., `build_bin`) handle the failure gracefully via `?`.

(Based on your team's feedback about avoiding `exit()` and preferring returning for cleanup.) [FEEDBACK_USED]</violation>
</file>

<file name="tools/building/src/main.rs">

<violation number="1" location="tools/building/src/main.rs:56">
P2: `todo!()` will panic at runtime with an ugly stack trace instead of using the existing error-handling path. Since `run_task` returns `Result<(), Error>`, these should return a descriptive error so the user sees a clean message rather than a panic backtrace.

(Based on your team's feedback about preferring returning for cleanup over abrupt exits.) [FEEDBACK_USED]</violation>
</file>

<file name="tools/building/src/deps.rs">

<violation number="1" location="tools/building/src/deps.rs:158">
P1: Bug: missing non-installable dependencies don't cause an error return. When `failures` is non-empty (e.g., Rust or Node.js not found), the function prints warnings but still returns `Ok(())`, allowing the build to proceed and fail with a confusing error later. The `if installable.is_empty()` check on this line should also verify `failures.is_empty()`—or better, return an error when `failures` is non-empty.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

eprintln!("See: https://graphite.art/volunteer/guide/project-setup/");
}

if installable.is_empty() {
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Bug: missing non-installable dependencies don't cause an error return. When failures is non-empty (e.g., Rust or Node.js not found), the function prints warnings but still returns Ok(()), allowing the build to proceed and fail with a confusing error later. The if installable.is_empty() check on this line should also verify failures.is_empty()—or better, return an error when failures is non-empty.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/building/src/deps.rs, line 158:

<comment>Bug: missing non-installable dependencies don't cause an error return. When `failures` is non-empty (e.g., Rust or Node.js not found), the function prints warnings but still returns `Ok(())`, allowing the build to proceed and fail with a confusing error later. The `if installable.is_empty()` check on this line should also verify `failures.is_empty()`—or better, return an error when `failures` is non-empty.</comment>

<file context>
@@ -0,0 +1,193 @@
+		eprintln!("See: https://graphite.art/volunteer/guide/project-setup/");
+	}
+
+	if installable.is_empty() {
+		return Ok(());
+	}
</file context>
Fix with Cubic

_ => (Target::Web, args),
};

let (action, rest) = match rest.first() {
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Bug: explicitly passing "run" as the action keyword causes parsing to fail. Unlike "build", "run" is not matched and consumed, so it leaks into the profile-parsing step where it's unrecognized, causing parse to return None. Add a match arm for "run" that consumes the token.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/building/src/lib.rs, line 37:

<comment>Bug: explicitly passing `"run"` as the action keyword causes parsing to fail. Unlike `"build"`, `"run"` is not matched and consumed, so it leaks into the profile-parsing step where it's unrecognized, causing `parse` to return `None`. Add a match arm for `"run"` that consumes the token.</comment>

<file context>
@@ -0,0 +1,92 @@
+			_ => (Target::Web, args),
+		};
+
+		let (action, rest) = match rest.first() {
+			Some(&"build") => (Action::Build, &rest[1..]),
+			_ => (Action::Run, rest),
</file context>
Fix with Cubic

Err(cef::InitError::AlreadyRunning) => {
tracing::error!("Another instance is already running, Exiting.");
exit(1);
panic!("Another instance is already running.");
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Inconsistent error handling: this "already running" path uses panic!() while the same condition in the lock acquisition above (line ~62) uses tracing::error! + std::process::exit(1). Consider handling both consistently — either both panic or both log-and-exit.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/src/lib.rs, line 88:

<comment>Inconsistent error handling: this "already running" path uses `panic!()` while the same condition in the lock acquisition above (line ~62) uses `tracing::error!` + `std::process::exit(1)`. Consider handling both consistently — either both panic or both log-and-exit.</comment>

<file context>
@@ -87,20 +85,16 @@ pub fn start() {
 		Err(cef::InitError::AlreadyRunning) => {
-			tracing::error!("Another instance is already running, Exiting.");
-			exit(1);
+			panic!("Another instance is already running.");
 		}
 		Err(cef::InitError::InitializationFailed(code)) => {
</file context>
Fix with Cubic

let status = Command::new(program).args(args).stdout(Stdio::inherit()).stderr(Stdio::inherit()).status()?;
if !status.success() {
std::process::exit(1);
panic!("Command '{}' with args {:?} failed with status: {}", program, args, status);
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Function returns Result but panics instead of returning Err. Since run_command already declares Result<(), Box<dyn Error>> as its return type, it should return an error here rather than panicking. This lets callers (e.g., build_bin) handle the failure gracefully via ?.

(Based on your team's feedback about avoiding exit() and preferring returning for cleanup.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/bundle/src/common.rs, line 50:

<comment>Function returns `Result` but panics instead of returning `Err`. Since `run_command` already declares `Result<(), Box<dyn Error>>` as its return type, it should return an error here rather than panicking. This lets callers (e.g., `build_bin`) handle the failure gracefully via `?`.

(Based on your team's feedback about avoiding `exit()` and preferring returning for cleanup.) </comment>

<file context>
@@ -45,7 +47,7 @@ pub(crate) fn build_bin(package: &str, bin: Option<&str>) -> Result<PathBuf, Box
 	let status = Command::new(program).args(args).stdout(Stdio::inherit()).stderr(Stdio::inherit()).status()?;
 	if !status.success() {
-		std::process::exit(1);
+		panic!("Command '{}' with args {:?} failed with status: {}", program, args, status);
 	}
 	Ok(())
</file context>
Suggested change
panic!("Command '{}' with args {:?} failed with status: {}", program, args, status);
return Err(format!("Command '{}' with args {:?} failed with status: {}", program, args, status).into());
Fix with Cubic

run("cargo run -p third-party-licenses --features desktop")?;
run("cargo run -r -p graphite-desktop-bundle -- open")?;
}
(Target::Desktop, Action::Run, Profile::Profiling) => todo!("profiling run for desktop"),
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: todo!() will panic at runtime with an ugly stack trace instead of using the existing error-handling path. Since run_task returns Result<(), Error>, these should return a descriptive error so the user sees a clean message rather than a panic backtrace.

(Based on your team's feedback about preferring returning for cleanup over abrupt exits.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/building/src/main.rs, line 56:

<comment>`todo!()` will panic at runtime with an ugly stack trace instead of using the existing error-handling path. Since `run_task` returns `Result<(), Error>`, these should return a descriptive error so the user sees a clean message rather than a panic backtrace.

(Based on your team's feedback about preferring returning for cleanup over abrupt exits.) </comment>

<file context>
@@ -0,0 +1,71 @@
+			run("cargo run -p third-party-licenses --features desktop")?;
+			run("cargo run -r -p graphite-desktop-bundle -- open")?;
+		}
+		(Target::Desktop, Action::Run, Profile::Profiling) => todo!("profiling run for desktop"),
+
+		(Target::Desktop, Action::Build, Profile::Debug) => {
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant