7.0 KiB
7.0 KiB
cl-cli — Project-specific development guidelines
This document captures project-specific knowledge to help advanced contributors work efficiently on this repository. It focuses on practical, non-obvious details (build, configuration, testing, and development tips) specific to this codebase.
1. Build and configuration
- Rust workspace/binaries
- Single crate with two binaries defined in
Cargo.toml:cl-cli→src/main.rs: the CLI entrypoint.webext→src/webext.rs: a Native Messaging host used by the browser extension.
- Library module tree under
src/lib.rsexposes common code to both binaries. - Toolchain: stable Rust; CI uses dtolnay/rust-toolchain@stable.
- Single crate with two binaries defined in
- Dependencies and async runtime
- Async via
tokio(features:rt,rt-multi-thread,macros). Both binaries use#[tokio::main]. - HTTP via
reqwest; serialization viaserde/serde_json; configuration viatoml.
- Async via
- Build
- Standard build works without extra flags:
cargo build(debug) orcargo build --release(optimized).- Individual binaries:
cargo build --bin cl-clicargo build --bin webext
- The web extension host (
webext) is a regular Rust binary; it is not bundled by NPM tooling.
- Standard build works without extra flags:
- Configuration file
- Expected location by default:
$HOME/.config/cl-cli/config.toml. - The CLI allows overriding the path via
--config <PATH>; the webext host always reads the default path. - Template:
config.toml.dist. Minimal fields:[[gitlab]] { token, domain }[[gitea]] { token, domain }[openproject] { token, base_url }
- Example of initial setup (copy the dist and edit):
mkdir -p "$HOME/.config/cl-cli" cp config.toml.dist "$HOME/.config/cl-cli/config.toml" $EDITOR "$HOME/.config/cl-cli/config.toml" - Error surface: parsing and IO errors are surfaced as
GeneralError; the CLI will print and exit non‑zero, thewebexthost will return an error payload.
- Expected location by default:
- Local OpenProject for development
docker-compose.yamlprovides a local OpenProject (13.x) athttp://localhost:8080with persisted volumes under.docker-data/.
2. Testing
- Test types present
- Unit tests live alongside code under
#[cfg(test)]modules (e.g.,src/gitea/issue.rs,src/webext.rs,src/planning/utils.rs). - Integration tests can be placed under
tests/. The crate exposes internal modules viasrc/lib.rsfor integration testing.
- Unit tests live alongside code under
- Running tests
cargo testruns unit and integration tests. CI also runscargo teston every push/PR.- Tests are pure and do not require network or external services; avoid adding network‑bound tests.
- Adding new tests
- Prefer unit tests near the logic being tested. For integration coverage across modules, place files under
tests/and use public items fromcl_cli. - Keep tests deterministic: no real HTTP calls; if needed, mock boundaries at the client layer.
- Prefer unit tests near the logic being tested. For integration coverage across modules, place files under
- Example integration test (verified locally during preparation)
- Minimal example using a pure helper. Create
tests/example_gitea_url.rs:use url::Url; #[test] fn converts_gitea_issue_html_url_to_api_url() { // Pure transformation; no network let input = Url::parse("https://gitea.champs-libres.be/champs-libres/test/issues/1").unwrap(); let out = cl_cli::gitea::issue::issue_html_url_to_api(&input).unwrap(); assert_eq!( out.as_str(), "https://gitea.champs-libres.be/api/v1/repos/champs-libres/test/issues/1" ); } - Run it with
cargo test. Remove the file if it was only created as a demo.
- Minimal example using a pure helper. Create
3. CLI usage tips (project‑specific)
cl-cli planning i2work <gitlab_issue_url> <openproject_project_identifier>creates an OpenProject work package from a GitLab issue.- The OpenProject project identifier is the short slug in URLs, e.g.
chillin.../projects/chill/.... - The command uses tokens from the configuration file to authenticate to GitLab and OpenProject.
- Example:
cl-cli planning i2work \ https://gitlab.com/Chill-Projet/chill-bundles/-/issues/240 \ chill
- The OpenProject project identifier is the short slug in URLs, e.g.
cl-cli testinvokes a debug routine (seesrc/debug.rs) primarily for local diagnostics.
4. Web extension native host (webext)
- Purpose: acts as a Native Messaging host for a browser extension under
web-extension/. - Protocol: communicates via stdin/stdout using 4‑byte length‑prefixed JSON messages.
- Input
serdeenum is tagged withtype; currently supports{"type":"Issue2Work", ...}. - Output is tagged with
result(OkorError) and containsdatawhen successful.
- Input
- Business flow: the host reads config from
$HOME/.config/cl-cli/config.toml, translates the input intoIssue2WorkCLI arguments, delegates toplanning::issue2work::handle_issue2work, and returns the created work package URL. - Testing the transport: see unit tests in
src/webext.rsthat exercise message framing and deserialization.
5. Code style and architectural notes
- Module layout
- Public library facade (
src/lib.rs) re‑exports internal modules for reuse by both binaries and tests. - Planning features under
src/planning/with a trait (Issue2WorkActionTrait) and concrete actions per platform. - Git providers (
src/gitlab,src/gitea) and OpenProject client live in dedicated modules.
- Public library facade (
- Error handling
- Unified lightweight
GeneralErrorencapsulates user‑facing messages; conversions fromreqwest::Errorand header errors are provided.
- Unified lightweight
- Data parsing
- Input/Output types rely on
serdewith explicit tagging for clarity and forward compatibility.
- Input/Output types rely on
- Concurrency
- All async entrypoints are
#[tokio::main]; downstream async functions returnimpl Futureto stay generic and testable.
- All async entrypoints are
- External calls
- Wrap external service interactions behind client modules; this eases mocking in tests and keeps pure helpers (like URL mappers) easily testable.
6. Continuous Integration
.gitea/workflows/release/check.yamlperforms:- Checkout → install stable toolchain →
cargo build→cargo test.
- Checkout → install stable toolchain →
- Release job (see
.gitea/workflows/release/build-and-release.yaml) builds release artifacts for distribution.
7. Troubleshooting / gotchas (project‑specific)
- Config path
- The CLI accepts
--config, but the webext host reads the default path only. Ensure$HOME/.config/cl-cli/config.tomlexists when using the browser integration.
- The CLI accepts
- Tokens scope
- Ensure personal access tokens for GitLab and OpenProject have sufficient scopes for reading issues and creating work packages respectively.
- Locale/URLs
Issue2Workrequires the OpenProject project identifier (slug), not its display name.
- HTTP environment
reqwesthonors proxy vars (HTTP_PROXY,HTTPS_PROXY) if present; be aware for corporate environments.
8. Commands quick reference
- Build:
cargo build --release - Run CLI:
cargo run --bin cl-cli -- <args> - Run webext host directly for dev:
cargo run --bin webext - Tests:
cargo test - Linting:
cargo clippy(not enforced in CI but recommended)