use std::collections::HashMap;
use autoschematic_core::{
connector::{Resource, ResourceAddress},
error_util::invalid_addr,
macros::FieldTypes,
util::RON,
};
use autoschematic_macros::FieldTypes;
use documented::{Documented, DocumentedFields};
use serde::{Deserialize, Serialize};
use super::addr::GitHubResourceAddress;
#[derive(Debug, Serialize, Deserialize, PartialEq, Documented, DocumentedFields, FieldTypes)]
#[serde(default, 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,
pub collaborators: HashMap<CollaboratorPrincipal, Role>,
}
impl Default for GitHubRepository {
fn default() -> Self {
Self {
description: Default::default(),
homepage: Default::default(),
topics: Default::default(),
private: true,
has_issues: true,
has_projects: true,
has_wiki: true,
allow_squash_merge: true,
allow_merge_commit: true,
allow_rebase_merge: true,
allow_auto_merge: false,
delete_branch_on_merge: false,
default_branch: "main".into(),
archived: false,
disabled: false,
collaborators: Default::default(),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Documented, DocumentedFields, FieldTypes)]
#[serde(deny_unknown_fields)]
pub struct RequiredStatusChecks {
pub strict: bool,
pub contexts: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Documented, DocumentedFields, FieldTypes)]
#[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, Documented, DocumentedFields, FieldTypes)]
#[serde(deny_unknown_fields)]
pub struct BranchRestrictions {
pub users: Vec<String>,
pub teams: Vec<String>,
pub apps: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Documented, DocumentedFields, FieldTypes)]
#[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(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Documented, DocumentedFields)]
pub enum CollaboratorPrincipal {
User(String),
Team(String),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Documented)]
pub enum Role {
Read,
Triage,
Write,
Maintain,
Admin,
Custom(String),
}
impl Role {
pub fn to_string(&self) -> String {
match self {
Role::Read => "read",
Role::Triage => "triage",
Role::Write => "write",
Role::Maintain => "maintain",
Role::Admin => "admin",
Role::Custom(s) => s,
}
.into()
}
pub fn from_str(s: &str) -> Self {
match s {
"read" => Role::Read,
"triage" => Role::Triage,
"write" => Role::Write,
"maintain" => Role::Maintain,
"admin" => Role::Admin,
s => Role::Custom(s.into()),
}
}
}
pub enum GitHubResource {
Repository(GitHubRepository),
BranchProtection(BranchProtection),
}
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()),
}
}
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)?)),
_ => Err(invalid_addr(&addr)),
}
}
}