use crate::types::Id;
use coodev_runner::{
GithubAuthorization, GlobalSecret, OrganizationSecret, RepositorySecret, Secret, Volume,
Workflow, WorkflowEvent, WorkflowMessage,
};
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use std::fs;
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
#[builder(setter(into), field(public))]
pub struct RunWorkflowConfig {
pub id: Id,
pub workflow: Workflow,
pub event: WorkflowEvent,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CancelWorkflowRun {
pub id: Id,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RegisterRunner {
pub id: Id,
pub name: String,
pub version: String,
pub max_runs: u64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum RunnerConfigScope {
Repository(String),
Organization(String),
Global,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RunnerVolume {
pub key: String,
pub content: String,
pub scope: RunnerConfigScope,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RunnerSecret {
pub key: String,
pub value: String,
pub scope: RunnerConfigScope,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RunnerConfig {
pub github_authorization: GithubAuthorization,
pub volumes: Vec<RunnerVolume>,
pub secrets: Vec<RunnerSecret>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum Message {
RegisterRunner(RegisterRunner),
WorkflowMessage(WorkflowMessage),
RunWorkflow(RunWorkflowConfig),
CancelWorkflowRun(CancelWorkflowRun),
RunnerConfig(RunnerConfig),
}
impl Into<Secret> for RunnerSecret {
fn into(self) -> Secret {
match self.scope {
RunnerConfigScope::Repository(repo) => Secret::Repository(RepositorySecret {
key: self.key,
value: self.value,
repository: repo,
}),
RunnerConfigScope::Organization(org) => Secret::Organization(OrganizationSecret {
key: self.key,
value: self.value,
organization: org,
}),
RunnerConfigScope::Global => Secret::Global(GlobalSecret {
key: self.key,
value: self.value,
}),
}
}
}
impl From<Secret> for RunnerSecret {
fn from(secret: Secret) -> Self {
match secret {
Secret::Global(secret) => RunnerSecret {
key: secret.key,
value: secret.value,
scope: RunnerConfigScope::Global,
},
Secret::Repository(secret) => RunnerSecret {
key: secret.key,
value: secret.value,
scope: RunnerConfigScope::Repository(secret.repository),
},
Secret::Organization(secret) => RunnerSecret {
key: secret.key,
value: secret.value,
scope: RunnerConfigScope::Organization(secret.organization),
},
}
}
}
impl TryFrom<Volume> for RunnerVolume {
type Error = anyhow::Error;
fn try_from(volume: Volume) -> Result<Self, Self::Error> {
match volume {
Volume::Global(volume) => {
let content = fs::read_to_string(&volume.path)?;
Ok(RunnerVolume {
key: volume.key,
content,
scope: RunnerConfigScope::Global,
})
}
Volume::Repository(volume) => {
let content = fs::read_to_string(&volume.path)?;
Ok(RunnerVolume {
key: volume.key,
content,
scope: RunnerConfigScope::Repository(volume.repository),
})
}
Volume::Organization(volume) => {
let content = fs::read_to_string(&volume.path)?;
Ok(RunnerVolume {
key: volume.key,
content,
scope: RunnerConfigScope::Organization(volume.organization),
})
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_workflow_event() {
let volume = RunnerVolume {
key: "test".into(),
content: "test".into(),
scope: RunnerConfigScope::Global,
};
let repo_secret = RunnerSecret {
key: "test".into(),
value: "test".into(),
scope: RunnerConfigScope::Repository("owner/name".into()),
};
let org_secret = RunnerSecret {
key: "test".into(),
value: "test".into(),
scope: RunnerConfigScope::Organization("owner".into()),
};
let msg = Message::RunnerConfig(RunnerConfig {
github_authorization: GithubAuthorization::PersonalAccessToken("test".into()),
volumes: vec![volume.clone()],
secrets: vec![repo_secret.clone(), org_secret.clone()],
});
let json = serde_json::to_string(&msg).unwrap();
println!("{}", json);
let msg2: Message = serde_json::from_str(&json).unwrap();
println!("{:?}", msg2);
}
#[test]
fn convert_secret_to_runner_secret() {
let secret = Secret::Repository(RepositorySecret {
key: "test".into(),
value: "test".into(),
repository: "owner/name".into(),
});
let runner_secret: RunnerSecret = secret.clone().into();
let secret2: Secret = runner_secret.into();
assert_eq!(secret, secret2);
}
}