From 7bc47cf4284980fb9358bf69a50ee961a2b324a4 Mon Sep 17 00:00:00 2001 From: "Stanislav N. aka pztrn" Date: Wed, 29 Sep 2021 07:35:31 +0500 Subject: [PATCH] Update to cron v3, ability to show next issues creation timestamps and little refactor. --- Makefile | 5 ++++ go.mod | 3 ++- go.sum | 6 +++-- internal/tasks/base.go | 56 +++++++++++++++++++++++++++-------------- internal/tasks/tasks.go | 25 ++++++++++++++++++ main.go | 10 +++++++- 6 files changed, 82 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 76e2ab3..13a5f16 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,11 @@ run: GPT_CONFIG=$(CONFIG) ./periodicator rm periodicator +run-show-next-creation-ts: + go build -ldflags $(LINKER_FLAGS) -o periodicator . + GPT_CONFIG=$(CONFIG) ./periodicator -show-next-creation-ts + rm periodicator + run-version: go build -ldflags $(LINKER_FLAGS) -o periodicator . GPT_CONFIG=$(CONFIG) ./periodicator -version diff --git a/go.mod b/go.mod index a21ed8d..443120b 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,13 @@ module go.dev.pztrn.name/periodicator go 1.17 require ( - github.com/robfig/cron v1.2.0 + github.com/robfig/cron/v3 v3.0.1 github.com/xanzy/go-gitlab v0.51.1 gopkg.in/yaml.v2 v2.2.2 ) require ( + github.com/adhocore/gronx v0.2.5 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/go.sum b/go.sum index 9fde858..5a2ff72 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/adhocore/gronx v0.2.5 h1:trVgNYPle0IcsGDt0XGz78zN8Soek0YrcQtQ+Cs+jko= +github.com/adhocore/gronx v0.2.5/go.mod h1:7oUY1WAU8rEJWmAxXR2DN0JaO4gi9khSgKjiRypqteg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -125,8 +127,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= -github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/internal/tasks/base.go b/internal/tasks/base.go index 60de63e..a1dfcbf 100644 --- a/internal/tasks/base.go +++ b/internal/tasks/base.go @@ -4,7 +4,7 @@ import ( "log" "time" - "github.com/robfig/cron" + "github.com/robfig/cron/v3" g "github.com/xanzy/go-gitlab" "go.dev.pztrn.name/periodicator/internal/gitlab" ) @@ -39,6 +39,37 @@ func (b *BaseTask) checkIfOpenedTaskExists(issues []*g.Issue) bool { return foundAndNotClosed } +func (b *BaseTask) getIssues() ([]*g.Issue, error) { + // nolint:wrapcheck + return b.client.GetIssuesByTitle(b.projectID, b.title) +} + +func (b *BaseTask) getLastCreationTimestamp(issues []*g.Issue) time.Time { + lastTaskCreationTS := b.executionStartTimestamp + + for _, issue := range issues { + if issue.ClosedAt != nil && issue.CreatedAt.After(lastTaskCreationTS) { + lastTaskCreationTS = *issue.CreatedAt + } + } + + return lastTaskCreationTS +} + +func (b *BaseTask) getNextCreationTimestamp(lastTaskCreationTS time.Time) time.Time { + // Set up cron job parser. + cp := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow) + + schedule, err := cp.Parse(b.cron) + if err != nil { + b.log("Failed to parse cron string: " + err.Error()) + + return lastTaskCreationTS + } + + return schedule.Next(lastTaskCreationTS) +} + func (b *BaseTask) log(message string) { log.Println("Task '" + b.title + "': " + message) } @@ -46,7 +77,7 @@ func (b *BaseTask) log(message string) { // Run executes task procedure. func (b *BaseTask) Run() { // Get similar tasks. - issues, err := b.client.GetIssuesByTitle(b.projectID, b.title) + issues, err := b.getIssues() if err != nil { b.log("Error while getting issues from Gitlab: " + err.Error()) @@ -65,29 +96,16 @@ func (b *BaseTask) Run() { b.log("No still opened tasks found, checking if we should create new one...") // Get latest task creation timestamp from Gitlab. - lastTaskCreationTS := b.executionStartTimestamp - - for _, issue := range issues { - if issue.ClosedAt != nil && issue.CreatedAt.After(lastTaskCreationTS) { - lastTaskCreationTS = *issue.CreatedAt - } - } + lastTaskCreationTS := b.getLastCreationTimestamp(issues) b.log("Last task creation timestamp: " + lastTaskCreationTS.String()) - // Set up cron job parser. - cp := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow) - - schedule, err := cp.Parse(b.cron) - if err != nil { - b.log("Failed to parse cron string: " + err.Error()) - + // Figure out next task creation and deadline timestamps. + nextCreationTS := b.getNextCreationTimestamp(lastTaskCreationTS) + if nextCreationTS.Equal(lastTaskCreationTS) { return } - // Figure out next task creation and deadline timestamps. - nextCreationTS := schedule.Next(lastTaskCreationTS) - // Check if task should be created and create if so. if nextCreationTS.Before(time.Now()) { // Deadlines should be calculated until first one will appear AFTER today. diff --git a/internal/tasks/tasks.go b/internal/tasks/tasks.go index ccb6460..2fba897 100644 --- a/internal/tasks/tasks.go +++ b/internal/tasks/tasks.go @@ -4,6 +4,31 @@ import ( "go.dev.pztrn.name/periodicator/internal/gitlab" ) +// PrintCreationTSes prints tasks creation timestamps. +func PrintCreationTSes(client *gitlab.Client, tasks []Config) { + for _, task := range tasks { + t := &BaseTask{ + client: client, + projectID: task.ProjectID, + title: task.Title, + body: task.Body, + tags: task.Tags, + executionStartTimestamp: task.ExecutionStart.GetTimestamp(), + cron: task.Cron, + dueIn: task.DueIn, + } + + // Get similar tasks. + // ToDo: refactor? + issues, err := t.getIssues() + if err != nil { + panic("Error while getting issues from Gitlab: " + err.Error()) + } + + t.log(t.getNextCreationTimestamp(t.getLastCreationTimestamp(issues)).String()) + } +} + // Process processes passed tasks. func Process(client *gitlab.Client, tasks []Config) { for _, task := range tasks { diff --git a/main.go b/main.go index da1a48f..b09fa68 100644 --- a/main.go +++ b/main.go @@ -11,7 +11,10 @@ import ( "go.dev.pztrn.name/periodicator/internal/tasks" ) -var showVersion = flag.Bool("version", false, "Show version information and exit") +var ( + showNextCreationTS = flag.Bool("show-next-creation-ts", false, "Show tasks next creation timestamps") + showVersion = flag.Bool("version", false, "Show version information and exit") +) func main() { flag.Parse() @@ -28,5 +31,10 @@ func main() { c := gitlab.NewGitlabClient(&cfg.Gitlab) + if *showNextCreationTS { + tasks.PrintCreationTSes(c, cfg.Tasks) + os.Exit(0) + } + tasks.Process(c, cfg.Tasks) }