autoschematic-connector-github 0.9.0

An Autoschematic connector for GitHub repository management
Documentation
use autoschematic_core::{
    connector::{Resource, ResourceAddress},
    error_util::invalid_addr,
    util::RON,
};
use serde::{Deserialize, Serialize};

use super::addr::GitHubResourceAddress;

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct GitHubRepository {
    pub description: Option<String>,
    pub homepage: Option<String>,
    pub topics: Vec<String>,
    pub private: bool,
    pub has_issues: bool,
    pub has_projects: bool,
    pub has_wiki: bool,
    pub allow_squash_merge: bool,
    pub allow_merge_commit: bool,
    pub allow_rebase_merge: bool,
    pub allow_auto_merge: bool,
    pub delete_branch_on_merge: bool,
    pub default_branch: String,
    pub archived: bool,
    pub disabled: bool,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct RequiredStatusChecks {
    pub strict: bool,
    pub contexts: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PullRequestReviewEnforcement {
    pub required_approving_review_count: u32,
    pub dismiss_stale_reviews: bool,
    pub require_code_owner_reviews: bool,
    pub require_last_push_approval: bool,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct BranchRestrictions {
    pub users: Vec<String>,
    pub teams: Vec<String>,
    pub apps: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct BranchProtection {
    pub required_status_checks: Option<RequiredStatusChecks>,
    pub enforce_admins: bool,
    pub required_pull_request_reviews: Option<PullRequestReviewEnforcement>,
    pub restrictions: Option<BranchRestrictions>,
    pub required_linear_history: bool,
    pub allow_force_pushes: bool,
    pub allow_deletions: bool,
    pub block_creations: bool,
    pub required_conversation_resolution: bool,
    pub lock_branch: bool,
    pub allow_fork_syncing: bool,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct CollaboratorPermissions {
    pub pull: bool,
    pub triage: bool,
    pub push: bool,
    pub maintain: bool,
    pub admin: bool,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct Collaborator {
    pub permissions: CollaboratorPermissions,
    pub role_name: String,
}

pub enum GitHubResource {
    Repository(GitHubRepository),
    BranchProtection(BranchProtection),
    Collaborator(Collaborator),
}

impl Resource for GitHubResource {
    fn to_bytes(&self) -> Result<Vec<u8>, anyhow::Error> {
        let pretty_config = autoschematic_core::util::PrettyConfig::default().struct_names(true);
        match self {
            GitHubResource::Repository(repo) => Ok(RON.to_string_pretty(&repo, pretty_config)?.into()),
            GitHubResource::BranchProtection(protection) => Ok(RON.to_string_pretty(&protection, pretty_config)?.into()),
            GitHubResource::Collaborator(collaborator) => Ok(RON.to_string_pretty(&collaborator, pretty_config)?.into()),
        }
    }

    fn from_bytes(addr: &impl ResourceAddress, s: &[u8]) -> Result<Self, anyhow::Error>
    where
        Self: Sized,
    {
        let addr = GitHubResourceAddress::from_path(&addr.to_path_buf())?;
        let s = std::str::from_utf8(s)?;

        match addr {
            GitHubResourceAddress::Repository { .. } => Ok(GitHubResource::Repository(RON.from_str(s)?)),
            GitHubResourceAddress::BranchProtection { .. } => Ok(GitHubResource::BranchProtection(RON.from_str(s)?)),
            GitHubResourceAddress::Collaborator { .. } => Ok(GitHubResource::Collaborator(RON.from_str(s)?)),
            _ => Err(invalid_addr(&addr)),
        }
    }
}