refactor: move gitea out of the way
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
@@ -1,19 +1,24 @@
|
||||
use std::{
|
||||
env::current_dir,
|
||||
io::Read,
|
||||
ops::Deref,
|
||||
path::{Path, PathBuf},
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use ::semver::Version;
|
||||
use anyhow::Context;
|
||||
use clap::{Parser, Subcommand};
|
||||
use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfigBuilder};
|
||||
use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfig, PleaseConfigBuilder};
|
||||
use cuddle_please_misc::{
|
||||
changelog_parser, get_most_significant_version, ChangeLogBuilder, ConsoleUi, DynUi,
|
||||
GiteaClient, GlobalArgs, NextVersion, StdinFn, VcsClient,
|
||||
changelog_parser, get_most_significant_version, ChangeLogBuilder, ConsoleUi,
|
||||
DynRemoteGitClient, DynUi, GiteaClient, GlobalArgs, LocalGitClient, NextVersion,
|
||||
RemoteGitEngine, StdinFn, VcsClient,
|
||||
};
|
||||
|
||||
use crate::release_command::ReleaseCommand;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Command {
|
||||
@@ -84,124 +89,13 @@ impl Command {
|
||||
|
||||
pub fn execute(self, current_dir: Option<&Path>) -> anyhow::Result<()> {
|
||||
let config = self.build_config(current_dir)?;
|
||||
let git_client = self.get_git(config.get_source())?;
|
||||
let gitea_client = self.get_gitea_client();
|
||||
|
||||
match &self.commands {
|
||||
Some(Commands::Release {}) => {
|
||||
tracing::debug!("running bare command");
|
||||
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
||||
// 2a. if not existing use default.
|
||||
// 2b. if not in a git repo abort. (unless --no-vcs is turned added)
|
||||
let git_client = self.get_git(config.get_source())?;
|
||||
|
||||
// 3. Create gitea client and do a health check
|
||||
let gitea_client = self.get_gitea_client();
|
||||
gitea_client
|
||||
.connect(config.get_owner(), config.get_repository())
|
||||
.context("failed to connect to gitea repository")?;
|
||||
// 4. Fetch git tags for the current repository
|
||||
let tags = gitea_client.get_tags(config.get_owner(), config.get_repository())?;
|
||||
|
||||
let significant_tag = get_most_significant_version(tags.iter().collect());
|
||||
|
||||
// 5. Fetch git commits since last git tag
|
||||
let commits = gitea_client.get_commits_since(
|
||||
config.get_owner(),
|
||||
config.get_repository(),
|
||||
significant_tag.map(|st| st.commit.sha.clone()),
|
||||
config.get_branch(),
|
||||
)?;
|
||||
|
||||
// 7. Create a versioning client
|
||||
let current_version = significant_tag
|
||||
.map(|st| Version::try_from(st).unwrap())
|
||||
.unwrap_or(Version::new(0, 1, 0));
|
||||
|
||||
// 8. Parse conventional commits and determine next version
|
||||
|
||||
let commit_strs = commits
|
||||
.iter()
|
||||
.map(|c| c.commit.message.as_str())
|
||||
.collect::<Vec<&str>>();
|
||||
|
||||
if commit_strs.is_empty() {
|
||||
tracing::info!("no commits to base release on");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let next_version = current_version.next(&commit_strs);
|
||||
|
||||
// Compose changelog
|
||||
let builder = ChangeLogBuilder::new(&commit_strs, next_version.to_string()).build();
|
||||
|
||||
let changelog_placement = config.get_source().join("CHANGELOG.md");
|
||||
|
||||
let changelog = match std::fs::read_to_string(&changelog_placement).ok() {
|
||||
Some(existing_changelog) => builder.prepend(existing_changelog)?,
|
||||
None => builder.generate()?,
|
||||
};
|
||||
|
||||
let changelog_last_changes = changelog_parser::last_changes(&changelog)?;
|
||||
|
||||
// 9b. check for release commit and release, if release exists continue
|
||||
// 10b. create release
|
||||
if let Some(first_commit) = commit_strs.first() {
|
||||
if first_commit.contains("chore(release): ") {
|
||||
if !self.global.dry_run {
|
||||
gitea_client.create_release(
|
||||
config.get_owner(),
|
||||
config.get_repository(),
|
||||
next_version.to_string(),
|
||||
changelog_last_changes.unwrap(),
|
||||
!next_version.pre.is_empty(),
|
||||
)?;
|
||||
} else {
|
||||
tracing::debug!("creating release (dry_run)");
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// 9a. Create / Update Pr
|
||||
// Create or update branch
|
||||
git_client.checkout_branch()?;
|
||||
|
||||
std::fs::write(changelog_placement, changelog.as_bytes())?;
|
||||
|
||||
git_client.commit_and_push(next_version.to_string(), self.global.dry_run)?;
|
||||
|
||||
let _pr_number = match gitea_client
|
||||
.get_pull_request(config.get_owner(), config.get_repository())?
|
||||
{
|
||||
Some(existing_pr) => {
|
||||
if !self.global.dry_run {
|
||||
gitea_client.update_pull_request(
|
||||
config.get_owner(),
|
||||
config.get_repository(),
|
||||
next_version.to_string(),
|
||||
changelog_last_changes.unwrap(),
|
||||
existing_pr,
|
||||
)?
|
||||
} else {
|
||||
tracing::debug!("updating pull request (dry_run)");
|
||||
1
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if !self.global.dry_run {
|
||||
gitea_client.create_pull_request(
|
||||
config.get_owner(),
|
||||
config.get_repository(),
|
||||
next_version.to_string(),
|
||||
changelog,
|
||||
config.get_branch(),
|
||||
)?
|
||||
} else {
|
||||
tracing::debug!("creating pull request (dry_run)");
|
||||
1
|
||||
}
|
||||
}
|
||||
};
|
||||
ReleaseCommand::new(config, git_client, gitea_client)
|
||||
.execute(self.global.dry_run)?;
|
||||
}
|
||||
|
||||
Some(Commands::Config { command }) => match command {
|
||||
@@ -222,7 +116,7 @@ impl Command {
|
||||
url.push_str(format!(":{port}").as_str());
|
||||
}
|
||||
|
||||
let client = GiteaClient::new(url, self.global.token);
|
||||
let client = GiteaClient::new(&url, self.global.token.as_ref().map(|t| t.as_str()));
|
||||
match command {
|
||||
GiteaCommand::Connect {} => {
|
||||
client.connect(config.get_owner(), config.get_repository())?;
|
||||
@@ -302,10 +196,7 @@ impl Command {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_config(
|
||||
&self,
|
||||
current_dir: Option<&Path>,
|
||||
) -> Result<cuddle_please_frontend::PleaseConfig, anyhow::Error> {
|
||||
fn build_config(&self, current_dir: Option<&Path>) -> Result<PleaseConfig, anyhow::Error> {
|
||||
let mut builder = &mut PleaseConfigBuilder::new();
|
||||
if self.global.config_stdin {
|
||||
if let Some(stdin_fn) = self.stdin.clone() {
|
||||
@@ -316,6 +207,7 @@ impl Command {
|
||||
let current_dir = get_current_path(current_dir, self.config.source.clone())?;
|
||||
let config = builder
|
||||
.with_config_file(¤t_dir)
|
||||
.with_source(¤t_dir)
|
||||
.with_execution_env(std::env::vars())
|
||||
.with_cli(self.config.clone())
|
||||
.build()?;
|
||||
@@ -323,14 +215,21 @@ impl Command {
|
||||
}
|
||||
|
||||
fn get_git(&self, current_dir: &Path) -> anyhow::Result<VcsClient> {
|
||||
VcsClient::new_git(current_dir)
|
||||
if self.global.no_vcs {
|
||||
Ok(VcsClient::new_noop())
|
||||
} else {
|
||||
VcsClient::new_git(current_dir)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_gitea_client(&self) -> GiteaClient {
|
||||
GiteaClient::new(
|
||||
self.config.api_url.clone().expect("api_url to be set"),
|
||||
self.global.token.clone(),
|
||||
)
|
||||
fn get_gitea_client(&self) -> DynRemoteGitClient {
|
||||
match self.global.engine {
|
||||
cuddle_please_misc::RemoteEngine::Local => Box::new(LocalGitClient::new()),
|
||||
cuddle_please_misc::RemoteEngine::Gitea => Box::new(GiteaClient::new(
|
||||
&self.config.api_url.clone().expect("api_url to be set"),
|
||||
self.global.token.as_ref().map(|t| t.as_str()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
mod command;
|
||||
mod release_command;
|
||||
|
||||
pub use command::Command as PleaseCommand;
|
||||
|
159
crates/cuddle-please-commands/src/release_command.rs
Normal file
159
crates/cuddle-please-commands/src/release_command.rs
Normal file
@@ -0,0 +1,159 @@
|
||||
use cuddle_please_frontend::PleaseConfig;
|
||||
|
||||
use std::{
|
||||
io::Read,
|
||||
ops::Deref,
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use ::semver::Version;
|
||||
use anyhow::Context;
|
||||
use clap::{Parser, Subcommand};
|
||||
use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfigBuilder};
|
||||
use cuddle_please_misc::{
|
||||
changelog_parser, get_most_significant_version, ChangeLogBuilder, ConsoleUi,
|
||||
DynRemoteGitClient, DynUi, GiteaClient, GlobalArgs, NextVersion, StdinFn, VcsClient,
|
||||
};
|
||||
|
||||
pub struct ReleaseCommand {
|
||||
config: PleaseConfig,
|
||||
git_client: VcsClient,
|
||||
gitea_client: DynRemoteGitClient,
|
||||
}
|
||||
|
||||
impl ReleaseCommand {
|
||||
pub fn new(
|
||||
config: PleaseConfig,
|
||||
git_client: VcsClient,
|
||||
gitea_client: DynRemoteGitClient,
|
||||
) -> Self {
|
||||
Self {
|
||||
config,
|
||||
git_client,
|
||||
gitea_client,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(&self, dry_run: bool) -> anyhow::Result<()> {
|
||||
tracing::debug!("running bare command");
|
||||
let owner = self.config.get_owner();
|
||||
let repository = self.config.get_repository();
|
||||
let branch = self.config.get_branch();
|
||||
let source = self.config.get_source();
|
||||
|
||||
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
||||
// 2a. if not existing use default.
|
||||
// 2b. if not in a git repo abort. (unless --no-vcs is turned added)
|
||||
|
||||
// 3. Create gitea client and do a health check
|
||||
self.gitea_client
|
||||
.connect(owner, repository)
|
||||
.context("failed to connect to gitea repository")?;
|
||||
// 4. Fetch git tags for the current repository
|
||||
let tags = self.gitea_client.get_tags(owner, repository)?;
|
||||
|
||||
let significant_tag = get_most_significant_version(tags.iter().collect());
|
||||
|
||||
// 5. Fetch git commits since last git tag
|
||||
let commits = self.gitea_client.get_commits_since(
|
||||
owner,
|
||||
repository,
|
||||
significant_tag.map(|st| st.commit.sha.as_str()),
|
||||
branch,
|
||||
)?;
|
||||
|
||||
// 7. Create a versioning client
|
||||
let current_version = significant_tag
|
||||
.map(|st| Version::try_from(st).unwrap())
|
||||
.unwrap_or(Version::new(0, 1, 0));
|
||||
|
||||
// 8. Parse conventional commits and determine next version
|
||||
|
||||
let commit_strs = commits
|
||||
.iter()
|
||||
.map(|c| c.commit.message.as_str())
|
||||
.collect::<Vec<&str>>();
|
||||
|
||||
if commit_strs.is_empty() {
|
||||
tracing::info!("no commits to base release on");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let next_version = current_version.next(&commit_strs);
|
||||
|
||||
// Compose changelog
|
||||
let builder = ChangeLogBuilder::new(&commit_strs, next_version.to_string()).build();
|
||||
|
||||
let changelog_placement = source.join("CHANGELOG.md");
|
||||
|
||||
let changelog = match std::fs::read_to_string(&changelog_placement).ok() {
|
||||
Some(existing_changelog) => builder.prepend(existing_changelog)?,
|
||||
None => builder.generate()?,
|
||||
};
|
||||
|
||||
let changelog_last_changes = changelog_parser::last_changes(&changelog)?;
|
||||
|
||||
// 9b. check for release commit and release, if release exists continue
|
||||
// 10b. create release
|
||||
if let Some(first_commit) = commit_strs.first() {
|
||||
if first_commit.contains("chore(release): ") {
|
||||
if !dry_run {
|
||||
self.gitea_client.create_release(
|
||||
owner,
|
||||
repository,
|
||||
&next_version.to_string(),
|
||||
&changelog_last_changes.unwrap(),
|
||||
!next_version.pre.is_empty(),
|
||||
)?;
|
||||
} else {
|
||||
tracing::debug!("creating release (dry_run)");
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// 9a. Create / Update Pr
|
||||
// Create or update branch
|
||||
self.git_client.checkout_branch()?;
|
||||
|
||||
std::fs::write(changelog_placement, changelog.as_bytes())?;
|
||||
|
||||
self.git_client
|
||||
.commit_and_push(next_version.to_string(), dry_run)?;
|
||||
|
||||
let _pr_number = match self.gitea_client.get_pull_request(owner, repository)? {
|
||||
Some(existing_pr) => {
|
||||
if !dry_run {
|
||||
self.gitea_client.update_pull_request(
|
||||
owner,
|
||||
repository,
|
||||
&next_version.to_string(),
|
||||
&changelog_last_changes.unwrap(),
|
||||
existing_pr,
|
||||
)?
|
||||
} else {
|
||||
tracing::debug!("updating pull request (dry_run)");
|
||||
1
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if !dry_run {
|
||||
self.gitea_client.create_pull_request(
|
||||
owner,
|
||||
repository,
|
||||
&next_version.to_string(),
|
||||
&changelog,
|
||||
branch,
|
||||
)?
|
||||
} else {
|
||||
tracing::debug!("creating pull request (dry_run)");
|
||||
1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user