Files
cl-cli/.junie/guidelines.md
2025-11-11 00:54:34 +01:00

131 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.rs` exposes common code to both binaries.
- Toolchain: stable Rust; CI uses dtolnay/rust-toolchain@stable.
- Dependencies and async runtime
- Async via `tokio` (features: `rt`, `rt-multi-thread`, `macros`). Both binaries use `#[tokio::main]`.
- HTTP via `reqwest`; serialization via `serde`/`serde_json`; configuration via `toml`.
- Build
- Standard build works without extra flags:
- `cargo build` (debug) or `cargo build --release` (optimized).
- Individual binaries:
- `cargo build --bin cl-cli`
- `cargo build --bin webext`
- The web extension host (`webext`) is a regular Rust binary; it is not bundled by NPM tooling.
- 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):
```bash
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 nonzero, the `webext` host will return an error payload.
- Local OpenProject for development
- `docker-compose.yaml` provides a local OpenProject (13.x) at `http://localhost:8080` with 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 via `src/lib.rs` for integration testing.
- Running tests
- `cargo test` runs unit and integration tests. CI also runs `cargo test` on every push/PR.
- Tests are pure and do not require network or external services; avoid adding networkbound 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 from `cl_cli`.
- Keep tests deterministic: no real HTTP calls; if needed, mock boundaries at the client layer.
- Example integration test (verified locally during preparation)
- Minimal example using a pure helper. Create `tests/example_gitea_url.rs`:
```rust
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.
## 3. CLI usage tips (projectspecific)
- `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. `chill` in `.../projects/chill/...`.
- The command uses tokens from the configuration file to authenticate to GitLab and OpenProject.
- Example:
```bash
cl-cli planning i2work \
https://gitlab.com/Chill-Projet/chill-bundles/-/issues/240 \
chill
```
- `cl-cli test` invokes a debug routine (see `src/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 4byte lengthprefixed JSON messages.
- Input `serde` enum is tagged with `type`; currently supports `{"type":"Issue2Work", ...}`.
- Output is tagged with `result` (`Ok` or `Error`) and contains `data` when successful.
- Business flow: the host reads config from `$HOME/.config/cl-cli/config.toml`, translates the input into `Issue2Work` CLI arguments, delegates to `planning::issue2work::handle_issue2work`, and returns the created work package URL.
- Testing the transport: see unit tests in `src/webext.rs` that exercise message framing and deserialization.
## 5. Code style and architectural notes
- Module layout
- Public library facade (`src/lib.rs`) reexports 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.
- Error handling
- Unified lightweight `GeneralError` encapsulates userfacing messages; conversions from `reqwest::Error` and header errors are provided.
- Data parsing
- Input/Output types rely on `serde` with explicit tagging for clarity and forward compatibility.
- Concurrency
- All async entrypoints are `#[tokio::main]`; downstream async functions return `impl Future` to stay generic and testable.
- 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.yaml` performs:
- Checkout → install stable toolchain → `cargo build` → `cargo test`.
- Release job (see `.gitea/workflows/release/build-and-release.yaml`) builds release artifacts for distribution.
## 7. Troubleshooting / gotchas (projectspecific)
- Config path
- The CLI accepts `--config`, but the webext host reads the default path only. Ensure `$HOME/.config/cl-cli/config.toml` exists when using the browser integration.
- Tokens scope
- Ensure personal access tokens for GitLab and OpenProject have sufficient scopes for reading issues and creating work packages respectively.
- Locale/URLs
- `Issue2Work` requires the OpenProject project identifier (slug), not its display name.
- HTTP environment
- `reqwest` honors 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)