Fornjot/tools/release-operator/src/release.rs
2022-12-06 10:09:07 +01:00

79 lines
2.0 KiB
Rust

use autolib::find_version_in_str;
use crate::{Actions, GitHub};
use std::fmt::{Display, Formatter};
pub struct Release {
sha: String,
label: String,
}
pub enum Outputs {
ReleaseDetected,
TagName,
}
impl Display for Outputs {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self {
Self::ReleaseDetected => write!(f, "release-detected"),
Self::TagName => write!(f, "tag-name"),
}
}
}
impl Release {
pub fn new(sha: String, label: String) -> Self {
Self { sha, label }
}
pub fn detect(&self) -> anyhow::Result<()> {
let sha = &self.sha;
let label = &self.label;
// Try and find the pull-request that the commit was part of to examine it.
// A release can only ever be triggered by a pull-request being merged.
if GitHub::find_pull_request_by(sha, label)?.is_none() {
log::info!(
"Could not find a pull request with hash {sha} and label \
{label}",
);
return Self::miss();
}
let commit: String = cmd_lib::run_fun!(git log -n 1 "${sha}")?;
// A release commits need to contain a semver version number.
let version = find_version_in_str(&commit)?;
match version {
Some(v) => Self::hit(&v.to_string()),
None => {
log::info!(
"Commit message is missing version number:\n\
{commit}",
);
Self::miss()
}
}
}
fn hit(tag: &str) -> anyhow::Result<()> {
let tag = format!("v{tag}");
log::info!("detected release of {tag}");
Actions::set_output([
(Outputs::ReleaseDetected, "true"),
(Outputs::TagName, &tag),
])?;
Ok(())
}
fn miss() -> anyhow::Result<()> {
log::info!("no release detected");
Actions::set_output([(Outputs::ReleaseDetected, "false")])?;
Ok(())
}
}