| |
.with_text(")"),
|
| |
);
|
| |
|
| + |
Self::h1(&mut doc, "Repositories");
|
| + |
Self::p_text(&mut doc, "Latest CI run for each repository.");
|
| + |
|
| + |
let mut table = Element::new(Tag::Table).with_class("repolist").with_child(
|
| + |
Element::new(Tag::Tr)
|
| + |
.with_child(Element::new(Tag::Th).with_text("Repository"))
|
| + |
.with_child(Element::new(Tag::Th).with_text("Run ID"))
|
| + |
.with_child(Element::new(Tag::Th).with_text("Status"))
|
| + |
.with_child(Element::new(Tag::Th).with_text("Info")),
|
| + |
);
|
| + |
|
| + |
for (alias, rid) in self.repos() {
|
| + |
let (run_ids, status, info_url) = match self.latest_run(rid) {
|
| + |
Some(run) => (
|
| + |
Self::run_ids(Some(run)),
|
| + |
run.state().to_string(),
|
| + |
Self::info_url(Some(run)),
|
| + |
),
|
| + |
None => (
|
| + |
Self::run_ids(None),
|
| + |
"unknown".to_string(),
|
| + |
Self::info_url(None),
|
| + |
),
|
| + |
};
|
| + |
|
| + |
table.push_child(
|
| + |
Element::new(Tag::Tr)
|
| + |
.with_child(Element::new(Tag::Td).with_child(Self::repository(rid, &alias)))
|
| + |
.with_child(Element::new(Tag::Td).with_child(run_ids))
|
| + |
.with_child(
|
| + |
Element::new(Tag::Td).with_child(
|
| + |
Element::new(Tag::Span)
|
| + |
.with_class("run-status")
|
| + |
.with_text(&status),
|
| + |
),
|
| + |
)
|
| + |
.with_child(Element::new(Tag::Td).with_child(info_url)),
|
| + |
);
|
| + |
}
|
| + |
doc.push_to_body(table);
|
| + |
|
| + |
Self::h1(&mut doc, "Recent status");
|
| |
let status = StatusData::from(self).as_json()?;
|
| |
doc.push_to_body(
|
| - |
Element::new(Tag::P).with_child(
|
| - |
Element::new(Tag::A)
|
| - |
.with_attribute("href", STATUS_JSON)
|
| - |
.with_text(STATUS_JSON),
|
| - |
),
|
| + |
Element::new(Tag::P)
|
| + |
.with_text("See also as a separate file ")
|
| + |
.with_child(
|
| + |
Element::new(Tag::A)
|
| + |
.with_attribute("href", STATUS_JSON)
|
| + |
.with_child(Element::new(Tag::Code).with_text(STATUS_JSON)),
|
| + |
)
|
| + |
.with_text(": "),
|
| |
);
|
| |
doc.push_to_body(
|
| |
Element::new(Tag::Blockquote).with_child(Element::new(Tag::Pre).with_text(&status)),
|
| |
);
|
| |
|
| - |
doc.push_to_body(Element::new(Tag::H2).with_text("Repositories"));
|
| + |
Ok(doc)
|
| + |
}
|
| |
|
| - |
doc.push_to_body(Element::new(Tag::P).with_text("Latest CI run for each repository."));
|
| + |
fn per_repo_page_as_html(&self, rid: RepoId, alias: &str, timestamp: &str) -> HtmlPage {
|
| + |
let mut doc = HtmlPage::default();
|
| |
|
| - |
let mut list = Element::new(Tag::Ul).with_class("repolist");
|
| - |
for (alias, rid) in self.repos() {
|
| - |
let mut item = Element::new(Tag::Li);
|
| + |
let title = format!("CI runs for repository {}", alias);
|
| + |
Self::head(&mut doc, &title);
|
| |
|
| - |
let runs = self.runs(rid);
|
| - |
item.push_child(
|
| - |
Element::new(Tag::Span).with_child(
|
| - |
Element::new(Tag::A)
|
| - |
.with_attribute("href", &format!("{}.html", rid_to_basename(rid)))
|
| - |
.with_text("Repository ")
|
| - |
.with_child(
|
| - |
Element::new(Tag::Span)
|
| - |
.with_class("alias)")
|
| - |
.with_text(&alias),
|
| - |
)
|
| - |
.with_text(" (")
|
| - |
.with_child(
|
| - |
Element::new(Tag::Code)
|
| - |
.with_class("repoid)")
|
| - |
.with_text(&rid.to_string()),
|
| - |
)
|
| - |
.with_text(&format!("), {} runs", runs.len())),
|
| - |
),
|
| - |
);
|
| + |
Self::h1(&mut doc, &title);
|
| + |
doc.push_to_body(
|
| + |
Element::new(Tag::P).with_text("Repository ID ").with_child(
|
| + |
Element::new(Tag::Code)
|
| + |
.with_class("repoid")
|
| + |
.with_text(&rid.to_string()),
|
| + |
),
|
| + |
);
|
| + |
Self::p_text(&mut doc, &format!("Last updated: {timestamp}"));
|
| + |
|
| + |
let mut table = Element::new(Tag::Table).with_class("run-list").with_child(
|
| + |
Element::new(Tag::Tr)
|
| + |
.with_child(Element::new(Tag::Th).with_text("Run ID"))
|
| + |
.with_child(Element::new(Tag::Th).with_text("Whence"))
|
| + |
.with_child(Element::new(Tag::Th).with_text("Status"))
|
| + |
.with_child(Element::new(Tag::Th).with_text("Info")),
|
| + |
);
|
| |
|
| - |
if let Some(run) = self.latest_run(rid) {
|
| - |
item.push_child(Element::new(Tag::Br));
|
| - |
item.push_child(
|
| + |
let mut runs = self.runs(rid);
|
| + |
runs.sort_by_cached_key(|run| run.timestamp());
|
| + |
runs.reverse();
|
| + |
for run in runs {
|
| + |
let current = match run.state() {
|
| + |
RunState::Triggered => Element::new(Tag::Span)
|
| + |
.with_attribute("state", "triggered")
|
| + |
.with_text("triggered"),
|
| + |
RunState::Running => Element::new(Tag::Span)
|
| + |
.with_class("running)")
|
| + |
.with_text("running"),
|
| + |
RunState::Finished => {
|
| + |
let result = if let Some(result) = run.result() {
|
| + |
result.to_string()
|
| + |
} else {
|
| + |
"unknown".into()
|
| + |
};
|
| |
Element::new(Tag::Span)
|
| - |
.with_text("latest run at ")
|
| - |
.with_text(run.timestamp())
|
| - |
.with_child(Element::new(Tag::Br))
|
| - |
.with_text("broker run ID: ")
|
| - |
.with_child(
|
| - |
Element::new(Tag::Code)
|
| - |
.with_class("broker_run_id")
|
| - |
.with_text(run.broker_run_id().as_str()),
|
| - |
)
|
| - |
.with_child(Element::new(Tag::Br))
|
| - |
.with_text("adapter run ID: ")
|
| - |
.with_child(if let Some(id) = run.adapter_run_id() {
|
| - |
Element::new(Tag::Code)
|
| - |
.with_class("adapter_run_id")
|
| - |
.with_text(id.as_str())
|
| - |
} else {
|
| - |
Element::new(Tag::Span).with_text("unknown")
|
| - |
})
|
| - |
.with_child(Element::new(Tag::Br))
|
| - |
.with_text(" ")
|
| - |
.with_child(Self::whence_as_html(run.whence())),
|
| - |
);
|
| - |
item.push_child(Element::new(Tag::Br));
|
| - |
|
| - |
let state = run.state().to_string();
|
| - |
item.push_child(Element::new(Tag::Span).with_class(&state).with_text(&state));
|
| - |
|
| - |
let result = match run.result() {
|
| - |
None => Element::new(Tag::Span)
|
| - |
.with_text(" ")
|
| - |
.with_class("unknown")
|
| - |
.with_text("unknown result"),
|
| - |
Some(RunResult::Success) => Element::new(Tag::Span)
|
| - |
.with_text(" ")
|
| - |
.with_class("success")
|
| - |
.with_text("success"),
|
| - |
Some(_) => Element::new(Tag::Span)
|
| - |
.with_text(" ")
|
| - |
.with_class("failure")
|
| - |
.with_text("failure"),
|
| - |
};
|
| - |
|
| - |
item.push_child(result);
|
| - |
|
| - |
if let Some(url) = run.adapter_info_url() {
|
| - |
item.push_child(Element::new(Tag::Br));
|
| - |
let log = Element::new(Tag::Span).with_child(
|
| - |
Element::new(Tag::A)
|
| - |
.with_attribute("href", url)
|
| - |
.with_text("log"),
|
| - |
);
|
| - |
item.push_child(log);
|
| + |
.with_class(&result)
|
| + |
.with_text(&result)
|
| |
}
|
| - |
}
|
| + |
};
|
| |
|
| - |
list.push_child(item);
|
| + |
table.push_child(
|
| + |
Element::new(Tag::Tr)
|
| + |
.with_child(Element::new(Tag::Td).with_child(Self::run_ids(Some(run))))
|
| + |
.with_child(
|
| + |
Element::new(Tag::Td).with_child(Self::whence_as_html(run.whence())),
|
| + |
)
|
| + |
.with_child(Element::new(Tag::Td).with_child(current))
|
| + |
.with_child(Element::new(Tag::Td).with_child(Self::info_url(Some(run)))),
|
| + |
);
|
| |
}
|
| - |
doc.push_to_body(list);
|
| |
|
| - |
Ok(doc)
|
| + |
doc.push_to_body(table);
|
| + |
|
| + |
doc
|
| + |
}
|
| + |
|
| + |
fn head(page: &mut HtmlPage, title: &str) {
|
| + |
page.push_to_head(Element::new(Tag::Title).with_text(title));
|
| + |
page.push_to_head(Element::new(Tag::Style).with_text(CSS));
|
| + |
page.push_to_head(
|
| + |
Element::new(Tag::Meta)
|
| + |
.with_attribute("http-equiv", "refresh")
|
| + |
.with_attribute("content", REFERESH_INTERVAL),
|
| + |
);
|
| + |
}
|
| + |
|
| + |
fn h1(page: &mut HtmlPage, text: &str) {
|
| + |
page.push_to_body(Element::new(Tag::H2).with_text(text));
|
| + |
}
|
| + |
|
| + |
fn p_text(page: &mut HtmlPage, text: &str) {
|
| + |
page.push_to_body(Element::new(Tag::P).with_text(text));
|
| + |
}
|
| + |
|
| + |
fn repository(repo_id: RepoId, alias: &str) -> Element {
|
| + |
Element::new(Tag::A)
|
| + |
.with_child(
|
| + |
Element::new(Tag::Code)
|
| + |
.with_class("alias)")
|
| + |
.with_text(alias),
|
| + |
)
|
| + |
.with_attribute("href", &format!("{}.html", rid_to_basename(repo_id)))
|
| + |
}
|
| + |
|
| + |
fn run_ids(run: Option<&Run>) -> Element {
|
| + |
if let Some(run) = run {
|
| + |
let adapter_run_id = if let Some(x) = run.adapter_run_id() {
|
| + |
Element::new(Tag::Span).with_text(x.as_str())
|
| + |
} else {
|
| + |
Element::new(Tag::Span)
|
| + |
};
|
| + |
|
| + |
Element::new(Tag::Span).with_child(
|
| + |
Element::new(Tag::Span)
|
| + |
.with_class("adapter-run-id")
|
| + |
.with_child(adapter_run_id)
|
| + |
.with_child(Element::new(Tag::Br))
|
| + |
.with_child(
|
| + |
Element::new(Tag::Span)
|
| + |
.with_class("broker-run-id")
|
| + |
.with_text(&run.broker_run_id().to_string()),
|
| + |
)
|
| + |
.with_child(Element::new(Tag::Br))
|
| + |
.with_text(run.timestamp()),
|
| + |
)
|
| + |
} else {
|
| + |
Element::new(Tag::Span)
|
| + |
}
|
| + |
}
|
| + |
|
| + |
fn info_url(run: Option<&Run>) -> Element {
|
| + |
if let Some(run) = run {
|
| + |
if let Some(url) = run.adapter_info_url() {
|
| + |
return Element::new(Tag::A)
|
| + |
.with_attribute("href", url)
|
| + |
.with_text("info");
|
| + |
}
|
| + |
}
|
| + |
Element::new(Tag::Span)
|
| |
}
|
| |
|
| |
fn whence_as_html(whence: &Whence) -> Element {
|
| |
}
|
| |
}
|
| |
|
| - |
fn per_repo_page_as_html(&self, rid: RepoId, alias: &str, timestamp: &str) -> HtmlPage {
|
| - |
let mut doc = HtmlPage::default();
|
| - |
|
| - |
doc.push_to_head(
|
| - |
Element::new(Tag::Title)
|
| - |
.with_text("CI runs for repository ")
|
| - |
.with_text(alias),
|
| - |
);
|
| - |
|
| - |
doc.push_to_head(Element::new(Tag::Style).with_text(CSS));
|
| - |
|
| - |
doc.push_to_body(
|
| - |
Element::new(Tag::H1)
|
| - |
.with_text("CI runs for repository ")
|
| - |
.with_text(alias),
|
| - |
);
|
| - |
|
| - |
doc.push_to_body(
|
| - |
Element::new(Tag::P)
|
| - |
.with_text("Last updated: ")
|
| - |
.with_text(timestamp),
|
| - |
);
|
| - |
|
| - |
doc.push_to_body(
|
| - |
Element::new(Tag::P)
|
| - |
.with_text("Repository ID ")
|
| - |
.with_child(Element::new(Tag::Code).with_text(&rid.to_string())),
|
| - |
);
|
| - |
|
| - |
let mut runs = self.runs(rid);
|
| - |
runs.sort_by_cached_key(|run| run.timestamp());
|
| - |
runs.reverse();
|
| - |
let mut list = Element::new(Tag::Ol).with_class("runlist");
|
| - |
for run in runs {
|
| - |
let current = match run.state() {
|
| - |
RunState::Triggered => Element::new(Tag::Span)
|
| - |
.with_attribute("state", "triggered")
|
| - |
.with_text("triggered"),
|
| - |
RunState::Running => Element::new(Tag::Span)
|
| - |
.with_class("running)")
|
| - |
.with_text("running"),
|
| - |
RunState::Finished => {
|
| - |
let result = if let Some(result) = run.result() {
|
| - |
result.to_string()
|
| - |
} else {
|
| - |
"unknown".into()
|
| - |
};
|
| - |
Element::new(Tag::Span)
|
| - |
.with_class(&result)
|
| - |
.with_text(&result)
|
| - |
}
|
| - |
};
|
| - |
|
| - |
let info_url = if let Some(url) = run.adapter_info_url() {
|
| - |
Element::new(Tag::Span).with_child(
|
| - |
Element::new(Tag::A)
|
| - |
.with_attribute("href", url)
|
| - |
.with_text("info from adapter"),
|
| - |
)
|
| - |
} else {
|
| - |
Element::new(Tag::Span)
|
| - |
.with_child(Element::new(Tag::Span).with_text("no info from adapter"))
|
| - |
};
|
| - |
|
| - |
list.push_child(
|
| - |
Element::new(Tag::Li)
|
| - |
.with_text("at ")
|
| - |
.with_text(run.timestamp())
|
| - |
.with_text("; currently ")
|
| - |
.with_child(current)
|
| - |
.with_text("; ")
|
| - |
.with_child(info_url)
|
| - |
.with_child(Element::new(Tag::Br))
|
| - |
.with_text("broker run ID: ")
|
| - |
.with_child(
|
| - |
Element::new(Tag::Code)
|
| - |
.with_class("broker_run_id")
|
| - |
.with_text(run.broker_run_id().as_str()),
|
| - |
)
|
| - |
.with_child(Element::new(Tag::Br))
|
| - |
.with_text("adapter run ID: ")
|
| - |
.with_child(if let Some(id) = run.adapter_run_id() {
|
| - |
Element::new(Tag::Code)
|
| - |
.with_class("adapter_run_id")
|
| - |
.with_text(id.as_str())
|
| - |
} else {
|
| - |
Element::new(Tag::Span).with_text("unknown")
|
| - |
})
|
| - |
.with_child(Element::new(Tag::Br))
|
| - |
.with_child(Self::whence_as_html(run.whence())),
|
| - |
);
|
| - |
}
|
| - |
|
| - |
doc.push_to_body(list);
|
| - |
|
| - |
doc
|
| - |
}
|
| - |
|
| |
fn repos(&self) -> Vec<(String, RepoId)> {
|
| |
let rids: HashSet<(String, RepoId)> = self
|
| |
.runs
|