feat: refactor frontend configuration
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
e235483783
commit
8cd68d569b
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -344,6 +344,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"conventional_commit_parser",
|
"conventional_commit_parser",
|
||||||
|
"cuddle-please-frontend",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"git-cliff-core",
|
"git-cliff-core",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@ -361,6 +362,23 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuddle-please-frontend"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"chrono",
|
||||||
|
"clap",
|
||||||
|
"dotenv",
|
||||||
|
"pretty_assertions",
|
||||||
|
"serde",
|
||||||
|
"serde_yaml",
|
||||||
|
"tempdir",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"tracing-test",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deunicode"
|
name = "deunicode"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["crates/cuddle-please"]
|
members = ["crates/cuddle-please", "crates/cuddle-please-frontend"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
cuddle-please = { path = "crates/cuddle-please" }
|
cuddle-please = { path = "crates/cuddle-please" }
|
||||||
|
cuddle-please-frontend = { path = "crates/cuddle-please-frontend" }
|
||||||
|
|
||||||
anyhow = { version = "1.0.71" }
|
anyhow = { version = "1.0.71" }
|
||||||
tracing = { version = "0.1", features = ["log"] }
|
tracing = { version = "0.1", features = ["log"] }
|
||||||
|
@ -34,7 +34,7 @@ See docs for more information about installation and some such
|
|||||||
### 0.1 Milestone
|
### 0.1 Milestone
|
||||||
|
|
||||||
- [x] Hide unneccessary commands
|
- [x] Hide unneccessary commands
|
||||||
- [ ] Redo configuration frontend
|
- [x] Redo configuration frontend
|
||||||
- [ ] Refactor command.rs into smaller bits so that bits are easier to test
|
- [ ] Refactor command.rs into smaller bits so that bits are easier to test
|
||||||
- [ ] Add reporter for PR and Repositories
|
- [ ] Add reporter for PR and Repositories
|
||||||
- [ ] Setup temporary git name and email to use for git committing
|
- [ ] Setup temporary git name and email to use for git committing
|
||||||
|
19
crates/cuddle-please-frontend/Cargo.toml
Normal file
19
crates/cuddle-please-frontend/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "cuddle-please-frontend"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
dotenv.workspace = true
|
||||||
|
serde_yaml.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
chrono.workspace = true
|
||||||
|
tempdir.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tracing-test = { workspace = true, features = ["no-env-filter"] }
|
||||||
|
pretty_assertions.workspace = true
|
71
crates/cuddle-please-frontend/src/gatheres/cli.rs
Normal file
71
crates/cuddle-please-frontend/src/gatheres/cli.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use clap::Args;
|
||||||
|
|
||||||
|
use crate::stage0_config::{
|
||||||
|
PleaseConfigBuilder, PleaseProjectConfigBuilder, PleaseSettingsConfigBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Args, Debug, Clone)]
|
||||||
|
pub struct ConfigArgs {
|
||||||
|
/// Which repository to publish against. If not supplied remote url will be inferred from environment or fail if not present.
|
||||||
|
#[arg(
|
||||||
|
env = "CUDDLE_PLEASE_API_URL",
|
||||||
|
long,
|
||||||
|
global = true,
|
||||||
|
help_heading = "Config"
|
||||||
|
)]
|
||||||
|
pub api_url: Option<String>,
|
||||||
|
|
||||||
|
/// repo is the name of repository you want to release for
|
||||||
|
#[arg(
|
||||||
|
env = "CUDDLE_PLEASE_REPO",
|
||||||
|
long,
|
||||||
|
global = true,
|
||||||
|
help_heading = "Config"
|
||||||
|
)]
|
||||||
|
pub repo: Option<String>,
|
||||||
|
|
||||||
|
/// owner is the name of user from which the repository belongs <user>/<repo>
|
||||||
|
#[arg(
|
||||||
|
env = "CUDDLE_PLEASE_OWNER",
|
||||||
|
long,
|
||||||
|
global = true,
|
||||||
|
help_heading = "Config"
|
||||||
|
)]
|
||||||
|
pub owner: Option<String>,
|
||||||
|
|
||||||
|
/// which source directory to use, if not set `std::env::current_dir` is used instead.
|
||||||
|
#[arg(
|
||||||
|
env = "CUDDLE_PLEASE_SOURCE",
|
||||||
|
long,
|
||||||
|
global = true,
|
||||||
|
help_heading = "Config"
|
||||||
|
)]
|
||||||
|
pub source: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// which branch is being run from
|
||||||
|
#[arg(
|
||||||
|
env = "CUDDLE_PLEASE_BRANCH",
|
||||||
|
long,
|
||||||
|
global = true,
|
||||||
|
help_heading = "Config"
|
||||||
|
)]
|
||||||
|
pub branch: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ConfigArgs> for PleaseConfigBuilder {
|
||||||
|
fn from(value: ConfigArgs) -> Self {
|
||||||
|
Self {
|
||||||
|
project: Some(PleaseProjectConfigBuilder {
|
||||||
|
owner: value.owner,
|
||||||
|
repository: value.repo,
|
||||||
|
source: value.source,
|
||||||
|
branch: value.branch,
|
||||||
|
}),
|
||||||
|
settings: Some(PleaseSettingsConfigBuilder {
|
||||||
|
api_url: value.api_url,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
crates/cuddle-please-frontend/src/gatheres/config_file.rs
Normal file
80
crates/cuddle-please-frontend/src/gatheres/config_file.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::stage0_config::PleaseConfigBuilder;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
struct CuddleEmbeddedPleaseConfig {
|
||||||
|
please: PleaseConfigBuilder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CuddleEmbeddedPleaseConfig> for PleaseConfigBuilder {
|
||||||
|
fn from(value: CuddleEmbeddedPleaseConfig) -> Self {
|
||||||
|
value.please
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
struct CuddlePleaseConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
please: PleaseConfigBuilder,
|
||||||
|
}
|
||||||
|
impl From<CuddlePleaseConfig> for PleaseConfigBuilder {
|
||||||
|
fn from(value: CuddlePleaseConfig) -> Self {
|
||||||
|
value.please
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CUDDLE_FILE_NAME: &str = "cuddle";
|
||||||
|
const CUDDLE_CONFIG_FILE_NAME: &str = "cuddle.please";
|
||||||
|
const YAML_EXTENSION: &str = "yaml";
|
||||||
|
|
||||||
|
pub fn get_config_from_config_file(current_dir: &Path) -> PleaseConfigBuilder {
|
||||||
|
let current_cuddle_path = current_dir
|
||||||
|
.clone()
|
||||||
|
.join(format!("{CUDDLE_FILE_NAME}.{YAML_EXTENSION}"));
|
||||||
|
let current_cuddle_config_path = current_dir
|
||||||
|
.clone()
|
||||||
|
.join(format!("{CUDDLE_CONFIG_FILE_NAME}.{YAML_EXTENSION}"));
|
||||||
|
let mut please_config = PleaseConfigBuilder::default();
|
||||||
|
|
||||||
|
if let Some(config) = get_config_from_file::<CuddleEmbeddedPleaseConfig>(current_cuddle_path) {
|
||||||
|
please_config = please_config.merge(&config).clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(config) = get_config_from_file::<CuddlePleaseConfig>(current_cuddle_config_path) {
|
||||||
|
please_config = please_config.merge(&config).clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
please_config
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_config_from_file<T>(current_cuddle_path: PathBuf) -> Option<PleaseConfigBuilder>
|
||||||
|
where
|
||||||
|
T: DeserializeOwned,
|
||||||
|
T: Into<PleaseConfigBuilder>,
|
||||||
|
{
|
||||||
|
match std::fs::File::open(¤t_cuddle_path) {
|
||||||
|
Ok(file) => match serde_yaml::from_reader::<_, T>(file) {
|
||||||
|
Ok(config) => {
|
||||||
|
return Some(config.into());
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!(
|
||||||
|
"{} doesn't contain a valid please config: {}",
|
||||||
|
¤t_cuddle_path.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!(
|
||||||
|
"did not find or was not allowed to read {}, error: {}",
|
||||||
|
¤t_cuddle_path.display(),
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
53
crates/cuddle-please-frontend/src/gatheres/execution_env.rs
Normal file
53
crates/cuddle-please-frontend/src/gatheres/execution_env.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
use crate::stage0_config::{PleaseConfigBuilder, PleaseProjectConfigBuilder};
|
||||||
|
|
||||||
|
pub fn get_from_environment(vars: std::env::Vars) -> PleaseConfigBuilder {
|
||||||
|
let vars: HashMap<String, String> = vars.collect();
|
||||||
|
|
||||||
|
let env = detect_environment(&vars);
|
||||||
|
|
||||||
|
match env {
|
||||||
|
ExecutionEnvironment::Local => PleaseConfigBuilder {
|
||||||
|
project: Some(PleaseProjectConfigBuilder {
|
||||||
|
source: Some(PathBuf::from(".")),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
settings: None,
|
||||||
|
},
|
||||||
|
ExecutionEnvironment::Drone => PleaseConfigBuilder {
|
||||||
|
project: Some(PleaseProjectConfigBuilder {
|
||||||
|
owner: Some(
|
||||||
|
vars.get("DRONE_REPO_OWNER")
|
||||||
|
.expect("DRONE_REPO_OWNER to be present")
|
||||||
|
.clone(),
|
||||||
|
),
|
||||||
|
repository: Some(
|
||||||
|
vars.get("DRONE_REPO_NAME")
|
||||||
|
.expect("DRONE_REPO_NAME to be present")
|
||||||
|
.clone(),
|
||||||
|
),
|
||||||
|
source: Some(PathBuf::from(".")),
|
||||||
|
branch: Some(
|
||||||
|
vars.get("DRONE_REPO_BRANCH")
|
||||||
|
.expect("DRONE_REPO_BRANCH to be present")
|
||||||
|
.clone(),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
settings: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detect_environment(vars: &HashMap<String, String>) -> ExecutionEnvironment {
|
||||||
|
if let Some(_) = vars.get("DRONE".into()) {
|
||||||
|
return ExecutionEnvironment::Drone;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecutionEnvironment::Local
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ExecutionEnvironment {
|
||||||
|
Local,
|
||||||
|
Drone,
|
||||||
|
}
|
9
crates/cuddle-please-frontend/src/gatheres/mod.rs
Normal file
9
crates/cuddle-please-frontend/src/gatheres/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
mod cli;
|
||||||
|
mod config_file;
|
||||||
|
mod execution_env;
|
||||||
|
mod stdin;
|
||||||
|
|
||||||
|
pub use cli::ConfigArgs;
|
||||||
|
pub(crate) use config_file::get_config_from_config_file;
|
||||||
|
pub(crate) use execution_env::get_from_environment;
|
||||||
|
pub(crate) use stdin::get_config_from_stdin;
|
19
crates/cuddle-please-frontend/src/gatheres/stdin.rs
Normal file
19
crates/cuddle-please-frontend/src/gatheres/stdin.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use crate::stage0_config::PleaseConfigBuilder;
|
||||||
|
|
||||||
|
pub fn get_config_from_stdin<'d, T>(stdin: &'d str) -> PleaseConfigBuilder
|
||||||
|
where
|
||||||
|
T: Deserialize<'d>,
|
||||||
|
T: Into<PleaseConfigBuilder>,
|
||||||
|
{
|
||||||
|
match serde_yaml::from_str::<'d, T>(stdin) {
|
||||||
|
Ok(config) => {
|
||||||
|
return config.into();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!("stdin doesn't contain a valid please config: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PleaseConfigBuilder::default()
|
||||||
|
}
|
95
crates/cuddle-please-frontend/src/lib.rs
Normal file
95
crates/cuddle-please-frontend/src/lib.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
pub mod gatheres;
|
||||||
|
mod stage0_config;
|
||||||
|
|
||||||
|
pub use gatheres::ConfigArgs;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PleaseProjectConfig {
|
||||||
|
pub owner: String,
|
||||||
|
pub repository: String,
|
||||||
|
pub source: PathBuf,
|
||||||
|
pub branch: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PleaseSettingsConfig {
|
||||||
|
pub api_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PleaseConfig {
|
||||||
|
pub project: PleaseProjectConfig,
|
||||||
|
pub settings: PleaseSettingsConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PleaseConfig {
|
||||||
|
pub fn get_owner<'a>(&'a self) -> &'a str {
|
||||||
|
&self.project.owner
|
||||||
|
}
|
||||||
|
pub fn get_repository<'a>(&'a self) -> &'a str {
|
||||||
|
&self.project.repository
|
||||||
|
}
|
||||||
|
pub fn get_source<'a>(&'a self) -> &'a PathBuf {
|
||||||
|
&self.project.source
|
||||||
|
}
|
||||||
|
pub fn get_branch<'a>(&'a self) -> &'a str {
|
||||||
|
&self.project.branch
|
||||||
|
}
|
||||||
|
pub fn get_api_url<'a>(&'a self) -> &'a str {
|
||||||
|
&self.settings.api_url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct PleaseConfigBuilder {
|
||||||
|
stdin: Option<stage0_config::PleaseConfigBuilder>,
|
||||||
|
execution_env: Option<stage0_config::PleaseConfigBuilder>,
|
||||||
|
cli: Option<stage0_config::PleaseConfigBuilder>,
|
||||||
|
config: Option<stage0_config::PleaseConfigBuilder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PleaseConfigBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_stdin(&mut self, stdin: String) -> &mut Self {
|
||||||
|
self.stdin = Some(gatheres::get_config_from_stdin::<
|
||||||
|
stage0_config::PleaseConfigBuilder,
|
||||||
|
>(stdin.as_str()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_config_file(&mut self, current_dir: &Path) -> &mut Self {
|
||||||
|
self.config = Some(gatheres::get_config_from_config_file(current_dir));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_execution_env(&mut self, env_bag: std::env::Vars) -> &mut Self {
|
||||||
|
self.execution_env = Some(gatheres::get_from_environment(env_bag));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_cli(&mut self, cli: gatheres::ConfigArgs) -> &mut Self {
|
||||||
|
self.cli = Some(cli.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&mut self) -> anyhow::Result<PleaseConfig> {
|
||||||
|
let gathered = vec![&self.execution_env, &self.config, &self.stdin, &self.cli];
|
||||||
|
|
||||||
|
let final_config = gathered
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.fold(stage0_config::PleaseConfigBuilder::default(), |mut a, x| {
|
||||||
|
a.merge(x).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(final_config.try_into()?)
|
||||||
|
}
|
||||||
|
}
|
111
crates/cuddle-please-frontend/src/stage0_config.rs
Normal file
111
crates/cuddle-please-frontend/src/stage0_config.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use std::{default, path::PathBuf};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{PleaseConfig, PleaseProjectConfig, PleaseSettingsConfig};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct PleaseProjectConfigBuilder {
|
||||||
|
pub owner: Option<String>,
|
||||||
|
pub repository: Option<String>,
|
||||||
|
pub source: Option<PathBuf>,
|
||||||
|
pub branch: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct PleaseSettingsConfigBuilder {
|
||||||
|
pub api_url: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct PleaseConfigBuilder {
|
||||||
|
pub project: Option<PleaseProjectConfigBuilder>,
|
||||||
|
pub settings: Option<PleaseSettingsConfigBuilder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PleaseConfigBuilder {
|
||||||
|
pub fn merge(&mut self, config: &PleaseConfigBuilder) -> &Self {
|
||||||
|
let config = config.clone();
|
||||||
|
let mut fproject = match self.project.clone() {
|
||||||
|
None => PleaseProjectConfigBuilder::default(),
|
||||||
|
Some(project) => project,
|
||||||
|
};
|
||||||
|
let mut fsettings = match self.settings.clone() {
|
||||||
|
None => PleaseSettingsConfigBuilder::default(),
|
||||||
|
Some(settings) => settings,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(mut project) = config.project {
|
||||||
|
if let Some(owner) = project.owner {
|
||||||
|
fproject.owner = Some(owner);
|
||||||
|
}
|
||||||
|
if let Some(repository) = project.repository {
|
||||||
|
fproject.repository = Some(repository);
|
||||||
|
}
|
||||||
|
if let Some(source) = project.source {
|
||||||
|
fproject.source = Some(source);
|
||||||
|
}
|
||||||
|
if let Some(branch) = project.branch {
|
||||||
|
fproject.branch = Some(branch);
|
||||||
|
}
|
||||||
|
self.project = Some(fproject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut settings) = config.settings {
|
||||||
|
if let Some(api_url) = settings.api_url {
|
||||||
|
fsettings.api_url = Some(api_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.settings = Some(fsettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PleaseConfigBuilder> for PleaseConfig {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: PleaseConfigBuilder) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
project: value
|
||||||
|
.project
|
||||||
|
.ok_or(value_is_missing("project"))?
|
||||||
|
.try_into()?,
|
||||||
|
settings: value
|
||||||
|
.settings
|
||||||
|
.ok_or(value_is_missing("settings"))?
|
||||||
|
.try_into()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PleaseProjectConfigBuilder> for PleaseProjectConfig {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: PleaseProjectConfigBuilder) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
owner: value.owner.ok_or(value_is_missing("owner"))?,
|
||||||
|
repository: value.repository.ok_or(value_is_missing("repository"))?,
|
||||||
|
source: value.source.ok_or(value_is_missing("source"))?,
|
||||||
|
branch: value.branch.ok_or(value_is_missing("branch"))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PleaseSettingsConfigBuilder> for PleaseSettingsConfig {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: PleaseSettingsConfigBuilder) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
api_url: value.api_url.ok_or(value_is_missing("api_url"))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_is_missing(message: &str) -> anyhow::Error {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"{} is required, pass via. cli, env or config file, see --help",
|
||||||
|
message.to_string()
|
||||||
|
)
|
||||||
|
}
|
@ -4,6 +4,8 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
cuddle-please-frontend.workspace = true
|
||||||
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
|
@ -8,11 +8,10 @@ use std::{
|
|||||||
use ::semver::Version;
|
use ::semver::Version;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfig, PleaseConfigBuilder};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cliff::{self, changelog_parser},
|
cliff::{self, changelog_parser},
|
||||||
environment::get_from_environment,
|
|
||||||
git_client::VcsClient,
|
git_client::VcsClient,
|
||||||
gitea_client::GiteaClient,
|
gitea_client::GiteaClient,
|
||||||
ui::{ConsoleUi, DynUi},
|
ui::{ConsoleUi, DynUi},
|
||||||
@ -27,6 +26,9 @@ pub struct Command {
|
|||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
global: GlobalArgs,
|
global: GlobalArgs,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
config: ConfigArgs,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
commands: Option<Commands>,
|
commands: Option<Commands>,
|
||||||
|
|
||||||
@ -49,32 +51,13 @@ struct GlobalArgs {
|
|||||||
)]
|
)]
|
||||||
token: Option<String>,
|
token: Option<String>,
|
||||||
|
|
||||||
/// Which repository to publish against. If not supplied remote url will be inferred from environment or fail if not present.
|
|
||||||
#[arg(long, global = true, help_heading = "Global")]
|
|
||||||
api_url: Option<String>,
|
|
||||||
|
|
||||||
/// repo is the name of repository you want to release for
|
|
||||||
#[arg(long, global = true, help_heading = "Global")]
|
|
||||||
repo: Option<String>,
|
|
||||||
|
|
||||||
/// owner is the name of user from which the repository belongs <user>/<repo>
|
|
||||||
#[arg(long, global = true, help_heading = "Global")]
|
|
||||||
owner: Option<String>,
|
|
||||||
|
|
||||||
/// which source directory to use, if not set `std::env::current_dir` is used instead.
|
|
||||||
#[arg(long, global = true, help_heading = "Global")]
|
|
||||||
source: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// which branch is being run from
|
|
||||||
#[arg(long, global = true, help_heading = "Global")]
|
|
||||||
branch: Option<String>,
|
|
||||||
|
|
||||||
/// whether to run in dry run mode (i.e. no pushes or releases)
|
/// whether to run in dry run mode (i.e. no pushes or releases)
|
||||||
#[arg(long, global = true, help_heading = "Global")]
|
#[arg(long, global = true, help_heading = "Global")]
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
|
|
||||||
/// Inject configuration from stdin
|
/// Inject configuration from stdin
|
||||||
#[arg(
|
#[arg(
|
||||||
|
env = "CUDDLE_PLEASE_CONFIG_STDIN",
|
||||||
long,
|
long,
|
||||||
global = true,
|
global = true,
|
||||||
help_heading = "Global",
|
help_heading = "Global",
|
||||||
@ -138,31 +121,23 @@ impl Command {
|
|||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config(
|
|
||||||
&self,
|
|
||||||
current_dir: &Path,
|
|
||||||
stdin: Option<String>,
|
|
||||||
) -> anyhow::Result<PleaseConfig> {
|
|
||||||
let mut config = get_config(current_dir, stdin)?;
|
|
||||||
|
|
||||||
self.get_from_environment(&mut config)?;
|
|
||||||
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn execute(self, current_dir: Option<&Path>) -> anyhow::Result<()> {
|
pub fn execute(self, current_dir: Option<&Path>) -> anyhow::Result<()> {
|
||||||
// 1. Parse the current directory
|
// 0. Get config
|
||||||
let current_dir = get_current_path(current_dir, self.global.source.clone())?;
|
let mut builder = &mut PleaseConfigBuilder::new();
|
||||||
let stdin = if self.global.config_stdin {
|
|
||||||
|
if self.global.config_stdin {
|
||||||
if let Some(stdin_fn) = self.stdin.clone() {
|
if let Some(stdin_fn) = self.stdin.clone() {
|
||||||
let output = (stdin_fn.lock().unwrap().deref())();
|
let output = (stdin_fn.lock().unwrap().deref())();
|
||||||
Some(output.unwrap())
|
builder = builder.with_stdin(output?);
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
None
|
// 1. Parse the current directory
|
||||||
};
|
let current_dir = get_current_path(current_dir, self.config.source.clone())?;
|
||||||
|
let config = builder
|
||||||
|
.with_config_file(¤t_dir)
|
||||||
|
.with_execution_env(std::env::vars())
|
||||||
|
.with_cli(self.config.clone())
|
||||||
|
.build()?;
|
||||||
|
|
||||||
match &self.commands {
|
match &self.commands {
|
||||||
Some(Commands::Release {}) => {
|
Some(Commands::Release {}) => {
|
||||||
@ -170,30 +145,24 @@ impl Command {
|
|||||||
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
||||||
// 2a. if not existing use default.
|
// 2a. if not existing use default.
|
||||||
// 2b. if not in a git repo abort. (unless --no-vcs is turned added)
|
// 2b. if not in a git repo abort. (unless --no-vcs is turned added)
|
||||||
let _config = self.get_config(¤t_dir, stdin)?;
|
let git_client = self.get_git(config.get_source())?;
|
||||||
|
|
||||||
let owner = self.global.owner.as_ref().expect("owner to be set");
|
|
||||||
let repo = self.global.repo.as_ref().expect("repo to be set");
|
|
||||||
let branch = self.global.branch.as_ref().expect("branch to be set");
|
|
||||||
|
|
||||||
let git_client = self.get_git(¤t_dir)?;
|
|
||||||
|
|
||||||
// 3. Create gitea client and do a health check
|
// 3. Create gitea client and do a health check
|
||||||
let gitea_client = self.get_gitea_client();
|
let gitea_client = self.get_gitea_client();
|
||||||
gitea_client
|
gitea_client
|
||||||
.connect(owner, repo)
|
.connect(config.get_owner(), config.get_repository())
|
||||||
.context("failed to connect to gitea repository")?;
|
.context("failed to connect to gitea repository")?;
|
||||||
// 4. Fetch git tags for the current repository
|
// 4. Fetch git tags for the current repository
|
||||||
let tags = gitea_client.get_tags(owner, repo)?;
|
let tags = gitea_client.get_tags(config.get_owner(), config.get_repository())?;
|
||||||
|
|
||||||
let significant_tag = get_most_significant_version(tags.iter().collect());
|
let significant_tag = get_most_significant_version(tags.iter().collect());
|
||||||
|
|
||||||
// 5. Fetch git commits since last git tag
|
// 5. Fetch git commits since last git tag
|
||||||
let commits = gitea_client.get_commits_since(
|
let commits = gitea_client.get_commits_since(
|
||||||
owner,
|
config.get_owner(),
|
||||||
repo,
|
config.get_repository(),
|
||||||
significant_tag.map(|st| st.commit.sha.clone()),
|
significant_tag.map(|st| st.commit.sha.clone()),
|
||||||
branch,
|
config.get_branch(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// 7. Create a versioning client
|
// 7. Create a versioning client
|
||||||
@ -219,12 +188,7 @@ impl Command {
|
|||||||
let builder =
|
let builder =
|
||||||
cliff::ChangeLogBuilder::new(&commit_strs, next_version.to_string()).build();
|
cliff::ChangeLogBuilder::new(&commit_strs, next_version.to_string()).build();
|
||||||
|
|
||||||
let changelog_placement = self
|
let changelog_placement = config.get_source().join("CHANGELOG.md");
|
||||||
.global
|
|
||||||
.source
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| s.join("CHANGELOG.md"))
|
|
||||||
.unwrap_or(PathBuf::from("CHANGELOG.md"));
|
|
||||||
|
|
||||||
let changelog = match std::fs::read_to_string(&changelog_placement).ok() {
|
let changelog = match std::fs::read_to_string(&changelog_placement).ok() {
|
||||||
Some(existing_changelog) => builder.prepend(existing_changelog)?,
|
Some(existing_changelog) => builder.prepend(existing_changelog)?,
|
||||||
@ -239,8 +203,8 @@ impl Command {
|
|||||||
if first_commit.contains("chore(release): ") {
|
if first_commit.contains("chore(release): ") {
|
||||||
if !self.global.dry_run {
|
if !self.global.dry_run {
|
||||||
gitea_client.create_release(
|
gitea_client.create_release(
|
||||||
owner,
|
config.get_owner(),
|
||||||
repo,
|
config.get_repository(),
|
||||||
next_version.to_string(),
|
next_version.to_string(),
|
||||||
changelog_last_changes.unwrap(),
|
changelog_last_changes.unwrap(),
|
||||||
!next_version.pre.is_empty(),
|
!next_version.pre.is_empty(),
|
||||||
@ -261,12 +225,14 @@ impl Command {
|
|||||||
|
|
||||||
git_client.commit_and_push(next_version.to_string(), self.global.dry_run)?;
|
git_client.commit_and_push(next_version.to_string(), self.global.dry_run)?;
|
||||||
|
|
||||||
let _pr_number = match gitea_client.get_pull_request(owner, repo)? {
|
let _pr_number = match gitea_client
|
||||||
|
.get_pull_request(config.get_owner(), config.get_repository())?
|
||||||
|
{
|
||||||
Some(existing_pr) => {
|
Some(existing_pr) => {
|
||||||
if !self.global.dry_run {
|
if !self.global.dry_run {
|
||||||
gitea_client.update_pull_request(
|
gitea_client.update_pull_request(
|
||||||
owner,
|
config.get_owner(),
|
||||||
repo,
|
config.get_repository(),
|
||||||
next_version.to_string(),
|
next_version.to_string(),
|
||||||
changelog_last_changes.unwrap(),
|
changelog_last_changes.unwrap(),
|
||||||
existing_pr,
|
existing_pr,
|
||||||
@ -279,11 +245,11 @@ impl Command {
|
|||||||
None => {
|
None => {
|
||||||
if !self.global.dry_run {
|
if !self.global.dry_run {
|
||||||
gitea_client.create_pull_request(
|
gitea_client.create_pull_request(
|
||||||
owner,
|
config.get_owner(),
|
||||||
repo,
|
config.get_repository(),
|
||||||
next_version.to_string(),
|
next_version.to_string(),
|
||||||
changelog,
|
changelog,
|
||||||
self.global.branch.clone().unwrap(),
|
config.get_branch(),
|
||||||
)?
|
)?
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!("creating pull request (dry_run)");
|
tracing::debug!("creating pull request (dry_run)");
|
||||||
@ -296,13 +262,12 @@ impl Command {
|
|||||||
Some(Commands::Config { command }) => match command {
|
Some(Commands::Config { command }) => match command {
|
||||||
ConfigCommand::List { .. } => {
|
ConfigCommand::List { .. } => {
|
||||||
tracing::debug!("running command: config list");
|
tracing::debug!("running command: config list");
|
||||||
let _config = self.get_config(current_dir.as_path(), stdin)?;
|
|
||||||
|
|
||||||
self.ui.write_str_ln("cuddle-config");
|
self.ui.write_str_ln("cuddle-config");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(Commands::Gitea { command }) => {
|
Some(Commands::Gitea { command }) => {
|
||||||
let git_url = url::Url::parse(&self.global.api_url.unwrap())?;
|
let git_url = url::Url::parse(config.get_api_url())?;
|
||||||
|
|
||||||
let mut url = String::new();
|
let mut url = String::new();
|
||||||
url.push_str(git_url.scheme());
|
url.push_str(git_url.scheme());
|
||||||
@ -315,13 +280,13 @@ impl Command {
|
|||||||
let client = GiteaClient::new(url, self.global.token);
|
let client = GiteaClient::new(url, self.global.token);
|
||||||
match command {
|
match command {
|
||||||
GiteaCommand::Connect {} => {
|
GiteaCommand::Connect {} => {
|
||||||
client.connect(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
client.connect(config.get_owner(), config.get_repository())?;
|
||||||
self.ui.write_str_ln("connected succesfully go gitea");
|
self.ui.write_str_ln("connected succesfully go gitea");
|
||||||
}
|
}
|
||||||
GiteaCommand::Tags { command } => match command {
|
GiteaCommand::Tags { command } => match command {
|
||||||
Some(GiteaTagsCommand::MostSignificant {}) => {
|
Some(GiteaTagsCommand::MostSignificant {}) => {
|
||||||
let tags = client
|
let tags =
|
||||||
.get_tags(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
client.get_tags(config.get_owner(), config.get_repository())?;
|
||||||
|
|
||||||
match get_most_significant_version(tags.iter().collect()) {
|
match get_most_significant_version(tags.iter().collect()) {
|
||||||
Some(tag) => {
|
Some(tag) => {
|
||||||
@ -336,8 +301,8 @@ impl Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let tags = client
|
let tags =
|
||||||
.get_tags(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
client.get_tags(config.get_owner(), config.get_repository())?;
|
||||||
self.ui.write_str_ln("got tags from gitea");
|
self.ui.write_str_ln("got tags from gitea");
|
||||||
for tag in tags {
|
for tag in tags {
|
||||||
self.ui.write_str_ln(&format!("- {}", tag.name))
|
self.ui.write_str_ln(&format!("- {}", tag.name))
|
||||||
@ -346,8 +311,8 @@ impl Command {
|
|||||||
},
|
},
|
||||||
GiteaCommand::SinceCommit { sha, branch } => {
|
GiteaCommand::SinceCommit { sha, branch } => {
|
||||||
let commits = client.get_commits_since(
|
let commits = client.get_commits_since(
|
||||||
self.global.owner.unwrap(),
|
config.get_owner(),
|
||||||
self.global.repo.unwrap(),
|
config.get_repository(),
|
||||||
Some(sha),
|
Some(sha),
|
||||||
branch,
|
branch,
|
||||||
)?;
|
)?;
|
||||||
@ -357,10 +322,8 @@ impl Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
GiteaCommand::CheckPr {} => {
|
GiteaCommand::CheckPr {} => {
|
||||||
let pr = client.get_pull_request(
|
let pr =
|
||||||
self.global.owner.unwrap(),
|
client.get_pull_request(config.get_owner(), config.get_repository())?;
|
||||||
self.global.repo.unwrap(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
match pr {
|
match pr {
|
||||||
Some(index) => {
|
Some(index) => {
|
||||||
@ -398,16 +361,9 @@ impl Command {
|
|||||||
VcsClient::new_git(current_dir)
|
VcsClient::new_git(current_dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_from_environment(&self, config: &mut PleaseConfig) -> anyhow::Result<()> {
|
|
||||||
let input_config = get_from_environment();
|
|
||||||
config.merge_mut(input_config);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_gitea_client(&self) -> GiteaClient {
|
fn get_gitea_client(&self) -> GiteaClient {
|
||||||
GiteaClient::new(
|
GiteaClient::new(
|
||||||
self.global.api_url.clone().expect("api_url to be set"),
|
self.config.api_url.clone().expect("api_url to be set"),
|
||||||
self.global.token.clone(),
|
self.global.token.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -469,7 +425,8 @@ fn get_current_path(
|
|||||||
.or_else(|| optional_current_dir.map(|p| p.to_path_buf())) // fall back on current env from environment
|
.or_else(|| optional_current_dir.map(|p| p.to_path_buf())) // fall back on current env from environment
|
||||||
.filter(|v| v.to_string_lossy() != "") // make sure we don't get empty values
|
.filter(|v| v.to_string_lossy() != "") // make sure we don't get empty values
|
||||||
//.and_then(|p| p.canonicalize().ok()) // Make sure we get the absolute path
|
//.and_then(|p| p.canonicalize().ok()) // Make sure we get the absolute path
|
||||||
.context("could not find current dir, pass --source as a replacement")?;
|
//.context("could not find current dir, pass --source as a replacement")?;
|
||||||
|
.unwrap_or(PathBuf::from("."));
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
anyhow::bail!("path doesn't exist {}", path.display());
|
anyhow::bail!("path doesn't exist {}", path.display());
|
||||||
@ -477,131 +434,3 @@ fn get_current_path(
|
|||||||
|
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct PleaseProjectConfig {
|
|
||||||
pub owner: Option<String>,
|
|
||||||
pub repository: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct PleaseSettingsConfig {
|
|
||||||
pub api_url: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
||||||
pub struct PleaseConfig {
|
|
||||||
pub project: Option<PleaseProjectConfig>,
|
|
||||||
pub settings: Option<PleaseSettingsConfig>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PleaseConfig {
|
|
||||||
fn merge(self, _config: PleaseConfig) -> Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn merge_mut(&mut self, _config: PleaseConfig) -> &mut Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct CuddleEmbeddedPleaseConfig {
|
|
||||||
please: PleaseConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CuddleEmbeddedPleaseConfig> for PleaseConfig {
|
|
||||||
fn from(value: CuddleEmbeddedPleaseConfig) -> Self {
|
|
||||||
value.please
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
struct CuddlePleaseConfig {
|
|
||||||
#[serde(flatten)]
|
|
||||||
please: PleaseConfig,
|
|
||||||
}
|
|
||||||
impl From<CuddlePleaseConfig> for PleaseConfig {
|
|
||||||
fn from(value: CuddlePleaseConfig) -> Self {
|
|
||||||
value.please
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CUDDLE_FILE_NAME: &str = "cuddle";
|
|
||||||
const CUDDLE_CONFIG_FILE_NAME: &str = "cuddle.please";
|
|
||||||
const YAML_EXTENSION: &str = "yaml";
|
|
||||||
|
|
||||||
fn get_config(current_dir: &Path, stdin: Option<String>) -> anyhow::Result<PleaseConfig> {
|
|
||||||
let current_cuddle_path = current_dir
|
|
||||||
.clone()
|
|
||||||
.join(format!("{CUDDLE_FILE_NAME}.{YAML_EXTENSION}"));
|
|
||||||
let current_cuddle_config_path = current_dir
|
|
||||||
.clone()
|
|
||||||
.join(format!("{CUDDLE_CONFIG_FILE_NAME}.{YAML_EXTENSION}"));
|
|
||||||
let mut please_config = PleaseConfig::default();
|
|
||||||
|
|
||||||
if let Some(config) = get_config_from_file::<CuddleEmbeddedPleaseConfig>(current_cuddle_path) {
|
|
||||||
please_config = please_config.merge(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(config) = get_config_from_file::<CuddlePleaseConfig>(current_cuddle_config_path) {
|
|
||||||
please_config = please_config.merge(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(input_config) = get_config_from_stdin::<CuddlePleaseConfig>(stdin.as_ref()) {
|
|
||||||
please_config = please_config.merge(input_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(please_config)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_config_from_file<T>(current_cuddle_path: PathBuf) -> Option<PleaseConfig>
|
|
||||||
where
|
|
||||||
T: DeserializeOwned,
|
|
||||||
T: Into<PleaseConfig>,
|
|
||||||
{
|
|
||||||
match std::fs::File::open(¤t_cuddle_path) {
|
|
||||||
Ok(file) => match serde_yaml::from_reader::<_, T>(file) {
|
|
||||||
Ok(config) => {
|
|
||||||
return Some(config.into());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
tracing::debug!(
|
|
||||||
"{} doesn't contain a valid please config: {}",
|
|
||||||
¤t_cuddle_path.display(),
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
tracing::debug!(
|
|
||||||
"did not find or was not allowed to read {}, error: {}",
|
|
||||||
¤t_cuddle_path.display(),
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_config_from_stdin<'d, T>(stdin: Option<&'d String>) -> Option<PleaseConfig>
|
|
||||||
where
|
|
||||||
T: Deserialize<'d>,
|
|
||||||
T: Into<PleaseConfig>,
|
|
||||||
{
|
|
||||||
match stdin {
|
|
||||||
Some(content) => match serde_yaml::from_str::<'d, T>(content) {
|
|
||||||
Ok(config) => {
|
|
||||||
return Some(config.into());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
tracing::debug!("stdin doesn't contain a valid please config: {}", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
tracing::trace!("Stdin was not set continueing",);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
use crate::command::{PleaseConfig, PleaseProjectConfig};
|
|
||||||
|
|
||||||
pub mod drone;
|
|
||||||
|
|
||||||
pub fn get_from_environment() -> PleaseConfig {
|
|
||||||
let env = detect_environment();
|
|
||||||
|
|
||||||
match env {
|
|
||||||
ExecutionEnvironment::Local => PleaseConfig {
|
|
||||||
project: None,
|
|
||||||
settings: None,
|
|
||||||
},
|
|
||||||
ExecutionEnvironment::Drone => PleaseConfig {
|
|
||||||
project: Some(PleaseProjectConfig {
|
|
||||||
owner: Some(
|
|
||||||
std::env::var("DRONE_REPO_OWNER").expect("DRONE_REPO_OWNER to be present"),
|
|
||||||
),
|
|
||||||
repository: Some(
|
|
||||||
std::env::var("DRONE_REPO_NAME").expect("DRONE_REPO_NAME to be present"),
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
settings: None,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn detect_environment() -> ExecutionEnvironment {
|
|
||||||
if std::env::var("DRONE").is_ok() {
|
|
||||||
return ExecutionEnvironment::Drone;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecutionEnvironment::Local
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExecutionEnvironment {
|
|
||||||
Local,
|
|
||||||
Drone,
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
pub mod cliff;
|
pub mod cliff;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod environment;
|
|
||||||
pub mod git_client;
|
pub mod git_client;
|
||||||
pub mod gitea_client;
|
pub mod gitea_client;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
pub mod cliff;
|
pub mod cliff;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod environment;
|
|
||||||
pub mod git_client;
|
pub mod git_client;
|
||||||
pub mod gitea_client;
|
pub mod gitea_client;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
6
crates/cuddle-please/testdata/cuddle-embed/cuddle.please.yaml
vendored
Normal file
6
crates/cuddle-please/testdata/cuddle-embed/cuddle.please.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
project:
|
||||||
|
owner: kjuulh
|
||||||
|
repository: cuddle-please
|
||||||
|
branch: main
|
||||||
|
settings:
|
||||||
|
api_url: https://some-example.gitea-instance
|
@ -0,0 +1,7 @@
|
|||||||
|
please:
|
||||||
|
project:
|
||||||
|
owner: kjuulh
|
||||||
|
repository: cuddle-please
|
||||||
|
branch: main
|
||||||
|
settings:
|
||||||
|
api_url: https://some-example.gitea-instance
|
@ -0,0 +1,6 @@
|
|||||||
|
project:
|
||||||
|
owner: kjuulh
|
||||||
|
repository: cuddle-please
|
||||||
|
branch: main
|
||||||
|
settings:
|
||||||
|
api_url: https://some-example.gitea-instance
|
@ -45,15 +45,19 @@ fn test_config_from_source_dir() {
|
|||||||
fn test_config_from_stdin() {
|
fn test_config_from_stdin() {
|
||||||
let mut args = get_base_args();
|
let mut args = get_base_args();
|
||||||
let ui = &BufferUi::default();
|
let ui = &BufferUi::default();
|
||||||
let current_dir = get_test_data_path("cuddle-embed");
|
let config = r#"
|
||||||
args.push("--source");
|
project:
|
||||||
args.push(current_dir.to_str().unwrap());
|
owner: kjuulh
|
||||||
args.push("--config-stdin");
|
repository: cuddle-please
|
||||||
|
branch: main
|
||||||
|
settings:
|
||||||
|
api_url: https://some-example.gitea-instance
|
||||||
|
"#;
|
||||||
|
|
||||||
Command::new_from_args_with_stdin(Some(ui), args, || Ok("please".into()))
|
args.push("--config-stdin");
|
||||||
|
Command::new_from_args_with_stdin(Some(ui), args, || Ok(config.into()))
|
||||||
.execute(None)
|
.execute(None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_output(ui, "cuddle-config\n", "");
|
assert_output(ui, "cuddle-config\n", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user