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

7.0 KiB
Raw Blame History

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-clisrc/main.rs: the CLI entrypoint.
      • webextsrc/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):
      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:
      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:
      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 buildcargo 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)