Skip to content

Commit

Permalink
Interval and timeout are parsed with humantime (e.g. 20s).
Browse files Browse the repository at this point in the history
  • Loading branch information
bittrance committed Sep 20, 2023
1 parent bdd3f7f commit 844a332
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 24 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ edition = "2021"
[dependencies]
clap = { version = "4.1.4", features = ["derive"] }
gix = { version = "0.51.0", features = ["default", "blocking-network-client", "blocking-http-transport-reqwest-native-tls", "serde"] }
humantime = "2.1.0"
serde = { version = "1.0.152", features = ["derive"] }
serde_yaml = "0.9.17"
tempfile = "3.3.0"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ The plan forward, roughly in falling priority:

- [x] --poll-once to check all repos that are due, then exit
- [ ] verify azdo support - Byron/gitoxide#1025
- [ ] Reasonable timeout duration entry (i.e. not serde default secs/nanos)
- [x] Reasonable timeout duration entry (i.e. not serde default secs/nanos)
- [x] Errors in scoped blocks should cancel, not wait for watchdog to reach deadline
- [ ] allow configuring notification actions
- [ ] specialized notification action to update github status
- [ ] new git sha and branch name in action env vars
- [ ] changed task config should override state loaded from disk
- [ ] docker packaging
- [ ] readme with design and deployment options
- [ ] intelligent gitconfig handling
Expand Down
16 changes: 8 additions & 8 deletions src/opts.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fs::File, path::PathBuf};
use std::{fs::File, path::PathBuf, time::Duration};

use clap::Parser;
use serde::Deserialize;
Expand All @@ -7,7 +7,7 @@ use crate::{
actions::Action,
errors::GitOpsError,
store::{FileStore, Store},
task::{GitOpsConfig, GitTask},
task::{GitTask, GitTaskConfig},
};

#[derive(Parser)]
Expand All @@ -34,19 +34,19 @@ pub struct CliOptions {
#[clap(long)]
pub environment: Vec<String>,
/// Check repo for changes at this interval
#[clap(long)]
pub interval: Option<f32>,
#[arg(long, value_parser = humantime::parse_duration)]
pub interval: Option<Duration>,
/// Max run time for repo fetch plus action in seconds
#[clap(long)]
pub timeout: Option<f32>,
#[arg(long, value_parser = humantime::parse_duration)]
pub timeout: Option<Duration>,
/// Run once and exit
#[clap(long)]
pub once_only: bool,
}

#[derive(Deserialize)]
struct ConfigFile {
tasks: Vec<GitOpsConfig>,
tasks: Vec<GitTaskConfig>,
}

fn tasks_from_file(opts: &CliOptions) -> Result<Vec<GitTask>, GitOpsError> {
Expand All @@ -62,7 +62,7 @@ fn tasks_from_file(opts: &CliOptions) -> Result<Vec<GitTask>, GitOpsError> {
}

fn tasks_from_opts(opts: &CliOptions) -> Result<Vec<GitTask>, GitOpsError> {
let mut config: GitOpsConfig = TryFrom::try_from(opts)?;
let mut config: GitTaskConfig = TryFrom::try_from(opts)?;
let action: Action = TryFrom::try_from(opts)?;
config.add_action(action);
Ok(vec![GitTask::from_config(config, opts)])
Expand Down
61 changes: 46 additions & 15 deletions src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{
};

use gix::{hash::Kind, ObjectId, Url};
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};

use crate::{
actions::{run_action, Action},
Expand All @@ -30,14 +30,14 @@ pub trait Task {
}

pub struct GitTask {
config: GitOpsConfig,
config: GitTaskConfig,
repo_dir: PathBuf,
pub state: State,
worker: Option<JoinHandle<Result<ObjectId, GitOpsError>>>,
}

impl GitTask {
pub fn from_config(config: GitOpsConfig, opts: &CliOptions) -> Self {
pub fn from_config(config: GitTaskConfig, opts: &CliOptions) -> Self {
let repo_dir = opts
.repo_dir
.as_ref()
Expand Down Expand Up @@ -138,24 +138,38 @@ impl Default for State {
}
}

fn human_readable_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
let s: String = Deserialize::deserialize(deserializer)?;
humantime::parse_duration(&s).map_err(serde::de::Error::custom)
}

#[derive(Clone, Deserialize)]
pub struct GitOpsConfig {
pub struct GitTaskConfig {
name: String,
git: GitConfig,
actions: Vec<Action>,
#[serde(default = "GitOpsConfig::default_interval")]
#[serde(
default = "GitTaskConfig::default_interval",
deserialize_with = "human_readable_duration"
)]
interval: Duration,
#[serde(default = "GitOpsConfig::default_timeout")]
#[serde(
default = "GitTaskConfig::default_timeout",
deserialize_with = "human_readable_duration"
)]
timeout: Duration,
}

impl GitOpsConfig {
impl GitTaskConfig {
pub fn add_action(&mut self, action: Action) {
self.actions.push(action);
}
}

impl TryFrom<&CliOptions> for GitOpsConfig {
impl TryFrom<&CliOptions> for GitTaskConfig {
type Error = GitOpsError;

fn try_from(opts: &CliOptions) -> Result<Self, Self::Error> {
Expand All @@ -164,17 +178,13 @@ impl TryFrom<&CliOptions> for GitOpsConfig {
name: url.path.to_string(),
git: TryFrom::try_from(opts)?,
actions: Vec::new(),
interval: opts
.interval
.map_or(GitOpsConfig::default_interval(), Duration::from_secs_f32),
timeout: opts
.timeout
.map_or(GitOpsConfig::default_timeout(), Duration::from_secs_f32),
interval: opts.interval.unwrap_or(Self::default_interval()),
timeout: opts.timeout.unwrap_or(Self::default_timeout()),
})
}
}

impl GitOpsConfig {
impl GitTaskConfig {
pub fn default_interval() -> Duration {
Duration::from_secs(60)
}
Expand All @@ -183,3 +193,24 @@ impl GitOpsConfig {
Duration::from_secs(3600)
}
}

#[cfg(test)]
mod tests {
use std::time::Duration;

use super::GitTaskConfig;

#[test]
fn parse_gittaskconfig() {
let raw_config = r#"name: testo
git:
url: https://github.com/bittrance/kitops
timeout: 3s
interval: 1m 2s
actions: []
"#;
let config = serde_yaml::from_str::<GitTaskConfig>(raw_config).unwrap();
assert_eq!(config.timeout, Duration::from_secs(3));
assert_eq!(config.interval, Duration::from_secs(62));
}
}

0 comments on commit 844a332

Please sign in to comment.