governor-application 2.0.3

Application use cases and machine contracts for cargo-governor
Documentation
//! Ports used by application use cases.

use async_trait::async_trait;
use governor_core::domain::changelog::Changelog;
use governor_core::domain::version::SemanticVersion;
use governor_owners::{PackageOwnersConfig, WorkspaceOwnersConfig};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};

use crate::error::ApplicationResult;

/// Release workspace snapshot loaded from Cargo metadata and manifests.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReleaseWorkspace {
    /// Absolute workspace root.
    pub root: PathBuf,
    /// Human-readable workspace name.
    pub name: String,
    /// Shared workspace version.
    pub current_version: SemanticVersion,
    /// Workspace packages.
    pub packages: Vec<ReleasePackage>,
}

/// Package info needed by release orchestration.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReleasePackage {
    /// Crate name.
    pub name: String,
    /// Crate version.
    pub version: SemanticVersion,
    /// Cargo.toml path for the crate.
    pub manifest_path: PathBuf,
    /// Internal workspace dependencies.
    pub dependencies: Vec<String>,
    /// Whether the crate should be published.
    pub publish: bool,
}

/// Owners workspace snapshot loaded from Cargo metadata and package manifests.
#[derive(Debug, Clone)]
pub struct OwnersWorkspace {
    /// Absolute workspace root.
    pub root: PathBuf,
    /// Workspace-level owners config.
    pub workspace: Option<WorkspaceOwnersConfig>,
    /// Package configs.
    pub packages: Vec<OwnerPackage>,
}

/// Package owners config.
#[derive(Debug, Clone)]
pub struct OwnerPackage {
    /// Crate name.
    pub name: String,
    /// Package-level owners config.
    pub owners: Option<PackageOwnersConfig>,
}

/// Result of updating Cargo manifests.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VersionUpdate {
    /// Files touched by the update.
    pub modified_files: Vec<String>,
}

/// Result of updating changelog.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChangelogUpdate {
    /// Whether the changelog was updated.
    pub updated: bool,
    /// Changed files.
    pub modified_files: Vec<String>,
}

/// Result of running a local command.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandReport {
    /// Logical check or command name.
    pub name: String,
    /// Exit status.
    pub success: bool,
    /// Exit code when available.
    pub exit_code: Option<i32>,
    /// Captured stdout.
    pub stdout: String,
    /// Captured stderr.
    pub stderr: String,
}

/// Port for workspace inspection and mutation.
#[async_trait]
pub trait WorkspacePort: Send + Sync {
    /// Name of the adapter.
    fn name(&self) -> &str;

    /// Load workspace release metadata.
    async fn load_release_workspace(
        &self,
        workspace_path: &Path,
    ) -> ApplicationResult<ReleaseWorkspace>;

    /// Load workspace owners metadata.
    async fn load_owners_workspace(
        &self,
        workspace_path: &Path,
    ) -> ApplicationResult<OwnersWorkspace>;

    /// Update shared workspace version and optional lockfile.
    async fn update_workspace_version(
        &self,
        workspace_path: &Path,
        version: &SemanticVersion,
        dry_run: bool,
    ) -> ApplicationResult<VersionUpdate>;

    /// Update CHANGELOG.md using the target version.
    async fn update_changelog(
        &self,
        workspace_path: &Path,
        changelog: &Changelog,
        dry_run: bool,
    ) -> ApplicationResult<ChangelogUpdate>;
}

/// Port for local cargo/build checks.
#[async_trait]
pub trait CommandPort: Send + Sync {
    /// Name of the adapter.
    fn name(&self) -> &str;

    /// Run a named pre-publish check inside the workspace.
    async fn run_check(
        &self,
        workspace_path: &Path,
        check: &str,
        capture_output: bool,
    ) -> ApplicationResult<CommandReport>;
}