Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ See [Upgrading from 2.x to 3.0](docs/upgrading-to-3.0.md) for what to change.
- CI checks the feature combinations `full`, `postgres,full`, `mysql,full` and `test-queue`.
- The library no longer depends on the `rsa` crate (RUSTSEC-2023-0071), which sqlx 0.9
made optional. It stays in the lockfile only through the CLI and dashboard binaries.
- **`cargo-hammerwork` is a binary only** ([#88](https://github.com/CodingAnarchy/hammerwork/issues/88)). The crate no longer has a library target: `cargo_hammerwork::commands`, `cargo_hammerwork::config`, `cargo_hammerwork::utils` and their glob re-exports are gone. Drive the CLI through the `cargo hammerwork` executable.
- **`hammerwork-web` exposes only `WebDashboard`, `DashboardConfig`, `AuthConfig` and `WebSocketConfig`** ([#88](https://github.com/CodingAnarchy/hammerwork/issues/88)). The `api`, `auth`, `config`, `live`, `security`, `server` and `websocket` modules are private, so `hammerwork_web::server::app_routes` and the other building blocks are no longer public API. `WebSocketConfig` is now re-exported at the crate root (it was `hammerwork_web::config::WebSocketConfig`).

## [2.5.0] - 2026-10-11

Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ The `cargo-hammerwork` crate uses **dynamic SQL queries** with `sqlx::query()` r
- Database-agnostic queries (PostgreSQL and MySQL)
- Runtime query building for CLI flexibility

**Security**: All queries use parameterized statements to prevent SQL injection. Comprehensive tests in `tests/sql_query_tests.rs` validate query correctness.
**Security**: All queries use parameterized statements to prevent SQL injection. Comprehensive tests in `cargo-hammerwork/src/integration_tests/sql_query.rs` validate query correctness.

### Feature Integration with CLI Tooling

Expand All @@ -309,7 +309,7 @@ The `cargo-hammerwork` crate uses **dynamic SQL queries** with `sqlx::query()` r

3. **CLI Testing Requirements**
- **Unit tests for command modules**: Each command module must have inline `#[cfg(test)]` modules
- **SQL Query Validation**: Comprehensive tests in `tests/sql_query_tests.rs` validate all dynamic SQL queries
- **SQL Query Validation**: Comprehensive tests in `cargo-hammerwork/src/integration_tests/sql_query.rs` validate all dynamic SQL queries
- **Integration tests**: Database-backed tests with `#[ignore]` attribute for optional execution
- **CLI argument parsing tests**: Validate clap command structure and argument validation
- **Configuration loading tests**: Test config file loading, environment variable precedence
Expand Down
1 change: 1 addition & 0 deletions cargo-hammerwork/src/commands/workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ impl WorkflowCommand {
Ok(())
}

#[cfg(test)]
pub fn print_json_graph(&self, jobs: &[JobNode]) -> Result<()> {
println!("{}", render_json_graph(jobs)?);
Ok(())
Expand Down
18 changes: 10 additions & 8 deletions cargo-hammerwork/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//!
//! ## Loading Configuration
//!
//! ```rust,no_run
//! ```rust,ignore
//! use cargo_hammerwork::config::Config;
//!
//! // Load configuration from file and environment
Expand All @@ -35,7 +35,7 @@
//!
//! ## Creating and Saving Configuration
//!
//! ```rust,no_run
//! ```rust,ignore
//! use cargo_hammerwork::config::Config;
//!
//! // Create a new configuration with custom values
Expand All @@ -51,7 +51,7 @@
//!
//! ## Environment Variable Override
//!
//! ```rust,no_run
//! ```rust,ignore
//! use std::env;
//! use cargo_hammerwork::config::Config;
//!
Expand Down Expand Up @@ -107,7 +107,7 @@ use std::path::{Path, PathBuf};
///
/// # Examples
///
/// ```rust
/// ```rust,ignore
/// use cargo_hammerwork::config::Config;
///
/// // Create configuration with defaults
Expand Down Expand Up @@ -191,17 +191,18 @@ impl Config {
///
/// # Examples
///
/// ```rust,no_run
/// ```rust,ignore
/// use cargo_hammerwork::config::Config;
///
/// let config = Config::load().expect("Failed to load configuration");
/// println!("Database URL: {:?}", config.database_url);
/// ```
#[cfg(test)]
pub fn load() -> Result<Self> {
Self::load_with(|key| env::var(key).ok())
}

/// [`Config::load`] reading environment variables through `get`.
/// `Config::load` reading environment variables through `get`.
///
/// A missing config file means defaults; a file that exists but cannot be read or parsed
/// is an error, so a typo in `config.toml` is reported instead of silently ignored.
Expand All @@ -212,7 +213,7 @@ impl Config {
Ok(config)
}

/// [`Config::load`], or, when the config file cannot be read or parsed, the defaults
/// `Config::load`, or, when the config file cannot be read or parsed, the defaults
/// with the environment variables applied, together with the error. A broken
/// `config.toml` must not also drop `DATABASE_URL` and the `HAMMERWORK_*` variables,
/// which take precedence over the file.
Expand Down Expand Up @@ -316,13 +317,14 @@ impl Config {
///
/// # Examples
///
/// ```rust,no_run
/// ```rust,ignore
/// use cargo_hammerwork::config::Config;
///
/// let mut config = Config::default();
/// config.database_url = Some("postgresql://localhost/hammerwork".to_string());
/// config.save().expect("Failed to save configuration");
/// ```
#[cfg(test)]
pub fn save(&self) -> Result<()> {
self.save_to(&Self::config_file_path()?)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cargo_hammerwork::commands::workflow::{JobNode, WorkflowCommand};
use crate::commands::workflow::{JobNode, WorkflowCommand};

/// Create a simple workflow command for testing output formats
fn create_test_command() -> WorkflowCommand {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
//! they fail if a command writes statuses the library does not recognise.
//!
//! Run with `DATABASE_URL` (Postgres) / `MYSQL_DATABASE_URL` (MySQL) pointing at a
//! migrated database: `cargo test -p cargo-hammerwork --test job_state_tests -- --ignored`.
//! migrated database: `cargo test -p cargo-hammerwork job_state -- --ignored`.

use cargo_hammerwork::commands::batch::BatchCommand;
use cargo_hammerwork::commands::job::JobCommand;
use cargo_hammerwork::config::Config;
use cargo_hammerwork::utils::database::{DatabasePool, JobQueueWrapper};
use crate::commands::batch::BatchCommand;
use crate::commands::job::JobCommand;
use crate::config::Config;
use crate::utils::database::{DatabasePool, JobQueueWrapper};
use hammerwork::queue::DatabaseQueue;
use hammerwork::{Job, JobId, JobStatus};
use serde_json::json;
Expand Down
7 changes: 7 additions & 0 deletions cargo-hammerwork/src/integration_tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Tests that span several command and utility modules. `cargo-hammerwork` is a binary
//! crate, so these live here instead of in `tests/`, where its internals are not visible.

mod graph_output_format;
mod job_state;
mod sql_query;
mod workflow_visualization;
Original file line number Diff line number Diff line change
Expand Up @@ -253,24 +253,24 @@ mod error_handling_tests {
#[cfg(test)]
mod builder_tests {
use super::*;
use cargo_hammerwork::commands::archive::build_archive_candidates_query;
use cargo_hammerwork::commands::backup::build_backup_query;
use cargo_hammerwork::commands::cron::build_cron_select_query;
use cargo_hammerwork::commands::job::{build_list_jobs_query, build_purge_query};
use cargo_hammerwork::commands::maintenance::{VacuumKind, build_vacuum_query};
use cargo_hammerwork::commands::monitor::{
use crate::commands::archive::build_archive_candidates_query;
use crate::commands::backup::build_backup_query;
use crate::commands::cron::build_cron_select_query;
use crate::commands::job::{build_list_jobs_query, build_purge_query};
use crate::commands::maintenance::{VacuumKind, build_vacuum_query};
use crate::commands::monitor::{
build_avg_time_query, build_recent_jobs_query, build_status_counts_query,
build_throughput_query,
};
use cargo_hammerwork::commands::queue::{
use crate::commands::queue::{
HealthMetric, build_detailed_stats_query, build_health_query, build_queue_total_query,
};
use cargo_hammerwork::commands::spawn::{
use crate::commands::spawn::{
build_pending_spawns_query, build_spawn_list_query, build_spawn_stats_breakdown_query,
build_spawn_stats_total_query,
};
use cargo_hammerwork::utils::job_ops::{JobSelector, StaleRunning};
use cargo_hammerwork::utils::sql::{Backend, Bind, FAILURE_STATUSES_SQL, bind_mysql, bind_pg};
use crate::utils::job_ops::{JobSelector, StaleRunning};
use crate::utils::sql::{Backend, Bind, FAILURE_STATUSES_SQL, bind_mysql, bind_pg};
use hammerwork::{JobPriority, JobStatus};

const HOSTILE: &str = "it's; DROP TABLE hammerwork_jobs --";
Expand Down Expand Up @@ -467,8 +467,8 @@ mod builder_tests {

#[test]
fn test_failure_statuses_include_timed_out_everywhere() {
use cargo_hammerwork::commands::monitor::{HealthCount, build_health_count_query};
use cargo_hammerwork::commands::queue::{HealthMetric, build_health_query};
use crate::commands::monitor::{HealthCount, build_health_count_query};
use crate::commands::queue::{HealthMetric, build_health_query};

for backend in [Backend::Postgres, Backend::MySql] {
let (sql, _) = build_health_query(backend, HealthMetric::RecentFailures, None);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cargo_hammerwork::commands::workflow::{JobNode, WorkflowCommand};
use crate::commands::workflow::{JobNode, WorkflowCommand};
use std::collections::{HashMap, HashSet};
use uuid::Uuid;

Expand Down Expand Up @@ -196,7 +196,7 @@ fn test_job_node_status_variations() {

#[test]
fn test_workflow_command_database_url_priority() {
use cargo_hammerwork::config::Config;
use crate::config::Config;

let config_with_url = Config {
database_url: Some("postgres://config/db".to_string()),
Expand Down
Loading
Loading