mirror of
https://github.com/coralogix/cx-cli.git
synced 2026-09-14 16:15:45 +08:00
13915ea843
AIAG-696 ## Summary ### Full API coverage - Implement remaining cx CLI commands covering all Coralogix APIs (dashboards, views, SLOs, incidents, notifications, webhooks, enrichments, parsing-rules, TCO, quotas, usage, archive, integrations, IAM, recording-rules, E2M, search-fields) - 27 command groups total - Add user-facing skills for all command groups (cx-observability-setup, cx-cost-optimization, cx-incident-management, cx-data-pipeline, cx-platform-admin, cx-create-dashboard) - Rename all skills to cx- prefix for consistency, update cross-references and docs - Add integration tests (wiremock) and E2E test scaffolding for all new commands - Update CLAUDE.md, README, CODEOWNERS, architecture docs, and contributor guides - Bug fixes: data_usage timestamp parsing, users error propagation, team_groups unused params, dashboard skill API wire values, stale skill paths ### CLI safety features - Add `--read-only` global flag that blocks all write operations before credential resolution - safe for exploration and agent use - Add agent mode detection (`CX_AGENT_MODE`, `CLAUDECODE`, `CLAUDE_CODE` env vars) - blocks write operations unless `--yes` is passed - Wire `confirm_destructive()` to all write subcommands across all 27 command groups (104 call sites) - interactive confirmation for create/update/delete/enable/disable operations - Mark `iam` and `archive` as `(risky)` in help output - Add `[requires --yes]` tags to all write subcommand help text (102 annotations) - Update skills with read-only and agent mode guidance ### Testing - 441 tests passing (88 ignored E2E) - Add `tests/write_command_gating/` - systematic verification that every write command is gated - Add `tests/read_only/` - read-only mode enforcement tests - Add `tests/agent_mode/` - agent mode detection and blocking tests - Add integration tests (wiremock) for all new command groups - Add E2E test scaffolding for all commands ## Test plan - [x] `cargo fmt --check` passes - [x] `cargo clippy` passes with no warnings - [x] `cargo test` passes (441 unit + integration tests) - [ ] `cargo test --test e2e -- --ignored --test-threads=1` passes against test team (requires CX_API_KEY) - [ ] `cx schema` outputs updated command tree with all new commands - [ ] Skills trigger correctly in Claude Code sessions --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
1.8 KiB
Rust
61 lines
1.8 KiB
Rust
#[path = "../common/mod.rs"]
|
|
mod common;
|
|
|
|
use serde_json::json;
|
|
use wiremock::matchers::{method, path};
|
|
use wiremock::{Mock, MockServer, ResponseTemplate};
|
|
|
|
use coralogix_cli::commands::contextual_data::run_list;
|
|
use coralogix_cli::config::OutputFormat;
|
|
|
|
#[tokio::test]
|
|
async fn list_contextual_data_from_mock() {
|
|
let server = MockServer::start().await;
|
|
|
|
let body = json!({
|
|
"integrations": [
|
|
{
|
|
"integration": {
|
|
"id": "cd-001",
|
|
"name": "GitHub Commits",
|
|
"description": "Enrich logs with GitHub commit data"
|
|
},
|
|
"amountIntegrations": 2,
|
|
"isDeprecated": false,
|
|
"isNew": true,
|
|
"upgradeAvailable": false,
|
|
"errors": []
|
|
}
|
|
]
|
|
});
|
|
|
|
Mock::given(method("GET"))
|
|
.and(path("/mgmt/openapi/5/integrations/contextual-data/v1"))
|
|
.respond_with(ResponseTemplate::new(200).set_body_json(&body))
|
|
.expect(1)
|
|
.mount(&server)
|
|
.await;
|
|
|
|
let target = common::test_target("test-profile", &server.uri());
|
|
run_list(&[target], OutputFormat::Json)
|
|
.await
|
|
.expect("run_list should succeed");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn list_contextual_data_empty() {
|
|
let server = MockServer::start().await;
|
|
|
|
Mock::given(method("GET"))
|
|
.and(path("/mgmt/openapi/5/integrations/contextual-data/v1"))
|
|
.respond_with(ResponseTemplate::new(200).set_body_json(json!({ "integrations": [] })))
|
|
.expect(1)
|
|
.mount(&server)
|
|
.await;
|
|
|
|
let target = common::test_target("test-profile", &server.uri());
|
|
run_list(&[target], OutputFormat::Text)
|
|
.await
|
|
.expect("run_list should succeed with empty");
|
|
}
|