First working rescheduling
This commit is contained in:
parent
adc6b7866a
commit
b25857f3af
7 changed files with 85 additions and 20 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use crate::task;
|
||||
use crate::util;
|
||||
|
||||
use anyhow::Context as _;
|
||||
use forgejo_api::structs::Issue;
|
||||
|
|
@ -33,12 +34,12 @@ fn task_from_issue(issue: &Issue) -> anyhow::Result<task::Task> {
|
|||
fn task_state_from_issue(issue: &Issue) -> anyhow::Result<task::State> {
|
||||
match issue.get_state()? {
|
||||
forgejo_api::structs::StateType::Open => Ok(task::State::Open {
|
||||
due: issue.due_date,
|
||||
due: issue.due_date.map(util::time_to_jiff),
|
||||
}),
|
||||
forgejo_api::structs::StateType::Closed => Ok(task::State::Completed {
|
||||
date: issue
|
||||
date: util::time_to_jiff(issue
|
||||
.closed_at
|
||||
.context("Closed issue without a closed_at date")?,
|
||||
.context("Closed issue without a closed_at date")?),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -124,19 +125,19 @@ async fn list_all_issues(ctx: &crate::Context) -> anyhow::Result<Vec<Issue>> {
|
|||
}
|
||||
|
||||
trait IssueExt {
|
||||
fn get_number(&self) -> anyhow::Result<u64>;
|
||||
fn get_number(&self) -> anyhow::Result<u32>;
|
||||
fn get_title(&self) -> anyhow::Result<String>;
|
||||
fn get_state(&self) -> anyhow::Result<forgejo_api::structs::StateType>;
|
||||
fn get_label_names(&self) -> anyhow::Result<Vec<String>>;
|
||||
}
|
||||
|
||||
impl IssueExt for Issue {
|
||||
fn get_number(&self) -> anyhow::Result<u64> {
|
||||
fn get_number(&self) -> anyhow::Result<u32> {
|
||||
Ok(self
|
||||
.number
|
||||
.context("Missing issue number")?
|
||||
.try_into()
|
||||
.context("Failed converting issue number to u64")?)
|
||||
.context("Failed converting issue number to u32")?)
|
||||
}
|
||||
|
||||
fn get_title(&self) -> anyhow::Result<String> {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ mod collect;
|
|||
mod ci_meta;
|
||||
mod context;
|
||||
mod scheduler;
|
||||
mod util;
|
||||
|
||||
use context::Context;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use crate::task;
|
||||
use crate::util;
|
||||
|
||||
use anyhow::Context as _;
|
||||
|
||||
pub async fn reschedule_recurring_tasks(
|
||||
ctx: &crate::Context,
|
||||
|
|
@ -17,10 +20,10 @@ pub async fn reschedule_recurring_tasks(
|
|||
continue;
|
||||
};
|
||||
|
||||
let due_date = next_due_date(*completed_date, recurring.interval);
|
||||
|
||||
let due_date = next_due_date(completed_date, recurring.interval);
|
||||
log::info!("Rescheduling {task} for {due_date}...");
|
||||
reopen_issue_with_due_date(ctx, task, due_date).await?;
|
||||
|
||||
reopen_issue_with_due_date(ctx, task, &due_date).await?;
|
||||
rescheduled += 1;
|
||||
}
|
||||
|
||||
|
|
@ -31,10 +34,41 @@ pub async fn reschedule_recurring_tasks(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn next_due_date(completed_date: time::OffsetDateTime, interval: task::RecurringInterval) -> time::OffsetDateTime {
|
||||
todo!()
|
||||
fn next_due_date(completed_date: &jiff::Zoned, interval: task::RecurringInterval) -> jiff::Zoned {
|
||||
let span = match interval {
|
||||
task::RecurringInterval::Months(m) => jiff::Span::new().months(m),
|
||||
task::RecurringInterval::Weeks(w) => jiff::Span::new().weeks(w),
|
||||
task::RecurringInterval::Days(d) => jiff::Span::new().days(d),
|
||||
};
|
||||
|
||||
completed_date + span
|
||||
}
|
||||
|
||||
async fn reopen_issue_with_due_date(ctx: &crate::Context, task: &task::Task, due_date: time::OffsetDateTime) -> anyhow::Result<()> {
|
||||
todo!()
|
||||
async fn reopen_issue_with_due_date(
|
||||
ctx: &crate::Context,
|
||||
task: &task::Task,
|
||||
due_date: &jiff::Zoned,
|
||||
) -> anyhow::Result<()> {
|
||||
ctx.forgejo
|
||||
.issue_edit_issue(
|
||||
&ctx.owner,
|
||||
&ctx.repo,
|
||||
task.issue_number.into(),
|
||||
forgejo_api::structs::EditIssueOption {
|
||||
due_date: Some(util::jiff_to_time(due_date)),
|
||||
state: Some("open".to_owned()),
|
||||
assignee: None,
|
||||
assignees: None,
|
||||
body: None,
|
||||
milestone: None,
|
||||
r#ref: None,
|
||||
title: None,
|
||||
unset_due_date: None,
|
||||
updated_at: None,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.context("Failed reopening recurring issue")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Task {
|
||||
/// Issue Number for referencing the task
|
||||
pub issue_number: u64,
|
||||
pub issue_number: u32,
|
||||
|
||||
/// Human-readable summary of the task
|
||||
pub title: String,
|
||||
|
|
@ -18,10 +18,10 @@ pub enum State {
|
|||
/// The task is open and pending completion.
|
||||
///
|
||||
/// An optional due date may be present.
|
||||
Open { due: Option<time::OffsetDateTime> },
|
||||
Open { due: Option<jiff::Zoned> },
|
||||
|
||||
/// The task has been completed at the specified time.
|
||||
Completed { date: time::OffsetDateTime },
|
||||
Completed { date: jiff::Zoned },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
10
src/util.rs
Normal file
10
src/util.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
pub fn time_to_jiff(t: time::OffsetDateTime) -> jiff::Zoned {
|
||||
let tz = jiff::tz::TimeZone::fixed(jiff::tz::offset(t.offset().whole_hours()));
|
||||
|
||||
jiff::Timestamp::new(t.unix_timestamp(), 0).unwrap()
|
||||
.to_zoned(tz)
|
||||
}
|
||||
|
||||
pub fn jiff_to_time(t: &jiff::Zoned) -> time::OffsetDateTime {
|
||||
time::OffsetDateTime::from_unix_timestamp(t.timestamp().as_second()).unwrap()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue