| |
use super::*;
|
| |
|
| |
/// Trigger a CI run.
|
| - |
#[derive(Parser)]
|
| + |
#[derive(Debug, Parser)]
|
| |
pub struct TriggerCmd {
|
| |
/// Set the node where the node originated from.
|
| |
#[clap(long)]
|
| |
node: Option<NodeId>,
|
| |
|
| + |
/// Trigger CI to run for all repositories on the local node.
|
| + |
#[clap(long, required_unless_present_any = ["patch","commit"])]
|
| + |
all: bool,
|
| + |
|
| |
/// Set the repository the event refers to. Can be a RID, or the
|
| |
/// repository name.
|
| - |
#[clap(long)]
|
| - |
repo: String,
|
| + |
#[clap(long, required_unless_present = "all")]
|
| + |
repo: Option<String>,
|
| |
|
| |
/// Set the name of the ref the event refers to.
|
| |
#[clap(long = "ref", aliases = ["name"], default_value = "main")]
|
| |
/// Set the commit the event refers to. Can be the SHA1 commit id,
|
| |
/// or a symbolic Git revision, as understood by `git rev-parse`.
|
| |
/// For example, `HEAD`.
|
| - |
#[clap(long, required_unless_present = "patch")]
|
| + |
#[clap(long, required_unless_present_any = ["patch","all"])]
|
| |
commit: Option<String>,
|
| |
|
| |
/// Trigger CI to run on this patch.
|
| - |
#[clap(long, required_unless_present = "commit")]
|
| + |
#[clap(long, required_unless_present_any = ["commit","all"])]
|
| |
patch: Option<PatchId>,
|
| |
|
| |
/// Write the event ID to this file, after adding the event to the
|
| |
|
| |
/// Output the event to trigger a CI run to the standard output,
|
| |
/// instead of adding to the event queue in the database.
|
| - |
#[clap(long)]
|
| + |
#[clap(long, conflicts_with = "all")]
|
| |
stdout: bool,
|
| |
|
| |
/// Output the event to trigger a CI run to a named file, instead
|
| |
/// of adding to the event queue in the database.
|
| - |
#[clap(long)]
|
| + |
#[clap(long, conflicts_with = "all")]
|
| |
output: Option<PathBuf>,
|
| |
}
|
| |
|
| |
impl Leaf for TriggerCmd {
|
| |
fn run(&self, args: &Args) -> Result<(), CibToolError> {
|
| |
let r = ergo::Radicle::new().map_err(TriggerError::Ergonomic)?;
|
| - |
|
| - |
let profile = r.profile();
|
| - |
let nid = self.node.unwrap_or(*profile.id());
|
| - |
let repo = r
|
| - |
.repository_by_name(&self.repo)
|
| - |
.map_err(TriggerError::Ergonomic)?;
|
| - |
|
| - |
let oid = self.oid(&r, &repo)?;
|
| - |
|
| - |
let base = r
|
| - |
.resolve_commit(&repo.id, &format!("{oid}^"))
|
| - |
.unwrap_or(oid);
|
| - |
|
| - |
let branch_name = self.branch(&r, &repo)?;
|
| - |
|
| - |
let event = CiEvent::branch_updated(nid, repo.id, &branch_name, oid, base)
|
| - |
.map_err(CibToolError::CiEvent)?;
|
| - |
|
| - |
if self.stdout {
|
| - |
let json = event.to_pretty_json().map_err(CibToolError::EventToJson2)?;
|
| - |
println!("{json}");
|
| - |
} else if let Some(filename) = &self.output {
|
| - |
let json = event.to_pretty_json().map_err(CibToolError::EventToJson2)?;
|
| - |
std::fs::write(filename, &json)
|
| - |
.map_err(|err| CibToolError::Write(filename.into(), err))?;
|
| - |
} else {
|
| - |
let db = args.open_db()?;
|
| - |
let id = db.push_queued_ci_event(event)?;
|
| - |
println!("{id}");
|
| - |
|
| - |
if let Some(filename) = &self.id_file {
|
| - |
write(filename, id.to_string().as_bytes())
|
| - |
.map_err(|e| CibToolError::WriteEventId(filename.into(), e))?;
|
| + |
if self.all {
|
| + |
for ri in r.repositories().map_err(TriggerError::Ergonomic)? {
|
| + |
let repo = r.repository(&ri.rid).map_err(TriggerError::Ergonomic)?;
|
| + |
self.trigger(args, &r, &repo)?;
|
| |
}
|
| + |
} else if let Some(repo) = &self.repo {
|
| + |
let repo = r
|
| + |
.repository_by_name(repo)
|
| + |
.map_err(TriggerError::Ergonomic)?;
|
| + |
self.trigger(args, &r, &repo)?;
|
| + |
} else {
|
| + |
Err(TriggerError::NoRepo)?
|
| |
}
|
| |
|
| |
Ok(())
|
| |
Ok(project.default_branch().clone())
|
| |
}
|
| |
}
|
| + |
|
| + |
fn trigger(
|
| + |
&self,
|
| + |
args: &Args,
|
| + |
r: &ergo::Radicle,
|
| + |
repo: &Repository,
|
| + |
) -> Result<(), TriggerError> {
|
| + |
let profile = r.profile();
|
| + |
let nid = self.node.unwrap_or(*profile.id());
|
| + |
|
| + |
let oid = self.oid(r, repo)?;
|
| + |
|
| + |
let base = r
|
| + |
.resolve_commit(&repo.id, &format!("{oid}^"))
|
| + |
.unwrap_or(oid);
|
| + |
|
| + |
let branch_name = self.branch(r, repo)?;
|
| + |
|
| + |
let event = CiEvent::branch_updated(nid, repo.id, &branch_name, oid, base)
|
| + |
.map_err(TriggerError::CiEvent)?;
|
| + |
|
| + |
if self.stdout {
|
| + |
let json = event.to_pretty_json().map_err(TriggerError::EventToJson2)?;
|
| + |
println!("{json}");
|
| + |
} else if let Some(filename) = &self.output {
|
| + |
let json = event.to_pretty_json().map_err(TriggerError::EventToJson2)?;
|
| + |
std::fs::write(filename, &json)
|
| + |
.map_err(|err| TriggerError::Write(filename.into(), err))?;
|
| + |
} else {
|
| + |
let db = args
|
| + |
.open_db()
|
| + |
.map_err(|err| TriggerError::OpenDb(Box::new(err)))?;
|
| + |
let id = db.push_queued_ci_event(event)?;
|
| + |
println!("{id}");
|
| + |
|
| + |
if let Some(filename) = &self.id_file {
|
| + |
write(filename, id.to_string().as_bytes())
|
| + |
.map_err(|e| TriggerError::WriteEventId(filename.into(), e))?;
|
| + |
}
|
| + |
}
|
| + |
|
| + |
Ok(())
|
| + |
}
|
| |
}
|
| |
|
| |
#[derive(Debug, thiserror::Error)]
|
| |
|
| |
#[error(transparent)]
|
| |
RefError(#[from] radicle_ci_broker::refs::RefError),
|
| + |
|
| + |
#[error("repository must be given with --repo")]
|
| + |
NoRepo,
|
| + |
|
| + |
#[error("failed to construct a CI event")]
|
| + |
CiEvent(#[source] CiEventError),
|
| + |
|
| + |
#[error(transparent)]
|
| + |
EventToJson2(#[from] CiEventError),
|
| + |
|
| + |
#[error(transparent)]
|
| + |
Db(#[from] DbError),
|
| + |
|
| + |
#[error("failed to write file: {0}")]
|
| + |
Write(PathBuf, #[source] std::io::Error),
|
| + |
|
| + |
#[error("failed to write event ID to file {0}")]
|
| + |
WriteEventId(PathBuf, #[source] std::io::Error),
|
| + |
|
| + |
#[error("failed to get database")]
|
| + |
OpenDb(#[source] Box<CibToolError>),
|
| |
}
|