Radish alpha
r
rad:zwTxygwuz5LDGBq255RA2CbNGrz8
Radicle CI broker
Radicle
Git
feat: add "run show" and "run update"
Merged liw opened 1 year ago

This is based on 1d149ed.

Signed-off-by: Lars Wirzenius liw@liw.fi

5 files changed +151 -4 2cc1dc4b f07da18f
modified ci-broker.md
@@ -930,3 +930,45 @@ then stdout contains "rad:zwTxygwuz5LDGBq255RA2CbNGrz8"
when I run cibtool --db x.db run list --adapter-run-id abracadabra
then stdout is exactly ""
~~~
+

+
## Update and show information about run to running
+

+
_Want:_ `cibtool` can update information about a CI run.
+

+
_Why:_ This is primarily needed for testing.
+

+
_Who:_ Lars.
+

+
~~~scenario
+
given an installed cibtool
+
when I run cibtool --db x.db run list
+
then stdout is exactly ""
+

+
when I run cibtool --db x.db run add --id x --repo rad:zwTxygwuz5LDGBq255RA2CbNGrz8 --alias x --url https://x/1 --branch main --commit f1815dde6ae406d8fe3cec0b96c4486766342716 --who x --triggered --timestamp 2024-07-09T02:00:00
+
when I run cibtool --db x.db run list
+
then stdout has one line
+
when I run cibtool --db x.db run show x
+
then stdout contains ""state": "triggered""
+
then stdout contains ""result": null"
+

+
when I run cibtool --db x.db run update --id x --running
+
when I run cibtool --db x.db run list
+
then stdout has one line
+
when I run cibtool --db x.db run show x
+
then stdout contains ""state": "running""
+
then stdout contains ""result": null"
+

+
when I run cibtool --db x.db run update --id x --success
+
when I run cibtool --db x.db run list
+
then stdout has one line
+
when I run cibtool --db x.db run show x
+
then stdout contains ""state": "finished""
+
then stdout contains ""result": "success""
+

+
when I run cibtool --db x.db run update --id x --failure
+
when I run cibtool --db x.db run list
+
then stdout has one line
+
when I run cibtool --db x.db run show x
+
then stdout contains ""state": "finished""
+
then stdout contains ""result": "failure""
+
~~~
modified ci-broker.yaml
@@ -12,3 +12,8 @@
  impl:
    rust:
      function: install_synthetic_events
+

+
- then: "stdout has one line"
+
  impl:
+
    rust:
+
      function: stdout_has_one_line
modified src/bin/cibtool.rs
@@ -536,6 +536,8 @@ impl RunCmd {
        match &self.cmd {
            RunSubCmd::Add(x) => x.run(args)?,
            RunSubCmd::List(x) => x.run(args)?,
+
            RunSubCmd::Update(x) => x.run(args)?,
+
            RunSubCmd::Show(x) => x.run(args)?,
        }
        Ok(())
    }
@@ -546,6 +548,12 @@ enum RunSubCmd {
    /// Add information about a CI run to the database.
    Add(AddRun),

+
    /// Update information about a CI run to the database.
+
    Update(UpdateRun),
+

+
    /// Show a CI run as JSON.
+
    Show(ShowRun),
+

    /// List known CI runs on this node to the database.
    List(ListRuns),
}
@@ -621,11 +629,13 @@ impl AddRun {
            run.set_adapter_info_url(url);
        }

-
        run.set_result(if self.success {
-
            RunResult::Success
+
        if self.success {
+
            run.set_result(RunResult::Success);
+
        } else if self.failure {
+
            run.set_result(RunResult::Failure);
        } else {
-
            RunResult::Failure
-
        });
+
            run.unset_result();
+
        }

        db.push_run(&run)?;

@@ -634,6 +644,78 @@ impl AddRun {
}

#[derive(Parser)]
+
struct UpdateRun {
+
    /// ID of run to update.
+
    #[clap(long)]
+
    id: RunId,
+

+
    /// Set the state of the CI run to "triggered".
+
    #[clap(long, required_unless_present_any = ["running", "success", "failure"])]
+
    triggered: bool,
+

+
    /// Set the state of the CI run to "running".
+
    #[clap(long)]
+
    #[clap(long, required_unless_present_any = ["triggered", "success", "failure"])]
+
    running: bool,
+

+
    /// Mark the CI run as finished and successful.
+
    #[clap(long, required_unless_present_any = ["triggered", "running", "failure"])]
+
    success: bool,
+

+
    /// Mark the CI run as finished and failed.
+
    #[clap(long, required_unless_present_any = ["triggered", "running", "success"])]
+
    failure: bool,
+
}
+

+
impl UpdateRun {
+
    #[allow(clippy::result_large_err)]
+
    fn run(&self, args: &Args) -> Result<(), CibToolError> {
+
        let db = args.open_db()?;
+

+
        let runs = db.find_runs(&self.id)?;
+
        if runs.is_empty() {
+
            Err(CibToolError::RunNotFound(self.id.clone()))
+
        } else {
+
            let mut run = runs.first().unwrap().clone(); // this is safe: runs is not empty
+

+
            run.unset_result();
+
            if self.triggered {
+
                run.set_state(RunState::Triggered);
+
            } else if self.running {
+
                run.set_state(RunState::Running);
+
            } else if self.success {
+
                run.set_state(RunState::Finished);
+
                run.set_result(RunResult::Success);
+
            } else if self.failure {
+
                run.set_state(RunState::Finished);
+
                run.set_result(RunResult::Failure);
+
            }
+

+
            db.update_run(&run)?;
+
            Ok(())
+
        }
+
    }
+
}
+

+
#[derive(Parser)]
+
struct ShowRun {
+
    /// Broker or adapter run IC.
+
    id: RunId,
+
}
+

+
impl ShowRun {
+
    #[allow(clippy::result_large_err)]
+
    fn run(&self, args: &Args) -> Result<(), CibToolError> {
+
        let db = args.open_db()?;
+
        let runs = db.find_runs(&self.id)?;
+
        let json = serde_json::to_string_pretty(&runs).map_err(CibToolError::RunToJson)?;
+
        println!("{json}");
+

+
        Ok(())
+
    }
+
}
+

+
#[derive(Parser)]
struct ListRuns {
    #[clap(long)]
    json: bool,
@@ -870,6 +952,9 @@ enum CibToolError {
    #[error("node has no repository called: {0}")]
    NotFound(String),

+
    #[error("cannot find CI run with id {0}")]
+
    RunNotFound(RunId),
+

    #[error("failed to open git repository in node storage: {0}")]
    RepoOpen(RepoId, #[source] radicle::storage::RepositoryError),

modified src/run.rs
@@ -97,6 +97,11 @@ impl Run {
        self.result = Some(result);
    }

+
    /// Unset result of the CI run.
+
    pub fn unset_result(&mut self) {
+
        self.result = None;
+
    }
+

    /// Return the result of the CI run.
    pub fn result(&self) -> Option<&RunResult> {
        self.result.as_ref()
modified src/subplot.rs
@@ -62,3 +62,13 @@ fn bindir() -> PathBuf {
    };
    path.canonicalize().unwrap()
}
+

+
#[step]
+
#[context(SubplotContext)]
+
#[context(Runcmd)]
+
fn stdout_has_one_line(runcmd: &Runcmd) {
+
    let linecount = runcmd.stdout_as_string().lines().count();
+
    if linecount != 1 {
+
        throw!(format!("stdout had {linecount} lines, expected 1"));
+
    }
+
}