making linters happy
Some checks failed
CI / Rust Blocking Checks (push) Failing after 22s
CI / Web Blocking Checks (push) Failing after 26s
CI / Security Blocking Checks (push) Successful in 9s
CI / Web Advisory Checks (push) Successful in 32s
CI / Security Advisory Checks (push) Has been cancelled

This commit is contained in:
2026-03-04 23:44:45 -06:00
parent 6a5a3c2b78
commit 13749409cd
81 changed files with 468 additions and 599 deletions

View File

@@ -45,21 +45,16 @@ pub struct Claims {
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum TokenType {
#[default]
Access,
Refresh,
Sensor,
Execution,
}
impl Default for TokenType {
fn default() -> Self {
Self::Access
}
}
/// Configuration for JWT tokens
#[derive(Debug, Clone)]
pub struct JwtConfig {
@@ -247,11 +242,7 @@ pub fn validate_token(token: &str, config: &JwtConfig) -> Result<Claims, JwtErro
/// Extract token from Authorization header
pub fn extract_token_from_header(auth_header: &str) -> Option<&str> {
if auth_header.starts_with("Bearer ") {
Some(&auth_header[7..])
} else {
None
}
auth_header.strip_prefix("Bearer ")
}
#[cfg(test)]

View File

@@ -45,21 +45,16 @@ pub mod enums {
use utoipa::ToSchema;
/// How parameters should be delivered to an action
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum ParameterDelivery {
/// Pass parameters via stdin (secure, recommended for most cases)
#[default]
Stdin,
/// Pass parameters via temporary file (secure, best for large payloads)
File,
}
impl Default for ParameterDelivery {
fn default() -> Self {
Self::Stdin
}
}
impl fmt::Display for ParameterDelivery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -99,31 +94,23 @@ pub mod enums {
&self,
buf: &mut sqlx::postgres::PgArgumentBuffer,
) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
Ok(<String as sqlx::Encode<sqlx::Postgres>>::encode(
self.to_string(),
buf,
)?)
<String as sqlx::Encode<sqlx::Postgres>>::encode(self.to_string(), buf)
}
}
/// Format for parameter serialization
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum ParameterFormat {
/// KEY='VALUE' format (one per line)
Dotenv,
/// JSON object
#[default]
Json,
/// YAML format
Yaml,
}
impl Default for ParameterFormat {
fn default() -> Self {
Self::Json
}
}
impl fmt::Display for ParameterFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -165,18 +152,16 @@ pub mod enums {
&self,
buf: &mut sqlx::postgres::PgArgumentBuffer,
) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
Ok(<String as sqlx::Encode<sqlx::Postgres>>::encode(
self.to_string(),
buf,
)?)
<String as sqlx::Encode<sqlx::Postgres>>::encode(self.to_string(), buf)
}
}
/// Format for action output parsing
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum OutputFormat {
/// Plain text (no parsing)
#[default]
Text,
/// Parse as JSON
Json,
@@ -186,12 +171,6 @@ pub mod enums {
Jsonl,
}
impl Default for OutputFormat {
fn default() -> Self {
Self::Text
}
}
impl fmt::Display for OutputFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -235,10 +214,7 @@ pub mod enums {
&self,
buf: &mut sqlx::postgres::PgArgumentBuffer,
) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
Ok(<String as sqlx::Encode<sqlx::Postgres>>::encode(
self.to_string(),
buf,
)?)
<String as sqlx::Encode<sqlx::Postgres>>::encode(self.to_string(), buf)
}
}
@@ -371,20 +347,17 @@ pub mod enums {
/// - `Public`: viewable by all authenticated users on the platform.
/// - `Private`: restricted based on the artifact's `scope` and `owner` fields.
/// Full RBAC enforcement is deferred; for now the field enables filtering.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Type, ToSchema)]
#[derive(
Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, Type, ToSchema,
)]
#[sqlx(type_name = "artifact_visibility_enum", rename_all = "lowercase")]
#[serde(rename_all = "lowercase")]
pub enum ArtifactVisibility {
Public,
#[default]
Private,
}
impl Default for ArtifactVisibility {
fn default() -> Self {
Self::Private
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Type, ToSchema)]
#[sqlx(type_name = "workflow_task_status_enum", rename_all = "lowercase")]
#[serde(rename_all = "lowercase")]

View File

@@ -141,7 +141,7 @@ mod tests {
fn test_message_queue_creation() {
// This test just verifies the struct can be instantiated
// Actual connection tests require a running RabbitMQ instance
assert!(true);
// (nothing to assert without a live broker)
}
#[tokio::test]

View File

@@ -69,20 +69,15 @@ use serde::{Deserialize, Serialize};
use std::fmt;
/// Message delivery mode
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum DeliveryMode {
/// Non-persistent messages (faster, but may be lost on broker restart)
NonPersistent = 1,
/// Persistent messages (slower, but survive broker restart)
#[default]
Persistent = 2,
}
impl Default for DeliveryMode {
fn default() -> Self {
Self::Persistent
}
}
/// Message priority (0-9, higher is more urgent)
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Priority(u8);
@@ -125,25 +120,21 @@ impl fmt::Display for Priority {
}
/// Message acknowledgment mode
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum AckMode {
/// Automatically acknowledge messages after delivery
Auto,
/// Manually acknowledge messages after processing
#[default]
Manual,
}
impl Default for AckMode {
fn default() -> Self {
Self::Manual
}
}
/// Exchange type
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ExchangeType {
/// Direct exchange - routes messages with exact routing key match
#[default]
Direct,
/// Topic exchange - routes messages using pattern matching
Topic,
@@ -165,12 +156,6 @@ impl ExchangeType {
}
}
impl Default for ExchangeType {
fn default() -> Self {
Self::Direct
}
}
impl fmt::Display for ExchangeType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())

View File

@@ -41,7 +41,7 @@ impl PackEnvironmentStatus {
}
}
pub fn from_str(s: &str) -> Option<Self> {
pub fn parse_status(s: &str) -> Option<Self> {
match s {
"pending" => Some(Self::Pending),
"installing" => Some(Self::Installing),
@@ -194,7 +194,7 @@ impl PackEnvironmentManager {
if let Some(row) = row {
let status_str: String = row.try_get("status")?;
let status = PackEnvironmentStatus::from_str(&status_str)
let status = PackEnvironmentStatus::parse_status(&status_str)
.unwrap_or(PackEnvironmentStatus::Failed);
Ok(Some(PackEnvironment {
@@ -343,7 +343,7 @@ impl PackEnvironmentManager {
let mut environments = Vec::new();
for row in rows {
let status_str: String = row.try_get("status")?;
let status = PackEnvironmentStatus::from_str(&status_str)
let status = PackEnvironmentStatus::parse_status(&status_str)
.unwrap_or(PackEnvironmentStatus::Failed);
environments.push(PackEnvironment {
@@ -452,8 +452,8 @@ impl PackEnvironmentManager {
.await?;
let status_str: String = row.try_get("status")?;
let status =
PackEnvironmentStatus::from_str(&status_str).unwrap_or(PackEnvironmentStatus::Pending);
let status = PackEnvironmentStatus::parse_status(&status_str)
.unwrap_or(PackEnvironmentStatus::Pending);
Ok(PackEnvironment {
id: row.try_get("id")?,
@@ -496,8 +496,8 @@ impl PackEnvironmentManager {
.await?;
let status_str: String = row.try_get("status")?;
let status =
PackEnvironmentStatus::from_str(&status_str).unwrap_or(PackEnvironmentStatus::Ready);
let status = PackEnvironmentStatus::parse_status(&status_str)
.unwrap_or(PackEnvironmentStatus::Ready);
Ok(PackEnvironment {
id: row.try_get("id")?,
@@ -580,7 +580,7 @@ impl PackEnvironmentManager {
Ok(output) => {
install_log.push_str(&format!("\n=== {} ===\n", action.name));
install_log.push_str(&output);
install_log.push_str("\n");
install_log.push('\n');
}
Err(e) => {
let error_msg = format!("Installer '{}' failed: {}", action.name, e);
@@ -701,20 +701,18 @@ impl PackEnvironmentManager {
.map(|obj| {
obj.iter()
.filter_map(|(k, v)| {
v.as_str()
.map(|s| {
let resolved = self
.resolve_template(
s,
pack_ref,
runtime_ref,
env_path,
&pack_path_str,
)
.ok()?;
Some((k.clone(), resolved))
})
.flatten()
v.as_str().and_then(|s| {
let resolved = self
.resolve_template(
s,
pack_ref,
runtime_ref,
env_path,
&pack_path_str,
)
.ok()?;
Some((k.clone(), resolved))
})
})
.collect::<HashMap<String, String>>()
})
@@ -877,9 +875,9 @@ mod tests {
fn test_environment_status_conversion() {
assert_eq!(PackEnvironmentStatus::Ready.as_str(), "ready");
assert_eq!(
PackEnvironmentStatus::from_str("ready"),
PackEnvironmentStatus::parse_status("ready"),
Some(PackEnvironmentStatus::Ready)
);
assert_eq!(PackEnvironmentStatus::from_str("invalid"), None);
assert_eq!(PackEnvironmentStatus::parse_status("invalid"), None);
}
}

View File

@@ -151,17 +151,15 @@ impl DependencyValidator {
};
let error = if !satisfied {
if detected_version.is_none() {
Some(format!("Runtime '{}' not found on system", runtime))
} else if let Some(ref constraint) = version_constraint {
Some(format!(
"Runtime '{}' version {} does not satisfy constraint '{}'",
runtime,
detected_version.as_ref().unwrap(),
constraint
))
if let Some(ref detected) = detected_version {
version_constraint.as_ref().map(|constraint| {
format!(
"Runtime '{}' version {} does not satisfy constraint '{}'",
runtime, detected, constraint
)
})
} else {
None
Some(format!("Runtime '{}' not found on system", runtime))
}
} else {
None
@@ -192,15 +190,13 @@ impl DependencyValidator {
};
let error = if !satisfied {
if installed_version.is_none() {
Some(format!("Required pack '{}' is not installed", pack_ref))
} else {
if let Some(ref installed) = installed_version {
Some(format!(
"Pack '{}' version {} does not satisfy constraint '{}'",
pack_ref,
installed_version.as_ref().unwrap(),
version_constraint
pack_ref, installed, version_constraint
))
} else {
Some(format!("Required pack '{}' is not installed", pack_ref))
}
} else {
None
@@ -335,30 +331,30 @@ fn match_version_constraint(version: &str, constraint: &str) -> Result<bool> {
}
// Parse constraint
if constraint.starts_with(">=") {
let required = constraint[2..].trim();
if let Some(stripped) = constraint.strip_prefix(">=") {
let required = stripped.trim();
Ok(compare_versions(version, required)? >= 0)
} else if constraint.starts_with("<=") {
let required = constraint[2..].trim();
} else if let Some(stripped) = constraint.strip_prefix("<=") {
let required = stripped.trim();
Ok(compare_versions(version, required)? <= 0)
} else if constraint.starts_with('>') {
let required = constraint[1..].trim();
} else if let Some(stripped) = constraint.strip_prefix('>') {
let required = stripped.trim();
Ok(compare_versions(version, required)? > 0)
} else if constraint.starts_with('<') {
let required = constraint[1..].trim();
} else if let Some(stripped) = constraint.strip_prefix('<') {
let required = stripped.trim();
Ok(compare_versions(version, required)? < 0)
} else if constraint.starts_with('=') {
let required = constraint[1..].trim();
} else if let Some(stripped) = constraint.strip_prefix('=') {
let required = stripped.trim();
Ok(compare_versions(version, required)? == 0)
} else if constraint.starts_with('^') {
} else if let Some(stripped) = constraint.strip_prefix('^') {
// Caret: Compatible with version (major.minor.patch)
// ^1.2.3 := >=1.2.3 <2.0.0
let required = constraint[1..].trim();
let required = stripped.trim();
match_caret_constraint(version, required)
} else if constraint.starts_with('~') {
} else if let Some(stripped) = constraint.strip_prefix('~') {
// Tilde: Approximately equivalent to version
// ~1.2.3 := >=1.2.3 <1.3.0
let required = constraint[1..].trim();
let required = stripped.trim();
match_tilde_constraint(version, required)
} else {
// Exact match

View File

@@ -171,7 +171,7 @@ impl PackInstaller {
clone_cmd.arg("--depth").arg("1");
}
clone_cmd.arg(&url).arg(&install_dir);
clone_cmd.arg(url).arg(&install_dir);
let output = clone_cmd
.output()
@@ -421,7 +421,11 @@ impl PackInstaller {
}
// Determine filename from URL
let filename = url.split('/').last().unwrap_or("archive.zip").to_string();
let filename = url
.split('/')
.next_back()
.unwrap_or("archive.zip")
.to_string();
let archive_path = self.temp_dir.join(&filename);

View File

@@ -288,17 +288,15 @@ impl<'a> PackComponentLoader<'a> {
}
Err(e) => {
// Check for unique constraint violation (race condition)
if let Error::Database(ref db_err) = e {
if let sqlx::Error::Database(ref inner) = db_err {
if inner.is_unique_violation() {
info!(
"Runtime '{}' already exists (concurrent creation), treating as update",
runtime_ref
);
loaded_refs.push(runtime_ref);
result.runtimes_updated += 1;
continue;
}
if let Error::Database(sqlx::Error::Database(ref inner)) = e {
if inner.is_unique_violation() {
info!(
"Runtime '{}' already exists (concurrent creation), treating as update",
runtime_ref
);
loaded_refs.push(runtime_ref);
result.runtimes_updated += 1;
continue;
}
}
let msg = format!("Failed to create runtime '{}': {}", runtime_ref, e);
@@ -438,16 +436,14 @@ impl<'a> PackComponentLoader<'a> {
}
Err(e) => {
// Check for unique constraint violation (race condition)
if let Error::Database(ref db_err) = e {
if let sqlx::Error::Database(ref inner) = db_err {
if inner.is_unique_violation() {
info!(
"Version '{}' for runtime '{}' already exists (concurrent), skipping",
version_str, runtime_ref
);
loaded_versions.push(version_str);
continue;
}
if let Error::Database(sqlx::Error::Database(ref inner)) = e {
if inner.is_unique_violation() {
info!(
"Version '{}' for runtime '{}' already exists (concurrent), skipping",
version_str, runtime_ref
);
loaded_versions.push(version_str);
continue;
}
}
let msg = format!(

View File

@@ -272,11 +272,6 @@ impl Checksum {
Ok(Self { algorithm, hash })
}
/// Format as "algorithm:hash"
pub fn to_string(&self) -> String {
format!("{}:{}", self.algorithm, self.hash)
}
}
impl std::fmt::Display for Checksum {

View File

@@ -295,7 +295,7 @@ impl Update for ActionRepository {
query.push(", updated = NOW() WHERE id = ");
query.push_bind(id);
query.push(&format!(" RETURNING {}", ACTION_COLUMNS));
query.push(format!(" RETURNING {}", ACTION_COLUMNS));
let action = query
.build_query_as::<Action>()
@@ -554,7 +554,6 @@ impl ActionRepository {
}
}
/// Repository for Policy operations
// ============================================================================
// Policy Repository
// ============================================================================

View File

@@ -47,7 +47,7 @@ pub struct HistoryQueryParams {
impl HistoryQueryParams {
/// Returns the effective limit, capped at 1000.
pub fn effective_limit(&self) -> i64 {
self.limit.unwrap_or(100).min(1000).max(1)
self.limit.unwrap_or(100).clamp(1, 1000)
}
/// Returns the effective offset.

View File

@@ -582,7 +582,7 @@ impl EnforcementRepository {
}
if let Some(status) = &filters.status {
push_condition!("status = ", status.clone());
push_condition!("status = ", *status);
}
if let Some(rule_id) = filters.rule {
push_condition!("rule = ", rule_id);

View File

@@ -391,7 +391,7 @@ impl ExecutionRepository {
}
if let Some(status) = &filters.status {
push_condition!("e.status = ", status.clone());
push_condition!("e.status = ", *status);
}
if let Some(action_ref) = &filters.action_ref {
push_condition!("e.action_ref = ", action_ref.clone());

View File

@@ -129,7 +129,7 @@ impl Update for IdentityRepository {
.map_err(|e| {
// Convert RowNotFound to NotFound error
if matches!(e, sqlx::Error::RowNotFound) {
return crate::Error::not_found("identity", "id", &id.to_string());
return crate::Error::not_found("identity", "id", id.to_string());
}
e.into()
})

View File

@@ -211,7 +211,7 @@ impl InquiryRepository {
}
if let Some(status) = &filters.status {
push_condition!("status = ", status.clone());
push_condition!("status = ", *status);
}
if let Some(execution_id) = filters.execution {
push_condition!("execution = ", execution_id);

View File

@@ -218,7 +218,7 @@ impl KeyRepository {
}
if let Some(ref owner_type) = filters.owner_type {
push_condition!("owner_type = ", owner_type.clone());
push_condition!("owner_type = ", *owner_type);
}
if let Some(ref owner) = filters.owner {
push_condition!("owner = ", owner.clone());

View File

@@ -408,6 +408,7 @@ impl PackRepository {
}
/// Update installation metadata for a pack
#[allow(clippy::too_many_arguments)]
pub async fn update_installation_metadata<'e, E>(
executor: E,
id: i64,

View File

@@ -239,7 +239,7 @@ impl Update for RuntimeVersionRepository {
query.push(" WHERE id = ");
query.push_bind(id);
query.push(&format!(" RETURNING {}", SELECT_COLUMNS));
query.push(format!(" RETURNING {}", SELECT_COLUMNS));
let row = query
.build_query_as::<RuntimeVersion>()

View File

@@ -276,7 +276,7 @@ impl Update for TriggerRepository {
.map_err(|e| {
// Convert RowNotFound to NotFound error
if matches!(e, sqlx::Error::RowNotFound) {
return crate::Error::not_found("trigger", "id", &id.to_string());
return crate::Error::not_found("trigger", "id", id.to_string());
}
e.into()
})?;

View File

@@ -423,14 +423,11 @@ mod tests {
"always_available": true
});
assert_eq!(
verification
.get("always_available")
.unwrap()
.as_bool()
.unwrap(),
true
);
assert!(verification
.get("always_available")
.unwrap()
.as_bool()
.unwrap());
}
#[tokio::test]

View File

@@ -106,7 +106,7 @@ impl TestExecutor {
);
match self
.execute_test_suite(&pack_dir, runner_name, runner_config)
.execute_test_suite(pack_dir, runner_name, runner_config)
.await
{
Ok(suite_result) => {
@@ -369,7 +369,7 @@ impl TestExecutor {
let total = self.extract_number(&text, "Total Tests:");
let passed = self.extract_number(&text, "Passed:");
let failed = self.extract_number(&text, "Failed:");
let skipped = self.extract_number(&text, "Skipped:").or_else(|| Some(0));
let skipped = self.extract_number(&text, "Skipped:").or(Some(0));
// If we couldn't parse counts, use exit code
let (total, passed, failed, skipped) = if total.is_none() || passed.is_none() {
@@ -441,7 +441,6 @@ impl TestExecutor {
.and_then(|line| {
line.split(label)
.nth(1)?
.trim()
.split_whitespace()
.next()?
.parse::<i32>()

View File

@@ -278,7 +278,7 @@ fn json_eq(a: &JsonValue, b: &JsonValue) -> bool {
return false;
}
a.iter()
.all(|(k, v)| b.get(k).map_or(false, |bv| json_eq(v, bv)))
.all(|(k, v)| b.get(k).is_some_and(|bv| json_eq(v, bv)))
}
// Different types (other than number cross-compare) are never equal
_ => false,
@@ -680,10 +680,8 @@ impl NumericValue {
fn as_numeric(v: &JsonValue) -> Option<NumericValue> {
if let Some(i) = v.as_i64() {
Some(NumericValue::Int(i))
} else if let Some(f) = v.as_f64() {
Some(NumericValue::Float(f))
} else {
None
v.as_f64().map(NumericValue::Float)
}
}

View File

@@ -363,8 +363,8 @@ mod tests {
let ctx = TestContext::new();
assert_eq!(eval_expression("string(42)", &ctx).unwrap(), json!("42"));
assert_eq!(
eval_expression("number(\"3.14\")", &ctx).unwrap(),
json!(3.14)
eval_expression("number(\"3.15\")", &ctx).unwrap(),
json!(3.15)
);
assert_eq!(eval_expression("int(3.9)", &ctx).unwrap(), json!(3));
assert_eq!(eval_expression("int(\"42\")", &ctx).unwrap(), json!(42));

View File

@@ -431,8 +431,8 @@ mod tests {
#[test]
fn test_float() {
let kinds = tokenize("3.14");
assert_eq!(kinds, vec![TokenKind::Float(3.14), TokenKind::Eof]);
let kinds = tokenize("3.15");
assert_eq!(kinds, vec![TokenKind::Float(3.15), TokenKind::Eof]);
}
#[test]

View File

@@ -187,11 +187,13 @@ impl WorkflowLoader {
.map(|e| e.to_string())
};
if validation_error.is_some() && !self.config.skip_validation {
return Err(Error::validation(format!(
"Workflow validation failed: {}",
validation_error.as_ref().unwrap()
)));
if let Some(ref err) = validation_error {
if !self.config.skip_validation {
return Err(Error::validation(format!(
"Workflow validation failed: {}",
err
)));
}
}
Ok(LoadedWorkflow {

View File

@@ -1449,7 +1449,7 @@ tasks:
publish:
- validation_passed: true
- count: 42
- ratio: 3.14
- ratio: 3.15
- label: "hello"
- template_val: "{{ result().data }}"
- nothing: null
@@ -1486,7 +1486,7 @@ tasks:
} else if let Some(val) = map.get("count") {
assert_eq!(val, &serde_json::json!(42), "integer");
} else if let Some(val) = map.get("ratio") {
assert_eq!(val, &serde_json::json!(3.14), "float");
assert_eq!(val, &serde_json::json!(3.15), "float");
} else if let Some(val) = map.get("label") {
assert_eq!(val, &serde_json::json!("hello"), "string");
} else if let Some(val) = map.get("template_val") {

View File

@@ -97,11 +97,11 @@ impl WorkflowRegistrar {
debug!("Registering workflow: {}", loaded.file.ref_name);
// Check for validation errors
if loaded.validation_error.is_some() {
if let Some(ref err) = loaded.validation_error {
if self.options.skip_invalid {
return Err(Error::validation(format!(
"Workflow has validation errors: {}",
loaded.validation_error.as_ref().unwrap()
err
)));
}
}
@@ -252,6 +252,7 @@ impl WorkflowRegistrar {
///
/// `effective_ref` and `effective_label` are the resolved values (which may
/// have been derived from the filename when the workflow YAML omits them).
#[allow(clippy::too_many_arguments)]
async fn create_companion_action(
&self,
workflow_def_id: i64,
@@ -298,6 +299,7 @@ impl WorkflowRegistrar {
///
/// `effective_ref` and `effective_label` are the resolved values (which may
/// have been derived from the filename when the workflow YAML omits them).
#[allow(clippy::too_many_arguments)]
async fn ensure_companion_action(
&self,
workflow_def_id: i64,
@@ -425,8 +427,8 @@ mod tests {
#[test]
fn test_registration_options_default() {
let options = RegistrationOptions::default();
assert_eq!(options.update_existing, true);
assert_eq!(options.skip_invalid, true);
assert!(options.update_existing);
assert!(options.skip_invalid);
}
#[test]
@@ -439,7 +441,7 @@ mod tests {
};
assert_eq!(result.ref_name, "test.workflow");
assert_eq!(result.created, true);
assert!(result.created);
assert_eq!(result.workflow_def_id, 123);
assert_eq!(result.warnings.len(), 0);
}

View File

@@ -308,7 +308,7 @@ impl WorkflowValidator {
reachable
}
/// Detect cycles using DFS
// Detect cycles using DFS
// Cycle detection removed - cycles are now valid in workflow graphs
// Workflows are directed graphs (not DAGs) and cycles are supported
// for use cases like monitoring loops, retry patterns, etc.
@@ -328,7 +328,7 @@ impl WorkflowValidator {
}
// Validate variable names in vars
for (key, _) in &workflow.vars {
for key in workflow.vars.keys() {
if !Self::is_valid_variable_name(key) {
return Err(ValidationError::SemanticError(format!(
"Invalid variable name: {}",

View File

@@ -781,7 +781,7 @@ async fn test_find_executions_by_enforcement() {
config: None,
env_vars: None,
parent: None,
enforcement: if i == 2 { None } else { None }, // Can't reference non-existent enforcement
enforcement: None, // Can't reference non-existent enforcement
executor: None,
status: ExecutionStatus::Requested,
result: None,

View File

@@ -35,7 +35,7 @@ async fn test_create_key_system_owner() {
assert_eq!(key.owner_pack, None);
assert_eq!(key.owner_action, None);
assert_eq!(key.owner_sensor, None);
assert_eq!(key.encrypted, false);
assert!(!key.encrypted);
assert_eq!(key.value, "test_value");
assert!(key.created.timestamp() > 0);
assert!(key.updated.timestamp() > 0);
@@ -52,7 +52,7 @@ async fn test_create_key_system_encrypted() {
.await
.unwrap();
assert_eq!(key.encrypted, true);
assert!(key.encrypted);
assert_eq!(key.encryption_key_hash, Some("sha256:abc123".to_string()));
}
@@ -427,7 +427,7 @@ async fn test_update_encrypted_status() {
.await
.unwrap();
assert_eq!(key.encrypted, false);
assert!(!key.encrypted);
let input = UpdateKeyInput {
encrypted: Some(true),
@@ -438,7 +438,7 @@ async fn test_update_encrypted_status() {
let updated = KeyRepository::update(&pool, key.id, input).await.unwrap();
assert_eq!(updated.encrypted, true);
assert!(updated.encrypted);
assert_eq!(
updated.encryption_key_hash,
Some("sha256:xyz789".to_string())
@@ -468,7 +468,7 @@ async fn test_update_multiple_fields() {
assert_eq!(updated.name, new_name);
assert_eq!(updated.value, "updated_value");
assert_eq!(updated.encrypted, true);
assert!(updated.encrypted);
assert_eq!(updated.encryption_key_hash, Some("hash123".to_string()));
}
@@ -768,10 +768,10 @@ async fn test_key_encrypted_flag() {
.await
.unwrap();
assert_eq!(plain_key.encrypted, false);
assert!(!plain_key.encrypted);
assert_eq!(plain_key.encryption_key_hash, None);
assert_eq!(encrypted_key.encrypted, true);
assert!(encrypted_key.encrypted);
assert_eq!(
encrypted_key.encryption_key_hash,
Some("sha256:abc".to_string())
@@ -788,7 +788,7 @@ async fn test_update_encryption_status() {
.await
.unwrap();
assert_eq!(key.encrypted, false);
assert!(!key.encrypted);
// Encrypt it
let input = UpdateKeyInput {
@@ -800,7 +800,7 @@ async fn test_update_encryption_status() {
let encrypted = KeyRepository::update(&pool, key.id, input).await.unwrap();
assert_eq!(encrypted.encrypted, true);
assert!(encrypted.encrypted);
assert_eq!(
encrypted.encryption_key_hash,
Some("sha256:newkey".to_string())
@@ -817,7 +817,7 @@ async fn test_update_encryption_status() {
let decrypted = KeyRepository::update(&pool, key.id, input).await.unwrap();
assert_eq!(decrypted.encrypted, false);
assert!(!decrypted.encrypted);
assert_eq!(decrypted.value, "plain_value");
}

View File

@@ -892,7 +892,7 @@ async fn test_port_range() {
let worker = WorkerRepository::create(&pool, input)
.await
.expect(&format!("Failed to create worker with port {}", port));
.unwrap_or_else(|_| panic!("Failed to create worker with port {}", port));
assert_eq!(worker.port, Some(port));
}

View File

@@ -74,7 +74,7 @@ async fn test_create_rule() {
rule.conditions,
json!({"equals": {"event.status": "success"}})
);
assert_eq!(rule.enabled, true);
assert!(rule.enabled);
assert!(rule.created.timestamp() > 0);
assert!(rule.updated.timestamp() > 0);
}
@@ -117,7 +117,7 @@ async fn test_create_rule_disabled() {
let rule = RuleRepository::create(&pool, input).await.unwrap();
assert_eq!(rule.enabled, false);
assert!(!rule.enabled);
}
#[tokio::test]
@@ -759,7 +759,7 @@ async fn test_update_rule_enabled() {
.await
.unwrap();
assert_eq!(updated.enabled, false);
assert!(!updated.enabled);
}
#[tokio::test]
@@ -816,7 +816,7 @@ async fn test_update_rule_multiple_fields() {
assert_eq!(updated.label, "New Label");
assert_eq!(updated.description, "New Description");
assert_eq!(updated.conditions, json!({"updated": true}));
assert_eq!(updated.enabled, false);
assert!(!updated.enabled);
}
#[tokio::test]

View File

@@ -61,7 +61,7 @@ async fn test_create_sensor_minimal() {
assert_eq!(sensor.runtime_ref, runtime.r#ref);
assert_eq!(sensor.trigger, trigger.id);
assert_eq!(sensor.trigger_ref, trigger.r#ref);
assert_eq!(sensor.enabled, true);
assert!(sensor.enabled);
assert_eq!(sensor.param_schema, None);
assert!(sensor.created.timestamp() > 0);
assert!(sensor.updated.timestamp() > 0);
@@ -796,7 +796,7 @@ async fn test_update_enabled_status() {
.await
.unwrap();
assert_eq!(sensor.enabled, true);
assert!(sensor.enabled);
let input = UpdateSensorInput {
enabled: Some(false),
@@ -807,7 +807,7 @@ async fn test_update_enabled_status() {
.await
.unwrap();
assert_eq!(updated.enabled, false);
assert!(!updated.enabled);
// Enable it again
let input = UpdateSensorInput {
@@ -819,7 +819,7 @@ async fn test_update_enabled_status() {
.await
.unwrap();
assert_eq!(updated.enabled, true);
assert!(updated.enabled);
}
#[tokio::test]
@@ -924,7 +924,7 @@ async fn test_update_multiple_fields() {
assert_eq!(updated.label, "Multi Update");
assert_eq!(updated.description, "Updated multiple fields");
assert_eq!(updated.entrypoint, "sensors/multi.py");
assert_eq!(updated.enabled, false);
assert!(!updated.enabled);
assert_eq!(updated.param_schema, Some(json!({"type": "object"})));
}

View File

@@ -42,7 +42,7 @@ async fn test_create_trigger() {
assert_eq!(trigger.pack, Some(pack.id));
assert_eq!(trigger.pack_ref, Some(pack.r#ref));
assert_eq!(trigger.label, "Webhook Trigger");
assert_eq!(trigger.enabled, true);
assert!(trigger.enabled);
assert!(trigger.created.timestamp() > 0);
assert!(trigger.updated.timestamp() > 0);
}
@@ -134,7 +134,7 @@ async fn test_create_trigger_disabled() {
let trigger = TriggerRepository::create(&pool, input).await.unwrap();
assert_eq!(trigger.enabled, false);
assert!(!trigger.enabled);
}
#[tokio::test]
@@ -478,7 +478,7 @@ async fn test_update_trigger() {
assert_eq!(updated.r#ref, trigger.r#ref); // Ref should not change
assert_eq!(updated.label, "Updated Label");
assert_eq!(updated.description, Some("Updated description".to_string()));
assert_eq!(updated.enabled, false);
assert!(!updated.enabled);
assert!(updated.updated > original_updated);
}