Radish alpha
r
Radicle CI broker
Radicle
Git (anonymous pull)
Log in to clone via SSH
refactor: change code to produce HTML report to run in a thread
Lars Wirzenius committed 1 year ago
commit ad807720336ae92c385db6acf50ab44d27796d68
parent 08706d1d4e1499fec483c0946ebec9fb4c17f982
3 files changed +55 -2
modified ci-broker.md
@@ -427,11 +427,15 @@ _Justification:_ This is useful for diagnosis, if nothing else.
_Stakeholder:_ Lars.

~~~scenario
+
given file radenv.sh
+
given file setup-node.sh
+
when I run bash radenv.sh bash setup-node.sh
+

given an installed cibtool
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 --finished --failure --timestamp 2024-07-09T02:00:00

given a directory reports
-
when I run cibtool --db x.db report --output-dir reports
+
when I run bash radenv.sh cibtool --db x.db report --output-dir reports

then file reports/index.html exists
then file reports/index.html contains "zwTxygwuz5LDGBq255RA2CbNGrz8"
modified src/bin/cibtool.rs
@@ -568,6 +568,8 @@ struct ReportCmd {
impl ReportCmd {
    #[allow(clippy::result_large_err)]
    fn run(&self, args: &Args) -> Result<(), CibToolError> {
+
        let profile = Profile::load().map_err(CibToolError::Profile)?;
+

        let db = args.open_db()?;

        let mut page = PageBuilder::default()
@@ -575,7 +577,9 @@ impl ReportCmd {
            .runs(db.get_all_runs()?)
            .build()?;

-
        page.write(&self.output_dir)?;
+
        page.set_output_dir(&self.output_dir);
+
        let thread = page.update_in_thread(db, &profile.config.node.alias, true);
+
        thread.join().unwrap()?;

        Ok(())
    }
modified src/pages.rs
@@ -12,6 +12,8 @@ use std::{
    fs::write,
    path::{Path, PathBuf},
    sync::{Arc, Mutex, MutexGuard},
+
    thread::{sleep, spawn, JoinHandle},
+
    time::Duration,
};

use html_page::{Document, Element, Tag};
@@ -22,6 +24,7 @@ use time::{macros::format_description, OffsetDateTime};
use radicle::prelude::RepoId;

use crate::{
+
    db::{Db, DbError},
    event::BrokerEvent,
    msg::{RunId, RunResult},
    run::{Run, RunState, Whence},
@@ -29,6 +32,7 @@ use crate::{

const CSS: &str = include_str!("radicle-ci.css");
const REFERESH_INTERVAL: &str = "300";
+
const UPDATE_INTERVAL: u64 = 300;

/// All possible errors returned from the status page module.
#[derive(Debug, thiserror::Error)]
@@ -41,6 +45,9 @@ pub enum PageError {

    #[error("no status data has been set for builder")]
    NoStatusData,
+

+
    #[error(transparent)]
+
    Db(#[from] DbError),
}

/// A builder for constructing a [`StatusPage`] value. It will only
@@ -439,12 +446,16 @@ impl PageData {
/// repository.
pub struct StatusPage {
    data: Arc<Mutex<PageData>>,
+
    node_alias: String,
+
    dirname: Option<PathBuf>,
}

impl StatusPage {
    fn new(data: PageData) -> Self {
        Self {
            data: Arc::new(Mutex::new(data)),
+
            node_alias: String::new(),
+
            dirname: None,
        }
    }

@@ -452,6 +463,10 @@ impl StatusPage {
        self.data.lock().expect("lock StatusPage::data")
    }

+
    pub fn set_output_dir(&mut self, dirname: &Path) {
+
        self.dirname = Some(dirname.into());
+
    }
+

    pub fn update_timestamp(&mut self) {
        let mut data = self.lock();
        data.timestamp = now();
@@ -473,6 +488,34 @@ impl StatusPage {
        }
    }

+
    pub fn update_in_thread(
+
        mut self,
+
        db: Db,
+
        node_alias: &str,
+
        once: bool,
+
    ) -> JoinHandle<Result<(), PageError>> {
+
        self.node_alias = node_alias.into();
+
        spawn(move || loop {
+
            self.update_and_write(&db)?;
+
            if once {
+
                return Ok(());
+
            }
+
            sleep(Duration::from_secs(UPDATE_INTERVAL));
+
        })
+
    }
+

+
    fn update_and_write(&mut self, db: &Db) -> Result<(), PageError> {
+
        if let Some(dirname) = &self.dirname {
+
            let mut page = PageBuilder::default()
+
                .node_alias(&self.node_alias)
+
                .runs(db.get_all_runs()?)
+
                .build()?;
+

+
            page.write(dirname)?;
+
        }
+
        Ok(())
+
    }
+

    /// Write the status page (as index.html) and per-repository pages
    /// (`<RID>.html`) into the directory given as an argument. The directory must exist.
    pub fn write(&mut self, dirname: &Path) -> Result<(), PageError> {
@@ -525,6 +568,8 @@ impl Clone for StatusPage {
    fn clone(&self) -> Self {
        Self {
            data: Arc::clone(&self.data),
+
            node_alias: self.node_alias.clone(),
+
            dirname: self.dirname.clone(),
        }
    }
}