use std::process::{Command, Stdio};
use anyhow::{ensure, Context, Result};
use chrono::Utc;
use clap::Args;
use semver::{Prerelease, Version};
use crate::{
npm::util::{bump_swc_cli, set_version},
util::{repository_root, wrap},
};
#[derive(Debug, Args)]
pub(super) struct NightlyCmd {}
impl NightlyCmd {
pub fn run(self) -> Result<()> {
wrap(|| {
let date = Utc::now().format("%Y%m%d").to_string();
let root_pkg_json = repository_root()?.join("./packages/core/package.json");
let content = serde_json::from_reader::<_, serde_json::Value>(
std::fs::File::open(root_pkg_json)
.context("failed to open ./packages/core/package.json")?,
)?;
let prev_version = Version::parse(content["version"].as_str().unwrap())?;
let version = find_first_nightly(&prev_version, &date)?;
println!("Publishing nightly version {}", version);
set_version(&version).context("failed to set version")?;
bump_swc_cli().context("failed to bump swc-cli")?;
let status = Command::new("sh")
.arg("./scripts/publish.sh")
.arg(format!("{}", version))
.status()
.context("failed to publish")?;
ensure!(status.success(), "failed to publish");
Ok(())
})
.context("failed to publish nightly version")
}
}
fn find_first_nightly(prev_version: &semver::Version, date: &str) -> Result<Version> {
let mut ver = prev_version.clone();
if prev_version.pre.is_empty() {
ver.patch += 1;
}
for i in 1.. {
ver.pre = Prerelease::new(&format!("nightly-{}.{}", date, i))?;
if ver <= *prev_version {
continue;
}
let tag = format!("v{}", ver);
let output = Command::new("git")
.arg("tag")
.arg("-l")
.stderr(Stdio::inherit())
.output()
.context("git tag -l failed")
.map(|v| v.stdout)
.and_then(|s| String::from_utf8(s).context("git tag -l returned non-utf8"))?;
if !output.contains(&tag) {
return Ok(ver);
}
}
unreachable!("failed to find a free nightly version")
}